--- title: Hierarchy keywords: fastai sidebar: home_sidebar nb_path: "nbs/04_hierarchy.ipynb" ---
%load_ext autoreload
%autoreload 2
from pct.functions import Constant
pre=Constant(5, name='precon')
namespace=pre.namespace
post=Constant(10, name='postcon', namespace=namespace)
hpct = PCTHierarchy(3,3, pre=[pre], post=[post], history=True, clear_names=False, links="dense", namespace=namespace)
hpct.hierarchy
print(hpct.get_parameters_list())
hpct.change_namespace()
hpct.summary()
Create a hierarchy from a configuration.
config = hpct.get_config()
print(config)
h = PCTHierarchy.from_config(config, namespace=namespace)
assert h.get_config() == hpct.get_config()
hpct.get_node(2,0).get_function('reference').set_value(1)
hpct.get_node(2,1).get_function('reference').set_value(1)
hpct.get_node(2,2).get_function('reference').set_value(1)
for level in range(3):
for col in range(3):
hpct.get_node(level,col).get_function('output').set_property('gain', 10)
hpct.summary()
The hierarchy details can be viewed as a configuration. That configuration can be used to create a hierarchy, as shown above.
hpct.get_config()
Get the output function, which will be the output function of the last node, or the last item of the post-processor functions, if present.
link = hpct.get_output_function()
print(link.get_config())
The hierarhcy can also be viewed graphically as a network of connected nodes.
ahpct = PCTHierarchy(2,2, links="dense")
test = 3
if test==1:
g = ahpct.graph()
pos=graphviz_layout(g, prog='dot')
nx.draw(g, pos=pos, with_labels=True, font_size=12, font_weight='bold', node_color='red', node_size=500)
if test ==2:
g = ahpct.graph()
pos = nx.multipartite_layout(g, subset_key="layer", align='horizontal')
pos['constant1'][0]+=0.2
c = pos['constant1'][0]
print(c)
nx.draw(g, pos=pos, with_labels=True, font_weight='bold', node_color='red', node_size=750, arrowsize=25)
if test ==3:
import os
if os.name=='nt':
ahpct.draw(file="ahpct.png", node_size=1500, figsize=(10,10))# with_labels=True, font_weight='bold', node_color='red', node_size=500, arrowsize=25, align='vertical'
hpct(verbose=True)
A hierarchy can be executed with the "run()" method, providing the number of iterations to run.
hpct1 = PCTHierarchy(3,3, pre=[pre], post=[post], history=True, links="dense")
namespace=hpct1.namespace
hpct1.get_node(2,0).get_function('reference').set_value(1)
hpct1.get_node(2,1).get_function('reference').set_value(1)
hpct1.get_node(2,2).get_function('reference').set_value(1)
for level in range(3):
for col in range(3):
hpct1.get_node(level,col).get_function('output').set_property('gain', 10)
hpct1.run(10)
print(hpct1.get_node(1,1).history.data)
assert hpct1.get_node(1,1).history.data == {'refcoll': {'weighted_sum6': [0.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0]}, 'percoll': {'weighted_sum5': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}, 'comcoll': {'subtract4': [0.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0]}, 'outcoll': {'proportional4': [0.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0, 300.0]}}
Save a hierarchy to file.
import json
hpct1.save("hpct.json")
Create a hierarchy from file.
loaded = PCTHierarchy.load("hpct.json", clear=False, namespace=namespace)
loaded.summary()
import networkx as nx
import matplotlib.pyplot as plt
# https://matplotlib.org/3.1.0/gallery/color/named_colors.html
loaded.draw(with_edge_labels=True, color_mapping={'w':'aqua','c':'limegreen','s':'goldenrod', 'p':'red', 'v':'silver'})
Build a hierarchy by adding nodes and functions manually.
Create an empty hierarchy.
myhpct = PCTHierarchy()
namespace=myhpct.namespace
myhpct.summary(build=False)
Add a node. Then nodes at particular positions.
myhpct.add_node(PCTNode(namespace=namespace))
myhpct.add_node(PCTNode(namespace=namespace), level=1)
myhpct.add_node(PCTNode(namespace=namespace), level=0)
myhpct.summary(build=False)
Replace functions at particular positions in the hierarchy.
myhpct.insert_function(level=0, col=0, collection="perception", function=Proportional(3, name="prop2", namespace=namespace))
myhpct.insert_function(level=1, col=0, collection="perception", function=WeightedSum(weights=[1,1], name="wsum", namespace=namespace))
myhpct.insert_function(level=0, col=1, collection="reference", function=Proportional(1, name="passthru", namespace=namespace))
Add pre and post processor functions.
myhpct.add_preprocessor(Constant(1, name="cons1", namespace=namespace))
myhpct.add_preprocessor(Proportional(5, name="prop1", namespace=namespace))
myhpct.add_postprocessor(Proportional(5, name="postprop1", namespace=namespace))
myhpct.add_postprocessor(Proportional(5, name="postprop2", namespace=namespace))
Link the functions together.
myhpct.set_links("prop1", "cons1")
myhpct.set_links("prop2", "prop1")
myhpct.add_links("wsum", "prop2", "variable")
myhpct.set_links("passthru", "proportional1")
myhpct.set_links("postprop1", "proportional")
myhpct.set_links("postprop2", "postprop1")
myhpct.get_node(0,0).get_function('reference').set_value(1)
myhpct.get_node(1,0).get_function('reference').set_value(1)
myhpct.get_node(0,0).get_function('output').set_property('gain', 10)
myhpct.get_node(0,1).get_function('output').set_property('gain', 10)
myhpct.get_node(1,0).get_function('output').set_property('gain', 10)
myhpct.summary(build=True)
myhpctconfig = myhpct.get_config()
#print(myhpctconfig)
assert myhpctconfig == {'type': 'PCTHierarchy', 'name': 'pcthierarchy', 'pre': {'pre0': {'type': 'Constant', 'name': 'cons1', 'value': 1, 'links': {}}, 'pre1': {'type': 'Proportional', 'name': 'prop1', 'value': 0, 'links': {0: 'cons1'}, 'gain': 5}}, 'levels': {'level0': {'level': 0, 'nodes': {'col0': {'col': 0, 'node': {'type': 'PCTNode', 'name': 'pctnode2', 'refcoll': {'0': {'type': 'Constant', 'name': 'constant2', 'value': 1, 'links': {}}}, 'percoll': {'0': {'type': 'Proportional', 'name': 'prop2', 'value': 0, 'links': {0: 'prop1'}, 'gain': 3}}, 'comcoll': {'0': {'type': 'Subtract', 'name': 'subtract2', 'value': 0, 'links': {0: 'constant2', 1: 'prop2'}}}, 'outcoll': {'0': {'type': 'Proportional', 'name': 'proportional2', 'value': 0, 'links': {0: 'subtract2'}, 'gain': 10}}}}, 'col1': {'col': 1, 'node': {'type': 'PCTNode', 'name': 'pctnode', 'refcoll': {'0': {'type': 'Proportional', 'name': 'passthru', 'value': 0, 'links': {0: 'proportional1'}, 'gain': 1}}, 'percoll': {'0': {'type': 'Variable', 'name': 'variable', 'value': 0, 'links': {}}}, 'comcoll': {'0': {'type': 'Subtract', 'name': 'subtract', 'value': 0, 'links': {0: 'passthru', 1: 'variable'}}}, 'outcoll': {'0': {'type': 'Proportional', 'name': 'proportional', 'value': 0, 'links': {0: 'subtract'}, 'gain': 10}}}}}}, 'level1': {'level': 1, 'nodes': {'col0': {'col': 0, 'node': {'type': 'PCTNode', 'name': 'pctnode1', 'refcoll': {'0': {'type': 'Constant', 'name': 'constant1', 'value': 1, 'links': {}}}, 'percoll': {'0': {'type': 'WeightedSum', 'name': 'wsum', 'value': 0, 'links': {0: 'prop2', 1: 'variable'}, 'weights': [1.0, 1.0]}}, 'comcoll': {'0': {'type': 'Subtract', 'name': 'subtract1', 'value': 0, 'links': {0: 'constant1', 1: 'wsum'}}}, 'outcoll': {'0': {'type': 'Proportional', 'name': 'proportional1', 'value': 0, 'links': {0: 'subtract1'}, 'gain': 10}}}}}}}, 'post': {'post0': {'type': 'Proportional', 'name': 'postprop1', 'value': 0, 'links': {0: 'proportional'}, 'gain': 5}, 'post1': {'type': 'Proportional', 'name': 'postprop2', 'value': 0, 'links': {0: 'postprop1'}, 'gain': 5}}}
Define the order in which the node will be processed.
myhpct.set_order(["pctnode2", "pctnode1", "pctnode"])
Run the hierarchy once.
out = myhpct(verbose=True)
print(out)
assert out == -35000
# ind = PCTHierarchy.from_config(config)