examples/jupyter_examples/Math expressions.ipynb
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Dynamic Expressions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Define wc_lang math expressions"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import warnings\n",
"warnings.simplefilter(\"ignore\")\n",
"import wc_lang\n",
"from wc_lang import (Model, SpeciesType, Species, Compartment, Parameter, Function, FunctionExpression, Observable,\n",
" StopCondition, ExpressionMethods)\n",
"\n",
"def make_test_reference_objects():\n",
" model = Model()\n",
" comp = model.compartments.create(id='comp')\n",
" objects = {\n",
" Observable: {},\n",
" Parameter: {},\n",
" Function: {},\n",
" Species: {},\n",
" }\n",
" for id in ['a', 'b', 'duped_id']:\n",
" objects[Parameter][id] = model.parameters.create(id=id)\n",
" for id in ['ccc', 'ddd', 'duped_id']:\n",
" objects[Observable][id] = model.observables.create(id=id)\n",
" for id in ['f', 'g', 'duped_id']:\n",
" objects[Function][id] = model.functions.create(id=id)\n",
" species_types = []\n",
" for i in range(4):\n",
" species_type = model.species_types.create(id='spec_type_{}'.format(i))\n",
" species = Species(species_type=species_type, compartment=comp)\n",
" objects[Species][species.get_id()] = species\n",
" return model, objects\n",
"\n",
"model, objects = make_test_reference_objects()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Function"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"id: fun_1\n"
]
}
],
"source": [
"# Function can reference Observables, Parameters, and other Functions, and it can use some Python functions\n",
"fun_1 = ExpressionMethods.make_obj(model, Function, 'fun_1', 'ccc + max(a, ddd)', objects)\n",
"# make_obj has this signature:\n",
"# def make_obj(model, model_type, id, expression, objects)\n",
"print('id:', fun_1.id)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"type of expression: FunctionExpression\n",
"valid_functions: (<built-in function ceil>, <built-in function floor>, <built-in function exp>, <built-in function pow>, <built-in function log>, <built-in function log10>, <built-in function min>, <built-in function max>)\n"
]
}
],
"source": [
"# each math expression has a corresponding Expression object\n",
"print('type of expression:', type(fun_1.expression).__name__)\n",
"# math expressions that can use Python functions have a list of valid functions in Meta\n",
"print('valid_functions:', FunctionExpression.Meta.valid_functions)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"expression: ccc + max(a, ddd)\n",
"observables: ['ccc', 'ddd']\n",
"parameters: ['a']\n",
"functions: []\n"
]
}
],
"source": [
"# references to the objects used are stored in a related attribute\n",
"print('expression:', fun_1.expression.expression)\n",
"for attr in ['observables', 'parameters', 'functions']:\n",
" print(\"{}: {}\".format(attr, [obj.get_id() for obj in getattr(fun_1.expression, attr)]))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"analyzed_expr tokens: ['ccc', '+', 'max', '(', 'a', ',', 'ddd', ')']\n",
"\n",
"analyzed_expr wc_tokens:\n",
" WcLangToken(tok_code=<TokCodes.wc_lang_obj_id: 1>, token_string='ccc', model_type=<class 'wc_lang.core.Observable'>, model_id='ccc', model=<wc_lang.core.Observable object at 0x7fc04c0cc748>)\n",
" WcLangToken(tok_code=<TokCodes.op: 4>, token_string='+', model_type=None, model_id=None, model=None)\n",
" WcLangToken(tok_code=<TokCodes.math_fun_id: 2>, token_string='max', model_type=None, model_id=None, model=None)\n",
" WcLangToken(tok_code=<TokCodes.op: 4>, token_string='(', model_type=None, model_id=None, model=None)\n",
" WcLangToken(tok_code=<TokCodes.wc_lang_obj_id: 1>, token_string='a', model_type=<class 'wc_lang.core.Parameter'>, model_id='a', model=<wc_lang.core.Parameter object at 0x7fc04c100828>)\n",
" WcLangToken(tok_code=<TokCodes.op: 4>, token_string=',', model_type=None, model_id=None, model=None)\n",
" WcLangToken(tok_code=<TokCodes.wc_lang_obj_id: 1>, token_string='ddd', model_type=<class 'wc_lang.core.Observable'>, model_id='ddd', model=<wc_lang.core.Observable object at 0x7fc04c0cc9b0>)\n",
" WcLangToken(tok_code=<TokCodes.op: 4>, token_string=')', model_type=None, model_id=None, model=None)\n"
]
}
],
"source": [
"# FunctionExpression contains an 'analyzed_expr', which is a tokenized, validated expression\n",
"# it contains the Python tokens from the expression ...\n",
"print('analyzed_expr tokens:', [t.string for t in fun_1.expression.analyzed_expr.tokens])\n",
"\n",
"# wc_tokens, which contain the interpretation of each Python token ...\n",
"print('\\nanalyzed_expr wc_tokens:\\n',\n",
" '\\n'.join([' '+str(wc_token) for wc_token in fun_1.expression.analyzed_expr.wc_tokens]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Stop condition"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<wc_lang.core.StopCondition: sc 1>\n"
]
}
],
"source": [
"# StopCondition is like Function, but it must return a boolean\n",
"sc_1 = ExpressionMethods.make_obj(model, StopCondition, 'sc 1', '1 < a + ddd', objects)\n",
"print(sc_1)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"'expression':\n",
" Evaluating 'a + ddd', a StopConditionExpression expression, should return a bool but it returns a float\n"
]
}
],
"source": [
"# expressions are validated by executing a test Python evaluation\n",
"# if a StopCondition doesn't return a boolean its validation fails\n",
"print(ExpressionMethods.make_obj(model, StopCondition, 'sc 1', 'a + ddd', objects))\n",
"# the test evaluation assumes that all referenced objects have values of 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Observable"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<wc_lang.core.Observable: ccc>\n"
]
}
],
"source": [
"# Observables can reference Species and other Observables\n",
"ccc = ExpressionMethods.make_obj(model, Observable, 'ccc', 'ccc + ddd - 2 * spec_type_0[comp]', objects)\n",
"print(ccc)\n",
"\n",
"# cycles aren't allowed, but they cannot be detected until all expression have been made"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}