Skip to content
Snippets Groups Projects
Commit 24a76101 authored by BAUCHER Achille's avatar BAUCHER Achille
Browse files

Comments on System modifiers

parent 8e309e8a
No related branches found
No related tags found
No related merge requests found
......@@ -4,3 +4,6 @@
- [ ] tabhl se nomme avec le nom de la variable attribuée
- [ ] Une seule fonction spéciale DYNAMO admise dans une équation
- [ ] New table politic, c'est la variable qui est rentréer en paramètre.
- [ ] Ajouter shéma de documentation
- [ ] Fonctions graphiques et tout de World3 à mettre dans System
- [ ] add_function ça fonctionne ça ?
\ No newline at end of file
"""Define the System class, used to contain, modify, simulate and plot a model.
"""
import inspect
import numpy as np
import networkx as nx
......@@ -15,16 +18,17 @@ class System:
"""
Base class for system dynamics.
A System stores two dictionnaries containing all
A System stores 3 dictionnaries containing all
nodes (constants, variables, and functions)
and equations (constan values, updating equations and initialisation equations)
and comments about nodes.
From this dictionnaries, it generates the updating pattern
and run the simulation.
"""
def __init__(self):
"""Initialise an empty System with nodes and equations dictionnaries"""
"""Initialise an empty System with nodes, equations and comments dictionnaries"""
self.nodes = {
'cst': set(),
'var': set(),
......@@ -36,67 +40,136 @@ class System:
'update': dict(),
'init': dict()
}
self.comments = {}
# Modifiers
# ---------- Modifiers ----------
def add_node(self, node, node_type):
"""Add a node to the System.
Parameters
----------
node : str
Name of the node.
node_type : str
Type (cst, var, fun) of the node.
"""
self.nodes[node_type].add(node)
def add_all_nodes(self, all_nodes):
"""Add all nodes in the dictionnary `all_nodes`.
Parameters
----------
all_nodes : dict(str: set(str))
Dictionnary of all nodes to add. Like:
{'cst': {all constant names},
'var': {all variable names},
'fun': {all function names}}
"""
for node_type in all_nodes:
for node in all_nodes[node_type]:
self.add_node(node, node_type)
def add_eq(self, node, eq_type, arguments):
"""Add an equation to the System.
Parameters
----------
node : str
Name of the node set by the equation.
eq_type : str
Type (cst, init, update) of the equation.
arguments : dict(str: set)
Arguments needed in the equation. Like:
{'cst': {constant names},
'var': {( variable name, index name)},
'fun': {dict_of_function_infomations}}
"""
# Check if some special functions (clip, step) are in arguments:
for fun in set(arguments['args']['fun']):
if fun not in instance_fun_names and fun in globals():
del arguments['args']['fun'][fun]
self.eqs[eq_type][node] = arguments
def add_all_eqs(self, all_eqs):
"""Add all equations.
Parameters
----------
all_nodes : dict(str: set(str))
Dictionnary of all equations to add. Like:
{'cst': {node name: equation},
'init': {node name: equation},
'update': {node name: equation}}
"""
for eq_type in all_eqs:
for node in all_eqs[eq_type]:
self.add_eq(node, eq_type, all_eqs[eq_type][node])
def add_comments(self, comments):
"""Add comments to the System.
Parameters
----------
comments : dict(str: str)
Each node name and its comment.
"""
for node, comment in comments.items():
self.comments[node] = comment
def add_units(self, units):
"""Unit of calculs. NOT USED.
"""
self.units = units
# Following functions are not used yet.
# def add_function(self, fun, name=None):
# """Add or reset a function to the system.
# The function should be any of init, update or set, and take the same arguments as defined in the system equations.
def add_function(self, fun, name=None):
if not name:
name = fun.__name__
for s in ('_', 'update', 'init', 'set'):
assert not name.startswith(s), "Fun name shouldn't start with '{s}'"
setattr(self, fun.__name__, fun)
# Parameters
# ----------
# fun : function
# Function taking appropriate arguments and return a value. If name is None, the function name should be one of `init_var`, `upadte_var`, `set_cst` with `var` a variable name and `cst` a constant name.
# name : str
# Name of the function in case we want it different than fun.__name__.
# """
# if not name:
# name = fun.__name__
# for s in ('_', 'update', 'init', 'set'):
# assert not name.startswith(s), "Fun name shouldn't start with '{s}'"
# setattr(self, fun.__name__, fun)
def add_functions(self, *args, **kwargs):
for fun in args:
self.add_function(fun)
for name, fun in kwargs.items():
self.add_function(fun, name)
def add_system_function(self, fun, name=None):
if not name:
name = fun.__name__
if any(name.startswith(s) for s in ('update', 'init', 'set')):
setattr(self, name, fun)
fun.__okdic__ = False
fun.__doc__ = f"User defined function\n{fun.__doc__}"
return
assert False, "Invalid function name. Should starts with 'init', 'update' or 'set'"
def add_system_functions(self, *args, **kwargs):
for fun in args:
self.add_system_function(fun)
for fun, name in kwargs:
sefl.add_system_function(fun, name)
# def add_functions(self, *args, **kwargs):
# for fun in args:
# self.add_function(fun)
# for name, fun in kwargs.items():
# self.add_function(fun, name)
# def add_system_function(self, fun, name=None):
# if not name:
# name = fun.__name__
# if any(name.startswith(s) for s in ('update', 'init', 'set')):
# setattr(self, name, fun)
# fun.__okdic__ = False
# fun.__doc__ = f"User defined function\n{fun.__doc__}"
# return
# assert False, "Invalid function name. Should starts with 'init', 'update' or 'set'"
# def add_system_functions(self, *args, **kwargs):
# for fun in args:
# self.add_system_function(fun)
# for fun, name in kwargs:
# sefl.add_system_function(fun, name)
# Getters
# ---------- Getters ----------
def iter_all_nodes(self):
return chain(*self.nodes.values())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment