Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 17 additions & 8 deletions CP/optimization/100potions.dzn
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
n = 100; %Water Number
w = 8; %Window Size
p = 140; %Leaves required in each Window
capacity= 380; %Total Energy we have for using holy Water
m= 4; %Mode numbers
n = 100; % number of potions, i.e. the number of segments we will grow on the tree
m = 4; % maximum number of segments emerging from a node (depends on the potion applied, see "nutrient")
w = 8; % window size, a segment count (evidently w <= n)
p = 140; % min number of leaves required in each window
capacity = 380; % total capacity of nutrients of a path through the tree

nutrient =
% For each potion (row) applied to a tree node, the nutrients
% required by each segment growing from that tree node (col).
% 381 is "beyond the capacity of nutrients" so essentially a
% stand-in for "infinity", that is, "that segment does not exist".

nutrient =
[|6,5,381,381
|4,1,5,381
|5,6,3,381
Expand Down Expand Up @@ -107,7 +112,11 @@ nutrient =
|4,381,381,381
|];

leave =
% For each potion (row) applied to a tree node, the number of
% leaves generated by each segment growing from that tree node (col).
% For unavailable segments, the number of leaves is 0.

leave =
[|68,36,0,0
|18,48,32,0
|83,90,18,0
Expand Down Expand Up @@ -208,4 +217,4 @@ leave =
|93,35,0,0
|6,3,51,0
|19,0,0,0
|];
|];
25 changes: 17 additions & 8 deletions CP/optimization/4potions.dzn
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
n = 4;
m = 4;
w = 2;
p = 8;
capacity= 19;
n = 4; % number of potions, i.e. the number of segments we will grow on the tree
m = 4; % maximum number of segments emerging from a node (depends on the potion applied, see "nutrient")
w = 2; % window size, a segment count (evidently w <= n)
p = 8; % min number of leaves required in each window
capacity = 19; % total capacity of nutrients of a path through the tree

nutrient =
% For each potion (row) applied to a tree node, the nutrients
% required by each segment growing from that tree node (col).
% 20 is "beyond the capacity of nutrients" so essentially a
% stand-in for "infinity", that is, "that segment does not exist".

nutrient =
[|4,2,3,7
|3,8,20,20
|5,4,6,20
|3,6,2,20
|];

leave =
% For each potion (row) applied to a tree node, the number of
% leaves generated by each segment growing from that tree node (col).
% For unavailable segments, the number of leaves is 0.

leave =
[|7,6,4,8
|5,8,0,0
|5,4,7,0
|6,9,3,0
|];
|];
77 changes: 63 additions & 14 deletions CP/optimization/yaocao.mzn
Original file line number Diff line number Diff line change
@@ -1,31 +1,74 @@
int: n; % number of potions
% Solving the "Yao Cao" problem
% https://www.coursera.org/learn/solving-algorithms-discrete-optimization/lecture/t2J76/3-2-1-optimization-in-cp

int: n; % number of potions, i.e. the number of segments we will grow on the tree
set of int: POTIONS = 1..n;
int: w; % window size
int: p; % num of leaves in each window
int: capacity; % capacity of nutrients
int: m; % max number of grown segments
int: w; % window size, a segment count (evidently w <= n)
int: p; % min number of leaves required in each window
int: capacity; % total capacity of nutrients of a path through the tree
int: m; % maximum number of segments emerging from a node (depends on the potion applied, see "nutrient")
set of int: SEGMENTS = 1..m;

array[POTIONS,SEGMENTS] of int: nutrient; % nutrient required
array[POTIONS,SEGMENTS] of int: leave; % num of leaves to grow
constraint assert(n>=w,"Window Size larger than number of potions (aka., number of segments)");

% For each potion (row) applied to a tree node, the nutrients
% required by each segment growing from that tree node (col).
% If the nutrient value is "beyond the capacity of nutrients", the
% meaning is "that segment does not exist" as we immediately
% would violate the nutrient limit if that segment were chosen-.

array[POTIONS,SEGMENTS] of int: nutrient;

% For each potion (row) applied to a tree node, the number of
% leaves generated by each segment growing from that tree node (col).
% For unavailable segments, the number of leaves is 0.

array[POTIONS,SEGMENTS] of int: leave;

% What we are looking for: for each potion applied to a
% tree node, we select the next segment to traverse. We do not
% have a choice in potion order, we have to use the potions
% in order of appearance.

array[POTIONS] of var SEGMENTS: choice;

array[POTIONS] of var SEGMENTS: choice; %Choice of segment for each potion
array[POTIONS] of var int: nutrient_list =
% Derived: the number of nutrients required for each segment,
% which his identified by the potion applied to its parent tree node.

array[POTIONS] of var int: nutrient_list =
[nutrient[i,choice[i]] | i in POTIONS];
array[POTIONS] of var int: leave_list =

% Derived: the number of leaves generated by each segment,
% which his identified by the potion applied to its parent tree node.

array[POTIONS] of var int: leave_list =
[leave[i,choice[i]] | i in POTIONS];

var int: total_nutrient = sum(nutrient_list);
var int: total_leaves = sum(leave_list);

constraint assert(n>=w,"Window Size larger than # of steps");
% Can't exceed the total nutrient capacity

%Capacity
constraint total_nutrient <= capacity;
%In each window, leave numbers should be larger than p

% In each window, number of leaves must reach the minimum

constraint forall(tail in w..n)
(sum(i in tail-w+1..tail)(leave_list[i]) >= p);

% Solving
% https://docs.minizinc.dev/en/stable/lib-stdlib-annotations.html#seq-search
% https://docs.minizinc.dev/en/stable/lib-stdlib-annotations.html#int-search
% On 100potions.dzn with "12th Gen Intel(R) Core(TM) i3-12100" + "Gecode 6.3.0":
% To find total_leaves = 6443; total_nutrient = 380:
% ssearch1 ~ 9 mins
% ssearch2+search1 ~ 27 s
% ssearch2+search2 ~ 27 s
% ssearch2+search3 ~ 15 s
% ssearch2+search4 ~ 11 s
% ssearch2+search5 ~ 9 s
% ssearch2+search6 ~ 19 s

solve :: ssearch2 maximize total_leaves;

ann: search1 = int_search(leave_list, input_order, indomain_min, complete);
Expand All @@ -37,8 +80,14 @@ ann: search6 = int_search(leave_list, smallest, indomain_max, complete);

ann: ssearch1 = seq_search([search1,
int_search([total_leaves], input_order, indomain_max, complete) ]);

ann: ssearch2 = seq_search([
int_search([total_leaves], input_order, indomain_max, complete),
search1 ]);

output ["choice = ",show(choice),";\n","total_leaves = ",show(total_leaves),";\n","total_nutrient = ", show(total_nutrient)];
output ["choice = ",show(choice),";\n","total_leaves = ",show(total_leaves),";\n","total_nutrient = ", show(total_nutrient)];
output ["\n"];
output ["Apply potion \(i)"++
", then select segment \(fix(choice[i]))"++
" which needs \(nutrient[i,fix(choice[i])]) nutrients"++
" and gives \(leave[i,fix(choice[i])]) leaves\n" | i in POTIONS];