--- title: Functions keywords: fastai sidebar: home_sidebar summary: "Functions that form the elements of a perceptual control node (system)." description: "Functions that form the elements of a perceptual control node (system)." nb_path: "nbs/02_functions.ipynb" ---
%load_ext autoreload
%autoreload 2
#%nbdev_default_export functions
#%reload_ext autoreload
#%autoreload 2
Each function outputs the result of applying the function logic and may be a scalar or array, depending on the input. The inputs are supplied as links to another function, from where the values are read. Unless the function is a simple case, such as a 'Constant'.
Parameters are supplied as arguments to the constructor of the class.
All functions include the methods defined by the BaseFunction class.
Standard class constructor. Different ways to create a function with the standard constructor.
prop = Proportional()
print(prop.get_config())
prop = Proportional("myprop", 10)
print(prop.get_config())
prop = Proportional(gain=10)
print(prop.get_config())
Configuration class constructor. Create the function by passing a configuration structure to the constructor.
prop = Proportional(**{'name': 'myprop', 'value': 5, 'gain': 20})
print(prop.get_config())
Configuration class method. Create the function by passing a configuration structure to a class method.
config = {'name': 'myprop', 'value': -0.5, 'gain': 21}
prop = Proportional.from_config(config)
print(prop.get_config())
prop = Proportional()
print(prop.get_config())
prop1 = Proportional.from_config(prop.get_config())
print(prop1.get_config())
assert prop.get_config() == prop1.get_config()
An example showing creating a WeightedSum function.
wts=[1,1,1]
ws = WeightedSum(weights=wts)
ns = ws.namespace
ws.add_link(Constant(10, namespace=ns))
ws.add_link(Constant(5, namespace=ns))
ws.add_link(Constant(20, namespace=ns))
assert ws() == 35
config = ws.get_config()
ws1 = WeightedSum.from_config(config, namespace=ns)
ws1.get_config()
scons = Constant(2, name='scons')
sig = Sigmoid()
sig.add_link(scons)
sig()
View the details of the function with the "summary", which prints the name, type, parameters, value and links (if any).
prop.summary()
As already seen the function details can be seen by retrieving the configuration.
print(prop.get_config())
Or you can print the function.
print(prop)
Set the decimal places for output display.
print(prop.output_string())
prop.set_decimal_places(2)
print(prop.output_string())
You can also view a function graphically as a network of connected nodes.
sub = Subtract(links=[Constant(1, name='cons'), Proportional(10, name='prop')], name='sub')
g = sub.graph()
print(g)
sub.draw(node_size=2000)
A function can be run simply by calling the variable.
out = sub()
print(out)
A function can be also run in a loop with the run() method and provided the loop count.
integrator = Integration(gain=9, slow=10)
integrator.add_link(sub)
o = integrator.run(steps=10, verbose=True)
integrator(verbose=True)
Save a function to file.
print(ws.get_config())
ws.save("ws.json")
Create a function from file.
wss = WeightedSum.load("ws.json", namespace=ns)
assert ws.get_config() == wss.get_config()
print(wss.get_config())
integrator = Integration(3, 10)
cons = Constant(5)
integrator.add_link(cons)
integrator.summary()
UniqueNamer.getInstance().clear() # initialises the list of function names
integ = Integration(**{'name': 'myinteg', 'value': 1, 'gain': 20, 'slow': 100})
prop = Proportional(5, name="myprop")
integ.add_link(prop)
print(integ.get_config())
assert integ.get_config() == {'type': 'Integration', 'name': 'myinteg', 'value': 1, 'links': {0: 'myprop'}, 'gain': 20, 'slow': 100}
You can also define the link when you create the function, as in this example with "Proportional".
const = Constant(1, name='const')
ns = const.namespace
pr = Proportional(name='pr', links=const, namespace=ns)
pr.summary()
assert pr() == 1
It can be the name of the linked function.
pr = Proportional(gain=10, name='pr', links='const', namespace=ns)
pr.summary()
assert pr() == 10
Or it can be a list of names.
sub = Subtract(links=['const', 'pr'], namespace=ns)
sub.summary()
assert sub()==0
output = integrator()
print(output)
assert output == 1.5
print(integrator.get_config())
integrator = Integration(3, 10)
ns=integrator.namespace
cons = Constant(5, namespace=ns)
integrator.add_link(cons)
config = integrator.get_config()
inte = Integration.from_config(config, namespace=ns)
print(inte())
target = {'type': 'Integration', 'name': 'integration', 'value': 1.5, 'links': {0: 'constant'}, 'gain': 3, 'slow': 10}
#print(target)
assert inte.get_config() == target