A set of benchmarks to compare a new prototype MiniZinc implementation
1% Copyright (c) 2016, Jacopo Mauro. All rights reserved. 2% This file is licensed under the terms of the ISC License. 3 4 5% Please note that you will need to set the MiniZinc standard library 6% environment variable $MZN_STDLIB_PATH to share/minizinc to include 7% the MiniSearch builtins 8 9include "lex_greatereq.mzn"; 10include "lex_less.mzn"; 11 12int: MAX_INT = 4096; 13%%%%%%%%%%%%%%%% 14% Input parameters 15%%%%%%%%%%%%%%%% 16 17% components 18set of int: comps; 19% ports 20set of int: ports; 21% multiple provide port 22set of int: multi_provide_ports; 23 24% locations 25set of int: locations; 26% resources 27set of int: resources; 28 29% map of components with their requirements number 30array[ comps, ports] of int: requirement_port_nums; 31% map of components with their provided multi-ports 32% -1 means infinite multi-port provider 33array[ comps, multi_provide_ports] of int: provide_port_nums; 34% map of components with their conflicts 35array[ comps, ports] of bool: conflicts; 36% map of multi-ports with their ports 37array[ multi_provide_ports, ports] of bool: multi_provides; 38 39% map of location with their costs 40array[ locations ] of int: costs; 41% map of locations with the resouces they provide 42array[ locations, resources ] of int: resource_provisions; 43% map of components with the resources they consume 44array[ comps, resources ] of int: resource_consumptions; 45 46%%%%%%%%%%%%%%%% 47% variables 48%%%%%%%%%%%%%%%% 49% bindings number 50array[ multi_provide_ports, ports, comps, comps] of var 0..MAX_INT: bindings; 51% components number 52array[ comps ] of var 0..MAX_INT: comps_num; 53% location to number of component map 54array[ locations, comps] of var 0..MAX_INT: comp_locations; 55 56% total number of components 57var 0..MAX_INT: sum_comp; 58 59%%%%%%%%%%%%%%%% 60% constraints (no location) 61%%%%%%%%%%%%%%%% 62 63% bind the total number of components 64constraint sum_comp = sum( i in comps)(comps_num[i]); 65 66% bindings 0 if the multiprovide does not provide port 67constraint forall(mport in multi_provide_ports, port in ports) ( 68 if multi_provides[mport,port] 69 then true 70 else forall(i in comps, j in comps) ( bindings[mport,port,i,j] = 0) 71 endif 72); 73 74% provides must be greater or equal to bindings & infinite provide port constraints 75constraint forall(mport in multi_provide_ports, pcomp in comps) ( 76 if provide_port_nums[pcomp,mport]=0 77 then forall(port in ports, rcomp in comps) ( 78 bindings[mport,port,pcomp,rcomp] = 0 79 ) 80 else 81 if (provide_port_nums[pcomp,mport] = -1) 82 then forall(port in ports, rcomp in comps) ( 83 (comps_num[pcomp] = 0) -> (bindings[mport,port,pcomp,rcomp]=0)) 84 else sum( port in ports, rcomp in comps)( 85 bindings[mport,port,pcomp,rcomp] ) <= comps_num[pcomp] * provide_port_nums[pcomp,mport] 86 endif 87 endif 88); 89 90% requires must be equal to bindings 91% note: here is possible to require also smaller than or equal 92constraint forall(port in ports, rcomp in comps) ( 93 sum( mport in multi_provide_ports, pcomp in comps)( 94 bindings[mport,port,pcomp,rcomp] ) = comps_num[rcomp] * requirement_port_nums[rcomp,port] 95); 96 97 98% conflict constraints if component provide same port 99constraint forall(port in ports, pcomp in comps) ( 100 if (conflicts[pcomp,port] /\ exists(mport in multi_provide_ports) ( 101 (multi_provides[mport,port]) /\ provide_port_nums[pcomp,mport] != 0)) 102 then comps_num[pcomp] <= 1 103 else true 104 endif 105); 106 107% conflict constraints 108constraint forall(port in ports, pcomp in comps, rcomp in comps) ( 109 if (conflicts[rcomp,port] /\ exists(mport in multi_provide_ports) ( 110 (multi_provides[mport,port]) /\ provide_port_nums[pcomp,mport] != 0)) 111 then comps_num[pcomp] > 0 -> comps_num[rcomp] = 0 112 else true 113 endif 114); 115 116% unicity constraint 117% note that we require that a component does not 118% require more than one port provided by a 119% multiple provide port 120constraint forall(mport in multi_provide_ports, pcomp in comps, rcomp in comps) ( 121 let 122 { int: max_req = sum(port in ports) ( 123 if multi_provides[mport,port] 124 then requirement_port_nums[rcomp,port] 125 else 0 126 endif 127 ) 128 } in 129 if pcomp = rcomp 130 then 131 ( comps_num[pcomp] >= max_req -> 132 sum(port in ports)(bindings[mport,port,pcomp,rcomp]) 133 <= max_req * (comps_num[rcomp] - 1)) 134 /\ 135 ( comps_num[pcomp] < max_req -> 136 forall (i in 1..max_req)( comps_num[pcomp] = i -> 137 sum(port in ports)(bindings[mport,port,pcomp,rcomp]) <= i * (i-1) )) 138 else 139 ( comps_num[pcomp] >= max_req -> 140 sum(port in ports)(bindings[mport,port,pcomp,rcomp]) 141 <= max_req * comps_num[rcomp] ) 142 /\ 143 ( comps_num[pcomp] < max_req -> 144 forall (i in 0..max_req)( comps_num[pcomp] = i -> 145 sum(port in ports)(bindings[mport,port,pcomp,rcomp]) <= i * comps_num[rcomp] ) ) 146 endif 147); 148 149%%%%%%%%%%%%%%%% 150% constraints for deciding locations 151%%%%%%%%%%%%%%%% 152 153% map location used or not used 154array[ locations ] of var 0..1: used_locations; 155constraint forall( l in locations)( 156 sum(c in comps)(comp_locations[l,c]) = 0 <-> used_locations[l] = 0 157); 158 159constraint forall( c in comps) ( 160 sum( l in locations) ( comp_locations[l,c]) = comps_num[c] 161); 162 163 164constraint forall( res in resources, loc in locations) ( 165 sum( comp in comps)( comp_locations[loc,comp] * resource_consumptions[comp,res] ) 166 <= resource_provisions[loc,res] 167); 168 169% the number of locations can not be greater than the number of components 170% i.e, one component per location in the worst case 171constraint sum(i in locations) (used_locations[i]) <= sum_comp; 172 173%------------------------------------------------------------------------------% 174% symmetry constraints (wrap in a unique predicate following minizinc specs 175 176 177constraint symmetry_breaking_constraint( 178 %if location are equal then first location has more comps than the second 179 %in lexicographically order (based on the cost) 180 forall( l1 in locations, l2 in locations)( 181 if l1 < l2 /\ forall ( r in resources)(resource_provisions[l1,r] = resource_provisions[l2,r] ) 182 then 183 if costs[l1] > costs[l2] 184 then lex_greatereq( 185 [comp_locations[l2,c] | c in comps], 186 [comp_locations[l1,c] | c in comps]) 187 /\ 188 (used_locations[l1] = 1 -> used_locations[l2] = 1) 189 else 190 lex_greatereq( 191 [comp_locations[l1,c] | c in comps], 192 [comp_locations[l2,c] | c in comps]) 193 /\ 194 (used_locations[l2] = 1 -> used_locations[l1] = 1) 195 endif 196 else 197 true 198 endif 199 )); 200 201 202%------------------------------------------------------------------------------% 203% Redundant constraints 204 205%constraint redundant_constraint( 206% % Ralf constraints 207% forall (rcomp in comps, port in ports)( 208% if requirement_port_nums[rcomp,port]!=0 209% then 210% comps_num[rcomp] > 0 -> sum( mport in multi_provide_ports, pcomp in comps)( 211% if provide_port_nums[pcomp,mport] != 0 /\ multi_provides[mport,port] 212% then comps_num[pcomp] 213% else 0 214% endif ) >= requirement_port_nums[rcomp,port] 215% else 216% true 217% endif 218% )); 219 220%------------------------------------------------------------------------------% 221% Constraints 222constraint 223 ( sum(l in locations)(comp_locations[l,1]) > 0 224 \/ sum(l in locations)(comp_locations[l,2]) > 0 225 ) 226/\ forall(x in locations)(comp_locations[x,3] < 2) 227/\ forall(x in locations)(comp_locations[x,4] < 2) 228; 229 230int: obj_min = sum(l in locations)(if costs[l] < 0 then costs[l] else 0 endif); 231int: obj_max = sum(l in locations)(if costs[l] > 0 then costs[l] else 0 endif); 232var obj_min..obj_max: objective; 233 234constraint objective = sum(l in locations)(used_locations[l] * costs[l]); 235 236%------------------------------------------------------------------------------% 237% Solve item 238 239array [locations] of locations: costs_asc = arg_sort(costs); 240array [locations] of locations: costs_desc = reverse(costs_asc); 241 242solve 243 :: seq_search([ 244 int_search([used_locations[costs_desc[i]] | i in locations], 245 input_order, indomain_min, complete), 246 int_search([comp_locations[l, i] | l in locations, i in comps], 247 first_fail, indomain_max, complete), 248 int_search(comps_num, first_fail, indomain_max, complete), 249 int_search([bindings[m,p,i,j] | m in multi_provide_ports, p in ports, i,j in comps], 250 first_fail, indomain_max, complete) 251 ]) 252 minimize objective; 253 254%------------------------------------------------------------------------------% 255% Output item 256 257output [ 258 "bindings = array4d(\(multi_provide_ports), \(ports), \(comps), \(comps), \(bindings));\n", 259 "comps_num = \(comps_num);\n", 260 "comp_locations = array2d(\(locations), \(comps), \(comp_locations));\n", 261 "used_locations = \(used_locations);\n", 262 "objective = \(objective);\n", 263 "% [\(objective), \(sum(x in locations)(sum(y in comps)(comp_locations[x,y])))]\n" 264]; 265 266