# Each cell (blank or not) must be adjacent to at least another for l in range(SIZE): for c in range(SIZE): lvars = [color[l2][c2] for l2, c2 in get_neighbors(l, c)] mdl.add(mdl.sum(lvars) < len(lvars)) # At least cell 0,0 or cell 0,1 is blank. # Build table of distance to one of these cells # Black cells are associated to a max distance SIZE*SIZE MAX_DIST = SIZE * SIZE distance = [[ mdl.integer_var(min=0, max=MAX_DIST, name="D" + str(l) + "_" + str(c)) for c in range(SIZE) ] for l in range(SIZE)] mdl.add(distance[0][0] == mdl.conditional(color[0][0], MAX_DIST, 0)) mdl.add(distance[0][1] == mdl.conditional(color[0][1], MAX_DIST, 0)) for c in range(2, SIZE): mdl.add(distance[0][c] == mdl.conditional( color[0][c], MAX_DIST, 1 + mdl.min(distance[l2][c2] for l2, c2 in get_neighbors(0, c)))) for l in range(1, SIZE): for c in range(SIZE): mdl.add(distance[l][c] == mdl.conditional( color[l][c], MAX_DIST, 1 + mdl.min(distance[l2][c2] for l2, c2 in get_neighbors(l, c)))) # Force distance of blank cells to be less than max for l in range(SIZE): for c in range(SIZE): mdl.add((color[l][c] > 0) | (distance[l][c] < MAX_DIST))
for k in range(2): #each bin's load can range(0..bin size) loads = [mdl.integer_var(0,bins[int(bin.id)].size[k], name="sizeBin"+str(bin.id)+",d"+str(k)) for bin in bins] mdl.add(mdl.pack(loads, wheres, [item.size[k] for item in items])) #===============SETUP OBJECTIVE=============== #maximize number of items allocated to all bins EXCEPT the big bin #nb_allocated_items = mdl.sum([(wheres[int(item.id)] != nb_bins) for item in items]) #maximize x_1 * x_2 * ... *x_n, where x_1, x_2,..., x_n is the number of items in bin 1, 2, ..., n product_x = 1 for bin in bins[0:len(bins)-1]: #get the number of items in the bin nb_items_in_bin = mdl.sum([(wheres[int(item.id)] == int(bin.id)) for item in items]) #if the bin is empty, assume it has 1 item so that the product won't be zero (ignore empty bins) x = mdl.conditional(nb_items_in_bin != 0, nb_items_in_bin, 1) #divided by 10 so that CPO won't have to handle big integer, just in case many x are large product_x = mdl.times(product_x, x/10) #add lecicographic objs #mdl.add(mdl.maximize_static_lex([nb_allocated_items, product_x])) mdl.add(mdl.maximize(product_x)) #solve the problem and print the solution print("...solving...") msol = mdl.solve(url = None, key = None, TimeLimit = None, SearchType = 'Auto') msol.print_solution() print("Obj vals: " + str(msol.get_objective_values())) print("x_1 * x_2 * ... * x_n = ",msol.get_objective_values()[0]*(10**nb_bins)) mdl.export_as_cpo(out='cpo.txt') with open('log.txt', "w") as text_file: