Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
236f974
feat: updating generics to be variable for cumulative
ImkoMarijnissen Sep 12, 2025
2e0c520
Merge branch 'main' into feat/variable-cumulative
ImkoMarijnissen Sep 16, 2025
d04fff2
feat: initial refactor
ImkoMarijnissen Sep 16, 2025
42807ed
fix: incremental backtracking
ImkoMarijnissen Sep 16, 2025
e351c9b
feat: lower-bound propagation of capacity
ImkoMarijnissen Sep 16, 2025
3e8a6e4
fix: include resource usage + processing time in the reason of propag…
ImkoMarijnissen Sep 16, 2025
502e214
fix: adding capacity to explanation as well + fixing returned predica…
ImkoMarijnissen Sep 16, 2025
ab03c1b
chore: only adding capacity predicate once
ImkoMarijnissen Sep 17, 2025
1e071bf
refactor: remove capacity bound from profile height explanation
ImkoMarijnissen Sep 17, 2025
21a5e5f
fix: adding lower-bound on resource usage and duration to explanation
ImkoMarijnissen Sep 17, 2025
4a9bcfe
fix: only fixing tasks when the duration and resource usage are also …
ImkoMarijnissen Sep 17, 2025
609d958
fix: perform check explanation after completing
ImkoMarijnissen Sep 17, 2025
177dab7
fix: also enqueue when variables are fixed
ImkoMarijnissen Sep 17, 2025
d50122c
fix: checking reason passed to context
ImkoMarijnissen Sep 17, 2025
eb73e2c
docs: fixing doc tests
ImkoMarijnissen Sep 19, 2025
973bf44
Merge branch 'main' into feat/variable-cumulative
ImkoMarijnissen Nov 11, 2025
ea63caa
fix: python interface only supports non-variable cumulative (for now)
ImkoMarijnissen Nov 11, 2025
b2bc454
Merge branch 'main' into feat/variable-cumulative
ImkoMarijnissen Nov 11, 2025
b382c2a
fix: empty domain reasons in incremental test cases per point
ImkoMarijnissen Nov 12, 2025
56a1922
Merge branch 'main' into feat/variable-cumulative
ImkoMarijnissen Dec 10, 2025
b3f2f0a
fix: getting reason for empty domain in test solver
ImkoMarijnissen Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 2 additions & 86 deletions minizinc/lib/fzn_cumulative.mzn
Original file line number Diff line number Diff line change
Expand Up @@ -13,93 +13,9 @@ predicate fzn_cumulative(array[int] of var int: s,
/\ if is_fixed(d) /\ is_fixed(r) /\ is_fixed(b) then
pumpkin_cumulative(s, fix(d), fix(r), fix(b))
else
fzn_decomposition_cumulative(s, d, r, b)
pumpkin_cumulative_vars(s, d, r, b)
endif
);

% The following predicate is taken from https://github.com/MiniZinc/libminizinc/blob/2.5.5/share/minizinc/std/cumulative.mzn
predicate fzn_decomposition_cumulative(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r,
var int: b) =
assert(index_set(s) == index_set(d) /\ index_set(s) == index_set(r),
"cumulative: the 3 array arguments must have identical index sets",
if length(s) >= 1 then
assert(lb_array(d) >= 0 /\ lb_array(r) >= 0,
"cumulative: durations and resource usages must be non-negative",
if
%% the previous test will not work for resources usages like [2,3,3,4,4] with a bound of 4 since the 2 appears exactly once
let { int: mr = lb_array(r);
int: mri = arg_min([ lb(r[i]) | i in index_set(r) ]) } in
forall(i in index_set(r))
(is_fixed(r[i]) /\ (fix(r[i]) + mr > ub(b) \/ i = mri))
then
if forall(i in index_set(d))(is_fixed(d[i]) /\ fix(d[i]) == 1)
then
all_different(s)
else
disjunctive(s, d)
endif
else
decomposition_cumulative(s, d, r, b)
endif
)
endif);

% The following predicate is taken from https://github.com/MiniZinc/libminizinc/blob/2.5.5/share/minizinc/std/fzn_cumulative.mzn
predicate decomposition_cumulative(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r, var int: b) =
let {
set of int: Tasks =
{i | i in index_set(s) where ub(r[i]) > 0 /\ ub(d[i]) > 0 }
} in
if 0==card(Tasks) then /*true*/ 0==card(index_set(s)) \/ b>=0
else
let {
int: early = min([ lb(s[i]) | i in Tasks ]),
int: late = max([ ub(s[i]) + ub(d[i]) | i in Tasks ])
} in (
if late - early > 5000 then
fzn_cumulative_task(s, d, r, b)
else
fzn_cumulative_time(s, d, r, b)
endif
)
endif
;

% The following predicate is taken from https://github.com/MiniZinc/libminizinc/blob/2.5.5/share/minizinc/std/fzn_cumulative.mzn
predicate fzn_cumulative_time(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r, var int: b) =
let {
set of int: Tasks =
{i | i in index_set(s) where ub(r[i]) > 0 /\ ub(d[i]) > 0 },
int: early = min([ lb(s[i]) | i in Tasks ]),
int: late = max([ ub(s[i]) + ub(d[i]) | i in Tasks ])
} in (
forall( t in early..late ) (
b >= sum( i in Tasks ) (
bool2int(s[i] <= t /\ t < s[i] + d[i]) * r[i]
)
)
);

% The following predicate is taken from https://github.com/MiniZinc/libminizinc/blob/2.5.5/share/minizinc/std/fzn_cumulative.mzn
predicate fzn_cumulative_task(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r, var int: b) =
let {
set of int: Tasks =
{i | i in index_set(s) where ub(r[i]) > 0 /\ ub(d[i]) > 0 }
} in (
forall( j in Tasks ) (
b >= r[j] + sum( i in Tasks where i != j ) (
bool2int(s[i] <= s[j] /\ s[j] < s[i] + d[i] ) * r[i]
)
)
);

predicate pumpkin_cumulative(array[int] of var int: s, array[int] of int: d, array[int] of int: r, int: b);
predicate pumpkin_cumulative_vars(array[int] of var int: s, array[int] of var int: d, array[int] of var int: r, var int: b);
predicate pumpkin_cumulative_vars(array[int] of var int: s, array[int] of var int: d, array[int] of var int: r, var int: b);
1 change: 1 addition & 0 deletions pumpkin-crates/core/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub mod constraint_arguments {
//! Contains inputs to constraints.

pub use crate::propagators::ArgDisjunctiveTask;
pub use crate::propagators::ArgTask;
pub use crate::propagators::CumulativeExplanationType;
pub use crate::propagators::CumulativeOptions;
pub use crate::propagators::CumulativePropagationMethod;
Expand Down
4 changes: 4 additions & 0 deletions pumpkin-crates/core/src/api/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ impl Solver {
pub fn upper_bound(&self, variable: &impl IntegerVariable) -> i32 {
self.satisfaction_solver.get_upper_bound(variable)
}

pub(crate) fn is_fixed(&self, variable: &impl IntegerVariable) -> bool {
self.lower_bound(variable) == self.upper_bound(variable)
}
}

/// Functions to create and retrieve integer and propositional variables.
Expand Down
Loading