Skip to content

Commit 4407efe

Browse files
committed
update docs
1 parent 089d102 commit 4407efe

File tree

6 files changed

+47
-25
lines changed

6 files changed

+47
-25
lines changed

README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
# funman
22

3-
The `funman` package implements multiple simulator model analysis methods.
4-
Current methods include:
5-
- Parameter Synthesis
6-
- Querying a Simulation
3+
The `funman` package performs Functional Model Analysis by processing a request and model pair that describes an analysis scenario. Funman supports a number of model formats, which correspond to the classes in `funman.models`:
4+
5+
- [GeneratedPetriNet](#funman.model.generated_models.petrinet.Model): AMR model for petri nets generated
6+
- [GeneratedRegNet](#funman.model.generated_models.regnet.Model): AMR model for regulatory networks
7+
- [RegnetModel](#funman.model.regnet.RegnetModel): MIRA model for regulatory networks
8+
- [PetrinetModel](#funman.model.petrinet.PetrinetModel): MIRA model for petri nets
9+
- [BilayerModel](#funman.model.bilayer.BilayerModel): ASKE model for bilayer networks
10+
11+
Requests correspond to the class `funman.server.query.FunmanWorkRequest` and specify the following keys:
12+
- [query](#funman.model.query): a soft constraint that a model must satisfy (legacy support, deprecated)
13+
- [constraints](#funman.representation.constraint): a list of hard or soft constraints that a model must satisfy
14+
- parameters: a list of bounded parameters that funman will either synthesize ("label": "all") or satsify ("label": "any"). Funman will check "all" values within the parameter bounds or if "any" within the bounds permit the model to satisfy the query and constraints.
15+
- [config](#funman.config): A dictionary of funman configuration options.
16+
label regions of the parameter space as satisfying the query and constraints, if synthesized, or find any legal value if asked to satsify.
17+
- [structure_parameters](#funman.representation.parameter): parameters shaping the way that funman structures its analysis. Funman requires that either the `num_steps` and `step_size` parameters are specified, or the `schedules` parameter is specified. If all are omitted, then funman defaults to checking one unit-sized step.
18+
19+
## **Running funman**
20+
21+
There are multiple ways to run Funman on a model and request pair. We recommend running funman in Docker, due to some complex dependencies on dReal (and its dependency on ibex). Funman has a Makefile that supports building three Docker use cases: 1) run a development container that mounts the source code, 2) run a container with a jupyter server, and 3) run a container with uvicorn serving a REST API. Examples of running each of these cases are illustrated by the tests (`test/test_api.py`, and `test/test_terarium.py`). It is also possible to pull a pre-generated image that will run the API, as described in `terarium/README.md`.
722

823
## **Use cases**
924
### **Compare Bilayer Model to Simulator**:

docs/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"sphinx.ext.inheritance_diagram",
2424
"sphinx.ext.napoleon",
2525
"sphinxcontrib.autodoc_pydantic",
26+
"myst_parser",
2627
]
2728

2829
autodoc_pydantic_model_show_json = True

docs/source/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ Welcome to funman's documentation!
1616
packages
1717
funman
1818

19+
README File
20+
===========
21+
22+
.. include:: ../../README.md
23+
:parser: myst_parser.sphinx_
1924

2025
Indices and tables
2126
==================

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ pycln
66
pytest-cov
77
twine
88
autodoc_pydantic
9+
myst-parser
910
parameterized

src/funman/representation/box.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def project(self, vars: Union[List[ModelParameter], List[str]]) -> "Box":
114114
115115
Parameters
116116
----------
117-
vars : Union[List[Parameter], List[str]]
117+
vars : Union[List[ModelParameter], List[str]]
118118
variables to project onto
119119
120120
Returns

src/funman/search/box_search.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,18 @@
4242

4343

4444
class FormulaStackFrame(BaseModel):
45-
formulas: List[FNode] = []
46-
simplified_formulas: List[FNode] = []
45+
_formulas: List[FNode] = []
46+
_simplified_formulas: List[FNode] = []
4747

4848
model_config = ConfigDict(
4949
arbitrary_types_allowed=True,
5050
)
5151

5252
def add_assertion(self, formula, is_simplified=False):
5353
if is_simplified:
54-
self.simplified_formulas.append(formula)
54+
self._simplified_formulas.append(formula)
5555
else:
56-
self.formulas.append(formula)
56+
self._formulas.append(formula)
5757

5858
# def __str__(self) -> str:
5959
# s_formulas = [f.serialize() for f in self.formulas]
@@ -65,8 +65,8 @@ def add_assertion(self, formula, is_simplified=False):
6565
class FormulaStack(BaseModel):
6666
formula_stack: List[FormulaStackFrame] = []
6767
time: int = -2
68-
solver: Optional[Solver] = None
69-
substitutions: Dict[FNode, FNode] = None
68+
_solver: Optional[Solver] = None
69+
_substitutions: Dict[FNode, FNode] = None
7070

7171
model_config = ConfigDict(
7272
arbitrary_types_allowed=True,
@@ -79,15 +79,15 @@ def __init__(self, *args, **kwargs):
7979
def pop(self, levels: int = 1, pop_solver: bool = True):
8080
for i in range(levels):
8181
if pop_solver:
82-
self.solver.pop(1)
82+
self._solver.pop(1)
8383
self.formula_stack.pop()
8484
self.time -= 1
8585

8686
def push(self, levels: int = 1, push_solver: bool = True):
8787
for i in range(levels):
8888
self.formula_stack.append(FormulaStackFrame())
8989
if push_solver:
90-
self.solver.push(1)
90+
self._solver.push(1)
9191
self.time += 1
9292

9393
# def __str__(self)-> str:
@@ -99,24 +99,24 @@ def add_assertion(self, formula):
9999
formula, is_simplified=False
100100
)
101101

102-
if self.substitutions is not None:
102+
if self._substitutions is not None:
103103
simplified_formula = formula.substitute(
104-
self.substitutions
104+
self._substitutions
105105
).simplify()
106106
self.formula_stack[self.time + 1].add_assertion(
107107
simplified_formula, is_simplified=True
108108
)
109-
self.solver.add_assertion(simplified_formula)
109+
self._solver.add_assertion(simplified_formula)
110110
else:
111-
self.solver.add_assertion(formula)
111+
self._solver.add_assertion(formula)
112112

113113
def to_list(self, simplified=False) -> List[FNode]:
114114
if simplified:
115115
return [
116-
f for sf in self.formula_stack for f in sf.simplified_formulas
116+
f for sf in self.formula_stack for f in sf._simplified_formulas
117117
]
118118
else:
119-
return [f for sf in self.formula_stack for f in sf.formulas]
119+
return [f for sf in self.formula_stack for f in sf._formulas]
120120

121121
def compute_assignment(
122122
self, episode: SearchEpisode, _smtlib_save_fn: Callable = None
@@ -125,21 +125,21 @@ def compute_assignment(
125125
original_formulas = [
126126
formula
127127
for frame in self.formula_stack
128-
for formula in frame.formulas
128+
for formula in frame._formulas
129129
]
130130
for formula in original_formulas:
131-
self.solver.add_assertion(formula)
131+
self._solver.add_assertion(formula)
132132
self.formula_stack[-1].add_assertion(
133133
formula, is_simplified=True
134134
) # formula is not simplified but want to layer on top of simplified formulas to compute state variables
135135
if _smtlib_save_fn:
136136
_smtlib_save_fn(filename=f"box_search_{episode._iteration}")
137137

138-
if not self.solver.solve():
138+
if not self._solver.solve():
139139
raise Exception(
140140
f"Could not compute Assignment from simplified formulas"
141141
)
142-
result = self.solver.get_model()
142+
result = self._solver.get_model()
143143
self.pop()
144144
return result
145145

@@ -176,7 +176,7 @@ def __init__(self, **kwargs):
176176
self._unknown_boxes = QueueSP()
177177
self.statistics = SearchStatistics()
178178
if self.config.substitute_subformulas and self.config.simplify_query:
179-
self._formula_stack.substitutions = self.problem._encodings[
179+
self._formula_stack._substitutions = self.problem._encodings[
180180
self.schedule
181181
]._encoder.substitutions(self.schedule)
182182

@@ -941,7 +941,7 @@ def _expand(
941941
)
942942

943943
with my_solver() as solver:
944-
episode._formula_stack.solver = solver
944+
episode._formula_stack._solver = solver
945945
l.info(f"{process_name} entering process loop")
946946
# print("Starting initializing dynamics of model")
947947
# self._initialize_encoding(solver, episode, [0])

0 commit comments

Comments
 (0)