def createVariables(givenBoardCondition, k): #creating dictionaries for each resource to hold their resources whVariables = {} brVariables = {} woVariables = {} shVariables = {} variableDictionary = {} #Running through each list value in the given board condition and splitting them based on the operators to just leave variable names ie. W_31 #Then creating a dictionary key value pair where the key is the variable name and the value is a Var with the variable name used as the # constructor value for node in givenBoardCondition: parts = node.replace(">>", " ").replace("&", " ").replace("|", " ").replace( "(", " ").replace(")", " ").split() for variable in parts: variable.strip() #if variables are greater than k, they are not included in the final dictionary if (int(variable[3]) <= k + 1): if "wh" in variable.lower(): whVariables[variable] = Var(variable) if "wo" in variable.lower(): woVariables[variable] = Var(variable) if "br" in variable.lower(): brVariables[variable] = Var(variable) if "sh" in variable.lower(): shVariables[variable] = Var(variable) #Merging variable dictionaries into 1 master dictionary containing all variables variableDictionary = mergeDictionaries(variableDictionary, whVariables, woVariables, shVariables, brVariables) return variableDictionary
def _parse_cnf(tokens: t.Iterable[str]) -> And[Or[Var]]: clauses = set() # type: t.Set[Or[Var]] clause = set() # type: t.Set[Var] for token in tokens: if token == '0': clauses.add(Or(clause)) clause = set() elif token == '%': # Some example files end with: # 0 # % # 0 # I don't know why. break elif token.startswith('-'): clause.add(Var(_parse_int(token[1:]), False)) else: clause.add(Var(_parse_int(token))) if clause: # A file may or may not end with a 0 # Adding an empty clause is not desirable clauses.add(Or(clause)) sentence = And(clauses) NNF._is_CNF_loose.set(sentence, True) return sentence
def load(fp: t.TextIO, var_labels: t.Optional[t.Dict[int, Name]] = None) -> NNF: """Load a sentence from an open file. An optional ``var_labels`` dictionary can map integers to other names. """ def decode_name(num: int) -> Name: if var_labels is not None: return var_labels[num] return num fmt, nodecount, edges, varcount = fp.readline().split() node_specs = dict(enumerate(line.split() for line in fp)) assert fmt == 'nnf' nodes = {} # type: t.Dict[int, NNF] for num, spec in node_specs.items(): if spec[0] == 'L': if spec[1].startswith('-'): nodes[num] = Var(decode_name(int(spec[1][1:])), False) else: nodes[num] = Var(decode_name(int(spec[1]))) elif spec[0] == 'A': nodes[num] = And(nodes[int(n)] for n in spec[2:]) elif spec[0] == 'O': nodes[num] = Or(nodes[int(n)] for n in spec[3:]) else: raise ValueError("Can't parse line {}: {}".format(num, spec)) if int(nodecount) == 0: raise ValueError("The sentence doesn't have any nodes.") return nodes[int(nodecount) - 1]
def create_variables(givenBoardCondition): #creating dictionaries for each resource to hold their resources whVariables = {} brVariables = {} woVariables = {} shVariables = {} variableDictionary = {} #Running through each list value in the given board condition and splitting them based on the operators to just leave variable names ie. W_31 #Then creating a dictionary key value pair where the key is the variable name and the value is a Var with the variable name used as the # constructor value for node in givenBoardCondition: parts = node.replace(">>", " ").replace("&", " ").replace("|", " ").replace( "(", " ").replace(")", " ").split() for variable in parts: variable.strip() if "wh" in variable.lower(): whVariables[parts[variable]] = Var(parts[variable]) if "wo" in variable.lower(): woVariables[parts[variable]] = Var(parts[variable]) if "br" in variable.lower(): brVariables[parts[variable]] = Var(parts[variable]) if "sh" in variable.lower(): shVariables[parts[variable]] = Var(parts[variable]) #Merging variable dictionaries into 1 master dictionary containing all variables variableDictionary = merge_dictionaries(merge_dictionaries, whVariables) variableDictionary = merge_dictionaries(merge_dictionaries, whVariables) variableDictionary = merge_dictionaries(merge_dictionaries, whVariables) variableDictionary = merge_dictionaries(merge_dictionaries, whVariables) return variableDictionary
def test_implicates_implicants_negation_rule_example(): """These failed an old version of the previous test. See issue #3.""" sentence = Or({And({~Var(1), Var(2)}), And({~Var(3), Var(1)})}) assert (sentence.negate().implicants().negate().children >= sentence.implicates().children) assert (sentence.negate().implicates().negate().children <= sentence.implicants().children)
def set_initial_state(grid_setup): """ Sets the inital state of a grid @param grid_setup: a 5x5 2-dimensional list of a grid state """ grid_range = range(5) # A range variable used to iterate through the grid # Instantiates Var objects for u, m and s cases for the 5x5 grid for i in grid_range: for j in grid_range: # These create objects for each condition and state in the form # mij, uij and sij. For example, m12 would be the condition that # the square at coordinates (1, 2) is a bomb (coords start at (0, 0)) m[i].append(Var('m' + str(i) + str(j))) u[i].append(Var('u' + str(i) + str(j))) s[i].append(Var('s' + str(i) + str(j))) # Each square's state is checked and constraints are added # The if conditional is used to ignore the center square since # we don't need constrainsts for it if not (i == 2 and j == 2): state = grid_setup[i][j] # Raises an exception if a square has an illegal value if not (-2 <= state <= 8): raise Exception( 'error: each square of the grid must have a' ' value between -2 and 8 inclusive. Square ' '[%d][%d] has a value of %d' % (i, j, state)) if state == -2: # mine E.add_constraint(m[i][j]) else: E.add_constraint(~m[i][j]) if state == -1: # unknown E.add_constraint(u[i][j]) else: E.add_constraint(~u[i][j]) if state > -1: # revealed square E.add_constraint(s[i][j]) else: E.add_constraint(~s[i][j]) # Initializing x and y cases for i in grid_range: for j in grid_range: # We are only initializing the x and y truth values for the inner # 9 squares # The outer ring of squares can sometimes be determined for x and # y values, but that is beyond our scope if 0 < i < 4 and 0 < j < 4: set_X_truth(grid_setup, i, j) set_Y_truth(grid_setup, i, j) else: x[i].append(Var("x" + str(i) + str(j))) y[i].append(Var("y" + str(i) + str(j)))
def rand_var(multi, sets=[1, 1, 2], val=None): x = 100000000 if multi == sets[0]: return Var(str(rand(x))) | Var(str(rand(x))) # 75% elif multi > sets[2]: return Var(str(rand(x))) & Var(str(rand(x))) # 25% return val # 50%
def __init__(self,size,id): self.position = {} # Position of the final ships self.startPosition = {} # Used to determine the independent positions of the starting ships self.hInterPosition = {} # Board for a ship's placed position that are not the starting position self.vInterPosition = {} # Board for a ship's placed position that are not the starting position # Sizes of ship (only one can be true per ship object) self.size2 = Var("%d%s" % (id, "size2")) # Destroyer self.size3 = Var("%d%s" % (id, "size3")) # Cruiser or Submarine self.size4 = Var("%d%s" % (id, "size4")) # Battleship # self.size5 = Var("%d%s" % (id, "size5")) self.horizontal = Var("%d%s" % (id, "horizontal")) # Horizontal if true, vertical if false self.vertical = Var("%d%s" % (id,"vertical")) # Vertical if true, horizontal if false (redundant but both vars exist to help with more readable code) for i in range(size): for j in range(size): # var for coordinate should be true if the starting ship coordinate is at that (x, y) position self.startPosition[(i + 1,j + 1)] = Var("%ds(%d,%d)" % (id, i + 1, j + 1)) for i in range(size): for j in range(size): # var for coordinate should be true if the remainder of the ships's coordinates are at that (x, y) position and the ship is placed horizontally self.hInterPosition[(i + 1,j + 1)] = Var("%dh(%d,%d)" % (id, i + 1, j + 1)) for i in range(size): for j in range(size): # var for coordinate should be true if the remainder of the ships's coordinates are at that (x, y) position and the ship is placed vertically self.vInterPosition[(i + 1,j + 1)] = Var("%dv(%d,%d)" % (id, i + 1, j + 1)) for i in range(size): for j in range(size): # var for coordinate should be true if there is a ship part on the coordinate's (x, y) position self.position[(i + 1,j + 1)] = Var("(%d,%d)" % (i + 1, j + 1))
def count_builder(name): Count = [] for i in range(BOARD_SIZE**2): Count.append([]) for j in range((BOARD_SIZE**2)+1): Count[i].append(Var(f'{name}_count_by_{i}_is_{j}')) Total_Count = [] for i in range(BOARD_SIZE**2+1): Total_Count.append(Var(f'{name}_total_is_{i}')) return Count, Total_Count
def check_correct(self): var = [] ret_string = "" chars = list(self.characters.keys()) sentence_vals = {x: False for x in chars} chars.remove('weapon') chars.remove('location') for char in chars: var.append(Var(char)) weapon = self.characters['weapon'].goals['murderweapon'].points sus_weapon = self.characters['weapon'].goals['suspectedweapon'].points location = self.characters['location'].goals['murderlocation'].points sus_location = self.characters['location'].goals['suspectedlocation'].points for char in chars: if self.characters[char].goals['issuspect'].points == 1: sus_killer = char if self.characters[char].goals['iskiller'].points == 1: killer = char w = Var('weapon') l = Var('location') sentence = And({w, l, Or(tuple(var))}) if killer == sus_killer: sentence_vals[killer] = True ret_string += "You got the killer!\n" else: ret_string += "The killer got away!\n" if weapon == sus_weapon: sentence_vals['weapon'] = True ret_string += "You correctly identified the weapon!\n" else: ret_string += "You didn't identify the murder weapon correctly.\n" if location == sus_location: sentence_vals['location'] = True ret_string += "You deduced the correct location!\n\n" else: ret_string += "The murder took place in another location.\n\n" if sentence.satisfied_by(sentence_vals): ret_string += "Congratulations, you solved the mystery!\n" else: ret_string += "Unfortunately, you didn't solve the mystery completely.\n" return ret_string
def process_node(node: NNF) -> Var: if isinstance(node, Var): return node assert isinstance(node, Internal) children = {process_node(c) for c in node.children} if len(children) == 1: [child] = children return child aux = Var.aux() if any(~var in children for var in children): if isinstance(node, And): clauses.append(Or({~aux})) else: clauses.append(Or({aux})) elif isinstance(node, And): clauses.append(Or({~c for c in children} | {aux})) for c in children: clauses.append(Or({~aux, c})) elif isinstance(node, Or): clauses.append(Or(children | {~aux})) for c in children: clauses.append(Or({~c, aux})) else: raise TypeError(node) return aux
def _parse_sat(tokens: 't.Deque[str]') -> NNF: cur = tokens.popleft() if cur == '(': content = _parse_sat(tokens) close = tokens.popleft() if close != ')': raise DecodeError( "Expected closing paren, found {!r}".format(close)) return content elif cur == '-': content = _parse_sat(tokens) if not isinstance(content, Var): raise DecodeError( "Only variables can be negated, not {!r}".format(content)) return ~content elif cur == '*(': children = [] while tokens[0] != ')': children.append(_parse_sat(tokens)) tokens.popleft() if children: return And(children) else: return true elif cur == '+(': children = [] while tokens[0] != ')': children.append(_parse_sat(tokens)) tokens.popleft() if children: return Or(children) else: return false else: return Var(_parse_int(cur))
def set_Y_truth(grid_setup, i, j): """ Sets the y truth values a given square in a grid @param grid_setup: 5x5 2-dimensional list of a grid state i: row number of the square j: column number of the square """ # This constant list is used to quickly get the coordinates of adjacent squares coords = [[i - 1, j - 1], [i - 1, j], [i - 1, j + 1], [i, j - 1], [i, j + 1], [i + 1, j - 1], [i + 1, j], [i + 1, j + 1]] counter = 0 # Used for counting the number of adjacent mines or unknown squares for n in range(len(coords)): adjacent_square = grid_setup[coords[n][0]][coords[n][1]] # The following conditional checks if the nth adjacent square is a mine # or unknown if adjacent_square == -1 or adjacent_square == -2: counter += 1 # Instantiates the y condition at the given coordinate and sets a constraint # for it y[i].append(Var("y" + str(i) + str(j))) if grid_setup[i][j] == counter: E.add_constraint(y[i][j]) else: E.add_constraint(~y[i][j])
def set_X_truth(grid_setup, i, j): """ Sets the x truth values a given square in a grid @param grid_setup: 5x5 2-dimensional list of a grid state i: row number of the square j: column number of the square """ # This constant list is used to quickly get the coordinates of adjacent squares coords = [[i - 1, j - 1], [i - 1, j], [i - 1, j + 1], [i, j - 1], [i, j + 1], [i + 1, j - 1], [i + 1, j], [i + 1, j + 1]] counter = 0 # Used for counting the number of adjacent mines for n in range(len(coords)): adjacent_row = coords[n][0] adjacent_col = coords[n][1] # The following conditional checks if the nth adjacent square is a mine if grid_setup[adjacent_row][adjacent_col] == -2: counter += 1 # Instantiates a Var object for the x condition at the given coordinate and # sets a constraint for it x[i].append(Var("x" + str(i) + str(j))) if grid_setup[i][j] == counter: E.add_constraint(x[i][j]) else: E.add_constraint(~x[i][j])
def unpack_variables(T, propositions) -> list: """ Returns a list of all variable inputs for building a constraint Arguments --------- T : tuple propositions : defaultdict(weakref.WeakValueDictionary) Returns ------- inputs : list List of inputs with only unqiue variables returned. """ inputs = set() for var in T: if hasattr(var, '__qualname__'): if var.__qualname__ in propositions: cls = var.__qualname__ for instance_id in propositions[cls]: inputs.add(propositions[cls][instance_id]._var) elif classname(var) in propositions: cls = classname(var) for instance_id in propositions[cls]: obj = propositions[cls][instance_id] # apply method to object to get return values ret = set(flatten([var(obj)])) # check return values are valid inputs res = unpack_variables(ret, propositions) # add nnf.Var attribute of object res.append(obj._var) inputs.update(res) # if object, add its nnf.Var attribute elif hasattr(var, '_var'): inputs.add(var._var) # if nnf.Var object elif isinstance(var, Var): inputs.add(var) elif isinstance(var, (list, tuple, set)): inputs.update(unpack_variables(var, propositions)) else: if isinstance(var, core.CustomNNF): warnings.warn( f"Provided input {var} is a literal, not a variable.") try: # convert to nnf.Var inputs.add(Var(var)) except Exception as e: raise ValueError( f"Provided input {var} is not of an annotated class or method," " instance of such as class or method, or of type nnf.Var." " Attempted conversion of {var} to nnf.Var also failed and" f" yielded the following error message: {e}") return list(inputs)
def clone_varset(models, model_vars, varset): clones = {} for m in models: bitvec = model_to_bitvec(m, model_vars) clones[bitvec] = {} for v in varset: clones[bitvec][v] = Var(model_to_varclone(m, model_vars, v)) return clones
def init_vars(name): grid = [] for i in range(size): row = [] for j in range(size): row.append(Var(f'{name}_{i}_{j}')) grid.append(row) return grid
def __init__(self, size): # Player board standardized to 6x6 for now due to computing limitations # May be used for any encoding assessing hits self.hit_board = {} for i in range(size): for j in range(size): # var for coordinate is true if the (x, y) position is hit self.hit_board[(i + 1,j + 1)] = Var("(%d,%d)" % (i + 1,j + 1))
def test_dsharp_compile_converting_names(sentence: And[Or[Var]]): sentence = And( Or(Var(str(var.name), var.true) for var in clause) for clause in sentence) compiled = dsharp.compile(sentence) assert all(isinstance(name, str) for name in compiled.vars()) if sentence.satisfiable(): assert sentence.equivalent(compiled)
def example_theory(): variables = createVariables(givenBoardCondition, k) #overall variables for overall node types and winning condition Wh = Var("Wh") Wo = Var("Wo") Sh = Var("Sh") Br = Var("Br") W = Var("W") #create variable arrays wood, wheat, sheep, brick = createVariableLists(variables) tree = buildTree(variables, createImplicationList(givenBoardCondition, k)) rowVariables = variablesToRows(variables) E = Encoding() #Making Constraints based on board condition E = createBoardConstraints(givenBoardCondition, variables, E, k) #Adding constraint for winning condition E.add_constraint(W.negate() | (Wh & Wo & Sh & Br)) #Setting W to always true so that the solver tries to find a winning model E.add_constraint(W) E = setOverallVariablesTrueOrFalse(Wh, Wo, Br, Sh, variables, wood, wheat, sheep, brick, E, S) E = leaf_constraints( findLeaves( tree, findAllParents(tree, createImplicationList(givenBoardCondition, k))), E, variables) E = implementRequiredNodes(S, E, Wo, Wh, Sh, Br) E = rowVariablesToConstraints(rowVariables, E) #print(findLeaves(tree,findAllParents(tree,createImplicationList(givenBoardCondition,k)))) print(E.constraints) return E
def kemeny(votes): labels = collections.Counter() for vote in votes: for name, truthiness in order_to_model(vote).items(): labels[Var(name, truthiness)] += 1 return { model_to_order(model) for model in amc.maxplus_reduce(lin(votes[0]), labels).models() }
def __init__(self): self.schedule = {} for time in range(num_time_slots): for processor in range(num_processors): for process in range(num_processes): self.schedule[time, processor, process] = Var('schedule_' + str(time) + '_' + str(processor) + '_' + str(process))
def slater(votes): totals = collections.Counter() for vote in votes: for name, truthiness in order_to_model(vote).items(): totals[Var(name, truthiness)] += 1 labels = {} for var in totals: labels[var] = 1 if totals[var] > totals[~var] else 0 return { model_to_order(model) for model in amc.maxplus_reduce(lin(votes[0]), labels).models() }
def set_up_props(): """Initializes the propositions to be used by the model""" #loop through all stops for i in range(len(stop_info)): #set up propositions for travel location = stop_info[i]["location"] drive[location] = Var('drive from ' + location) transit[location] = Var('take transit from ' + location) plane[location] = Var('take a plane from ' + location) #set up other delay propositions roadwork[location] = Var('roadwork happening on the path from ' + location) accident[location] = Var('accident on the path from ' + location) toll[location] = Var('tolls on the path from ' + location) #set up weather propositions sunny[location] = Var('sunny from ' + location) rainy[location] = Var('rainy from ' + location) snowstorm[location] = Var('snowstorm from ' + location)
def build_negated_solution_nnf(self): nnf = None # Suppose our solution is {a=True, b=False, c=True}. # We could construct ~(a&~b&c), but the NNF library # would then have to perform the outer negation for us. # We can instead construct something that's already # in NNF, which is equivalent to what the NNF library # would give us: ~a|b|~c for prop,assignment in self.soln.items(): var = Var(prop, true=not assignment) if nnf is None: nnf = var else: nnf |= var return nnf
def __init__(self, pilot_id, start): # Name the pilots starting at A, B, ... self.pilot_id = chr(pilot_id + 65) self.starting_airport = start # Increase static counter Pilot.count += 1 self.location = [] # Initialize array of Var's for each pilot representing their location for timestep in range(N_TIMESTEPS): airports = [] for num in range(N_AIRPORTS): airport = Airport(num) airports.append(Var(airport)) self.location.append(airports)
def test_dimacs_cnf_serialize(): sample_input = """c Example CNF format file c p cnf 4 3 1 3 -4 0 4 0 2 -3 """ assert dimacs.loads(sample_input) == And( {Or({Var(1), Var(3), ~Var(4)}), Or({Var(4)}), Or({Var(2), ~Var(3)})})
def test_forget(sentence: nnf.NNF): # Assumption to reduce the time in testing assume(sentence.size() <= 15) # Test that forgetting a backbone variable doesn't change the theory T = sentence & Var('added_var') assert sentence.equivalent(T.forget({'added_var'})) # Test the tseitin projection assert sentence.equivalent(sentence.to_CNF().forget_aux()) # Test that models of a projected theory are consistent with the original names = list(sentence.vars())[:2] T = sentence.forget(names) assert not any([v in T.vars() for v in names]) for m in T.models(): assert sentence.condition(m).satisfiable()
def test_dimacs_sat_serialize(): # http://www.domagoj-babic.com/uploads/ResearchProjects/Spear/dimacs-cnf.pdf sample_input = """c Sample SAT format c p sat 4 (*(+(1 3 -4) +(4) +(2 3))) """ assert dimacs.loads(sample_input) == And( {Or({Var(1), Var(3), ~Var(4)}), Or({Var(4)}), Or({Var(2), Var(3)})})
def test_storing_function_constraint(): # assert failures when creating, # add_method(e) with no arguments # add_implies_all(e) with no left or right # add_at_most_k with incorrect k test = Var('test') with pytest.raises(ValueError): constraint.add_at_least_one(b) constraint.add_at_most_k(b, 0) constraint.add_implies_all(b) constraint.add_implies_all(b, left=[], right=[test]) constraint.add_none_of(b) assert len(b.constraints) == 0 constraint.add_implies_all(b, left=test, right=test) assert len(b.constraints) == 1 for c in b.constraints: assert c._constraint is cbuilder.implies_all assert c._left == c._right assert c._left == (test, )