def test_before_from_avails(self) -> None: fm = FARGModel() ca = fm.build(self.pons_start_canvas()) cr0 = CellRef(ca, 0) qarg = QBeforeFromAvails(source=cr0) self.assertCountEqual(as_iter(qarg.get_items( fm, [])), [Before(4), Before(5), Before(6)])
def features_of(self) -> Iterable[Node]: for operand in as_iter(self.operands): yield Before(operand) if self.operator: yield self.operator if self.operands and self.operator: result = self.operator(*self.operands) yield After(result)
def on_build(self, g, thisid, kwargs): try: mateid = kwargs[self.this_port_label] except KeyError: return None for thatid in as_iter(mateid): g.add_edge(thisid, self.this_port_label, thatid, self.that_port_label) return self.this_port_label
def Tagged(g, tagclass, *nodeids): '''Are all the nodeids tagged with tagclass? If nodeids is empty, returns False. Each nodeid can be a nodeid or an iterable of of nodeids.''' if not nodeids: return False for n in nodeids: for nodeid in as_iter(n): if not g.has_tag(nodeid, tagclass): return False return True
def call(cls, g: 'ActiveGraph', acs: Union['Ac', Iterable['Ac'], None], actor: NRef, env: AcEnv) -> None: '''Runs acs, starting from given AcEnv. env will likely be modified.''' for ac in as_iter(acs): try: ac.go(g, actor, env) except (AcFalse, FargDone, Fizzle): raise except Exception as exc: raise AcError(ac, exc, env)
def short(self) -> str: delta = short(self.last_delta) if self.last_delta else '' avs = ' '.join(str(a) for a in as_iter(self.avails)) ls: List = [] if delta: ls.append(delta) if avs: ls.append(avs) inside = '; '.join(ls) return f'[{inside}]'
def do_timestep( self, num=1, action: Union[Action, List[Action], None]=None, actor: Union[int, None]=None ) -> None: '''Executes n timesteps. On each timestep, we decay saliences, choose active nodes, generate Action objects from the active nodes, choose which Actions to perform, execute those Actions, and update support. If action is non-None, we run the specified Action unconditionally. Otherwise, if actor is non-None, we run all the Actions provided by the actor (assumed to be an ActiveNode) unconditionally.''' for i in range(num): self.graph['t'] += 1 self.clear_touched_and_new() self.decay_saliences() # TODO rm self.decay_activations() self.propagate_support() support.log_support(self) self.propagate_activation() log_activation(self) self.update_coarse_views() if action is not None: actions_to_do = as_iter(action) elif actor is not None: actions_to_do = self.collect_actions([actor]) else: actions_to_do = self.get_actions_from_graph() if ShowActionsPerformed.is_logging(): print('ACTIONS PERFORMED') if not actions_to_do: print(' (none)') for a in actions_to_do: if ShowActionsPerformed.is_logging(): print(f' {a.actor}: {a}') self.do_action(a) self.do_touches() self.update_all_support() d = self.done() if d: ShowResults(d) ShowResults(f"t={self.graph['t']}\n") break
def on_build(self, g, thisid): # Give activation to each member and make each member inhibit all # following members. members = as_iter(self.action_nodes) for i, member in enumerate(members): g.set_activation_from_to(thisid, member, 0.3) g.add_edge(thisid, 'child_action', member, 'parent_action') for later_member in members[i + 1:]: g.set_activation_from_to(member, later_member, -1.0) for next_member in members[i + 1:i + 2]: g.add_edge(member, 'next_action', next_member, 'prev_action')
def go(self, g, actor, env): nodes = self.get(g, actor, env, 'nodes') a = g.activation(actor) if a is None: a = 1.0 #boost_amount = max(a * 10.0, 0.2) boost_amount = clip(0.2, 10.0, a * 10.0) for node in as_iter(nodes): #print('BOOST', node) # TODO Make the boost_amount a function of actor's activation g.boost_activation(node, boost_amount)
def coalesce_conditions(cond_exprs, action_stmts): cond_exprs = (as_list(cond_exprs) + as_list(s.implicit_cond_expr() for s in as_iter(action_stmts))) if not cond_exprs: return None else: ce = cond_exprs[0] for nextce in cond_exprs[1:]: if nextce: ce = ce.coalesced_with(nextce) return ce
def search( fm: 'FARGModel', items: Searchable, pred: Union[Type, Callable] ) -> Iterable[Union['Elem', 'CellRef']]: print('SEARCH', items, pred) for item in as_iter(items): if hasattr(item, 'search'): yield from item.search(fm, pred) else: # TODO Figure out the correct response here print('NO-SEARCH', item) raise NotImplementedError
def expand_port_label(self, port_label: PortLabels) \ -> Union[Set[PortLabel], None]: '''Returns a set containing each PortLabel in port_label along with all its descendants in the hierarchy, or None if port_label is None or empty.''' if not port_label: return None else: result = set() for parent_label in as_iter(port_label): result.update( self.hierarchy.parent_and_all_descendants(parent_label)) return result
def __init__(self, g: 'ActiveGraph', nodes: NRefs, weight_f: Union[Callable[[NRef], float], None] = None): self.nodes = [] self.weights = [] if not weight_f: weight_f = g.activation for node in as_iter(nodes): if is_iter(node): weight = sum(weight_f(n) for n in node) else: weight = weight_f(node) self.add(node, weight)
def is_match(self, g, nodeid): if self.id is not None: if self.id != nodeid: return False if self.cl is not None: for cl in self.cl: if not g.is_of_class(nodeid, cl): return False if self.datum is not None: node_datum = g.datum(nodeid) for datum in as_iter(self.datum): if not datum_match(datum, node_datum): return False return True
def go(self, g, actor): # HACK Should ask g for the agent class, maybe more. #print('BUILDAG', list(g.as_nodes(self.problem))) for problem in as_iter(self.problem): reason = g.getattr(problem, 'reason') #print('REASON', reason) # TODO assumptions about 'reason' agent = g.add_node( reason.agent_nodeclass, behalf_of=self.behalf_of, problem=problem ) g.boost_activation_from_to(actor, agent) g.sleep(self.behalf_of)
def go(self, g): for rid in as_iter(self.resultid): if g.is_of_class(rid, Brick) or not g.has_tag(rid, Avail): continue g.remove_tag(rid, Avail) g.add_tag(Failed, rid) operatorid = g.neighbor(rid, port_label='source') if not operatorid: continue g.add_tag(Failed, operatorid) operands = g.neighbors(operatorid, port_label='source') for operand in operands: g.add_tag(Avail, operand) g.remove_tag(operand, Consumed)
def has_avail_value( elem: Union['CellRef', Elem, None], v: Value ) -> Union[bool, None, 'CellRef', Elem]: if elem is None: return False elif isinstance(elem, CellRef): return any(elem.has_avail_value(v1) for v1 in as_iter(v)) elif elem == v: return elem else: return False '''
def test_cellref_basics(self) -> None: ca = StepCanvas([Step([4, 5, 6])]) cr0 = CellRef(ca, 0) cr1 = CellRef(ca, 1) # StepCanvas[0] self.assertEqual(cr0.value, Step([4, 5, 6])) self.assertCountEqual(as_iter(cr0.avails), [4, 5, 6]) taken, remaining = cr0.take_avails([4, 5]) self.assertCountEqual(taken, [4, 5]) self.assertCountEqual(remaining, [6]) self.assertEqual(cr0.value, Step([4, 5, 6])) self.assertTrue(cr0.has_a_value()) self.assertTrue(cr0.has_avail_value(4)) self.assertFalse(cr0.has_avail_value(7)) with self.assertRaises(ValuesNotAvail) as cm: taken, remaining = cr0.take_avails([4, 7]) self.assertEqual( cm.exception, ValuesNotAvail(cellref=cr0, avails=(4, None), unavails=(None, 7))) #StepCanvas[1] self.assertEqual(cr1.value, None) self.assertFalse(cr1.has_a_value()) self.assertCountEqual(as_iter(cr1.avails), []) with self.assertRaises(ValuesNotAvail) as cm: taken, remaining = cr1.take_avails([4, 7]) self.assertEqual( cm.exception, ValuesNotAvail(cellref=cr1, avails=(4, 7), unavails=())) # paint cr1.paint(Step([6], StepDelta([4, 5], [9], '+'))) self.assertEqual(ca[1], Step([6], StepDelta([4, 5], [9], '+')))
def is_already_built(self, g, old_nodeid=None): #TODO old_nodeid should somehow override the old_node in #self.link_specs. '''Has a node meeting the spec in relation to old_nodeid already been built?''' if self.link_specs: for link_spec in as_iter(self.link_specs): for neighbor in g.neighbors( old_nodeid, port_label=link_spec.old_node_port_label): if self.meets(g, old_nodeid, neighbor): return True else: # INEFFICIENT: With no link_spec, we examine all nodes in the graph return not any( g.class_of(nodeid) == self.new_nodeclass for nodeid in g.nodes())
def append( cls, ls: Union[List['Criterion'], 'Criterion', None], cs: Union[List['Criterion'], 'Criterion', None] ) -> Union[List['Criterion'], None]: if not cs: return ls elif ls is None: return cs else: print('APPEND1', ls) ls = as_list(ls) print('APPEND2', ls) for c in as_iter(cs): ls.append(c) return ls
def __call__(self, x, lb=None) -> float: '''How well does x satisfy 'has an element for each of the matchers'?''' x = list(as_iter(x)) # local copy of x, so we can remove items # when matched if len(x) < len(self.matchers): return 0.0 best_matches: List[IndexAndWeight] = [] for m in self.matchers: bm = max( (IndexAndWeight(i, m(x[i], lb=lb)) for i in range(len(x))), key=attrgetter('w')) if bm.w < 0.001: return 0.0 best_matches.append(bm) del x[bm.i] return reduce(operator.mul, (bm.w for bm in best_matches))
def is_exact_match(self, g, nodeid): '''Same as .is_match() but classes must match exactly, i.e. it's not enough for nodeid's class to be a subclass of a class specified in the NodeMatcher.''' if self.id is not None: if self.id != nodeid: return False if self.cl is not None: for cl in self.cl: if not cl == g.class_of(nodeid): return False if self.datum is not None: node_datum = g.datum(nodeid) for datum in as_iter(self.datum): if not datum_match(datum, node_datum): return False return True
def make_activations_in( cls, features: Union[Sequence[Hashable], None] = None, activations_in: Union[ADict, None] = None) -> Union[ADict, None]: if not features: return activations_in if activations_in is None: activations_in = {} else: activations_in = copy(activations_in) for feature in as_iter(features): if isinstance(feature, NodeA): activations_in[feature.node] = feature.a else: activations_in[feature] = max(1.0, activations_in.get(feature, 1.0)) return activations_in
def slipnet_dquery( g: Graph, p: Propagator, features: Iterable[Hashable] = None, activations_in: Dict[Hashable, float] = None) -> Dict[Hashable, float]: '''Pass either features or a dictionary of activations. Returns dictionary of activations.''' if activations_in is None: activations_in = {} for f in as_iter(features): if isinstance(f, NodeA): a = f.a f = f.node else: a = 1.0 activations_in[f] = a #print('DQ', type(activations_in)) return p.propagate(g, activations_in)
def run( # type: ignore[override] self, fm: FARGModel, builder: Optional[Actor], to_build: Nodes, sources: Sources ) -> CodeletResults: built: List[Node] = [] for node in as_iter(to_build): node = fm.replace_refs(node, sources) node = fm.build(node, builder=builder) built.append(node) ''' if builder: return NewState(builder, Wake) else: return None ''' return {'built': set(built)}
def see_query(q: Iterable[Node] = (Before(4), After(9)), pred: WSPred = Consumer, seed: int = 1, sngraphs: Union[Graph, Iterable[Graph]] = eqn_graph) -> None: global fm, ls, nodes, activations_in fm = FARGModel(seed=seed, slipnet=Slipnet(Graph.augment(*as_iter(sngraphs)))) activations_in = dict((node, 1.0) for node in q) lenable(LogAdjustedDeltas) nodes = fm.pulse_slipnet( activations_in=activations_in, # type: ignore[arg-type] pred=pred, k=5, num_get=3, alog=fm.start_alog((None, None))) ls = list(fm.alogs.logs.values()) print('\nPlotted, final activations:') ls[0].plot(n=15, pr=True) print('\nNodes chosen:') pts(nodes, key=short)
def make_node_matcher(info, id=None, cl=None, datum=None): '''Constructs a NodeMatcher object with correct arguments, incorporating info into id, cl, and datum. Can modify caller's id, cl, and/or datum.''' for i in as_iter(info): if i is None: continue elif is_nodeid(i): id = i # If more than one nodeid, the last takes priority elif isclass(info): if cl is None: cl = set() cl.add(info) else: if cl is None: cl = set() if datum is None: datum = set() cl.add(info.__class__) datum.add(info) return NodeMatcher(id, cl, datum)
def dquery( self, features: Iterable[Hashable] = None, activations_in: Dict[Hashable, float] = None) -> Dict[Hashable, float]: '''Pass either features or a dictionary of activations. Returns dictionary of activations.''' if activations_in is None: activations_in = {} for f in as_iter(features): if isinstance(f, NodeA): a = f.a f = f.node else: try: a = f.default_a except AttributeError: a = 1.0 activations_in[f] = max(activations_in.get(f, 0.0), a) #print('DQ', type(activations_in)) return self.propagator.propagate(self, activations_in)
def declare_parent(self, p, *children): '''Declares that 'p' is an ancestor of each element of 'children', where each such element is viewed as_iter.''' for ch in children: for c in as_iter(ch): descs = set() # c and all c's descendants descs.add(c) descs.update(self.descendants[c]) ancs = set() # p and all p's ancestors ancs.add(p) ancs.update(self.ancestors[p]) # Make p and all p's ancestors ancestors of # c and all c's descendants for d in descs: for a in ancs: self.ancestors[d].add(a) # Make c and all c's descendants descendants of # p and all p's ancestors for a in ancs: for d in descs: self.descendants[a].add(d) self.parents_of[c][p] = None
def go(self, g): for nodeid in as_iter(self.node_or_nodes): g.datum(nodeid).fail(g, nodeid)