this repo has no description
at develop 8.7 kB view raw
1/* 2% FlatZinc built-in redefinitions for linear solvers. 3% 4% AUTHORS 5% Sebastian Brand 6% Gleb Belov 7*/ 8 9%-----------------------------------------------------------------------------% 10% Auxiliary: indicator constraints 11% p -> x # 0 where p is a 0/1 variable and # is a comparison 12 13% Base cases 14 15%% used e.g. in element 16predicate aux_float_eq_if_1(var float: x, var float: y, var int: p) = 17 if is_fixed(p) then 18 if 1==fix(p) then x==y else true endif 19 elseif is_fixed(x) /\ is_fixed(y) then %%% Needed to avoid constant domain var 20 if fix(x)!=fix(y) then p==0 else true endif 21 elseif is_fixed(x-y) then %%% Hypothetically possible to land here 22 if 0.0!=fix(x-y) then p==0 else true endif 23 elseif fPostprocessDomains /\ fPostproDom_AUX /\ fPostproDom_DIFF then 24 aux_float_eq_zero_if_1__POST(x - y, p, p) 25 elseif fMZN__UseIndicators then 26 aux_float_eq_if_1__IND(x, y, p) 27 else 28 aux_float_le_if_1(x, y, p) /\ 29 aux_float_ge_if_1(x, y, p) 30 endif; 31 32predicate aux_int_eq_if_1(var int: x, var int: y, var int: p) = 33 if is_fixed(p) then 34 if fix(p) = 1 then (x = y) else true endif 35 elseif is_fixed(x) /\ is_fixed(y) then 36 if fix(x) != fix(y) then (p = 0) else true endif 37 % elseif is_fixed(x-y) then % TODO: Necessary for integers?? 38 % if 0.0!=fix(x-y) then p==0 else true endif 39 % elseif fPostprocessDomains /\ fPostproDom_AUX /\ fPostproDom_DIFF then 40 % % TODO MIPDomains 41 % elseif fMZN__UseIndicators then % TODO: Necessary for integers?? 42 % aux_float_eq_if_1__IND(x, y, p) 43 else 44 aux_int_le_if_1(x, y, p) /\ 45 aux_int_ge_if_1(x, y, p) 46 endif; 47 48predicate aux_float_ne_if_1(var float: x, var float: y, var int: p) = 49 if is_fixed(p) then 50 if fix(p) = 1 then (x = y) else true endif 51 elseif is_fixed(x) /\ is_fixed(y) then %%% Needed to avoid constant domain var 52 if (fix(x) = fix(y)) then (p = 0) else true endif 53 elseif is_fixed(x-y) then %%% Hypothetically possible to land here 54 if (0.0 = fix(x-y)) then (p = 0) else true endif 55 % TODO: What is necessary for not equals? 56 % elseif fPostprocessDomains /\ fPostproDom_AUX /\ fPostproDom_DIFF then 57 % aux_float_ne_zero_if_1__POST(x - y, p, p) 58 % elseif fMZN__UseIndicators then 59 % aux_float_ne_if_1__IND(x, y, p) 60 else 61 let { array[1..2] of var bool: q } in 62 ( q[1] -> (x < y) ) /\ 63 ( q[2] -> (x > y) ) /\ 64 (sum(q) = p) 65 endif; 66 67predicate aux_int_ne_if_1(var int: x, var int: y, var int: p) = 68 if is_fixed(p) then 69 if fix(p) = 1 then (x != y) else true endif 70 elseif is_fixed(x) /\ is_fixed(y) then 71 if fix(x) = fix(y) then (p = 0) else true endif 72 % elseif is_fixed(x-y) then % TODO: Necessary for integers?? 73 % if 0.0!=fix(x-y) then p==0 else true endif 74 % elseif fPostprocessDomains /\ fPostproDom_AUX /\ fPostproDom_DIFF then 75 % % TODO MIPDomains 76 % elseif fMZN__UseIndicators then % TODO: Necessary for integers?? 77 % aux_float_eq_if_1__IND(x, y, p) 78 else 79 let { array[1..2] of var bool: q } in 80 ( q[1] -> (x < y) ) /\ 81 ( q[2] -> (x > y) ) /\ 82 (sum(q) = p) 83 endif; 84 85predicate aux_int_le_zero_if_0(var int: x, var int: p) = 86 if is_fixed(p) then 87 if 0==fix(p) then x<=0 else true endif %% 0==fix !! 88 elseif lb(x)>0 then 89 p==1 90 elseif not (0 in dom(x)) then 91 let { 92 constraint assert( ub(x) < infinity, 93 "aux_int_le_zero_if_0: variable \(x)'s domain: dom(\(x)) = \(dom(x)), should have finite upper bound\n" ), 94 set of int: sDomNeg = dom(x) intersect -infinity..-1, 95 constraint assert( card( sDomNeg ) > 0, 96 "Variable \(x): dom(\(x)) = \(dom(x)), but dom() intersect -inf..-1: \(sDomNeg)\n" ), 97 } in 98 aux_int_le_if_0( x, max( sDomNeg ), p ) 99 elseif fPostprocessDomains /\ fPostproDom_AUX then 100 aux_int_le_zero_if_1__POST(x, 1-p) 101 elseif fMZN__UseIndicators then 102 aux_int_le_zero_if_0__IND(x, p) 103 else 104 assert( ub(x)<infinity, "Variable \(x) needs finite upper bound for a big-M constraint, current domain \(dom(x))" ) /\ 105 x <= ub(x) * p 106 endif; 107 108predicate aux_float_le_zero_if_0(var float: x, var int: p) = 109 %% TODO actually only need has_ub(x) in ub(x)*p but lb/ub fail on var float (not on var -infinity..const) 22.2.19 110 assert( has_bounds(x), "Variable \(x) needs finite bounds for a big-M constraint" ) /\ 111 if is_fixed(p) then 112 if 0==fix(p) then x<=0.0 else true endif 113 elseif lb(x)>0.0 then 114 p==1 115 elseif fPostprocessDomains /\ fPostproDom_AUX then 116 aux_float_le_zero_if_1__POST(x, 1-p, 1-p) 117 elseif fMZN__UseIndicators then 118 aux_float_le_zero_if_0__IND(x, p) 119 else 120 x <= ub(x) * p 121 endif; 122 123predicate aux_float_lt_zero_if_0(var float: x, var int: p) = 124 assert( has_bounds(x), "Variable \(x) needs finite bounds for a big-M constraint" ) /\ 125 if is_fixed(p) then 126 if 0==fix(p) then x<0.0 else true endif 127 elseif lb(x)>=0.0 then 128 p==1 129 elseif fPostprocessDomains /\ fPostproDom_AUX then 130 aux_float_lt_zero_if_1__POST(x, 1-p, 1-p, float_lt_EPS) 131 elseif fMZN__UseIndicators then 132 aux_float_le_zero_if_0__IND(x+float_lt_EPS, p) %% Here just absolute EPS, TODO 133 else 134%% let { float: rho = float_lt_EPS_coef__ * max(abs(ub(x)), abs(lb(x))) } % same order of magnitude as ub(x) 135 let { float: rho = float_lt_EPS } % absolute eps 136 in 137 %%% This one causes 2x- derivation of EPS: 138 %% x < (ub(x) + rho) * p 139 %%% Better? 140 x <= (ub(x) + rho) * p - rho 141 %%% This just uses absolute eps: 142 %% x < (ub(x) + float_lt_EPS) * p 143 endif; 144 145 146% Derived cases 147predicate aux_int_le_if_0(var int: x, var int: y, var int: p) = 148 aux_int_le_zero_if_0(x - y, p); 149 150predicate aux_int_ge_if_0(var int: x, var int: y, var int: p) = 151 aux_int_le_zero_if_0(y - x, p); 152 153predicate aux_int_le_if_1(var int: x, var int: y, var int: p) = 154 aux_int_le_zero_if_0(x - y, 1 - p); 155 156predicate aux_int_ge_if_1(var int: x, var int: y, var int: p) = 157 aux_int_le_zero_if_0(y - x, 1 - p); 158 159predicate aux_int_lt_if_0(var int: x, var int: y, var int: p) = 160 aux_int_le_zero_if_0(x - y + 1, p); 161 162predicate aux_int_gt_if_0(var int: x, var int: y, var int: p) = 163 aux_int_le_zero_if_0(y - x + 1, p); 164 165predicate aux_int_lt_if_1(var int: x, var int: y, var int: p) = 166 aux_int_le_zero_if_0(x - y + 1, 1 - p); 167 168predicate aux_int_gt_if_1(var int: x, var int: y, var int: p) = 169 aux_int_le_zero_if_0(y - x + 1, 1 - p); 170 171%% int: switching differences to float to avoid creating integer vars 172/* Used anywhere? 173predicate aux_int_le_if_0(var float: x, var float: y, var int: p) = 174 aux_float_le_zero_if_0(x - y, p); 175 176predicate aux_int_ge_if_0(var float: x, var float: y, var int: p) = 177 aux_float_le_zero_if_0(y - x, p); 178 179predicate aux_int_le_if_1(var float: x, var float: y, var int: p) = 180 aux_float_le_zero_if_0(x - y, 1 - p); 181 182predicate aux_int_ge_if_1(var float: x, var float: y, var int: p) = 183 aux_float_le_zero_if_0(y - x, 1 - p); 184 185predicate aux_int_lt_if_0(var float: x, var float: y, var int: p) = 186 aux_float_le_zero_if_0(x - y + 1.0, p); 187 188predicate aux_int_gt_if_0(var float: x, var float: y, var int: p) = 189 aux_float_le_zero_if_0(y - x + 1.0, p); 190 191predicate aux_int_lt_if_1(var float: x, float: y, var int: p) = 192 aux_float_le_zero_if_0(x - y + 1.0, 1 - p); 193*/ 194 195predicate aux_float_le_if_0(var float: x, var float: y, var int: p) = 196 aux_float_le_zero_if_0(x - y, p); 197 198predicate aux_float_ge_if_0(var float: x, var float: y, var int: p) = 199 aux_float_le_zero_if_0(y - x, p); 200 201predicate aux_float_le_if_1(var float: x, var float: y, var int: p) = 202 aux_float_le_zero_if_0(x - y, 1 - p); 203 204predicate aux_float_ge_if_1(var float: x, var float: y, var int: p) = 205 aux_float_le_zero_if_0(y - x, 1 - p); 206 207predicate aux_float_lt_if_0(var float: x, var float: y, var int: p) = 208 aux_float_lt_zero_if_0(x - y, p); 209 210predicate aux_float_gt_if_0(var float: x, var float: y, var int: p) = 211 aux_float_lt_zero_if_0(y - x, p); 212 213predicate aux_float_lt_if_1(var float: x, var float: y, var int: p) = 214 aux_float_lt_zero_if_0(x - y, 1 - p); 215 216predicate aux_float_gt_if_1(var float: x, var float: y, var int: p) = 217 aux_float_lt_zero_if_0(y - x, 1 - p); 218 219 220% -------------------------- Domains postpro --------------------------- 221 %% To avoid looking if an original int var x-y exists and has eq_encode: 222 %% Passing both int and float version of the indicator for flexibility: 223predicate aux_float_eq_zero_if_1__POST(var float: x, var int: pI, var float: p); 224 225predicate aux_int_le_zero_if_1__POST(var int: x, var int: p); 226predicate aux_float_le_zero_if_1__POST(var float: x, var int: pI, var float: p); 227predicate aux_float_lt_zero_if_1__POST(var float: x, var int: pI, var float: p, float: eps);