def ai_player_csp(state, board): csp = constraint.Problem() rows, cols = len(state[0]), len(state[0][0]) fringe_cells = set() for i, j in np.ndindex((rows, cols)): if state[0][i][j].isdigit(): n = int(state[0][i][j]) neighbors = [(x, y) for x, y in surrounding_cells(i, j, rows, cols) if state[0][x][y] == '#'] fringe_cells.update(neighbors) csp.addConstraint(constraint.ExactSumConstraint(n), neighbors) csp.addVariables(fringe_cells, [0, 1]) solutions = csp.getSolutions() print(len(solutions)) if solutions: fringe_dict = defaultdict(float) for solution in solutions: for cell in solution.keys(): fringe_dict[cell] += solution[cell] safe = min(fringe_dict, key=fringe_dict.get) mine = max(fringe_dict, key=fringe_dict.get) if fringe_dict[safe] != fringe_dict[mine]: return safe return ai_player(state, board)
def round_seq_preserving_sum(seq: Seq[float], minval=1, maxval:int=None) -> Opt[List[int]]: """ Round the elements of seq preserving the sum so that sum(seq_rounded) == sum(seq) given: sum(seq) will be rounded """ seqsum = round(sum(seq)) if maxval is None: maxval = int(min(max(seq) + 1, seqsum)) p = constraint.Problem() numvars = len(seq) variables = list(range(numvars)) domain = list(range(minval, maxval+1)) p.addVariables(variables, domain) for var, optimalval in zip(variables, seq): func = lambda intval, floatval: abs(intval - floatval) <= 1 p.addConstraint(partial(func, optimalval), [var]) p.addConstraint(constraint.ExactSumConstraint(seqsum), variables) solutions = p.getSolutions() if not solutions: return None solutions.sort(key=lambda sol: sum(abs(v-x) for v, x in zip(list(sol.values()), seq))) solution = list(solutions[0].items()) solution.sort() varnames, values = list(zip(*solution)) return values
def puzzle_as_CP(fixed, boxsize, solver=constraint.BacktrackingSolver()): """puzzle_as_CP(fixed, boxsize) -> constraint.Problem Returns a constraint problem representing a Sudoku puzzle, based on 'fixed' cell dictionary.""" p = empty_puzzle_as_CP(boxsize, solver) for cell in fixed: p.addConstraint(constraint.ExactSumConstraint(fixed[cell]), [cell]) return p
def p(n): p = constraint.Problem() p.addVariables(range(n), N) p.addConstraint(constraint.AllDifferentConstraint()) p.addConstraint(constraint.ExactSumConstraint(2020)) try: print(prod(p.getSolution().values())) except: print("")
def post_randomize(self): last_level = self.stack_level[self.program_cnt - 1] for i in range(len(self.program_h)): self.program_h[i].program_id = i self.program_h[i].call_stack_level = self.stack_level[i] # Top-down generate the entire call stack. # A program can only call the programs in the next level. for i in range(last_level): program_list = [] next_program_list = [] idx = 0 # sub_program_id_pool = [] # sub_program_cnt = [] for j in range(len(self.stack_level)): if self.stack_level[j] == i: program_list.append(j) if self.stack_level[j] == i + 1: next_program_list.append(j) # Randomly duplicate some sub programs in the pool to create a case that # one sub program is called by multiple caller. Also it's possible to call # the same sub program in one program multiple times. total_sub_program_cnt = random.randint(len(next_program_list), len(next_program_list) + 1) sub_program_id_pool = [None] * total_sub_program_cnt for j in range(len(sub_program_id_pool)): if j < len(next_program_list): sub_program_id_pool[j] = next_program_list[j] else: sub_program_id_pool[j] = random.choice(next_program_list) random.shuffle(sub_program_id_pool) sub_program_cnt = [None] * len(program_list) for i in range(len(program_list)): sub_program_cnt[i] = i # Distribute the programs of the next level among the programs of current level # Make sure all program has a caller so that no program is obsolete. problem = constraint.Problem(constraint.MinConflictsSolver()) problem.addVariables(sub_program_cnt, range(0, len(sub_program_id_pool) + 1)) problem.addConstraint( constraint.ExactSumConstraint(len(sub_program_id_pool)), [item for item in sub_program_cnt]) solution = problem.getSolution() for j in range(len(program_list)): id = program_list[j] self.program_h[id].sub_program_id = [ None ] * solution[sub_program_cnt[j]] for i in range(len(self.program_h[id].sub_program_id)): self.program_h[id].sub_program_id[i] = sub_program_id_pool[ idx] idx += 1
def p3(): # ways of making 60 problem = constraint.Problem() problem.addVariable("1p", range(61)) # range 0-60 problem.addVariable("3p", range(21)) problem.addVariable("5p", range(13)) problem.addVariable("10p", range(7)) problem.addVariable("20p", range(4)) problem.addConstraint(constraint.ExactSumConstraint(60, [1, 3, 5, 10, 20]), ["1p", "3p", "5p", "10p", "20p"]) def print_solutions(solutions): for s in solutions: print(format(s["1p"], s["3p"], s["5p"], s["10p"], s["20p"])) solutions = problem.getSolutions() #print_solutions(solutions) print("Total number of ways: {}".format(len(solutions)))
import constraint problem = constraint.Problem() # The maximum amount of each coin type can't be more than 60 # (coin_value*num_of_coints) <= 60 problem.addVariable("1 cent", range(61)) problem.addVariable("3 cent", range(21)) problem.addVariable("5 cent", range(13)) problem.addVariable("10 cent", range(7)) problem.addVariable("20 cent", range(4)) problem.addConstraint( constraint.ExactSumConstraint(60,[1,3,5,10,20]), ["1 cent", "3 cent", "5 cent","10 cent", "20 cent"] ) # Where we explicitly give the order in which the weights should be allocated # We could've used a custom constraint instead, BUT in this case the program will # run slightly slower - this is because built-in functions are optimized and # they find the solution more quickly # def custom_constraint(a, b, c, d, e): # if a + 3*b + 5*c + 10*d + 20*e == 60: # return True # problem.addConstraint(o, ["1 cent", "3 cent", "5 cent","10 cent", "20 cent"]) # A function that prints out the amount of each coin # in every acceptable combination def print_solutions(solutions):
for i in Block_List: filter_neighbours = [] if (i[3] != -1): row_temp = i[1] col_temp = i[2] if (row_temp == 0 and col_temp == 0): if (checkDown(row_temp, col_temp, matrix)): temp_coord = str(row_temp + 1) + str(col_temp) filter_neighbours.append(temp_coord) if (checkRight(row_temp, col_temp, matrix)): temp_coord = str(row_temp) + str(col_temp + 1) filter_neighbours.append(temp_coord) if (len(filter_neighbours) > 0): problem.addConstraint(constraint.ExactSumConstraint(i[3]), filter_neighbours) elif (row_temp == 0 and col_temp == cols - 1): if (checkDown(row_temp, col_temp, matrix)): temp_coord = str(row_temp + 1) + str(col_temp) filter_neighbours.append(temp_coord) if (checkLeft(row_temp, col_temp, matrix)): temp_coord = str(row_temp) + str(col_temp - 1) filter_neighbours.append(temp_coord) if (len(filter_neighbours) > 0): problem.addConstraint(constraint.ExactSumConstraint(i[3]), filter_neighbours) elif (row_temp == rows - 1 and col_temp == 0): if (checkUp(row_temp, col_temp, matrix)):
# Dati su novcici od 1, 2, 5, 10, 20 dinara. Napisati program koji # pronalazi sve moguce kombinacije tako da zbir svih novcica bude 50. # Sve rezultate ispisati na standardni izlaz koristeci datu komandu ispisa. import constraint problem = constraint.Problem() problem.addVariable("1 din", range(0, 51)) problem.addVariable("2 din", range(0, 26)) problem.addVariable("5 din", range(0, 11)) problem.addVariable("10 din", range(0, 6)) problem.addVariable("20 din", range(0, 3)) problem.addConstraint(constraint.ExactSumConstraint(50, [1, 2, 5, 10, 20]), ["1 din", "2 din", "5 din", "10 din", "20 din"]) resenje = problem.getSolutions() for r in resenje: print("-----------------") print("""1 din: {0:d}\n2 din: {1:d}\n5 din: {2:d}\n10 din: {3:d}\n20 din: {4:d}""".format(r["1 din"], r["2 din"], r["5 din"], r["10 din"], r["20 din"]))
import termcolor GOOD = 0 EVIL = 1 players = list(range(1, 11)) players_evil = 4 players_good = len(players) - players_evil problem = constraint.Problem() # Every player is good or evil problem.addVariables(players, [GOOD, EVIL]) # There are always an exact number of evil players problem.addConstraint(constraint.ExactSumConstraint(players_evil)) # Assume no evil players if a mission passes mission_passed = known_good_player = constraint.ExactSumConstraint(GOOD) # Assume at most 1 evil player if the 4th mission passes mission_4_passed = constraint.MaxSumConstraint(EVIL) # Know at least 1 evil player is on every failed mission mission_failed = known_evil_player = constraint.MinSumConstraint(EVIL) # problem.addConstraint(known_good_player, [1]) # The following is a simulated game # Players 1, 2, 3, 4 are evil, but we don't "know" this problem.addConstraint(mission_failed, [1, 2, 3])
def partition_curvedspace(x, numpart, curve, minval=1, maxdev=1, accuracy=1): """ Partition a curved space defined by curve into `numpart` partitions, each with a min. value of `minval` curve: a bpf curve where y goes from 0 to some integer (this values is not important) NB: curve must be a monotonically growing curve starting at 0. See the example using .integrated() to learn how to make a monotonically growing curve out of any distribution NB: returns None if no solution is possible Example 1 ========= Divide 23 into 6 partitions following an exponential curve curve = bpf.expon(3, 0, 0, 1, 1) partition_curvedspace_int(23, 6, curve) --> [1, 1, 2, 4, 6, 9] Example 2 ========= Partition a distance following, an arbitraty curve, where the y defines the relative duration of the partitions. In this case, the curve defined the derivative of our space. curve = bpf.linear( 0, 1, 0.5, 0, 1, 1) partition_curvedspace_int(21, 7, curve.integrated()) --> [5, 3, 2, 1, 2, 3, 5] Example 3 ========= Partition a distance following an arbitrary curve, with fractional values with a precission of 0.001 curve = bpf.linear(0, 1, 0.5, 0, 1, 1) dist = 21 numpart = 7 upscale = 1000 parts = partition_curvedspace_int(dist*upscale, numpart, curve.integrated()) parts = [part/upscale for part in parts] --> [5.143, 3.429, 1.714, 0.428, 1.714, 3.429, 5.143] """ assert curve(curve.x0) == 0 and curve(curve.x1) > 0, \ "The curve should be a monotonically growing curve, starting at 0" if accuracy > 1: raise ValueError("0 < accuracy <= 1") elif 0 < accuracy < 1: scale = int(1.0/accuracy) parts = partition_curvedspace(x*scale, numpart, curve, minval=minval*scale, maxdev=maxdev, accuracy=1) if not parts: scale += 1 parts = partition_curvedspace(x*scale, numpart, curve, minval=minval*scale, maxdev=maxdev, accuracy=1) if not parts: warnings.warn("No parts with this accuracy") return None fscale = float(scale) def roundgrid(x, grid): numdig = len(str(grid).split(".")[1]) return round(round(x*(1.0/grid))*grid, numdig) return [roundgrid(part/fscale, accuracy) for part in parts] normcurve = curve.fit_between(0, 1) normcurve = (normcurve / normcurve(1)) * x optimal_results = np.diff(normcurve.map(numpart+1)) maxval = min(int(max(optimal_results) + 1), x-(numpart-1)*minval) # maxval = x - minval * (numpart - 1) V = list(range(numpart)) p = constraint.Problem() p.addVariables(V, list(range(minval, maxval))) def objective(solution): values = list(solution.values()) return sum(abs(val-res) for val, res in zip(values, optimal_results)) for var, res in zip(V, optimal_results): func = lambda x, res: abs(x-res) <= maxdev p.addConstraint(partial(func, res), [var]) p.addConstraint(constraint.ExactSumConstraint(x), V) solutions = p.getSolutions() if not solutions: logger.warning("No solutions") return None solutions.sort(key=objective) # each solution is a dict with integers as keys best = [value for name, value in sorted(solutions[0].items())] return best
# Calculate in how many ways you can return change for 60 cents. import constraint problem = constraint.Problem() # The maximum amount of each coin type can't be more than 60 # (coin_value*num_of_coints) <= 60 problem.addVariable("1 cent", range(61)) problem.addVariable("3 cent", range(21)) problem.addVariable("5 cent", range(13)) problem.addVariable("10 cent", range(7)) problem.addVariable("20 cent", range(4)) problem.addConstraint(constraint.ExactSumConstraint(60, [1, 3, 5, 10, 20]), ["1 cent", "3 cent", "5 cent", "10 cent", "20 cent"]) # Where we explicitly give the order in which the weights should be allocated # We could've used a custom constraint instead, BUT in this case the program will # run slightly slower - this is because built-in functions are optimized and # they find the solution more quickly # def custom_constraint(a, b, c, d, e): # if a + 3*b + 5*c + 10*d + 20*e == 60: # return True # problem.addConstraint(o, ["1 cent", "3 cent", "5 cent","10 cent", "20 cent"]) # A function that prints out the amount of each coin # in every acceptable combination
def backend(r: int, c: int, r_num: List[List[int]], c_num: List[List[int]], crossed_cells: List[Tuple[int, int]] = None): # Setup CP problem object problem = cp.Problem() # Create variables variables = [f"A_{row}_{col}" for row in range(r) for col in range(c)] problem.addVariables(variables, [0, 1]) # Create starting constraints (crossed-out cells) if crossed_cells and len(crossed_cells) != 0: crossed_variables = [f"A_{row}_{col}" for row, col in crossed_cells] problem.addConstraint(cp.InSetConstraint({0}), crossed_variables) # Create row-sum and column-sum constraints for row in range(r): constraint_vars = [v for v in variables if re.search(f"_{row}_", v)] row_sum = sum(r_num[row]) # Add constraint to CP object # Doesn't work because of https://github.com/python-constraint/python-constraint/issues/48 # Understand what's happening ToDo # problem.addConstraint(lambda *args: sum(args) == row_sum, constraint_vars) problem.addConstraint(cp.ExactSumConstraint(row_sum), constraint_vars) # multi-group constraints group_details = r_num[row] constraint_group = partial(detect_groups, group_details) problem.addConstraint(constraint_group, constraint_vars) # Constraints to speed-up processing if row_sum == c: # The whole row must be 1's problem.addConstraint(cp.InSetConstraint({1}), constraint_vars) for col in range(c): constraint_vars = [v for v in variables if re.search(f"_{col}$", v)] col_sum = sum(c_num[col]) # Add constraint to CP object # problem.addConstraint(lambda *args: sum(args) == col_sum, constraint_vars) problem.addConstraint(cp.ExactSumConstraint(col_sum), constraint_vars) # multi-group constraints group_details = c_num[col] constraint_group = partial(detect_groups, group_details) problem.addConstraint(constraint_group, constraint_vars) # Constraints to speed-up processing if col_sum == r: # The whole column must be 1's problem.addConstraint(cp.InSetConstraint({1}), constraint_vars) # Solve # Convert dict solution into array ToDO solutions = problem.getSolutions() solutions_array = [] for solution in solutions: variables_in_order = [solution[k] for k in sorted(solution)] solutions_array.append(np.array(variables_in_order).reshape((r, c))) return solutions_array
import constraint # 10e = 1170din problem = constraint.Problem() problem.addVariable("#brasno", range(0, 11)) problem.addVariable("#plazma", range(0, 21)) problem.addVariable("#jaja", range(0, 8)) problem.addVariable("#mleko", range(0, 6)) problem.addVariable("#visnja", range(0, 4)) problem.addVariable("#nutela", range(0, 9)) problem.addConstraint(constraint.ExactSumConstraint(10)) problem.addConstraint( constraint.MaxSumConstraint(1170, [30, 300, 50, 170, 400, 450])) problem.addConstraint( constraint.MaxSumConstraint(500, [30, 10, 150, 32, 3, 15])) problem.addConstraint(constraint.MaxSumConstraint(150, [5, 30, 2, 15, 45, 68])) best_protein = -1 for solution in problem.getSolutions(): kolicina_proteina = 20 * solution["#brasno"]\ + 15 * solution["#plazma"]\ + 70 * solution["#jaja"]\ + 40 * solution["#mleko"]\ + 40 * solution["#visnja"]\ + 7 * solution["#nutela"] if best_protein < kolicina_proteina: best_protein = kolicina_proteina
import constraint coins = [1, 2, 5, 10, 20, 50, 100, 200] CSP = constraint.Problem() for coin in coins: CSP.addVariable(coin, range(0, 201, coin)) CSP.addConstraint(constraint.ExactSumConstraint(200)) print len(CSP.getSolutions())
# mora uvek da odgovara redosledu kojim smo mi definisali promenljive, # u konkretnom primeru (videti oblik u kom ispisuje resenje), # promenljive ce se dodati u sledecem redosledu: # '1 din', '2 din', '10 din', '20 din', '5 din' # (nacin na koji se kljucevi organizuju u recniku nije striktno definisan, # primetimo da niske nisu sortirane) # posledica je da postavljanje ogranicenja # problem.addConstraint(constraint.ExactSumConstraint(50,[1,2,5,10,20])) # nece ispravno dodeliti tezine, na primer, # tezinu 5 dodeli promenljivoj '10 din' umesto '5 din' kako bismo ocekivali # I nacin da se resi ovaj problem je da redosled promenljivih # koji odgovara redosledu tezina za ExactSumConstraint prosledimo # kao dodatni argument za funkciju addConstraint problem.addConstraint(constraint.ExactSumConstraint(50, [1, 2, 5, 10, 20]), ["1 din", "2 din", "5 din", "10 din", "20 din"]) # II nacin je da definisemo svoju funkciju koja predstavlja ogranicenje, samo ce sada solver nesto sporije da radi posto ugradjene funkcije imaju optimizovanu pretragu i brze dolaze do resenja # #def o(a, b, c, d, e): # if a + 2*b + 5*c + 10*d + 20*e == 50: # return True # #problem.addConstraint(o, ["1 din", "2 din", "5 din","10 din", "20 din"]) # resenja = problem.getSolutions() for r in resenja: print("---") print("""1 din: {0:d}
def solve(board): problem = constraint.Problem(constraint.BacktrackingSolver()) # Build Variables for y in range(SIZE): for x in range(SIZE): if board[y,x] == -1: problem.addVariable(str([y,x]), [1, 100]) # Constraints for variables near numbers for y in range(SIZE): for x in range(SIZE): if board[y,x] in [0,1,2,3,4]: val = 0 adj_vars = [] if y>0 and board[y-1,x] == -1: adj_vars.append(str([y-1,x])) if y<SIZE-1 and board[y+1,x] == -1: adj_vars.append(str([y+1,x])) if x>0 and board[y,x-1] == -1: adj_vars.append(str([y,x-1])) if x<SIZE-1 and board[y,x+1] == -1: adj_vars.append(str([y,x+1])) val += 100*board[y,x] + len(adj_vars) - board[y,x] problem.addConstraint(constraint.ExactSumConstraint(val), adj_vars) # Sum of each scan must be less than 200, since only 1 light per scan # For horizontal scans for y in range(SIZE): curr_scan = [] for x in range(SIZE): if board[y,x] == -1: curr_scan.append(str([y,x])) else: if len(curr_scan) > 0: problem.addConstraint(constraint.MaxSumConstraint(199), curr_scan) curr_scan = [] if len(curr_scan) > 0: problem.addConstraint(constraint.MaxSumConstraint(199), curr_scan) # For vertical scans for x in range(SIZE): curr_scan = [] for y in range(SIZE): if board[y,x] == -1: curr_scan.append(str([y,x])) else: if len(curr_scan) > 0: problem.addConstraint(constraint.MaxSumConstraint(199), curr_scan) curr_scan = [] if len(curr_scan) > 0: problem.addConstraint(constraint.MaxSumConstraint(199), curr_scan) # For each point, pair of scans passing through point must contain 100 at least once scans = [] for y in range(SIZE): for x in range(SIZE): if board[y,x] != -1: continue scan = [] scan.append(str([y,x])) # Up for i in reversed(range(y)): if board[i,x] >= 0: break else: scan.append(str([i,x])) # Down for i in range(y+1,SIZE): if board[i,x] >= 0: break else: scan.append(str([i,x])) # Left for i in reversed(range(x)): if board[y,i] >= 0: break else: scan.append(str([y,i])) # Right for i in range(x+1,SIZE): if board[y,i] >= 0: break else: scan.append(str([y,i])) scan.sort() if scan not in scans: scans.append(scan) for scan in scans: problem.addConstraint(constraint.SomeInSetConstraint([100]), scan) solution = problem.getSolution() for y in range(SIZE): for x in range(SIZE): if str([y,x]) in solution: board[y,x] = -1 if solution[str([y,x])] == 1 else 100 return board
# Cŕeation d’une variable python de dimension n cols = range(n) # Cŕeation d’une variable cols dont le domaine est {1, ..., n} pb.addVariables(cols, range(n)) # Ajout de la contrainte AllDiff pb.addConstraint(constraint.AllDifferentConstraint()) # Ŕecuṕeration de l’ensemble des solutions possibles s = pb.getSolution() print(s) n = 3 p = constraint.Problem() x = range(1, n**2 + 1) p.addVariables(x, x) p.addConstraint(constraint.AllDifferentConstraint()) # Variable contenant la somme de chaque ligne/colonne/diagonale s = n**2 * (n**2 + 1) / 6 # Ajout des contraintes du carŕe magique for k in range(n): # ligne k p.addConstraint(constraint.ExactSumConstraint(s), [x[k*n+i] for i in range(n)]) # colonne k p.addConstraint(constraint.ExactSumConstraint(s), [x[k+n*i] for i in range(n)]) # première diagonale p.addConstraint(constraint.ExactSumConstraint(s), [x[n*i+i] for i in range(n)]) # deuxième diagonale p.addConstraint(constraint.ExactSumConstraint(s), [x[(n-1)*i] for i in range(1, n+1)]) s = p.getSolution() print(s)