def _check_intersect(s, h1, h2): # When two houses intersect, # some numbers cannot at the same time be outside of the intersection # Thus they must be inside the intersection changed = 0 log.append("In House {0} & {1}:", h1, h2) h1u = util.difference(h1, h2) # h1 unique tiles h2u = util.difference(h2, h1) # h2 unique tiles h1un = s.get_numbers(h1u) # h1 unique numbers h2un = s.get_numbers(h2u) # h2 unique numbers h1i = Sudoku.other(h1un) # h1 intersect-only numbers h2i = Sudoku.other(h2un) # h2 intersect-only numbers hi = util.union(h1i, h2i) # intersect-only numbers if len(hi) > 0: @log.rollback def rem(): log.indent() log.append("Intersection contains {0}", hi) log.indent() result = max(section_remove(s, h2u, h1i), section_remove(s, h1u, h2i)) log.dedent(2) return result changed = rem() return changed
def BOTTOM_INTRO(goal, assumptions, size): """ Proofs of the form prove <#> via bottom-intro: prove <[prop]> via [rule]: ... prove <~[prop]> via [rule]: ... """ # try instantiating [prop] with all assumed props and subprops all_props = union({prop, *prop.subprops} for prop in assumptions) for prop in all_props: if prop.kind == PropKind.NOT: unwrapped = prop.contained for prop_proof_size, unwrapped_proof_size in share(size - 2, 2): prop_proof = find_proof(prop, assumptions, prop_proof_size) unwrapped_proof = find_proof(unwrapped, assumptions, unwrapped_proof_size) if prop_proof is not None and unwrapped_proof is not None: return [unwrapped_proof, prop_proof] else: negated = Prop(PropKind.NOT, prop) for prop_proof_size, negated_proof_size in share(size - 2, 2): prop_proof = find_proof(prop, assumptions, prop_proof_size) negated_proof = find_proof(negated, assumptions, negated_proof_size) if prop_proof is not None and negated_proof is not None: return [prop_proof, negated_proof]
def sentas_to_deltas(self, sentas: Iterable[SentA]) \ -> Iterable[Delta]: # Find max incoming activation and sum of incoming activations for # each node. maxin_d: Dict[Node, float] = defaultdict(float) # positive influences possumin_d: Dict[Node, float] = defaultdict(float) minin_d: Dict[Node, float] = defaultdict(float) # negative influences negsumin_d: Dict[Node, float] = defaultdict(float) for senta in sentas: if senta.a >= 0: maxin_d[senta.to_node] = max(maxin_d[senta.to_node], senta.a) possumin_d[senta.to_node] += senta.a elif senta.a < 0: minin_d[senta.to_node] = min(minin_d[senta.to_node], senta.a) negsumin_d[senta.to_node] += senta.a # Make Deltas from the Tyrrell averages of the SentA's multiplier = 1.0 - self.alpha for node in union(maxin_d.keys(), minin_d.keys()): amt = multiplier * ( ((maxin_d.get(node, 0.0) + self.tyrrell_alpha * possumin_d.get(node, 0.0)) / (1 + self.tyrrell_alpha)) + ((minin_d.get(node, 0.0) + self.tyrrell_beta * negsumin_d.get(node, 0.0)) / (1 + self.tyrrell_beta))) if abs(amt) >= epsilon: yield Delta(node, amt)
def propagate_once(self, g, old_d): # Decay. new_d: Dict[Node, float] = defaultdict( float, ((node, self.clip_a(g, node, a * self.alpha)) for node, a in old_d.items())) # TODO Remove nodes with a < epsilon # Find max incoming activation and sum of incoming activations for # each node. maxin_d: Dict[Node, float] = defaultdict(float) # positive influences possumin_d: Dict[Node, float] = defaultdict(float) minin_d: Dict[Node, float] = defaultdict(float) # negative influences negsumin_d: Dict[Node, float] = defaultdict(float) for delta in self.make_deltas(g, old_d): amt = ( delta.amt * (1.0 + self.positive_feedback_rate * old_d.get(delta.nodeid, 0.0)) * (1.0 - self.alpha)) ''' if delta.nodeid == Before(7) and delta.amt < 0.0: print() print('DE', delta, ' ', amt) print() ''' if amt >= epsilon: maxin_d[delta.nodeid] = max(maxin_d[delta.nodeid], amt) possumin_d[delta.nodeid] += amt elif amt <= -epsilon: minin_d[delta.nodeid] = min(minin_d[delta.nodeid], amt) negsumin_d[delta.nodeid] += amt # Apply the Tyrrell averages of the deltas for node in union(maxin_d.keys(), minin_d.keys()): #print('PR', node, maxin_d.get(node, 0.0), possumin_d.get(node, 0.0), minin_d.get(node, 0.0), negsumin_d.get(node, 0.0)) ''' print('PR1', node, minin_d.get(node, 0.0), negsumin_d.get(node, 0.0), ( (minin_d.get(node, 0.0) + self.tyrrell_beta * negsumin_d.get(node, 0.0)) / (1 + self.tyrrell_beta) )) ''' new_a = new_d[node] + ( (maxin_d.get(node, 0.0) + self.tyrrell_alpha * possumin_d.get(node, 0.0)) / (1 + self.tyrrell_alpha)) + ( (minin_d.get(node, 0.0) + self.tyrrell_beta * negsumin_d.get(node, 0.0)) / (1 + self.tyrrell_beta)) new_d[node] = self.clip_a(g, node, new_a) # TODO Record this in self.flows? return self.normalize(new_d)
def add_two_gsets(gset1: GSet, gset2: GSet) -> GSet: '''Combine the gsets, analogous to '+' in the Hopfield equation to combine two images.''' result: GSet = defaultdict(set) # type: ignore[arg-type] edges = union(gset1.keys(), gset2.keys()) for edge in edges: if edge in gset1: if edge in gset2: f = avg_of_funcs( gset1[edge], gset2[edge] ) else: f = gset1[edge] else: f = gset2[edge] result[edge] = f return result
def add_two_psets(self, pset1: PSet, pset2: PSet) -> PSet: '''Combines the psets, analogous to '+' in the Hopfield equation to combine two images. The default implementation calls .avg_of_funcs() on the Cartesian product of all the edges (FromTo addresses) in both psets.''' result: PSet = defaultdict(set) # type: ignore[arg-type] edges = union(pset1.keys(), pset2.keys()) for edge in edges: if edge in pset1: if edge in pset2: f = self.avg_of_funcs(pset1[edge], pset2[edge]) else: f = pset1[edge] else: f = pset2[edge] result[edge] = f return dict( # remove None funcs (k, v) for k, v in result.items() if v is not None)
def concentric_walk(self, start_node: Node, dlimit: int) -> Iterable[Node]: '''Returns a generator of Nodes, starting at start_node, moving out progressively further hops until reaching dlimit (inclusive).''' if dlimit >= 0 and self.has_node(start_node): yield start_node dist = 1 seen = {start_node} prev_nodes = {start_node} while dist <= dlimit: new_nodes = union(*(self.neighbors(node) for node in prev_nodes)) - seen if not new_nodes: break yield from new_nodes # TODO OPTIMIZE Don't make new sets if this is last iteration seen |= new_nodes prev_nodes = new_nodes dist += 1
def on_blocked(self) -> Actions: '''Actions to perform when this node is Blocked.''' agents = self.g.neighbors(self, 'agents') agents_problems = union(*(self.g.neighbors(agent, 'problem') for agent in agents)) tags_with_agent, tags_without_agent = [], [] for tag in self.g.tags_of(self, 'Blocked'): if tag in agents_problems: tags_with_agent.append(tag) else: tags_without_agent.append(tag) if tags_without_agent: return BuildAgent(self, choice(tags_without_agent)) else: return BoostFromTo( intersection( agents, self.g.neighbors(tags_with_agent, neighbor_label='problem')))
def concentric_walk_NodeD(self, start_node: Node, dlimit: Optional[int] = None) -> Iterable[NodeD]: '''Returns a generator of NodeDs, starting at start_node, moving out progressively further hops until reaching dlimit (inclusive). If no dlimit is specified, the walk will include all nodes that have any path from start_node.''' if self.has_node(start_node) and (dlimit is None or dlimit > 0): yield NodeD(start_node, 0) dist = 1 seen = {start_node} prev_nodes = {start_node} while True: new_nodes = union(*(self.neighbors(node) for node in prev_nodes)) - seen if not new_nodes: break for node in new_nodes: yield NodeD(node, dist) seen |= new_nodes prev_nodes = new_nodes dist += 1 if dlimit and dist > dlimit: break
def subprops(self): if self.kind == PropKind.NAME: return set() return set(self.args) | union(arg.subprops for arg in self.args)
nruns=10, niters=20 ): eqn = eqn * ndups global gg gg = make_gset(make_generators(eqn)) for _ in range(nruns): c = list(startc) * ndups print(c) run_gset(c, gg, niters=niters) print() if __name__ == '__main__': eqns = set(make_eqns()) gens = union(*(make_generators(e) for e in eqns)) psa(*gens) startc = (None, '+', 3, None, 10) c = list(startc) print(c) g = (0, 4, add_n(n=1)) #(4, 2, add_n(n=1)) run_generator(c, g) print(c) a, b, f = g #print(avg_of_funcs('+', '-')) gset1 = make_gset(make_generators((2, '+', 3, '=', 5))) psa(*gset1.items()) gset2 = make_gset(make_generators((4, 'x', 6, '=', 24))) print() psa(*gset1.items()) gset = add_gsets(gset1, gset2)
def neighbors(self, node: Node) -> Set[Node]: return union([hop.to_node for hop in self.hops_from_node(node)], [hop.from_node for hop in self.hops_to_node(node)])