Compare commits
18 Commits
oncogenic_
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| ae419e5e0e | |||
| f0019619b3 | |||
|
|
363446821e | ||
|
|
90c8e4f4c0 | ||
| fafe8dbe07 | |||
|
|
3237c2eae5 | ||
|
|
092fd94b56 | ||
|
|
f86316cdbd | ||
|
|
a864329883 | ||
|
|
48b4f1bb4d | ||
|
|
af26ca543b | ||
|
|
888ed4e68e | ||
|
|
a1fb5836a5 | ||
|
|
8be615b293 | ||
|
|
b4d58b94be | ||
|
|
33ca0fd6e9 | ||
|
|
632286ec7f | ||
|
|
98894fc6e1 |
112
.github/workflows/tests.yml
vendored
Normal file
112
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master, refactor]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bdd:
|
||||||
|
name: BDD tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y g++ make bison flex
|
||||||
|
|
||||||
|
- name: Build CUDD
|
||||||
|
working-directory: reactics-bdd
|
||||||
|
run: ./build_cudd.sh
|
||||||
|
|
||||||
|
- name: Build ReactICS BDD module
|
||||||
|
working-directory: reactics-bdd
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Run BDD tests
|
||||||
|
run: bash tests/run_tests.sh
|
||||||
|
|
||||||
|
smt:
|
||||||
|
name: SMT tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: pip install z3-solver pytest
|
||||||
|
|
||||||
|
- name: Run SMT tests
|
||||||
|
run: python3 -m pytest tests/test_smt.py -v
|
||||||
|
|
||||||
|
generators:
|
||||||
|
name: Generator tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: bdd
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y g++ make bison flex
|
||||||
|
|
||||||
|
- name: Build CUDD
|
||||||
|
working-directory: reactics-bdd
|
||||||
|
run: ./build_cudd.sh
|
||||||
|
|
||||||
|
- name: Build ReactICS BDD module
|
||||||
|
working-directory: reactics-bdd
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: Run generator tests
|
||||||
|
shell: bash --noprofile --norc {0}
|
||||||
|
run: |
|
||||||
|
set -uo pipefail
|
||||||
|
REACTICS="$PWD/reactics-bdd/reactics"
|
||||||
|
GENERATORS="$PWD/examples/bdd/generators"
|
||||||
|
passed=0
|
||||||
|
failed=0
|
||||||
|
check_gen() {
|
||||||
|
local name="$1" gen_cmd="$2" property="$3" expected="$4"
|
||||||
|
local tmpfile=$(mktemp /tmp/reactics_gen_XXXXXX.drs)
|
||||||
|
if ! eval "$gen_cmd" > "$tmpfile" 2>&1; then
|
||||||
|
echo " FAIL: $name (generator crashed)"
|
||||||
|
failed=$((failed + 1))
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local result=$("$REACTICS" -c "$property" "$tmpfile" 2>&1 | grep -oE "(holds|does not hold)" || true)
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
if [ "$result" = "$expected" ]; then
|
||||||
|
echo " PASS: $name"
|
||||||
|
passed=$((passed + 1))
|
||||||
|
else
|
||||||
|
echo " FAIL: $name (expected '$expected', got '$result')"
|
||||||
|
failed=$((failed + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
check_gen "tgc(3) f1" "python3 $GENERATORS/gen_tgc.py 3" f1 "holds"
|
||||||
|
check_gen "tgc(3) f3" "python3 $GENERATORS/gen_tgc.py 3" f3 "holds"
|
||||||
|
check_gen "tgc(4) f2" "python3 $GENERATORS/gen_tgc.py 4" f2 "holds"
|
||||||
|
check_gen "asm(3) f1" "python3 $GENERATORS/gen_asm.py 3" f1 "holds"
|
||||||
|
check_gen "asm(3) f2" "python3 $GENERATORS/gen_asm.py 3" f2 "holds"
|
||||||
|
check_gen "drs(2,2,2,a) f0" "python3 $GENERATORS/gen_drs.py 2 2 2 a" f0 "does not hold"
|
||||||
|
check_gen "drs(2,2,2,b) f0" "python3 $GENERATORS/gen_drs.py 2 2 2 b" f0 "holds"
|
||||||
|
echo
|
||||||
|
echo "Generator results: $passed passed, $failed failed"
|
||||||
|
if [ "$failed" -gt 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
107
README.md
107
README.md
@@ -3,110 +3,9 @@
|
|||||||
Reaction Systems Verification Toolkit
|
Reaction Systems Verification Toolkit
|
||||||
|
|
||||||
The toolkit consists of two separate modules implementing:
|
The toolkit consists of two separate modules implementing:
|
||||||
* Methods implemented using binary decision diagrams (BDD) for storing and manipulating the state space of the verified system.
|
|
||||||
|
* Methods using binary decision diagrams (BDD) for storing and manipulating the state space of the verified system.
|
||||||
* Methods translating the verification problems into satisfiability modulo theories (SMT).
|
* Methods translating the verification problems into satisfiability modulo theories (SMT).
|
||||||
|
|
||||||
# Installation
|
See: https://reactics.org
|
||||||
|
|
||||||
## Installing everything manually
|
|
||||||
|
|
||||||
(to be added)
|
|
||||||
|
|
||||||
## Virtual Machine
|
|
||||||
|
|
||||||
The easiest way to try out ReactICS is to download [the VM where everything is alread installed](http://reactionsystems.org/ReactICS.zip). This a VirtualBox virtual machine. After booting it up, you can log in as `reactics` with the same password. After logging in, ReactICS is available in the `reactics` directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cd reactics
|
|
||||||
```
|
|
||||||
|
|
||||||
An update and setup needs to be performed before running any type of verification:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics setup
|
|
||||||
```
|
|
||||||
|
|
||||||
After performing these steps you should be ready to start using ReactICS.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
The `examples` directory contains sample input files.
|
|
||||||
|
|
||||||
### Multi-agent reaction systems (rsCTLK verification)
|
|
||||||
|
|
||||||
To quickly test the BDD module you can perform verification of the TGC controller consiting of three trains:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics bdd -c f1 examples/bdd/tgc.rs
|
|
||||||
```
|
|
||||||
|
|
||||||
The above command tests the formula labelled `f1` in the input file.
|
|
||||||
|
|
||||||
### Reachability
|
|
||||||
|
|
||||||
To test the SMT module you can perform reachability verification of the scalable chain system:
|
|
||||||
|
|
||||||
Running the benchmark without any arguments tells us what parameters are available:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics smt examples/smt/scalable_chain.py
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
-- ReactICS -- Reaction Systems Model Checker --
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
arguments: <chainLen> <maxConc> <formulaNumber>
|
|
||||||
```
|
|
||||||
|
|
||||||
We may execute the benchmark for `chainLen=2`, `maxConc=3`, and `formulaNumber=1` using the following command:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics smt examples/smt/chain_reaction.py 2 3 1
|
|
||||||
```
|
|
||||||
|
|
||||||
### rsLTL verification
|
|
||||||
|
|
||||||
To test the SMT module for rsLTL verification the scalable chain system benchmark may be used.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics smt examples/smt/scalable_chain.py 2 5 1
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Reaction synthesis
|
|
||||||
|
|
||||||
To test the reaction synthesis approach on a mutual exclution protocol modelling three processes, run the following command (three processes, parametric verification, result optimised with OptSMT):
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics smt examples/smt/mutex_param.py 3 p -o
|
|
||||||
```
|
|
||||||
|
|
||||||
To check the available parameters for the benchmark, we run it with `-h`:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ ./reactics smt examples/smt/mutex_param.py -h
|
|
||||||
|
|
||||||
------------------------------------------------
|
|
||||||
-- ReactICS -- Reaction Systems Model Checker --
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
usage: mutex_param.py [-h] [-v] [-o] scaling {p,np-p,np-np}
|
|
||||||
|
|
||||||
positional arguments:
|
|
||||||
scaling scaling parameter value
|
|
||||||
{p,np-p,np-np} Selects the mode: p - parameter synthesis (parametric
|
|
||||||
implementation), np-p - non-parametric with parametric
|
|
||||||
implementation (with the parameters substituted), np-np -
|
|
||||||
non-parametric with non-parametric implementation
|
|
||||||
(parameters substituted)
|
|
||||||
|
|
||||||
optional arguments:
|
|
||||||
-h, --help show this help message and exit
|
|
||||||
-v, --verbose turn verbosity on
|
|
||||||
-o, --optimise minimise the parametric computation result
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
65
TESTING.md
Normal file
65
TESTING.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Testing ReactICS
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **BDD module**: compiled (`./reactics setup` or `make` in `reactics-bdd/`)
|
||||||
|
- **SMT module**: Python 3 with `z3-solver` and `pytest` installed
|
||||||
|
|
||||||
|
```
|
||||||
|
pip install z3-solver pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running all tests
|
||||||
|
|
||||||
|
```
|
||||||
|
./run_tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs the BDD, SMT, and generator test suites in sequence.
|
||||||
|
|
||||||
|
## BDD tests
|
||||||
|
|
||||||
|
```
|
||||||
|
bash tests/run_tests.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
10 regression tests that run the compiled `reactics-bdd/reactics` binary
|
||||||
|
against example `.drs` files and compare output to saved baselines in
|
||||||
|
`tests/expected/`. Covers:
|
||||||
|
|
||||||
|
- Parsed system printing (`-P`)
|
||||||
|
- Reaction listing (`-r`)
|
||||||
|
- Reachable state enumeration (`-s`)
|
||||||
|
- RSCTLK model checking (`-c`) for properties f1--f4
|
||||||
|
|
||||||
|
Input files: `examples/bdd/tgc.drs`, `examples/bdd/tgc4.drs`,
|
||||||
|
`reactics-bdd/in/trivial.drs`.
|
||||||
|
|
||||||
|
To update baselines after an intentional output change, delete the
|
||||||
|
relevant file in `tests/expected/` and re-run; the test will regenerate it.
|
||||||
|
|
||||||
|
## SMT tests
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 -m pytest tests/test_smt.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
23 pytest tests exercising the Python API directly. Organised by layer:
|
||||||
|
|
||||||
|
- **Data model** -- ReactionSystem, concentrations, context automata,
|
||||||
|
formula construction (BagDescription, rsLTL)
|
||||||
|
- **SmtCheckerRS** -- basic reachability (no concentrations)
|
||||||
|
- **SmtCheckerRSC** -- reachability and rsLTL model checking with
|
||||||
|
concentrations (chain reaction, heat shock response)
|
||||||
|
- **SmtCheckerRSCParam** -- parametric verification
|
||||||
|
- **RSC-to-RS translation** -- verifying the translated system
|
||||||
|
|
||||||
|
## Generator tests
|
||||||
|
|
||||||
|
7 tests that run each generator (from `examples/bdd/generators/`),
|
||||||
|
feed the output into the BDD model checker, and verify the expected
|
||||||
|
verification result (holds / does not hold).
|
||||||
|
|
||||||
|
Generators using old syntax (`examples/bdd/generators/old_syntax/`)
|
||||||
|
are not tested this way as they are not compatible with the current
|
||||||
|
parser.
|
||||||
103
examples/bdd/generators/gen_asm.py
Normal file
103
examples/bdd/generators/gen_asm.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the Assembly-line (ASM) benchmark.
|
||||||
|
|
||||||
|
Produces a distributed reaction system modelling an assembly line
|
||||||
|
where N sequential processes pass activation tokens. Each process
|
||||||
|
cycles through entities a -> y,b -> c -> d, and the final process
|
||||||
|
signals 'done'. Uses a context automaton for scheduling.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
OPTIONS = "options { use-context-automaton; make-progressive; };\n"
|
||||||
|
|
||||||
|
PROC_TEMPLATE = """
|
||||||
|
proc{i} {{
|
||||||
|
{{{{a}}, {{s}} -> {{y}}}};
|
||||||
|
{{{{y}}, {{s}} -> {{y}}}};
|
||||||
|
{{{{a}}, {{s}} -> {{b}}}};
|
||||||
|
{{{{b}}, {{s}} -> {{c}}}};
|
||||||
|
{{{{c}}, {{s}} -> {{d}}}};
|
||||||
|
{{{{d,y}}, {{s}} -> {{dy}}}};
|
||||||
|
}};
|
||||||
|
"""
|
||||||
|
|
||||||
|
FINAL_PROC = """
|
||||||
|
procFinal {
|
||||||
|
{{done}, {s} -> {done}};
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
|
||||||
|
CA_TEMPLATE = """
|
||||||
|
context-automaton {{
|
||||||
|
states {{ init, act }};
|
||||||
|
init-state {{ init }};
|
||||||
|
transitions {{
|
||||||
|
{transitions}
|
||||||
|
}};
|
||||||
|
}};
|
||||||
|
"""
|
||||||
|
|
||||||
|
PROPERTY_TEMPLATE = '\nrsctlk-property {{ {name} : {formula} }};\n'
|
||||||
|
|
||||||
|
|
||||||
|
def generate(n):
|
||||||
|
out = OPTIONS
|
||||||
|
out += "\nreactions {\n"
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
out += PROC_TEMPLATE.format(i=i)
|
||||||
|
out += FINAL_PROC
|
||||||
|
out += "};\n"
|
||||||
|
|
||||||
|
indent = 8 * " "
|
||||||
|
transitions = ""
|
||||||
|
|
||||||
|
# init -> act: first process gets activated
|
||||||
|
transitions += "{indent}{{ proc1={{a}} }}: init -> act;\n".format(indent=indent)
|
||||||
|
|
||||||
|
# act -> act: process stays idle (dy not produced)
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
transitions += "{indent}{{ proc{i}={{}} }}: act -> act : ~proc{i}.dy;\n".format(
|
||||||
|
indent=indent, i=i)
|
||||||
|
|
||||||
|
# act -> act: next process gets activated when previous produces 'dy'
|
||||||
|
for i in range(2, n + 1):
|
||||||
|
transitions += "{indent}{{ proc{i}={{a}} }}: act -> act : proc{prev}.dy;\n".format(
|
||||||
|
indent=indent, i=i, prev=i - 1)
|
||||||
|
|
||||||
|
# act -> act: final process signals done when all have produced 'dy'
|
||||||
|
all_dy = " AND ".join("proc{}.dy".format(i) for i in range(1, n + 1))
|
||||||
|
transitions += "{indent}{{ procFinal={{done}} }}: act -> act : {guard};\n".format(
|
||||||
|
indent=indent, guard=all_dy)
|
||||||
|
|
||||||
|
out += CA_TEMPLATE.format(transitions=transitions)
|
||||||
|
|
||||||
|
# f1: the assembly line eventually completes
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f1", formula="EF( procFinal.done )")
|
||||||
|
|
||||||
|
# f2: last process knows its predecessor has produced 'y'
|
||||||
|
f2 = "AG( proc{n}.d IMPLIES K[proc{n}]( proc{prev}.y ) )".format(n=n, prev=n - 1)
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f2", formula=f2)
|
||||||
|
|
||||||
|
# x1: negation of f1 (sanity check -- should also hold)
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="x1", formula="EF( ~procFinal.done )")
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument("n", type=int, help="number of processes (must be > 1)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.n < 2:
|
||||||
|
parser.error("number of processes must be > 1")
|
||||||
|
|
||||||
|
print(generate(args.n))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
301
examples/bdd/generators/gen_drs.py
Executable file
301
examples/bdd/generators/gen_drs.py
Executable file
@@ -0,0 +1,301 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the DRS (Distributed Reaction Systems) epistemic benchmark.
|
||||||
|
|
||||||
|
Produces a distributed reaction system with epistemic properties
|
||||||
|
(knowledge operators). The system models signal transduction cascades
|
||||||
|
with configurable depth (x), number of components (y), threshold (z),
|
||||||
|
and context automaton variant (a or b).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
|
||||||
|
class SingleReaction:
|
||||||
|
def __init__(self, reactants=None, inhibitors=None, products=None):
|
||||||
|
self.reactants = set(reactants) if reactants is not None else set()
|
||||||
|
self.inhibitors = set(inhibitors) if inhibitors is not None else set()
|
||||||
|
self.products = set(products) if products is not None else set()
|
||||||
|
|
||||||
|
def get_reactants(self):
|
||||||
|
return "{" + ", ".join(self.reactants) + "}"
|
||||||
|
|
||||||
|
def get_inhibitors(self):
|
||||||
|
return "{" + ", ".join(self.inhibitors) + "}"
|
||||||
|
|
||||||
|
def get_products(self):
|
||||||
|
return "{" + ", ".join(self.products) + "}"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
"{"
|
||||||
|
+ f"{self.get_reactants()}, {self.get_inhibitors()} -> {self.get_products()}"
|
||||||
|
+ "};"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Reactions:
|
||||||
|
def __init__(self):
|
||||||
|
self.reactions = []
|
||||||
|
|
||||||
|
def add(self, reaction):
|
||||||
|
self.reactions.append(reaction)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ret = ""
|
||||||
|
for r in self.reactions:
|
||||||
|
ret += f"{r}\n"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
class Transition:
|
||||||
|
def __init__(self, src, dst, guard, context):
|
||||||
|
self.src = src
|
||||||
|
self.dst = dst
|
||||||
|
self.guard = guard
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def get_context_str(self):
|
||||||
|
r = []
|
||||||
|
for proc, entities in self.context:
|
||||||
|
ent_str = ",".join(entities)
|
||||||
|
r.append(f"{proc}={{{ent_str}}}")
|
||||||
|
|
||||||
|
r = " ".join(r)
|
||||||
|
return "{ " + r + " }"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.guard:
|
||||||
|
return f"{self.get_context_str()}: {self.src} -> {self.dst} : {self.guard};"
|
||||||
|
else:
|
||||||
|
return f"{self.get_context_str()}: {self.src} -> {self.dst};"
|
||||||
|
|
||||||
|
|
||||||
|
class Automaton:
|
||||||
|
def __init__(self):
|
||||||
|
self.transitions = []
|
||||||
|
self.states = []
|
||||||
|
self.init_state = None
|
||||||
|
|
||||||
|
def add_transition(self, transition):
|
||||||
|
self.transitions.append(transition)
|
||||||
|
|
||||||
|
def add_state(self, state):
|
||||||
|
if state not in self.states:
|
||||||
|
self.states.append(state)
|
||||||
|
|
||||||
|
def set_init_state(self, state):
|
||||||
|
assert state in self.states, f"{state} not in states"
|
||||||
|
self.init_state = state
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
r = "context-automaton {\n"
|
||||||
|
r += "\tstates { " + ", ".join(self.states) + " };\n"
|
||||||
|
r += f"\tinit-state {{ {self.init_state} }};\n"
|
||||||
|
r += "\ttransitions {\n"
|
||||||
|
for tr in self.transitions:
|
||||||
|
r += "\t\t" + str(tr) + "\n"
|
||||||
|
r += "\t};\n"
|
||||||
|
r += "};\n"
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
class DRSGenerator:
|
||||||
|
def __init__(self, x, y, z, aut):
|
||||||
|
assert y >= z
|
||||||
|
assert x >= 2 and y >= 2 and z >= 2
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.z = z
|
||||||
|
self.aut_id = aut
|
||||||
|
self.n = self.y
|
||||||
|
self.reactions = {}
|
||||||
|
|
||||||
|
self.automaton = Automaton()
|
||||||
|
|
||||||
|
self.generate()
|
||||||
|
|
||||||
|
def generate_agent_zero(self):
|
||||||
|
rcts = Reactions()
|
||||||
|
for i in range(1, self.y + 1):
|
||||||
|
rcts.add(SingleReaction(["RTK"], ["h"], [f"RTK{i}"]))
|
||||||
|
for j in range(1, self.x + 1):
|
||||||
|
rcts.add(SingleReaction([f"EN:{j}_{i}"], ["h"], [f"ENi:{self.x}_{i}"]))
|
||||||
|
return rcts
|
||||||
|
|
||||||
|
def generate_reactions_for_component(self, i):
|
||||||
|
self.reactions.setdefault(i, Reactions())
|
||||||
|
rcts = self.reactions[i]
|
||||||
|
rcts.add(SingleReaction(["GF"], ["h"], ["GF"]))
|
||||||
|
rcts.add(SingleReaction(["GF"], ["h", f"RTK{i}"], ["RTK"]))
|
||||||
|
rcts.add(SingleReaction(["RTK"], [f"ENi:1_{i}"], [f"EN:1_{i}"]))
|
||||||
|
for j in range(1, self.x):
|
||||||
|
rcts.add(
|
||||||
|
SingleReaction([f"EN:{j}_{i}"], [f"ENi:{j+1}_{i}"], [f"EN:{j+1}_{i}"])
|
||||||
|
)
|
||||||
|
|
||||||
|
indices = list(range(1, self.y + 1))
|
||||||
|
for comb in itertools.combinations(indices, self.z):
|
||||||
|
reactants = []
|
||||||
|
for i in comb:
|
||||||
|
reactants.append(f"EN:{self.x}_{i}")
|
||||||
|
rcts.add(SingleReaction(reactants, ["h"], ["TF"]))
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
|
||||||
|
print(f"# Generated for: x = {self.x}, y = {self.y}, z = {self.z}")
|
||||||
|
|
||||||
|
print("options { use-context-automaton; make-progressive; };")
|
||||||
|
print("reactions {")
|
||||||
|
|
||||||
|
for i in range(1, self.y + 1):
|
||||||
|
self.generate_reactions_for_component(i)
|
||||||
|
|
||||||
|
rcts_0 = self.generate_agent_zero()
|
||||||
|
|
||||||
|
print("proc0 {")
|
||||||
|
print(rcts_0)
|
||||||
|
print("};")
|
||||||
|
|
||||||
|
for proc, reactions in self.reactions.items():
|
||||||
|
print(f"proc{proc} {{")
|
||||||
|
print(reactions)
|
||||||
|
print("};")
|
||||||
|
|
||||||
|
print("};")
|
||||||
|
|
||||||
|
if self.aut_id == "a":
|
||||||
|
self.generate_automaton_4(self.n)
|
||||||
|
elif self.aut_id == "b":
|
||||||
|
self.generate_automaton_5(self.n)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(f"Unknown automaton identifier: {self.aut_id}")
|
||||||
|
|
||||||
|
self.generate_formula()
|
||||||
|
|
||||||
|
def generate_automaton_4(self, n):
|
||||||
|
aut = self.automaton
|
||||||
|
|
||||||
|
aut.add_state("qI")
|
||||||
|
aut.add_state("qS")
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
aut.add_state(f"q{i}A")
|
||||||
|
aut.add_state(f"q{i}B")
|
||||||
|
aut.add_state(f"q{i}C")
|
||||||
|
aut.add_state(f"q{i}D")
|
||||||
|
|
||||||
|
aut.set_init_state("qI")
|
||||||
|
|
||||||
|
aut.add_transition(
|
||||||
|
Transition("qI", "qS", "", [(f"proc{i}", ["GF"]) for i in range(0, n + 1)])
|
||||||
|
)
|
||||||
|
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
aut.add_transition(Transition("qS", f"q{i}A", "", [(f"proc{i}", [])]))
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(
|
||||||
|
f"q{i}A", f"q{i}B", "", [(f"proc{v}", []) for v in range(0, n + 1)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
aut.add_transition(Transition(f"q{i}B", f"q{i}C", "", [(f"proc{i}", [])]))
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(
|
||||||
|
f"q{i}C", f"q{i}D", "", [(f"proc{v}", []) for v in range(0, n + 1)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
for j in range(1, n + 1):
|
||||||
|
if i == j:
|
||||||
|
continue
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(f"q{i}B", f"q{j}A", "", [(f"proc{j}", [])])
|
||||||
|
)
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(f"q{i}D", f"q{j}A", "", [(f"proc{j}", [])])
|
||||||
|
)
|
||||||
|
|
||||||
|
print(aut)
|
||||||
|
|
||||||
|
def generate_automaton_5(self, n):
|
||||||
|
|
||||||
|
aut = self.automaton
|
||||||
|
|
||||||
|
for i in range(0, (4 * n + 1)):
|
||||||
|
aut.add_state(f"q{i}")
|
||||||
|
|
||||||
|
aut.set_init_state("q0")
|
||||||
|
|
||||||
|
aut.add_transition(
|
||||||
|
Transition("q0", "q1", "", [(f"proc{i}", ["GF"]) for i in range(0, n + 1)])
|
||||||
|
)
|
||||||
|
|
||||||
|
for i in range(0, n): # 0, ..., n-1
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(f"q{4*i+1}", f"q{4*i+2}", "", [(f"proc{i+1}", [])])
|
||||||
|
)
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(
|
||||||
|
f"q{4*i+2}",
|
||||||
|
f"q{4*i+3}",
|
||||||
|
"",
|
||||||
|
[(f"proc{v}", []) for v in range(0, n + 1)],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(f"q{4*i+3}", f"q{4*i+4}", "", [(f"proc{i+1}", [])])
|
||||||
|
)
|
||||||
|
|
||||||
|
for i in range(0, n - 1): # 0, ..., n-2
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(
|
||||||
|
f"q{4*i+4}",
|
||||||
|
f"q{4*i+5}",
|
||||||
|
"",
|
||||||
|
[(f"proc{v}", []) for v in range(0, n + 1)],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
aut.add_transition(
|
||||||
|
Transition(f"q{4*n}", "q1", "", [(f"proc{i}", []) for i in range(0, n + 1)])
|
||||||
|
)
|
||||||
|
|
||||||
|
print(aut)
|
||||||
|
|
||||||
|
def generate_formula(self):
|
||||||
|
|
||||||
|
disjunction = " OR ".join([f"proc{i}.TF" for i in range(1, self.y + 1)])
|
||||||
|
conjunction = " AND ".join([f"~proc{i}.TF" for i in range(1, self.y + 1)])
|
||||||
|
|
||||||
|
r = (
|
||||||
|
"rsctlk-property { f0 : AG( K[proc0]( "
|
||||||
|
+ disjunction
|
||||||
|
+ " ) OR K[proc0]( "
|
||||||
|
+ conjunction
|
||||||
|
+ " ) ) };"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(r)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument("x", type=int, help="cascade depth (>= 2)")
|
||||||
|
parser.add_argument("y", type=int, help="number of components (>= 2, >= z)")
|
||||||
|
parser.add_argument("z", type=int, help="threshold (>= 2, <= y)")
|
||||||
|
parser.add_argument("aut", choices=["a", "b"], help="automaton variant")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.x < 2 or args.y < 2 or args.z < 2:
|
||||||
|
parser.error("x, y, z must all be >= 2")
|
||||||
|
if args.y < args.z:
|
||||||
|
parser.error("y must be >= z")
|
||||||
|
|
||||||
|
DRSGenerator(x=args.x, y=args.y, z=args.z, aut=args.aut)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,13 +1,20 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the Traffic Guard Controller (TGC) benchmark.
|
||||||
|
|
||||||
from sys import argv,exit
|
Produces a distributed reaction system where N processes compete
|
||||||
|
for access to a shared resource, governed by a context automaton
|
||||||
OPTIONS_STR = """
|
with green/red states. Generates RSCTLK properties for liveness,
|
||||||
options { use-context-automaton; make-progressive; };
|
reachability, and mutual exclusion (epistemic).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PROC_STR = """
|
import argparse
|
||||||
proc{:d} {{
|
|
||||||
|
|
||||||
|
OPTIONS = "options { use-context-automaton; make-progressive; };\n"
|
||||||
|
|
||||||
|
PROC_TEMPLATE = """
|
||||||
|
proc{i} {{
|
||||||
{{{{out}}, {{}} -> {{approach}}}};
|
{{{{out}}, {{}} -> {{approach}}}};
|
||||||
{{{{approach}}, {{req}} -> {{req}}}};
|
{{{{approach}}, {{req}} -> {{req}}}};
|
||||||
{{{{allowed}}, {{}} -> {{in}}}};
|
{{{{allowed}}, {{}} -> {{in}}}};
|
||||||
@@ -16,102 +23,94 @@ PROC_STR = """
|
|||||||
}};
|
}};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CA_STR = """
|
CA_TEMPLATE = """
|
||||||
context-automaton {{
|
context-automaton {{
|
||||||
states {{ init, green, red }};
|
states {{ init, green, red }};
|
||||||
init-state {{ init }};
|
init-state {{ init }};
|
||||||
transitions {{
|
transitions {{
|
||||||
{:s}
|
{transitions}
|
||||||
}};
|
}};
|
||||||
}};
|
}};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PROPERTY_STR = """
|
PROPERTY_TEMPLATE = '\nrsctlk-property {{ {name} : {formula} }};\n'
|
||||||
rsctlk-property {{ {:s} : {:s} }};
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
def conj(fmt, indices, sep=" AND "):
|
||||||
|
return sep.join(fmt.format(i=i) for i in indices)
|
||||||
|
|
||||||
if len(argv) < 1:
|
|
||||||
print("Usage: {:s} <number of processes>".format(argv[0]))
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
def generate(n):
|
||||||
|
out = OPTIONS
|
||||||
|
out += "\nreactions {\n"
|
||||||
|
for i in range(n):
|
||||||
|
out += PROC_TEMPLATE.format(i=i)
|
||||||
|
out += "};\n"
|
||||||
|
|
||||||
assert n > 1, "number of proc must be > 1"
|
indent = 8 * " "
|
||||||
|
transitions = ""
|
||||||
|
|
||||||
out = ""
|
# init -> green: all processes start with 'out'
|
||||||
|
transitions += indent + "{ "
|
||||||
|
transitions += " ".join("proc{:d}={{out}}".format(i) for i in range(n))
|
||||||
|
transitions += " }: init -> green;\n"
|
||||||
|
|
||||||
out += OPTIONS_STR
|
# green -> red: a process requests
|
||||||
out += "reactions {\n"
|
for i in range(n):
|
||||||
for i in range(n):
|
transitions += "{indent}{{ proc{i}={{allowed}} }}: green -> red : proc{i}.req;\n".format(
|
||||||
out += PROC_STR.format(i)
|
indent=indent, i=i)
|
||||||
out += "};\n"
|
|
||||||
|
|
||||||
transitions = ""
|
# green -> green: no requests pending
|
||||||
|
no_req = conj("~proc{i}.req", range(n))
|
||||||
|
for i in range(n):
|
||||||
|
transitions += "{indent}{{ proc{i}={{}} }}: green -> green : {guard};\n".format(
|
||||||
|
indent=indent, i=i, guard=no_req)
|
||||||
|
|
||||||
init_trans = 8*" " + "{ "
|
# red -> green: a process leaves
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
init_trans += "proc{:d}={{out}} ".format(i)
|
transitions += "{indent}{{ proc{i}={{}} }}: red -> green : proc{i}.leave;\n".format(
|
||||||
init_trans += "}: init -> green;\n"
|
indent=indent, i=i)
|
||||||
transitions += init_trans
|
|
||||||
|
|
||||||
for i in range(n):
|
# red -> red: no process leaves
|
||||||
transitions += "{:s}{{ proc{:d}={{allowed}} }}: green -> red : proc{:d}.req;\n".format(8*" ", i, i)
|
no_leave = conj("~proc{i}.leave", range(n))
|
||||||
|
for i in range(n):
|
||||||
|
transitions += "{indent}{{ proc{i}={{}} }}: red -> red : {guard};\n".format(
|
||||||
|
indent=indent, i=i, guard=no_leave)
|
||||||
|
|
||||||
no_req_cond = "~proc0.req"
|
out += CA_TEMPLATE.format(transitions=transitions)
|
||||||
for i in range(1, n):
|
|
||||||
no_req_cond += " AND ~proc{:d}.req".format(i)
|
|
||||||
|
|
||||||
for i in range(n):
|
# f1: each process can eventually enter
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: green -> green : {:s};\n".format(8*" ", i, no_req_cond)
|
f1 = conj("EF( E<proc{i}.allowed>X( proc{i}.in ) )", range(n))
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f1", formula=f1)
|
||||||
|
|
||||||
for i in range(n):
|
# f2: all processes can simultaneously approach
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: red -> green : proc{:d}.leave;\n".format(8*" ", i, i)
|
f2 = "EF( " + conj("proc{i}.approach", range(n)) + " )"
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f2", formula=f2)
|
||||||
|
|
||||||
no_leave_cond = "~proc0.leave"
|
# f3: mutual exclusion (knowledge)
|
||||||
for i in range(1, n):
|
others_not_in = conj("~proc{i}.in", range(1, n))
|
||||||
no_leave_cond += " AND ~proc{:d}.leave".format(i)
|
f3 = "AG( proc0.in IMPLIES K[proc0]({}) )".format(others_not_in)
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f3", formula=f3)
|
||||||
|
|
||||||
for i in range(n):
|
# f4: mutual exclusion (common knowledge)
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: red -> red : {:s};\n".format(8*" ", i, no_leave_cond)
|
all_agents = conj("proc{i}", range(n), sep=",")
|
||||||
|
f4 = "AG( proc0.in IMPLIES C[{}]({}) )".format(all_agents, others_not_in)
|
||||||
|
out += PROPERTY_TEMPLATE.format(name="f4", formula=f4)
|
||||||
|
|
||||||
out += CA_STR.format(transitions)
|
return out
|
||||||
|
|
||||||
## f1
|
|
||||||
#formula = "EF( proc0.in )"
|
|
||||||
#out += PROPERTY_STR.format("f1",formula)
|
|
||||||
|
|
||||||
# f1
|
def main():
|
||||||
formula = "EF( E<proc0.allowed>X( proc0.in ) )"
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
for i in range(1, n):
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
formula += " AND EF( E<proc{:d}.allowed>X( proc{:d}.in ) )".format(i, i)
|
parser.add_argument("n", type=int, help="number of processes (must be > 1)")
|
||||||
out += PROPERTY_STR.format("f1",formula)
|
args = parser.parse_args()
|
||||||
|
|
||||||
# f2
|
if args.n < 2:
|
||||||
formula = "EF( proc0.approach"
|
parser.error("number of processes must be > 1")
|
||||||
for i in range(1, n):
|
|
||||||
formula += " AND proc{:d}.approach".format(i)
|
|
||||||
formula += " )"
|
|
||||||
out += PROPERTY_STR.format("f2",formula)
|
|
||||||
|
|
||||||
# f3
|
print(generate(args.n))
|
||||||
subf = "~proc1.in"
|
|
||||||
for i in range(2, n):
|
|
||||||
subf += " AND ~proc{:d}.in".format(i)
|
|
||||||
formula = "AG( proc0.in IMPLIES K[proc0]({:s}) )".format(subf)
|
|
||||||
out += PROPERTY_STR.format("f3",formula)
|
|
||||||
|
|
||||||
# f4
|
|
||||||
subf = "~proc1.in"
|
|
||||||
for i in range(2, n):
|
|
||||||
subf += " AND ~proc{:d}.in".format(i)
|
|
||||||
all_agents = "proc0"
|
|
||||||
for i in range(1, n):
|
|
||||||
all_agents += ",proc{:d}".format(i)
|
|
||||||
formula = "AG( proc0.in IMPLIES C[{:s}]({:s}) )".format(all_agents,subf)
|
|
||||||
out += PROPERTY_STR.format("f4",formula)
|
|
||||||
|
|
||||||
print(out)
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
62
examples/bdd/generators/old_syntax/gen_abstract.py
Normal file
62
examples/bdd/generators/old_syntax/gen_abstract.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the Abstract Pipeline benchmark.
|
||||||
|
|
||||||
|
Produces a reaction system modelling a pipeline of N modules,
|
||||||
|
each cycling through entities a -> y,b -> c -> d before passing
|
||||||
|
activation to the next module. The final reaction requires all
|
||||||
|
modules to have completed (all y_i present).
|
||||||
|
|
||||||
|
NOTE: generates old-syntax input (context-entities, initial-contexts,
|
||||||
|
rsctl-property) which is not compatible with the current parser.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
def generate(n, variant):
|
||||||
|
out = "reactions {\n"
|
||||||
|
out += "\t{ {x},{s} -> {a1} };\n"
|
||||||
|
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
out += "\t{{ {{a{i}}},{{s}} -> {{y{i}}} }};\n".format(i=i)
|
||||||
|
out += "\t{{ {{a{i}}},{{s}} -> {{b{i}}} }};\n".format(i=i)
|
||||||
|
out += "\t{{ {{b{i}}},{{s}} -> {{c{i}}} }};\n".format(i=i)
|
||||||
|
out += "\t{{ {{c{i}}},{{s}} -> {{d{i}}} }};\n".format(i=i)
|
||||||
|
out += "\t{{ {{d{i},y{i}}},{{s}} -> {{a{j}}} }};\n".format(i=i, j=i + 1)
|
||||||
|
out += "\t{{ {{y{i}}},{{s}} -> {{y{i}}} }};\n".format(i=i)
|
||||||
|
|
||||||
|
final_reactants = "a" + str(n + 1)
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
final_reactants += ",y" + str(i)
|
||||||
|
out += "\t{{ {{{r}}},{{s}} -> {{r}} }};\n".format(r=final_reactants)
|
||||||
|
out += "}\n"
|
||||||
|
|
||||||
|
if variant == 1:
|
||||||
|
out += "context-entities { s }\n"
|
||||||
|
elif variant == 2:
|
||||||
|
ctx = "s"
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
if i % 2 == 0:
|
||||||
|
ctx += ",a" + str(i)
|
||||||
|
out += "context-entities {{ {} }}\n".format(ctx)
|
||||||
|
|
||||||
|
out += "initial-contexts { {x} }\n"
|
||||||
|
out += "rsctl-property { E[{}]F(r) }\n"
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument("n", type=int, help="number of pipeline modules")
|
||||||
|
parser.add_argument("variant", type=int, choices=[1, 2],
|
||||||
|
help="context variant (1: minimal, 2: extended)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
print(generate(args.n, args.variant))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
88
examples/bdd/generators/old_syntax/gen_bc.py
Normal file
88
examples/bdd/generators/old_syntax/gen_bc.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the Binary Counter (BC) benchmark.
|
||||||
|
|
||||||
|
Produces a reaction system modelling an N-bit binary counter
|
||||||
|
with increment and decrement operations controlled via context
|
||||||
|
entities. Generates one of four RSCTL properties.
|
||||||
|
|
||||||
|
NOTE: generates old-syntax input (context-entities, initial-contexts,
|
||||||
|
rsctl-property) which is not compatible with the current parser.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
K = 8 # constant used by property 3
|
||||||
|
|
||||||
|
|
||||||
|
def generate(n, prop):
|
||||||
|
out = "reactions {\n"
|
||||||
|
|
||||||
|
# (1) no dec, no inc: bits persist
|
||||||
|
out += "\t# (1) no decrement, no increment\n"
|
||||||
|
for j in range(n):
|
||||||
|
out += "\t{{{{p{j}}},{{dec,inc}} -> {{p{j}}}}};\n".format(j=j)
|
||||||
|
|
||||||
|
# (2) increment operation
|
||||||
|
out += "\n\t# (2) increment operation\n"
|
||||||
|
out += "\t{{inc},{dec,p0} -> {p0}};\n"
|
||||||
|
for j in range(1, n):
|
||||||
|
bits = ",".join("p" + str(k) for k in range(j))
|
||||||
|
out += "\t{{{{inc,{bits}}},{{dec,p{j}}} -> {{p{j}}}}};\n".format(bits=bits, j=j)
|
||||||
|
|
||||||
|
out += "\n\t# the more significant bits remain (inc)\n"
|
||||||
|
for j in range(n):
|
||||||
|
for k in range(j + 1, n):
|
||||||
|
out += "\t{{{{inc,p{k}}},{{dec,p{j}}} -> {{p{k}}}}};\n".format(j=j, k=k)
|
||||||
|
|
||||||
|
# (3) decrement operation
|
||||||
|
out += "\n\t# (3) decrement operation\n"
|
||||||
|
for j in range(n):
|
||||||
|
bits = ",".join("p" + str(k) for k in range(j + 1))
|
||||||
|
out += "\t{{{{dec}},{{inc,{bits}}} -> {{p{j}}}}};\n".format(bits=bits, j=j)
|
||||||
|
|
||||||
|
out += "\n\t# the more significant bits remain (dec)\n"
|
||||||
|
for j in range(n):
|
||||||
|
for k in range(j + 1, n):
|
||||||
|
out += "\t{{{{dec,p{j},p{k}}},{{inc}} -> {{p{k}}}}};\n".format(j=j, k=k)
|
||||||
|
|
||||||
|
out += "}\n\n"
|
||||||
|
out += "context-entities { inc,dec }\n"
|
||||||
|
out += "initial-contexts { {} }\n"
|
||||||
|
|
||||||
|
if prop == 1:
|
||||||
|
all_neg = " AND ".join("~p" + str(i) for i in range(n))
|
||||||
|
all_pos = " AND ".join("p" + str(i) for i in range(n))
|
||||||
|
out += "rsctl-property {{ AG(({}) IMPLIES E[{{inc}},{{dec}}]F({})) }}\n".format(
|
||||||
|
all_neg, all_pos)
|
||||||
|
elif prop == 2:
|
||||||
|
all_pos = " AND ".join("p" + str(i) for i in range(n))
|
||||||
|
all_neg = " AND ".join("~p" + str(i) for i in range(n))
|
||||||
|
out += "rsctl-property {{ AG(({}) IMPLIES A[{{inc}}]X({})) }}\n".format(
|
||||||
|
all_pos, all_neg)
|
||||||
|
elif prop == 3:
|
||||||
|
parts = ["p" + str(i) for i in range(n - K)]
|
||||||
|
parts += ["~p" + str(i) for i in range(n - K, n)]
|
||||||
|
out += "rsctl-property {{ E[{{inc}}]F({}) }}\n".format(" AND ".join(parts))
|
||||||
|
elif prop == 4:
|
||||||
|
out += "rsctl-property {{ AG( p{} IMPLIES EF ~p{} ) }}\n".format(n - 1, n - 1)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument("n", type=int, help="number of bits")
|
||||||
|
parser.add_argument("property", type=int, choices=[1, 2, 3, 4],
|
||||||
|
help="property to generate (1-4)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.property == 3 and args.n < K + 1:
|
||||||
|
parser.error("n must be >= {} for property 3".format(K + 1))
|
||||||
|
|
||||||
|
print(generate(args.n, args.property))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
71
examples/bdd/generators/old_syntax/gen_mutex.py
Normal file
71
examples/bdd/generators/old_syntax/gen_mutex.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generator for the Mutual Exclusion (Mutex) benchmark.
|
||||||
|
|
||||||
|
Produces a reaction system modelling N processes competing for
|
||||||
|
exclusive access to a critical section, using activation signals,
|
||||||
|
request tokens, and a lock. Generates one of three RSCTL properties.
|
||||||
|
|
||||||
|
NOTE: generates old-syntax input (context-entities, initial-contexts,
|
||||||
|
rsctl-property) which is not compatible with the current parser.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
def generate(n, formula):
|
||||||
|
out = "reactions {\n"
|
||||||
|
for i in range(n):
|
||||||
|
out += "\t{{{{out{i},act{i}}},{{}} -> {{request{i}}}}};\n".format(i=i)
|
||||||
|
out += "\t{{{{out{i}}},{{act{i}}} -> {{out{i}}}}};\n".format(i=i)
|
||||||
|
|
||||||
|
for j in range(n):
|
||||||
|
if i != j:
|
||||||
|
out += "\t{{{{request{i},act{i},act{j}}},{{}} -> {{request{i}}}}};\n".format(
|
||||||
|
i=i, j=j)
|
||||||
|
|
||||||
|
out += "\t{{{{request{i}}},{{act{i}}} -> {{request{i}}}}};\n".format(i=i)
|
||||||
|
|
||||||
|
other_acts = ",".join("act" + str(j) for j in range(n) if i != j)
|
||||||
|
out += "\t{{{{request{i},act{i}}},{{{others},lock}} -> {{in{i},lock}}}};\n".format(
|
||||||
|
i=i, others=other_acts)
|
||||||
|
|
||||||
|
out += "\t{{{{in{i},act{i}}},{{}} -> {{out{i},done}}}};\n".format(i=i)
|
||||||
|
out += "\t{{{{in{i}}},{{act{i}}} -> {{in{i}}}}};\n".format(i=i)
|
||||||
|
|
||||||
|
out += "\t{{lock},{done} -> {lock}};\n"
|
||||||
|
out += "}\n"
|
||||||
|
|
||||||
|
ctx_ents = ",".join("act" + str(i) for i in range(n))
|
||||||
|
out += "context-entities {{ {} }}\n".format(ctx_ents)
|
||||||
|
|
||||||
|
init_ents = ",".join("out" + str(i) for i in range(n))
|
||||||
|
out += "initial-contexts {{ {{{}}} }}\n".format(init_ents)
|
||||||
|
|
||||||
|
if formula == 1:
|
||||||
|
out += "rsctl-property { A[{act1}]F(in1) }\n"
|
||||||
|
elif formula == 2:
|
||||||
|
out += "rsctl-property { E[{act1}]F(in1) }\n"
|
||||||
|
elif formula == 3:
|
||||||
|
pairs = []
|
||||||
|
for i in range(n):
|
||||||
|
for j in range(i + 1, n):
|
||||||
|
pairs.append("~(in{} AND in{})".format(i, j))
|
||||||
|
out += "rsctl-property {{ AG({}) }}\n".format(" AND ".join(pairs))
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser.add_argument("n", type=int, help="number of processes")
|
||||||
|
parser.add_argument("formula", type=int, choices=[1, 2, 3],
|
||||||
|
help="formula to generate (1: A[]F, 2: E[]F, 3: AG mutex)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
print(generate(args.n, args.formula))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
70
examples/bdd/tgc4.drs
Normal file
70
examples/bdd/tgc4.drs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
options { use-context-automaton; make-progressive; };
|
||||||
|
reactions {
|
||||||
|
|
||||||
|
proc0 {
|
||||||
|
{{out}, {} -> {approach}};
|
||||||
|
{{approach}, {req} -> {req}};
|
||||||
|
{{allowed}, {} -> {in}};
|
||||||
|
{{in}, {} -> {out,leave}};
|
||||||
|
{{req}, {in} -> {req}};
|
||||||
|
};
|
||||||
|
|
||||||
|
proc1 {
|
||||||
|
{{out}, {} -> {approach}};
|
||||||
|
{{approach}, {req} -> {req}};
|
||||||
|
{{allowed}, {} -> {in}};
|
||||||
|
{{in}, {} -> {out,leave}};
|
||||||
|
{{req}, {in} -> {req}};
|
||||||
|
};
|
||||||
|
|
||||||
|
proc2 {
|
||||||
|
{{out}, {} -> {approach}};
|
||||||
|
{{approach}, {req} -> {req}};
|
||||||
|
{{allowed}, {} -> {in}};
|
||||||
|
{{in}, {} -> {out,leave}};
|
||||||
|
{{req}, {in} -> {req}};
|
||||||
|
};
|
||||||
|
|
||||||
|
proc3 {
|
||||||
|
{{out}, {} -> {approach}};
|
||||||
|
{{approach}, {req} -> {req}};
|
||||||
|
{{allowed}, {} -> {in}};
|
||||||
|
{{in}, {} -> {out,leave}};
|
||||||
|
{{req}, {in} -> {req}};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
context-automaton {
|
||||||
|
states { init, green, red };
|
||||||
|
init-state { init };
|
||||||
|
transitions {
|
||||||
|
{ proc0={out} proc1={out} proc2={out} proc3={out} }: init -> green;
|
||||||
|
{ proc0={allowed} }: green -> red : proc0.req;
|
||||||
|
{ proc1={allowed} }: green -> red : proc1.req;
|
||||||
|
{ proc2={allowed} }: green -> red : proc2.req;
|
||||||
|
{ proc3={allowed} }: green -> red : proc3.req;
|
||||||
|
{ proc0={} }: green -> green : ~proc0.req AND ~proc1.req AND ~proc2.req AND ~proc3.req;
|
||||||
|
{ proc1={} }: green -> green : ~proc0.req AND ~proc1.req AND ~proc2.req AND ~proc3.req;
|
||||||
|
{ proc2={} }: green -> green : ~proc0.req AND ~proc1.req AND ~proc2.req AND ~proc3.req;
|
||||||
|
{ proc3={} }: green -> green : ~proc0.req AND ~proc1.req AND ~proc2.req AND ~proc3.req;
|
||||||
|
{ proc0={} }: red -> green : proc0.leave;
|
||||||
|
{ proc1={} }: red -> green : proc1.leave;
|
||||||
|
{ proc2={} }: red -> green : proc2.leave;
|
||||||
|
{ proc3={} }: red -> green : proc3.leave;
|
||||||
|
{ proc0={} }: red -> red : ~proc0.leave AND ~proc1.leave AND ~proc2.leave AND ~proc3.leave;
|
||||||
|
{ proc1={} }: red -> red : ~proc0.leave AND ~proc1.leave AND ~proc2.leave AND ~proc3.leave;
|
||||||
|
{ proc2={} }: red -> red : ~proc0.leave AND ~proc1.leave AND ~proc2.leave AND ~proc3.leave;
|
||||||
|
{ proc3={} }: red -> red : ~proc0.leave AND ~proc1.leave AND ~proc2.leave AND ~proc3.leave;
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
rsctlk-property { f1 : EF( E<proc0.allowed>X( proc0.in ) ) AND EF( E<proc1.allowed>X( proc1.in ) ) AND EF( E<proc2.allowed>X( proc2.in ) ) AND EF( E<proc3.allowed>X( proc3.in ) ) };
|
||||||
|
|
||||||
|
rsctlk-property { f2 : EF( proc0.approach AND proc1.approach AND proc2.approach AND proc3.approach ) };
|
||||||
|
|
||||||
|
rsctlk-property { f3 : AG( proc0.in IMPLIES K[proc0](~proc1.in AND ~proc2.in AND ~proc3.in) ) };
|
||||||
|
|
||||||
|
rsctlk-property { f4 : AG( proc0.in IMPLIES C[proc0,proc1,proc2,proc3](~proc1.in AND ~proc2.in AND ~proc3.in) ) };
|
||||||
|
|
||||||
4
examples/smt/chain_reaction.py
Normal file → Executable file
4
examples/smt/chain_reaction.py
Normal file → Executable file
@@ -28,7 +28,6 @@ import resource
|
|||||||
|
|
||||||
|
|
||||||
def chain_reaction(print_system=False):
|
def chain_reaction(print_system=False):
|
||||||
|
|
||||||
if len(sys.argv) < 1 + 3:
|
if len(sys.argv) < 1 + 3:
|
||||||
print("{source} <N> <M> <type>".format(source=sys.argv[0]))
|
print("{source} <N> <M> <type>".format(source=sys.argv[0]))
|
||||||
print()
|
print()
|
||||||
@@ -39,7 +38,7 @@ def chain_reaction(print_system=False):
|
|||||||
print()
|
print()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
chainLen = int(sys.argv[1])
|
chainLen = int(sys.argv[1])
|
||||||
maxConc = int(sys.argv[2]) # depth (max concentration)
|
maxConc = int(sys.argv[2]) # depth (max concentration)
|
||||||
|
|
||||||
verify_rsc = bool(int(sys.argv[3]))
|
verify_rsc = bool(int(sys.argv[3]))
|
||||||
@@ -115,7 +114,6 @@ def chain_reaction(print_system=False):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
chain_reaction()
|
chain_reaction()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
117
examples/smt/heat_shock_response.py
Normal file → Executable file
117
examples/smt/heat_shock_response.py
Normal file → Executable file
@@ -28,8 +28,7 @@ import resource
|
|||||||
|
|
||||||
|
|
||||||
def heat_shock_response(print_system=True, verify_rsc=True):
|
def heat_shock_response(print_system=True, verify_rsc=True):
|
||||||
|
if len(sys.argv) < 1 + 1:
|
||||||
if len(sys.argv) < 1+1:
|
|
||||||
print("{source} <type>".format(source=sys.argv[0]))
|
print("{source} <type>".format(source=sys.argv[0]))
|
||||||
print("type:")
|
print("type:")
|
||||||
print(" - 1 -- RSC")
|
print(" - 1 -- RSC")
|
||||||
@@ -37,72 +36,80 @@ def heat_shock_response(print_system=True, verify_rsc=True):
|
|||||||
print()
|
print()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
verify_rsc=bool(int(sys.argv[1]))
|
verify_rsc = bool(int(sys.argv[1]))
|
||||||
|
|
||||||
stress_temp = 42
|
stress_temp = 42
|
||||||
max_temp = 50
|
max_temp = 50
|
||||||
|
|
||||||
r = ReactionSystemWithConcentrations()
|
|
||||||
r.add_bg_set_entity(("hsp",1))
|
|
||||||
r.add_bg_set_entity(("hsf",1))
|
|
||||||
r.add_bg_set_entity(("hsf2",1))
|
|
||||||
r.add_bg_set_entity(("hsf3",1))
|
|
||||||
r.add_bg_set_entity(("hse",1))
|
|
||||||
r.add_bg_set_entity(("mfp",1))
|
|
||||||
r.add_bg_set_entity(("prot",1))
|
|
||||||
r.add_bg_set_entity(("hsf3:hse",1))
|
|
||||||
r.add_bg_set_entity(("hsp:mfp",1))
|
|
||||||
r.add_bg_set_entity(("hsp:hsf",1))
|
|
||||||
r.add_bg_set_entity(("temp",max_temp))
|
|
||||||
r.add_bg_set_entity(("heat",1))
|
|
||||||
r.add_bg_set_entity(("cool",1))
|
|
||||||
|
|
||||||
r.add_reaction([("hsf",1)], [("hsp",1)], [("hsf3",1)])
|
|
||||||
r.add_reaction([("hsf",1),("hsp",1),("mfp",1)], [], [("hsf3",1)])
|
|
||||||
r.add_reaction([("hsf3",1)], [("hse",1),("hsp",1)],[("hsf",1)])
|
|
||||||
r.add_reaction([("hsf3",1),("hsp",1),("mfp",1)], [("hse",1)], [("hsf",1)])
|
|
||||||
r.add_reaction([("hsf3",1),("hse",1)], [("hsp",1)], [("hsf3:hse",1)])
|
|
||||||
r.add_reaction([("hsp",1),("hsf3",1),("mfp",1),("hse",1)],[], [("hsf3:hse",1)])
|
|
||||||
r.add_reaction([("hse",1)], [("hsf3",1)], [("hse",1)])
|
|
||||||
r.add_reaction([("hsp",1),("hsf3",1),("hse",1)], [("mfp",1)], [("hse",1)])
|
|
||||||
r.add_reaction([("hsf3:hse",1)], [("hsp",1)], [("hsp",1),("hsf3:hse",1)])
|
|
||||||
r.add_reaction([("hsp",1),("mfp",1),("hsf3:hse",1)],[], [("hsp",1),("hsf3:hse",1)])
|
|
||||||
r.add_reaction([("hsf",1),("hsp",1)], [("mfp",1)], [("hsp:hsf",1)])
|
|
||||||
r.add_reaction([("hsp:hsf",1),("temp",stress_temp)],[], [("hsf",1),("hsp",1)])
|
|
||||||
r.add_reaction([("hsp:hsf",1)], [("temp",stress_temp)],[("hsp:hsf",1)])
|
|
||||||
r.add_reaction([("hsp",1),("hsf3:hse",1)], [("mfp",1)], [("hse",1),("hsp:hsf",1)])
|
|
||||||
r.add_reaction([("temp",stress_temp),("prot",1)], [], [("mfp",1),("prot",1)])
|
|
||||||
r.add_reaction([("prot",1)], [("temp",stress_temp)], [("prot",1)])
|
|
||||||
r.add_reaction([("hsp",1),("mfp",1)], [], [("hsp:mfp",1)])
|
|
||||||
r.add_reaction([("mfp",1)], [("hsp",1)], [("mfp",1)])
|
|
||||||
r.add_reaction([("hsp:mfp",1)], [], [("hsp",1),("prot",1)])
|
|
||||||
|
|
||||||
r.add_reaction_inc("temp", "heat", [("temp",1)],[("temp",max_temp)])
|
r = ReactionSystemWithConcentrations()
|
||||||
r.add_reaction_dec("temp", "cool", [("temp",1)],[])
|
r.add_bg_set_entity(("hsp", 1))
|
||||||
|
r.add_bg_set_entity(("hsf", 1))
|
||||||
|
r.add_bg_set_entity(("hsf2", 1))
|
||||||
|
r.add_bg_set_entity(("hsf3", 1))
|
||||||
|
r.add_bg_set_entity(("hse", 1))
|
||||||
|
r.add_bg_set_entity(("mfp", 1))
|
||||||
|
r.add_bg_set_entity(("prot", 1))
|
||||||
|
r.add_bg_set_entity(("hsf3:hse", 1))
|
||||||
|
r.add_bg_set_entity(("hsp:mfp", 1))
|
||||||
|
r.add_bg_set_entity(("hsp:hsf", 1))
|
||||||
|
r.add_bg_set_entity(("temp", max_temp))
|
||||||
|
r.add_bg_set_entity(("heat", 1))
|
||||||
|
r.add_bg_set_entity(("cool", 1))
|
||||||
|
|
||||||
r.add_permanency("temp",[("heat",1),("cool",1)])
|
r.add_reaction([("hsf", 1)], [("hsp", 1)], [("hsf3", 1)])
|
||||||
|
r.add_reaction([("hsf", 1), ("hsp", 1), ("mfp", 1)], [], [("hsf3", 1)])
|
||||||
|
r.add_reaction([("hsf3", 1)], [("hse", 1), ("hsp", 1)], [("hsf", 1)])
|
||||||
|
r.add_reaction([("hsf3", 1), ("hsp", 1), ("mfp", 1)], [("hse", 1)], [("hsf", 1)])
|
||||||
|
r.add_reaction([("hsf3", 1), ("hse", 1)], [("hsp", 1)], [("hsf3:hse", 1)])
|
||||||
|
r.add_reaction(
|
||||||
|
[("hsp", 1), ("hsf3", 1), ("mfp", 1), ("hse", 1)], [], [("hsf3:hse", 1)]
|
||||||
|
)
|
||||||
|
r.add_reaction([("hse", 1)], [("hsf3", 1)], [("hse", 1)])
|
||||||
|
r.add_reaction([("hsp", 1), ("hsf3", 1), ("hse", 1)], [("mfp", 1)], [("hse", 1)])
|
||||||
|
r.add_reaction([("hsf3:hse", 1)], [("hsp", 1)], [("hsp", 1), ("hsf3:hse", 1)])
|
||||||
|
r.add_reaction(
|
||||||
|
[("hsp", 1), ("mfp", 1), ("hsf3:hse", 1)], [], [("hsp", 1), ("hsf3:hse", 1)]
|
||||||
|
)
|
||||||
|
r.add_reaction([("hsf", 1), ("hsp", 1)], [("mfp", 1)], [("hsp:hsf", 1)])
|
||||||
|
r.add_reaction(
|
||||||
|
[("hsp:hsf", 1), ("temp", stress_temp)], [], [("hsf", 1), ("hsp", 1)]
|
||||||
|
)
|
||||||
|
r.add_reaction([("hsp:hsf", 1)], [("temp", stress_temp)], [("hsp:hsf", 1)])
|
||||||
|
r.add_reaction(
|
||||||
|
[("hsp", 1), ("hsf3:hse", 1)], [("mfp", 1)], [("hse", 1), ("hsp:hsf", 1)]
|
||||||
|
)
|
||||||
|
r.add_reaction([("temp", stress_temp), ("prot", 1)], [], [("mfp", 1), ("prot", 1)])
|
||||||
|
r.add_reaction([("prot", 1)], [("temp", stress_temp)], [("prot", 1)])
|
||||||
|
r.add_reaction([("hsp", 1), ("mfp", 1)], [], [("hsp:mfp", 1)])
|
||||||
|
r.add_reaction([("mfp", 1)], [("hsp", 1)], [("mfp", 1)])
|
||||||
|
r.add_reaction([("hsp:mfp", 1)], [], [("hsp", 1), ("prot", 1)])
|
||||||
|
|
||||||
|
r.add_reaction_inc("temp", "heat", [("temp", 1)], [("temp", max_temp)])
|
||||||
|
r.add_reaction_dec("temp", "cool", [("temp", 1)], [])
|
||||||
|
|
||||||
|
r.add_permanency("temp", [("heat", 1), ("cool", 1)])
|
||||||
|
|
||||||
c = ContextAutomatonWithConcentrations(r)
|
c = ContextAutomatonWithConcentrations(r)
|
||||||
c.add_init_state("0")
|
c.add_init_state("0")
|
||||||
c.add_state("1")
|
c.add_state("1")
|
||||||
c.add_transition("0", [("hsf",1),("prot",1),("hse",1),("temp",35)], "1")
|
c.add_transition("0", [("hsf", 1), ("prot", 1), ("hse", 1), ("temp", 35)], "1")
|
||||||
c.add_transition("1", [("cool",1)], "1")
|
c.add_transition("1", [("cool", 1)], "1")
|
||||||
c.add_transition("1", [("heat",1)], "1")
|
c.add_transition("1", [("heat", 1)], "1")
|
||||||
c.add_transition("1", [], "1")
|
c.add_transition("1", [], "1")
|
||||||
|
|
||||||
rc = ReactionSystemWithAutomaton(r,c)
|
rc = ReactionSystemWithAutomaton(r, c)
|
||||||
|
|
||||||
if print_system:
|
if print_system:
|
||||||
rc.show()
|
rc.show()
|
||||||
|
|
||||||
prop_req = [ ("mfp",1) ]
|
prop_req = [("mfp", 1)]
|
||||||
prop_block = [ ]
|
prop_block = []
|
||||||
prop = (prop_req,prop_block)
|
prop = (prop_req, prop_block)
|
||||||
rs_prop = (state_translate_rsc2rs(prop_req),state_translate_rsc2rs(prop_block))
|
rs_prop = (state_translate_rsc2rs(prop_req), state_translate_rsc2rs(prop_block))
|
||||||
|
|
||||||
if verify_rsc:
|
if verify_rsc:
|
||||||
smt_rsc = SmtCheckerRSC(rc)
|
smt_rsc = SmtCheckerRSC(rc)
|
||||||
smt_rsc.check_reachability(prop,max_level=40)
|
smt_rsc.check_reachability(prop, max_level=40)
|
||||||
else:
|
else:
|
||||||
orc = rc.get_ordinary_reaction_system_with_automaton()
|
orc = rc.get_ordinary_reaction_system_with_automaton()
|
||||||
if print_system:
|
if print_system:
|
||||||
@@ -117,10 +124,10 @@ def state_translate_rsc2rs(p):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
heat_shock_response()
|
heat_shock_response()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
17
examples/smt/mutex_param.py
Normal file → Executable file
17
examples/smt/mutex_param.py
Normal file → Executable file
@@ -42,7 +42,7 @@ def powerset(iterable, N=None):
|
|||||||
def mutex_param_bench(cmd_args):
|
def mutex_param_bench(cmd_args):
|
||||||
"""
|
"""
|
||||||
Mutex Benchmark
|
Mutex Benchmark
|
||||||
|
|
||||||
Parametric
|
Parametric
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -77,7 +77,6 @@ def mutex_param_bench(cmd_args):
|
|||||||
Inhib = [("s", 1)]
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
for i in range(n_proc):
|
for i in range(n_proc):
|
||||||
|
|
||||||
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
@@ -189,7 +188,7 @@ def mutex_param_bench(cmd_args):
|
|||||||
def mutex_nonparam_bench(cmd_args):
|
def mutex_nonparam_bench(cmd_args):
|
||||||
"""
|
"""
|
||||||
Mutex Benchmark
|
Mutex Benchmark
|
||||||
|
|
||||||
Parametric
|
Parametric
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -217,7 +216,6 @@ def mutex_nonparam_bench(cmd_args):
|
|||||||
Inhib = [("s", 1)]
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
for i in range(n_proc):
|
for i in range(n_proc):
|
||||||
|
|
||||||
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
@@ -297,7 +295,7 @@ def mutex_nonparam_bench(cmd_args):
|
|||||||
def mutex_nonparam_bench_oldimpl(cmd_args):
|
def mutex_nonparam_bench_oldimpl(cmd_args):
|
||||||
"""
|
"""
|
||||||
Mutex Benchmark
|
Mutex Benchmark
|
||||||
|
|
||||||
Parametric
|
Parametric
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -325,7 +323,6 @@ def mutex_nonparam_bench_oldimpl(cmd_args):
|
|||||||
Inhib = [("s", 1)]
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
for i in range(n_proc):
|
for i in range(n_proc):
|
||||||
|
|
||||||
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
@@ -407,7 +404,6 @@ def state_translate_rsc2rs(p):
|
|||||||
|
|
||||||
|
|
||||||
def mutex_bench_main(cmd_args):
|
def mutex_bench_main(cmd_args):
|
||||||
|
|
||||||
mode = cmd_args.mode
|
mode = cmd_args.mode
|
||||||
|
|
||||||
if mode == "p":
|
if mode == "p":
|
||||||
@@ -422,17 +418,16 @@ def mutex_bench_main(cmd_args):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"scaling",
|
"scaling",
|
||||||
help="scaling parameter value",
|
help="scaling parameter value",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"mode",
|
"mode",
|
||||||
choices=['p', 'np-p', 'np-np'],
|
choices=["p", "np-p", "np-np"],
|
||||||
help="Selects the mode: p - parameter synthesis (parametric implementation), np-p - non-parametric with parametric implementation (with the parameters substituted), np-np - non-parametric with non-parametric implementation (parameters substituted)",
|
help="Selects the mode: p - parameter synthesis (parametric implementation), np-p - non-parametric with parametric implementation (with the parameters substituted), np-np - non-parametric with non-parametric implementation (parameters substituted)",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -447,7 +442,7 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
mutex_bench_main(args)
|
mutex_bench_main(args)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
150
examples/smt/scalable_chain.py
Normal file → Executable file
150
examples/smt/scalable_chain.py
Normal file → Executable file
@@ -31,76 +31,102 @@ from itertools import chain, combinations
|
|||||||
import sys
|
import sys
|
||||||
import resource
|
import resource
|
||||||
|
|
||||||
|
|
||||||
def generate_system(chainLen, maxConc):
|
def generate_system(chainLen, maxConc):
|
||||||
"""
|
"""
|
||||||
This function generates the reaction system with concentrations
|
This function generates the reaction system with concentrations
|
||||||
for the scalable chain benchmark
|
for the scalable chain benchmark
|
||||||
|
|
||||||
chainLen is the length of the chain
|
chainLen is the length of the chain
|
||||||
maxConc is the maximal concentration
|
maxConc is the maximal concentration
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = ReactionSystemWithConcentrations()
|
|
||||||
r.add_bg_set_entity(("inc",1))
|
|
||||||
r.add_bg_set_entity(("dec",1))
|
|
||||||
|
|
||||||
for i in range(1,chainLen+1):
|
|
||||||
r.add_bg_set_entity(("e_" + str(i),maxConc))
|
|
||||||
|
|
||||||
for i in range(1,chainLen+1):
|
|
||||||
ent = "e_" + str(i)
|
|
||||||
r.add_reaction_inc(ent, "inc", [(ent, 1)],[(ent,maxConc)])
|
|
||||||
r.add_reaction_dec(ent, "dec", [(ent, 1)],[])
|
|
||||||
if i < chainLen:
|
|
||||||
r.add_reaction([(ent,maxConc)],[],[("e_"+str(i+1),1)])
|
|
||||||
|
|
||||||
r.add_reaction([("e_" + str(chainLen),maxConc)],[("dec",1)],[("e_" + str(chainLen),maxConc)])
|
r = ReactionSystemWithConcentrations()
|
||||||
|
r.add_bg_set_entity(("inc", 1))
|
||||||
|
r.add_bg_set_entity(("dec", 1))
|
||||||
|
|
||||||
|
for i in range(1, chainLen + 1):
|
||||||
|
r.add_bg_set_entity(("e_" + str(i), maxConc))
|
||||||
|
|
||||||
|
for i in range(1, chainLen + 1):
|
||||||
|
ent = "e_" + str(i)
|
||||||
|
r.add_reaction_inc(ent, "inc", [(ent, 1)], [(ent, maxConc)])
|
||||||
|
r.add_reaction_dec(ent, "dec", [(ent, 1)], [])
|
||||||
|
if i < chainLen:
|
||||||
|
r.add_reaction([(ent, maxConc)], [], [("e_" + str(i + 1), 1)])
|
||||||
|
|
||||||
|
r.add_reaction(
|
||||||
|
[("e_" + str(chainLen), maxConc)],
|
||||||
|
[("dec", 1)],
|
||||||
|
[("e_" + str(chainLen), maxConc)],
|
||||||
|
)
|
||||||
|
|
||||||
c = ContextAutomatonWithConcentrations(r)
|
c = ContextAutomatonWithConcentrations(r)
|
||||||
c.add_init_state("init")
|
c.add_init_state("init")
|
||||||
c.add_state("working")
|
c.add_state("working")
|
||||||
c.add_transition("init", [("e_1",1),("inc",1)], "working")
|
c.add_transition("init", [("e_1", 1), ("inc", 1)], "working")
|
||||||
c.add_transition("working", [("inc",1)], "working")
|
c.add_transition("working", [("inc", 1)], "working")
|
||||||
|
|
||||||
rc = ReactionSystemWithAutomaton(r,c)
|
rc = ReactionSystemWithAutomaton(r, c)
|
||||||
|
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
|
||||||
def generate_formula(formula_number, chainLen, maxConc):
|
def generate_formula(formula_number, chainLen, maxConc):
|
||||||
"""
|
"""
|
||||||
This function generates the rsLTL formula
|
This function generates the rsLTL formula
|
||||||
corresponding to the formula_number parameter
|
corresponding to the formula_number parameter
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if formula_number == 1:
|
if formula_number == 1:
|
||||||
ret = Formula_rsLTL.f_F( BagDescription.f_entity("inc") > 0, (BagDescription.f_entity('e_'+str(chainLen)) >= maxConc) )
|
ret = Formula_rsLTL.f_F(
|
||||||
|
BagDescription.f_entity("inc") > 0,
|
||||||
|
(BagDescription.f_entity("e_" + str(chainLen)) >= maxConc),
|
||||||
|
)
|
||||||
|
|
||||||
elif formula_number == 2:
|
elif formula_number == 2:
|
||||||
f_tmp = Formula_rsLTL.f_F( BagDescription.f_entity("inc") > 0, (BagDescription.f_entity('e_'+str(chainLen)) == maxConc) )
|
f_tmp = Formula_rsLTL.f_F(
|
||||||
for i in range(chainLen-1,0,-1):
|
BagDescription.f_entity("inc") > 0,
|
||||||
f_tmp = Formula_rsLTL.f_F( BagDescription.f_entity("inc") > 0, f_tmp & (BagDescription.f_entity('e_'+str(i)) == maxConc) )
|
(BagDescription.f_entity("e_" + str(chainLen)) == maxConc),
|
||||||
|
)
|
||||||
|
for i in range(chainLen - 1, 0, -1):
|
||||||
|
f_tmp = Formula_rsLTL.f_F(
|
||||||
|
BagDescription.f_entity("inc") > 0,
|
||||||
|
f_tmp & (BagDescription.f_entity("e_" + str(i)) == maxConc),
|
||||||
|
)
|
||||||
ret = f_tmp
|
ret = f_tmp
|
||||||
|
|
||||||
elif formula_number == 3:
|
elif formula_number == 3:
|
||||||
ret = Formula_rsLTL.f_G( BagDescription.f_TRUE(),
|
ret = Formula_rsLTL.f_G(
|
||||||
|
BagDescription.f_TRUE(),
|
||||||
Formula_rsLTL.f_Implies(
|
Formula_rsLTL.f_Implies(
|
||||||
(BagDescription.f_entity('e_1') == 1),
|
(BagDescription.f_entity("e_1") == 1),
|
||||||
Formula_rsLTL.f_F(
|
Formula_rsLTL.f_F(
|
||||||
BagDescription.f_entity("inc") > 0,
|
BagDescription.f_entity("inc") > 0,
|
||||||
(BagDescription.f_entity('e_'+str(chainLen)) == maxConc)
|
(BagDescription.f_entity("e_" + str(chainLen)) == maxConc),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif formula_number == 4:
|
elif formula_number == 4:
|
||||||
ret = Formula_rsLTL.f_F( BagDescription.f_entity("inc") > 0 , BagDescription.f_entity('e_1') == maxConc )
|
ret = Formula_rsLTL.f_F(
|
||||||
|
BagDescription.f_entity("inc") > 0,
|
||||||
|
BagDescription.f_entity("e_1") == maxConc,
|
||||||
|
)
|
||||||
|
|
||||||
elif formula_number == 5:
|
elif formula_number == 5:
|
||||||
ret = Formula_rsLTL.f_X(BagDescription.f_TRUE(), Formula_rsLTL.f_U( BagDescription.f_entity("inc") > 0 , BagDescription.f_entity('e_1') > 0, BagDescription.f_entity('e_2') > 0 ) )
|
ret = Formula_rsLTL.f_X(
|
||||||
|
BagDescription.f_TRUE(),
|
||||||
|
Formula_rsLTL.f_U(
|
||||||
|
BagDescription.f_entity("inc") > 0,
|
||||||
|
BagDescription.f_entity("e_1") > 0,
|
||||||
|
BagDescription.f_entity("e_2") > 0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ret = None
|
ret = None
|
||||||
|
|
||||||
assert ret is not None, "Unknown formula"
|
assert ret is not None, "Unknown formula"
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
@@ -110,64 +136,64 @@ def save_statistics(smt_rsc, formula_number, chainLen, maxConc):
|
|||||||
"""
|
"""
|
||||||
Saves the statistics fetched from smt_rsc into files
|
Saves the statistics fetched from smt_rsc into files
|
||||||
"""
|
"""
|
||||||
time=0
|
time = 0
|
||||||
mem_usage=resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/(1024*1024)
|
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024 * 1024)
|
||||||
filename_t="bench_rsc_F" + str(formula_number) + "_time.log"
|
filename_t = "bench_rsc_F" + str(formula_number) + "_time.log"
|
||||||
filename_m="bench_rsc_F" + str(formula_number) + "_mem.log"
|
filename_m = "bench_rsc_F" + str(formula_number) + "_mem.log"
|
||||||
time=smt_rsc.get_verification_time()
|
time = smt_rsc.get_verification_time()
|
||||||
|
|
||||||
f=open(filename_t, 'a')
|
f = open(filename_t, "a")
|
||||||
log_str="(" + str(chainLen) + "," + str(maxConc) + "," + str(time) + ")\n"
|
log_str = "(" + str(chainLen) + "," + str(maxConc) + "," + str(time) + ")\n"
|
||||||
f.write(log_str)
|
f.write(log_str)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
f=open(filename_m, 'a')
|
f = open(filename_m, "a")
|
||||||
log_str="(" + str(chainLen) + "," + str(maxConc) + "," + str(mem_usage) + ")\n"
|
log_str = "(" + str(chainLen) + "," + str(maxConc) + "," + str(mem_usage) + ")\n"
|
||||||
f.write(log_str)
|
f.write(log_str)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def scalable_chain(print_system=False):
|
def scalable_chain(print_system=False):
|
||||||
"""
|
"""
|
||||||
This is the entry point for the benchmark
|
This is the entry point for the benchmark
|
||||||
"""
|
"""
|
||||||
if len(sys.argv) < 1+3:
|
if len(sys.argv) < 1 + 3:
|
||||||
print("arguments: <chainLen> <maxConc> <formulaNumber>")
|
print("arguments: <chainLen> <maxConc> <formulaNumber>")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
chainLen=int(sys.argv[1]) # chain length
|
chainLen = int(sys.argv[1]) # chain length
|
||||||
maxConc=int(sys.argv[2]) # depth (max concentration)
|
maxConc = int(sys.argv[2]) # depth (max concentration)
|
||||||
formula_number=int(sys.argv[3])
|
formula_number = int(sys.argv[3])
|
||||||
|
|
||||||
if chainLen < 1 or maxConc < 1:
|
if chainLen < 1 or maxConc < 1:
|
||||||
print("be reasonable")
|
print("be reasonable")
|
||||||
exit(1)
|
exit(1)
|
||||||
if not formula_number in range(1,5+1):
|
if not formula_number in range(1, 5 + 1):
|
||||||
print("formulaNumber must be in 1..5")
|
print("formulaNumber must be in 1..5")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Generate the reaction systems with concentrations
|
# Generate the reaction systems with concentrations
|
||||||
rc = generate_system(chainLen, maxConc)
|
rc = generate_system(chainLen, maxConc)
|
||||||
|
|
||||||
# Generate the formula
|
# Generate the formula
|
||||||
form = generate_formula(formula_number, chainLen, maxConc)
|
form = generate_formula(formula_number, chainLen, maxConc)
|
||||||
|
|
||||||
# Optional dump/print of the system
|
# Optional dump/print of the system
|
||||||
if print_system:
|
if print_system:
|
||||||
rc.show()
|
rc.show()
|
||||||
|
|
||||||
# Create an instance of the SMT checker for RS with concentrations
|
# Create an instance of the SMT checker for RS with concentrations
|
||||||
smt_rsc = SmtCheckerRSC(rc)
|
smt_rsc = SmtCheckerRSC(rc)
|
||||||
|
|
||||||
# Start the verification process
|
# Start the verification process
|
||||||
smt_rsc.check_rsltl(formula=form)
|
smt_rsc.check_rsltl(formula=form)
|
||||||
|
|
||||||
save_statistics(smt_rsc, formula_number, chainLen, maxConc)
|
save_statistics(smt_rsc, formula_number, chainLen, maxConc)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
scalable_chain(print_system=True)
|
scalable_chain(print_system=True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|||||||
97
experiments/drs_cell_signal/run.sh
Executable file
97
experiments/drs_cell_signal/run.sh
Executable file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
x_values="2 3 4"
|
||||||
|
y_values="`seq 2 20`"
|
||||||
|
z_values="`seq 2 20`"
|
||||||
|
aut_values="a b"
|
||||||
|
|
||||||
|
reactics="$1"
|
||||||
|
reactics_opts="-z -x -vv -B -c"
|
||||||
|
|
||||||
|
input_generator="../../examples/bdd/generators/gen_drs.py"
|
||||||
|
|
||||||
|
benchname="sig"
|
||||||
|
formname="f0"
|
||||||
|
|
||||||
|
outdir="results_${benchname}"
|
||||||
|
|
||||||
|
if [[ -z "$1" ]]
|
||||||
|
then
|
||||||
|
echo "Usage: $0 <path to reactics>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -x "$reactics" ]]
|
||||||
|
then
|
||||||
|
echo "Provided path to ReactICS not executable"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$outdir" ]]
|
||||||
|
then
|
||||||
|
echo "Creating output directory: $outdir"
|
||||||
|
mkdir -p $outdir
|
||||||
|
fi
|
||||||
|
|
||||||
|
#ulimit -t 3600
|
||||||
|
#ulimit -v 2097152
|
||||||
|
ulimit -t 3600
|
||||||
|
#ulimit -v 1000000
|
||||||
|
|
||||||
|
for a in $aut_values
|
||||||
|
do
|
||||||
|
for z in $z_values
|
||||||
|
do
|
||||||
|
for y in $y_values
|
||||||
|
do
|
||||||
|
for x in $x_values
|
||||||
|
do
|
||||||
|
|
||||||
|
if [[ $y -lt $z ]]
|
||||||
|
then
|
||||||
|
# Skip undesired values
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $y -ne $z ]]
|
||||||
|
then
|
||||||
|
# More aggressive skipping
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
bench_identifier="${benchname}_F${formname}_A${a}"
|
||||||
|
|
||||||
|
filename_base="${outdir}/${benchname}_F${formname}__x${x}_y${y}_z${z}_A${a}"
|
||||||
|
outfile="${filename_base}.out"
|
||||||
|
infile="${filename_base}.drs"
|
||||||
|
|
||||||
|
stopfile="DONE_${bench_identifier}"
|
||||||
|
|
||||||
|
if [[ -e "$stopfile" ]]
|
||||||
|
then
|
||||||
|
echo "Time limit -- SKIPPING"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
$input_generator $x $y $z $a > ${infile}
|
||||||
|
|
||||||
|
$reactics $reactics_opts $formname $infile |& tee ${outfile}
|
||||||
|
exitcode=$?
|
||||||
|
echo "ReactICS exit code: $exitcode"
|
||||||
|
|
||||||
|
result="$(tail -1 $outfile | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
||||||
|
if [ "$result" = "" ]
|
||||||
|
then
|
||||||
|
echo "TIME LIMIT; marking as finished"
|
||||||
|
#touch $stopfile
|
||||||
|
else
|
||||||
|
echo "$x ; $y ; $z ; $a ; $exitcode $result" >> $outdir/summary_${bench_identifier}.txt
|
||||||
|
echo "$x $y $z $a $(echo $result | sed 's/;/ /g')" >> $outdir/${bench_identifier}.dat
|
||||||
|
echo $result
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
# EOF
|
||||||
454
experiments/reaction_mining_mutex/pmutex.py
Executable file
454
experiments/reaction_mining_mutex/pmutex.py
Executable file
@@ -0,0 +1,454 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015-2019 Artur Meski
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
|
# copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
from rs import *
|
||||||
|
from smt import *
|
||||||
|
from logics import *
|
||||||
|
from rsltl_shortcuts import *
|
||||||
|
|
||||||
|
from itertools import chain, combinations
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import resource
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
def powerset(iterable, N=None):
|
||||||
|
if N is None:
|
||||||
|
N = len(s)
|
||||||
|
s = list(iterable)
|
||||||
|
return chain.from_iterable(combinations(s, r) for r in range(N + 1))
|
||||||
|
|
||||||
|
|
||||||
|
def mutex_param_bench(cmd_args):
|
||||||
|
"""
|
||||||
|
Mutex Benchmark
|
||||||
|
|
||||||
|
Parametric
|
||||||
|
"""
|
||||||
|
|
||||||
|
base_entities = ["out", "req", "in", "act"]
|
||||||
|
shared_entities = ["lock", "done", "s"]
|
||||||
|
|
||||||
|
if not cmd_args.scaling:
|
||||||
|
print("Missing scaling parameter")
|
||||||
|
return
|
||||||
|
n_proc = int(cmd_args.scaling)
|
||||||
|
|
||||||
|
r = ReactionSystemWithConcentrationsParam()
|
||||||
|
|
||||||
|
def E(a, b, c=1):
|
||||||
|
return (a + "_" + str(b), c)
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
for ent in base_entities:
|
||||||
|
max_conc = 1
|
||||||
|
if ent == "in":
|
||||||
|
max_conc = 3
|
||||||
|
elif ent == "req":
|
||||||
|
max_conc = 2
|
||||||
|
r.add_bg_set_entity(E(ent, i, max_conc))
|
||||||
|
|
||||||
|
for ent in shared_entities:
|
||||||
|
max_conc = 1
|
||||||
|
r.add_bg_set_entity((ent, max_conc))
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
|
for j in range(n_proc):
|
||||||
|
if i != j:
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i), E("act", i), E("act", j)], Inhib, [E("req", i)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("req", i)], [E("act", i)], [E("req", i, 2)])
|
||||||
|
|
||||||
|
enter_inhib = [E("act", j) for j in range(n_proc) if i != j] + [("lock", 1)]
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i, 2), E("act", i)], enter_inhib, [E("in", i, 3), ("lock", 1)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("in", i, 3), E("act", i)], Inhib, [E("in", i, 2)])
|
||||||
|
r.add_reaction([E("in", i, 2), E("act", i)], Inhib, [E("in", i, 1)])
|
||||||
|
|
||||||
|
r.add_reaction([E("in", i), E("act", i)], Inhib, [E("out", i), ("done", 1)])
|
||||||
|
r.add_reaction([E("in", i)], [E("act", i)], [E("in", i)])
|
||||||
|
|
||||||
|
r.add_reaction([("lock", 1)], [("done", 1)], [("lock", 1)])
|
||||||
|
|
||||||
|
lda1 = r.get_param("lda1")
|
||||||
|
lda2 = r.get_param("lda2")
|
||||||
|
lda3 = r.get_param("lda3")
|
||||||
|
|
||||||
|
r.add_reaction(lda1, lda2, lda3)
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
c = ContextAutomatonWithConcentrations(r)
|
||||||
|
c.add_init_state("0")
|
||||||
|
c.add_state("1")
|
||||||
|
|
||||||
|
init_ctx = []
|
||||||
|
for i in range(n_proc):
|
||||||
|
init_ctx.append(E("out", i))
|
||||||
|
|
||||||
|
# the experiments starts with adding x and y:
|
||||||
|
c.add_transition("0", init_ctx, "1")
|
||||||
|
|
||||||
|
all_act = powerset([E("act", i) for i in range(n_proc)], 2)
|
||||||
|
|
||||||
|
for actions in all_act:
|
||||||
|
actions = list(actions)
|
||||||
|
|
||||||
|
c.add_transition("1", actions, "1")
|
||||||
|
|
||||||
|
# for all the remaining steps we have empty context sequences
|
||||||
|
# c.add_transition("1", [], "1")
|
||||||
|
# c.add_transition("1", [("h", 1)], "1")
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
rc = ReactionSystemWithAutomaton(r, c)
|
||||||
|
rc.show()
|
||||||
|
|
||||||
|
f_attack = ltl_F(
|
||||||
|
True, bag_And(bag_entity("in_0") == 1, bag_entity("in_" + str(n_proc - 1)) == 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
ent_of_Nth_proc = [
|
||||||
|
ent + "_" + str(n_proc - 1) for ent in base_entities
|
||||||
|
] + shared_entities
|
||||||
|
disallow = ["in_" + str(n_proc - 1)]
|
||||||
|
for ent in r.background_set:
|
||||||
|
if ent not in ent_of_Nth_proc:
|
||||||
|
disallow.append(ent)
|
||||||
|
|
||||||
|
# disallow.append("act_" + str(n_proc-1))
|
||||||
|
|
||||||
|
# disallow = ["in_0", "in_" + str(n_proc)] #, "req_0", "req_1"]
|
||||||
|
lda1_disallow = [param_entity(lda1, ent) == 0 for ent in disallow]
|
||||||
|
lda2_disallow = [param_entity(lda2, ent) == 0 for ent in disallow]
|
||||||
|
lda3_disallow = [param_entity(lda3, ent) == 0 for ent in disallow]
|
||||||
|
lda_disallow = lda1_disallow + lda2_disallow + lda3_disallow
|
||||||
|
|
||||||
|
# for bent in base_entities:
|
||||||
|
# print(param_entity(lda3, bent + "_0"))
|
||||||
|
|
||||||
|
param_constr = param_And(*lda_disallow)
|
||||||
|
|
||||||
|
smt_rsc = SmtCheckerRSCParam(rc, optimise=cmd_args.optimise)
|
||||||
|
smt_rsc.check_rsltl(
|
||||||
|
formulae_list=[f_attack], param_constr=param_constr
|
||||||
|
) # , max_level=4, cont_if_sat=True)
|
||||||
|
|
||||||
|
log_suffix = ""
|
||||||
|
if cmd_args.optimise:
|
||||||
|
log_suffix = "_OPT"
|
||||||
|
|
||||||
|
time = 0
|
||||||
|
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024 * 1024)
|
||||||
|
filename_t = "bench_mutex_param" + log_suffix + "_time.dat"
|
||||||
|
filename_m = "bench_mutex_param" + log_suffix + "_mem.dat"
|
||||||
|
time = smt_rsc.get_verification_time()
|
||||||
|
|
||||||
|
with open(filename_t, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, time)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
with open(filename_m, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, mem_usage)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
|
||||||
|
def mutex_nonparam_bench(cmd_args):
|
||||||
|
"""
|
||||||
|
Mutex Benchmark
|
||||||
|
|
||||||
|
Parametric
|
||||||
|
"""
|
||||||
|
|
||||||
|
base_entities = ["out", "req", "in", "act"]
|
||||||
|
shared_entities = ["lock", "done", "s"]
|
||||||
|
|
||||||
|
if not cmd_args.scaling:
|
||||||
|
raise RuntimeError("Missing scaling parameter")
|
||||||
|
n_proc = int(cmd_args.scaling)
|
||||||
|
|
||||||
|
r = ReactionSystemWithConcentrationsParam()
|
||||||
|
|
||||||
|
def E(a, b):
|
||||||
|
return (a + "_" + str(b), 1)
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
for ent in base_entities:
|
||||||
|
r.add_bg_set_entity(E(ent, i))
|
||||||
|
|
||||||
|
for ent in shared_entities:
|
||||||
|
r.add_bg_set_entity((ent, 1))
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
|
for j in range(n_proc):
|
||||||
|
if i != j:
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i), E("act", i), E("act", j)], Inhib, [E("req", i)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("req", i)], [E("act", i)], [E("req", i)])
|
||||||
|
|
||||||
|
enter_inhib = [E("act", j) for j in range(n_proc) if i != j] + [("lock", 1)]
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i), E("act", i)], enter_inhib, [E("in", i), ("lock", 1)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("in", i), E("act", i)], Inhib, [E("out", i), ("done", 1)])
|
||||||
|
r.add_reaction([E("in", i)], [E("act", i)], [E("in", i)])
|
||||||
|
|
||||||
|
r.add_reaction([("lock", 1)], [("done", 1)], [("lock", 1)])
|
||||||
|
|
||||||
|
r.add_reaction(
|
||||||
|
[E("out", n_proc - 1)], [("s", 1)], [("done", 1), E("req", n_proc - 1)]
|
||||||
|
)
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
c = ContextAutomatonWithConcentrations(r)
|
||||||
|
c.add_init_state("0")
|
||||||
|
c.add_state("1")
|
||||||
|
|
||||||
|
init_ctx = []
|
||||||
|
for i in range(n_proc):
|
||||||
|
init_ctx.append(E("out", i))
|
||||||
|
|
||||||
|
# the experiments starts with adding x and y:
|
||||||
|
c.add_transition("0", init_ctx, "1")
|
||||||
|
|
||||||
|
all_act = powerset([E("act", i) for i in range(n_proc)], 2)
|
||||||
|
|
||||||
|
for actions in all_act:
|
||||||
|
actions = list(actions)
|
||||||
|
|
||||||
|
c.add_transition("1", actions, "1")
|
||||||
|
|
||||||
|
# for all the remaining steps we have empty context sequences
|
||||||
|
# c.add_transition("1", [], "1")
|
||||||
|
# c.add_transition("1", [("h", 1)], "1")
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
rc = ReactionSystemWithAutomaton(r, c)
|
||||||
|
rc.show()
|
||||||
|
|
||||||
|
f_attack = ltl_F(
|
||||||
|
True, bag_And(bag_entity("in_0") == 1, bag_entity("in_" + str(n_proc - 1)) == 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
smt_rsc = SmtCheckerRSCParam(rc, optimise=cmd_args.optimise)
|
||||||
|
smt_rsc.check_rsltl(formulae_list=[f_attack])
|
||||||
|
|
||||||
|
time = 0
|
||||||
|
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024 * 1024)
|
||||||
|
filename_t = "bench_mutex_nonparam_time.dat"
|
||||||
|
filename_m = "bench_mutex_nonparam_mem.dat"
|
||||||
|
time = smt_rsc.get_verification_time()
|
||||||
|
|
||||||
|
with open(filename_t, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, time)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
with open(filename_m, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, mem_usage)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
|
||||||
|
def mutex_nonparam_bench_oldimpl(cmd_args):
|
||||||
|
"""
|
||||||
|
Mutex Benchmark
|
||||||
|
|
||||||
|
Parametric
|
||||||
|
"""
|
||||||
|
|
||||||
|
base_entities = ["out", "req", "in", "act"]
|
||||||
|
shared_entities = ["lock", "done", "s"]
|
||||||
|
|
||||||
|
if not cmd_args.scaling:
|
||||||
|
raise RuntimeError("Missing scaling parameter")
|
||||||
|
n_proc = int(cmd_args.scaling)
|
||||||
|
|
||||||
|
r = ReactionSystemWithConcentrations()
|
||||||
|
|
||||||
|
def E(a, b):
|
||||||
|
return (a + "_" + str(b), 1)
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
for ent in base_entities:
|
||||||
|
r.add_bg_set_entity(E(ent, i))
|
||||||
|
|
||||||
|
for ent in shared_entities:
|
||||||
|
r.add_bg_set_entity((ent, 1))
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
Inhib = [("s", 1)]
|
||||||
|
|
||||||
|
for i in range(n_proc):
|
||||||
|
r.add_reaction([E("out", i), E("act", i)], Inhib, [E("req", i)])
|
||||||
|
r.add_reaction([E("out", i)], [E("act", i)], [E("out", i)])
|
||||||
|
|
||||||
|
for j in range(n_proc):
|
||||||
|
if i != j:
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i), E("act", i), E("act", j)], Inhib, [E("req", i)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("req", i)], [E("act", i)], [E("req", i)])
|
||||||
|
|
||||||
|
enter_inhib = [E("act", j) for j in range(n_proc) if i != j] + [("lock", 1)]
|
||||||
|
r.add_reaction(
|
||||||
|
[E("req", i), E("act", i)], enter_inhib, [E("in", i), ("lock", 1)]
|
||||||
|
)
|
||||||
|
|
||||||
|
r.add_reaction([E("in", i), E("act", i)], Inhib, [E("out", i), ("done", 1)])
|
||||||
|
r.add_reaction([E("in", i)], [E("act", i)], [E("in", i)])
|
||||||
|
|
||||||
|
r.add_reaction([("lock", 1)], [("done", 1)], [("lock", 1)])
|
||||||
|
|
||||||
|
r.add_reaction(
|
||||||
|
[E("out", n_proc - 1)], [("s", 1)], [("done", 1), E("req", n_proc - 1)]
|
||||||
|
)
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
c = ContextAutomatonWithConcentrations(r)
|
||||||
|
c.add_init_state("0")
|
||||||
|
c.add_state("1")
|
||||||
|
|
||||||
|
init_ctx = []
|
||||||
|
for i in range(n_proc):
|
||||||
|
init_ctx.append(E("out", i))
|
||||||
|
|
||||||
|
# the experiments starts with adding x and y:
|
||||||
|
c.add_transition("0", init_ctx, "1")
|
||||||
|
|
||||||
|
all_act = powerset([E("act", i) for i in range(n_proc)], 2)
|
||||||
|
|
||||||
|
for actions in all_act:
|
||||||
|
actions = list(actions)
|
||||||
|
|
||||||
|
c.add_transition("1", actions, "1")
|
||||||
|
|
||||||
|
# for all the remaining steps we have empty context sequences
|
||||||
|
# c.add_transition("1", [], "1")
|
||||||
|
# c.add_transition("1", [("h", 1)], "1")
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
rc = ReactionSystemWithAutomaton(r, c)
|
||||||
|
rc.show()
|
||||||
|
|
||||||
|
f_attack = ltl_F(
|
||||||
|
True, bag_And(bag_entity("in_0") == 1, bag_entity("in_" + str(n_proc - 1)) == 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
smt_rsc = SmtCheckerRSC(rc)
|
||||||
|
smt_rsc.check_rsltl(formula=f_attack)
|
||||||
|
|
||||||
|
time = 0
|
||||||
|
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / (1024 * 1024)
|
||||||
|
filename_t = "bench_mutex_nonparam_oldimpl_time.dat"
|
||||||
|
filename_m = "bench_mutex_nonparam_oldimpl_mem.dat"
|
||||||
|
time = smt_rsc.get_verification_time()
|
||||||
|
|
||||||
|
with open(filename_t, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, time)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
with open(filename_m, "a") as f:
|
||||||
|
log_str = "{:d} {:f}\n".format(n_proc, mem_usage)
|
||||||
|
f.write(log_str)
|
||||||
|
|
||||||
|
|
||||||
|
def state_translate_rsc2rs(p):
|
||||||
|
return [e[0] + "#" + str(e[1]) for e in p]
|
||||||
|
|
||||||
|
|
||||||
|
def mutex_bench_main(cmd_args):
|
||||||
|
mode = cmd_args.mode
|
||||||
|
|
||||||
|
if mode == "p":
|
||||||
|
mutex_param_bench(cmd_args)
|
||||||
|
elif mode == "np-p":
|
||||||
|
mutex_nonparam_bench(cmd_args)
|
||||||
|
elif mode == "np-np":
|
||||||
|
mutex_nonparam_bench_oldimpl(cmd_args)
|
||||||
|
else:
|
||||||
|
print("Unrecognised mode")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"scaling",
|
||||||
|
help="scaling parameter value",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"mode",
|
||||||
|
choices=["p", "np-p", "np-np"],
|
||||||
|
help="Selects the mode: p - parameter synthesis (parametric implementation), np-p - non-parametric with parametric implementation (with the parameters substituted), np-np - non-parametric with non-parametric implementation (parameters substituted)",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", "--verbose", help="turn verbosity on", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-o",
|
||||||
|
"--optimise",
|
||||||
|
help="minimise the parametric computation result",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
mutex_bench_main(args)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
# EOF
|
||||||
26
experiments/reaction_mining_mutex/run_mutex_param.sh
Executable file
26
experiments/reaction_mining_mutex/run_mutex_param.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# sudo systemsetup -getcomputersleep
|
||||||
|
#sudo systemsetup -setcomputersleep Never
|
||||||
|
# sudo systemsetup -setcomputersleep 1
|
||||||
|
|
||||||
|
REACTICS_SMT="../../reactics-smt"
|
||||||
|
export PYTHONPATH="$PYTHONPATH:$REACTICS_SMT"
|
||||||
|
|
||||||
|
REACTICS_SCRIPT="./pmutex.py"
|
||||||
|
|
||||||
|
for i in `seq 2 50`
|
||||||
|
do
|
||||||
|
for special_mode in "p" "np-p" "np-np"
|
||||||
|
do
|
||||||
|
echo "$i (sm=${special_mode})"
|
||||||
|
if [[ $special_mode -eq 1 ]]
|
||||||
|
then
|
||||||
|
$REACTICS_SCRIPT $i $special_mode
|
||||||
|
$REACTICS_SCRIPT -o $i $special_mode
|
||||||
|
else
|
||||||
|
$REACTICS_SCRIPT $i $special_mode
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
18
reactics
18
reactics
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2019 Artur Meski
|
# Copyright (c) 2019 Artur Meski
|
||||||
@@ -52,16 +52,24 @@ then
|
|||||||
then
|
then
|
||||||
python3 $*
|
python3 $*
|
||||||
else
|
else
|
||||||
echo "Nothing to do"
|
echo "Provide path to an example script (typically from ./examples/smt)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [[ "$mode" == "setup" ]]
|
elif [[ "$mode" == "setup" ]]
|
||||||
then
|
then
|
||||||
|
|
||||||
git pull
|
which -s gmake
|
||||||
|
if [[ $? -eq 0 ]]
|
||||||
|
then
|
||||||
|
MAKE="gmake"
|
||||||
|
else
|
||||||
|
MAKE="make"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git pull
|
||||||
cd $REACTICS_BDD
|
cd $REACTICS_BDD
|
||||||
./build_cudd.sh
|
./build_cudd.sh
|
||||||
make
|
$MAKE
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ CXXFLAGS = -std=c++14 -O3 -DPUBLIC_RELEASE -DNDEBUG #-g
|
|||||||
CXXFLAGS = -std=c++14 -O3 -DPUBLIC_RELEASE #-g
|
CXXFLAGS = -std=c++14 -O3 -DPUBLIC_RELEASE #-g
|
||||||
LDLIBS = $(CUDD_INCLUDE)
|
LDLIBS = $(CUDD_INCLUDE)
|
||||||
|
|
||||||
OBJ = rs.o ctx_aut.o symrs.o mc.o rsin_driver.o rsin_parser.o rsin_parser.lex.o formrsctlk.o stateconstr.o
|
OBJ = rs.o ctx_aut.o symrs.o mc.o rsin_driver.o rsin_parser.o rsin_parser.lex.o formrsctlk.o stateconstr.o export.o
|
||||||
|
|
||||||
all: reactics
|
all: reactics
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "ctx_aut.hh"
|
#include "ctx_aut.hh"
|
||||||
#include "rs.hh"
|
|
||||||
#include "macro.hh"
|
#include "macro.hh"
|
||||||
|
#include "rs.hh"
|
||||||
#include "stateconstr.hh"
|
#include "stateconstr.hh"
|
||||||
|
|
||||||
CtxAut::CtxAut(Options *opts, RctSys *parent_rctsys)
|
CtxAut::CtxAut(Options *opts, RctSys *parent_rctsys)
|
||||||
@@ -13,12 +13,7 @@ CtxAut::CtxAut(Options *opts, RctSys *parent_rctsys)
|
|||||||
|
|
||||||
bool CtxAut::hasState(std::string name)
|
bool CtxAut::hasState(std::string name)
|
||||||
{
|
{
|
||||||
if (states_names.find(name) == states_names.end()) {
|
return states_names.find(name) != states_names.end();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
State CtxAut::getStateID(std::string name)
|
State CtxAut::getStateID(std::string name)
|
||||||
@@ -75,11 +70,13 @@ void CtxAut::printAutomaton(void)
|
|||||||
|
|
||||||
void CtxAut::showStates(void)
|
void CtxAut::showStates(void)
|
||||||
{
|
{
|
||||||
cout << "# Context Automaton States:" << endl;
|
if (states_ids.size() > 0) {
|
||||||
cout << " = Init state: " << getStateName(init_state_id) << endl;
|
cout << "# Context Automaton States:" << endl;
|
||||||
|
cout << " = Init state: " << getStateName(init_state_id) << endl;
|
||||||
|
|
||||||
for (const auto &s : states_ids) {
|
for (const auto &s : states_ids) {
|
||||||
cout << " * " << s << endl;
|
cout << " * " << s << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +95,8 @@ void CtxAut::saveCurrentContextSet(Process proc_id)
|
|||||||
tmpEntities.clear();
|
tmpEntities.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CtxAut::addTransition(std::string srcStateName, std::string dstStateName, StateConstr *stateConstr)
|
void CtxAut::addTransition(std::string srcStateName, std::string dstStateName,
|
||||||
|
StateConstr *stateConstr)
|
||||||
{
|
{
|
||||||
VERB_L3("Saving transition");
|
VERB_L3("Saving transition");
|
||||||
|
|
||||||
@@ -115,12 +113,17 @@ void CtxAut::addTransition(std::string srcStateName, std::string dstStateName, S
|
|||||||
|
|
||||||
void CtxAut::showTransitions(void)
|
void CtxAut::showTransitions(void)
|
||||||
{
|
{
|
||||||
|
if (transitions.size() == 0) {
|
||||||
|
cout << "Empty context automaton" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cout << "# Context Automaton Transitions:" << endl;
|
cout << "# Context Automaton Transitions:" << endl;
|
||||||
|
|
||||||
for (const auto &t : transitions) {
|
for (const auto &t : transitions) {
|
||||||
cout << " * [" << getStateName(t.src_state) << " -> " << getStateName(
|
cout << " * [" << getStateName(t.src_state) << " -> "
|
||||||
t.dst_state)
|
<< getStateName(t.dst_state) << "]: { "
|
||||||
<< "]: { " << parent_rctsys->procEntitiesToStr(t.ctx) << "}";
|
<< parent_rctsys->procEntitiesToStr(t.ctx) << "}";
|
||||||
|
|
||||||
if (t.state_constr != nullptr) {
|
if (t.state_constr != nullptr) {
|
||||||
cout << " " << t.state_constr->toStr();
|
cout << " " << t.state_constr->toStr();
|
||||||
@@ -162,8 +165,8 @@ void CtxAut::makeProgressive(void)
|
|||||||
State curr_st = t.src_state;
|
State curr_st = t.src_state;
|
||||||
|
|
||||||
if (t.state_constr != nullptr) {
|
if (t.state_constr != nullptr) {
|
||||||
constrs[curr_st] = new StateConstr(
|
constrs[curr_st] =
|
||||||
STC_OR, constrs[curr_st], t.state_constr);
|
new StateConstr(STC_OR, constrs[curr_st], t.state_constr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,13 +177,11 @@ void CtxAut::makeProgressive(void)
|
|||||||
state_constr = new StateConstr(STC_NOT, constrs[getStateID(s)]);
|
state_constr = new StateConstr(STC_NOT, constrs[getStateID(s)]);
|
||||||
addTransition(s, special_loc, state_constr);
|
addTransition(s, special_loc, state_constr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addTransition(special_loc, special_loc, nullptr);
|
addTransition(special_loc, special_loc, nullptr);
|
||||||
|
|
||||||
made_progressive = true;
|
made_progressive = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** EOF **/
|
/** EOF **/
|
||||||
|
|||||||
@@ -12,10 +12,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
// #include "rs.hh"
|
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
// #include "options.hh"
|
|
||||||
// #include "stateconstr.hh"
|
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
@@ -27,6 +24,7 @@ class StateConstr;
|
|||||||
class CtxAut
|
class CtxAut
|
||||||
{
|
{
|
||||||
friend class SymRS;
|
friend class SymRS;
|
||||||
|
friend class RSExporter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CtxAut(Options *opts, RctSys *parent_rctsys);
|
CtxAut(Options *opts, RctSys *parent_rctsys);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
TMPINPUT="tmp_$RANDOM$RANDOM.rs"
|
TMPINPUT="tmp_$RANDOM$RANDOM.drs"
|
||||||
|
|
||||||
CMD="./reactics -B"
|
CMD="./reactics -B"
|
||||||
|
|
||||||
|
|||||||
913
reactics-bdd/export.cc
Normal file
913
reactics-bdd/export.cc
Normal file
@@ -0,0 +1,913 @@
|
|||||||
|
|
||||||
|
#include "export.hh"
|
||||||
|
|
||||||
|
|
||||||
|
RSExporter::RSExporter(RctSys *rs, rsin_driver *drv, std::ostream & outStream):
|
||||||
|
rs(rs), drv(drv), output(outStream) {
|
||||||
|
|
||||||
|
// Store all possible inputs (reactants and inhibitors) and outputs (products) for each process
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const auto & rr : rs->proc_reactions[proc]) {
|
||||||
|
for (const auto & e : rr.rctt)
|
||||||
|
procInputs[proc].insert(e);
|
||||||
|
|
||||||
|
for (const auto & e : rr.inhib)
|
||||||
|
procInputs[proc].insert(e);
|
||||||
|
|
||||||
|
for (const auto & e : rr.prod)
|
||||||
|
procOutputs[proc].insert(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add possible inputs from context automaton
|
||||||
|
|
||||||
|
for (const auto & trans : rs->ctx_aut->transitions) {
|
||||||
|
for (const auto & procCtx : trans.ctx) {
|
||||||
|
for (const auto & e : procCtx.second) {
|
||||||
|
procInputs[procCtx.first].insert(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportToISPL() {
|
||||||
|
exportEnvironment();
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc)
|
||||||
|
exportAgent(proc);
|
||||||
|
|
||||||
|
parseFormulas();
|
||||||
|
exportEvaluation();
|
||||||
|
exportInitStates();
|
||||||
|
exportFormulae();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironment() {
|
||||||
|
output << "Agent Environment\n\n";
|
||||||
|
|
||||||
|
exportEnvironmentVars();
|
||||||
|
exportEnvironmentActions();
|
||||||
|
exportEnvironmentProtocol();
|
||||||
|
exportEnvironmentEvolution();
|
||||||
|
|
||||||
|
output << "\nend Agent\n" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironmentVars() {
|
||||||
|
output << "Obsvars:\n"
|
||||||
|
<< indent << "mode: {init, clear, select_active_agents, activate_agents,\n"
|
||||||
|
<< indent << indent << "distribute_local, add_context, distribute_global, produce,\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << indent << indent << "collect_" << rs->processes_ids[proc]
|
||||||
|
<< "_" << rs->entities_ids[e] << ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << indent << "finalize\n" << indent << "};\n\n";
|
||||||
|
|
||||||
|
output << indent << "-- Boolean variables denoting entities available for each agent --\n\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procInputs[proc]) {
|
||||||
|
output << indent << rs->processes_ids[proc]
|
||||||
|
<< "_" << rs->entities_ids[e] << ": 0..1;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "-- Boolean variables denoting which agents are active --\n\n";
|
||||||
|
|
||||||
|
for (const string & procName : rs->processes_ids)
|
||||||
|
output << indent << "Active_" << procName << ": 0..1;\n";
|
||||||
|
|
||||||
|
output << "end Obsvars\n\n"
|
||||||
|
<< "Vars:\n\n";
|
||||||
|
|
||||||
|
output << indent << "-- Context automaton details --\n\n";
|
||||||
|
|
||||||
|
output << indent << "state: {";
|
||||||
|
|
||||||
|
for (size_t i=0; i<rs->ctx_aut->statesCount(); ++i) {
|
||||||
|
string stName = rs->ctx_aut->getStateName(i);
|
||||||
|
|
||||||
|
// Skip the dummy state used for closure
|
||||||
|
if (stName == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (i) output << ", ";
|
||||||
|
|
||||||
|
output << stName;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "};\n";
|
||||||
|
|
||||||
|
// Add dummy transition leading to the initial state (no agent is active)
|
||||||
|
output << indent << "transition: {"
|
||||||
|
<< "\n" << indent << indent << "init_0";
|
||||||
|
|
||||||
|
int trId {1};
|
||||||
|
|
||||||
|
for (const CtxAutTransition & trans : rs->ctx_aut->transitions) {
|
||||||
|
string dstName = rs->ctx_aut->getStateName(trans.dst_state);
|
||||||
|
|
||||||
|
if (dstName == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
output << ",";
|
||||||
|
output << "\n" << indent << indent << rs->ctx_aut->getStateName(trans.src_state)
|
||||||
|
<< "_" << dstName << "_" << trId;
|
||||||
|
++trId;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "\n};\n\n";
|
||||||
|
|
||||||
|
output << indent << "-- Boolean variables denoting existence of entities in the environment.\n\n";
|
||||||
|
|
||||||
|
for (const string & entityName : rs->entities_ids)
|
||||||
|
output << indent << entityName << " : 0..1;\n";
|
||||||
|
|
||||||
|
output << "end Vars" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironmentActions() {
|
||||||
|
output << "\nActions = {\n"
|
||||||
|
<< indent << "init, clear, select_active_agents, activate_agents,\n"
|
||||||
|
<< indent << "distribute_local, add_context, distribute_global, produce,\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << indent << "collect_" << rs->processes_ids[proc]
|
||||||
|
<< "_" << rs->entities_ids[e] << ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "finalize, sleep\n};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironmentProtocol() {
|
||||||
|
output << "\nProtocol:\n"
|
||||||
|
<< indent << "mode=clear : {clear};\n"
|
||||||
|
<< indent << "mode=select_active_agents : {select_active_agents};\n"
|
||||||
|
<< indent << "mode=activate_agents : {activate_agents};\n\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << indent << "mode=collect_" << rs->processes_ids[proc]
|
||||||
|
<< "_" << rs->entities_ids[e]
|
||||||
|
<< ": {collect_" << rs->processes_ids[proc]
|
||||||
|
<< "_" << rs->entities_ids[e] << "};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "mode=distribute_local : {distribute_local};\n"
|
||||||
|
<< indent << "mode=add_context : {add_context};\n"
|
||||||
|
<< indent << "mode=distribute_global : {distribute_global};\n"
|
||||||
|
<< indent << "mode=produce : {produce};\n"
|
||||||
|
<< indent << "mode=finalize : {finalize};\n\n"
|
||||||
|
<< indent << "Other : {sleep};\n"
|
||||||
|
<< "end Protocol\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironmentEvolution() {
|
||||||
|
output << "\nEvolution:\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Reset the environment state after the previous computation step.
|
||||||
|
// (reset agent activity status, availability of entities, etc.)
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Reset the environment state after the previous computation step.\n"
|
||||||
|
<< indent <<"-- (reset agent activity status, availability of entities, etc.)\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
for (const string & procName : rs->processes_ids)
|
||||||
|
output << "Active_" << procName << "=0 and ";
|
||||||
|
|
||||||
|
output << "\n" << indent << indent;
|
||||||
|
|
||||||
|
for (const string & entityName : rs->entities_ids)
|
||||||
|
output << entityName << "=0 and ";
|
||||||
|
|
||||||
|
output << "\n" << indent << indent << "mode=select_active_agents\n"
|
||||||
|
<< indent << indent << indent << "if mode=clear;\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Active agents are selected based on the current context automaton transition.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Active agents are selected based on the current context automaton transition.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
// For the dummy initial transition leading to the initial state no agent is active
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc)
|
||||||
|
output << "Active_" << rs->getProcessName(proc) << "=0 and ";
|
||||||
|
|
||||||
|
output << "mode=activate_agents\n"
|
||||||
|
<< indent << indent << "if mode=select_active_agents and transition=init_0;\n\n" << indent;
|
||||||
|
|
||||||
|
unsigned transNo = 1;
|
||||||
|
|
||||||
|
for (const CtxAutTransition & trans : rs->ctx_aut->transitions) {
|
||||||
|
vector<bool> isActive(rs->getNumberOfProcesses(), false);
|
||||||
|
|
||||||
|
string dstName = rs->ctx_aut->getStateName(trans.dst_state);
|
||||||
|
|
||||||
|
if (dstName == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto & entry : trans.ctx)
|
||||||
|
isActive[entry.first] = true;
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc)
|
||||||
|
output << "Active_" << rs->getProcessName(proc) << "="
|
||||||
|
<< (isActive[proc] ? "1" : "0")
|
||||||
|
<< " and ";
|
||||||
|
|
||||||
|
output << "mode=activate_agents\n"
|
||||||
|
<< indent << indent << "if mode=select_active_agents and transition="
|
||||||
|
<< rs->ctx_aut->getStateName(trans.src_state) << "_"
|
||||||
|
<< rs->ctx_aut->getStateName(trans.dst_state) << "_"
|
||||||
|
<< to_string(transNo) << ";\n\n" << indent;
|
||||||
|
|
||||||
|
++transNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Conduct a series of queries to active agents regarding products
|
||||||
|
// that may have been produced in the last step when they were active.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << "--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent << "-- Conduct a series of queries to active agents regarding products\n"
|
||||||
|
<< indent << "-- that may have been produced in the last step when they were active.\n"
|
||||||
|
<< indent << "--------------------------------------------------------------------------------\n\n";
|
||||||
|
|
||||||
|
vector<pair<Process, Entity>> procProducts;
|
||||||
|
|
||||||
|
for (Process proc=0; proc < rs->getNumberOfProcesses(); ++proc)
|
||||||
|
for (const Entity & e : procOutputs[proc])
|
||||||
|
procProducts.push_back(make_pair(proc, e));
|
||||||
|
|
||||||
|
output << indent << "mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts[0].first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts[0].second) << "\n"
|
||||||
|
<< indent << indent << "if mode=activate_agents;\n\n";
|
||||||
|
|
||||||
|
for (unsigned pairIdx=1; pairIdx < procProducts.size(); ++pairIdx) {
|
||||||
|
output << indent << rs->getEntityName(procProducts[pairIdx-1].second)
|
||||||
|
<< "=1 and mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts[pairIdx].first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx].second) << "\n"
|
||||||
|
<< indent << indent << "if mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts[pairIdx-1].first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx-1].second)
|
||||||
|
<< " and " << rs->getProcessName(procProducts[pairIdx-1].first)
|
||||||
|
<< ".Action=produce_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx-1].second)
|
||||||
|
<< ";\n";
|
||||||
|
|
||||||
|
output << indent << "mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts[pairIdx].first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx].second) << "\n"
|
||||||
|
<< indent << indent << "if mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts[pairIdx-1].first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx-1].second)
|
||||||
|
<< " and (" << rs->getProcessName(procProducts[pairIdx-1].first)
|
||||||
|
<< ".Action=not_produce_"
|
||||||
|
<< rs->getEntityName(procProducts[pairIdx-1].second)
|
||||||
|
<< " or " << rs->getProcessName(procProducts[pairIdx-1].first)
|
||||||
|
<< ".Action=sleep);\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << rs->getEntityName(procProducts.rbegin()->second)
|
||||||
|
<< "=1 and mode=distribute_local\n"
|
||||||
|
<< indent << indent << "if mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts.rbegin()->first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts.rbegin()->second)
|
||||||
|
<< " and " << rs->getProcessName(procProducts.rbegin()->first)
|
||||||
|
<< ".Action=produce_"
|
||||||
|
<< rs->getEntityName(procProducts.rbegin()->second)
|
||||||
|
<< ";\n";
|
||||||
|
|
||||||
|
output << indent << "mode=distribute_local\n"
|
||||||
|
<< indent << indent << "if mode=collect_"
|
||||||
|
<< rs->getProcessName(procProducts.rbegin()->first) << "_"
|
||||||
|
<< rs->getEntityName(procProducts.rbegin()->second)
|
||||||
|
<< " and (" << rs->getProcessName(procProducts.rbegin()->first)
|
||||||
|
<< ".Action=not_produce_"
|
||||||
|
<< rs->getEntityName(procProducts.rbegin()->second)
|
||||||
|
<< " or " << rs->getProcessName(procProducts.rbegin()->first)
|
||||||
|
<< ".Action=sleep);\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// The entities available in the environment are distributed between the agents.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- The entities available in the environment are distributed between the agents. \n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procInputs[proc]) {
|
||||||
|
if (!first)
|
||||||
|
output << " and ";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
output << rs->getProcessName(proc) << "_" << rs->getEntityName(e) << "=" << rs->getEntityName(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "\n" << indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "and mode=add_context\n" << indent << indent
|
||||||
|
<< "if mode=distribute_local;\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// A set of additional entities, if any, is provided for each active agent
|
||||||
|
// following the context automaton transition description.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- A set of additional entities, if any, is provided for each active agent\n"
|
||||||
|
<< indent <<"-- following the context automaton transition description.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
transNo = 1;
|
||||||
|
vector<tuple<State, State, unsigned>> noCtxTrans;
|
||||||
|
|
||||||
|
for (const CtxAutTransition & trans : rs->ctx_aut->transitions) {
|
||||||
|
if (rs->ctx_aut->getStateName(trans.dst_state) == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string ctxStr {""};
|
||||||
|
string separator {""};
|
||||||
|
first = true;
|
||||||
|
|
||||||
|
for (const auto & procCtx : trans.ctx) {
|
||||||
|
for (auto ent : procCtx.second) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
separator = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
separator = "and ";
|
||||||
|
|
||||||
|
ctxStr += separator + rs->getProcessName(procCtx.first) + "_" + rs->getEntityName(ent) + "=1 ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctxStr.length() > 0)
|
||||||
|
output << indent << ctxStr
|
||||||
|
<< "and mode=distribute_global\n" << indent << indent
|
||||||
|
<< "if mode=add_context and transition="
|
||||||
|
<< rs->ctx_aut->getStateName(trans.src_state) << "_" << rs->ctx_aut->getStateName(trans.dst_state) << "_" << transNo
|
||||||
|
<< ";\n\n";
|
||||||
|
else
|
||||||
|
noCtxTrans.push_back({trans.src_state, trans.dst_state, transNo});
|
||||||
|
|
||||||
|
++transNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Mode change for transitions having no additional entities in the context
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if (noCtxTrans.size() > 0) {
|
||||||
|
output << indent << "mode=distribute_global if mode=add_context and\n"
|
||||||
|
<< indent << indent << " (transition=init_0";
|
||||||
|
|
||||||
|
for (const auto & trans : noCtxTrans) {
|
||||||
|
output << " or transition=" << rs->ctx_aut->getStateName(get<0>(trans))
|
||||||
|
<< "_" << rs->ctx_aut->getStateName(get<1>(trans))
|
||||||
|
<< "_" << get<2>(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
output << ");\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Notify active agents to execute all possible reactions.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent << "--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Notify active agents to execute all possible reactions.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
output << "mode=produce if mode=distribute_global;\n\n";
|
||||||
|
|
||||||
|
output << indent << "mode=finalize\n"
|
||||||
|
<< indent << indent << "if mode=produce;\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Select next computation step (choose context automaton transition).
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Select next computation step (choose context automaton transition).\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n"
|
||||||
|
<< indent;
|
||||||
|
|
||||||
|
transNo = 1;
|
||||||
|
|
||||||
|
for (const CtxAutTransition & trans : rs->ctx_aut->transitions) {
|
||||||
|
if (rs->ctx_aut->getStateName(trans.dst_state) == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
output << indent << "mode=clear and state="
|
||||||
|
<< rs->ctx_aut->getStateName(trans.dst_state)
|
||||||
|
<< " and transition="
|
||||||
|
<< rs->ctx_aut->getStateName(trans.src_state) << "_"
|
||||||
|
<< rs->ctx_aut->getStateName(trans.dst_state) << "_"
|
||||||
|
<< transNo << "\n" << indent << indent;
|
||||||
|
|
||||||
|
output << "\n" << indent << indent << "if mode=finalize and state="
|
||||||
|
<< rs->ctx_aut->getStateName(trans.src_state);
|
||||||
|
|
||||||
|
if (trans.state_constr)
|
||||||
|
output << " and " << stateConstrToStr(trans.state_constr);
|
||||||
|
|
||||||
|
output << ";\n\n";
|
||||||
|
|
||||||
|
++transNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "end Evolution\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEnvironmentInitState() {
|
||||||
|
output << indent << "Environment.mode=clear\n\n";
|
||||||
|
|
||||||
|
for (const string & procName : rs->processes_ids)
|
||||||
|
output << indent << indent << "and Environment.Active_" << procName << "=0\n";
|
||||||
|
|
||||||
|
output << "\n";
|
||||||
|
|
||||||
|
for (const string & entName : rs->entities_ids)
|
||||||
|
output << indent << indent << "and Environment." << entName << "=0\n";
|
||||||
|
|
||||||
|
output << "\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
for (const Entity & e : procInputs[proc])
|
||||||
|
output << indent << indent << "and Environment." << rs->getProcessName(proc) << "_"
|
||||||
|
<< rs->entities_ids[e] << "=0\n";
|
||||||
|
|
||||||
|
output << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
State initState = rs->ctx_aut->getInitState();
|
||||||
|
output << indent << indent
|
||||||
|
<< "and Environment.state="
|
||||||
|
<< rs->ctx_aut->getStateName(initState) << "\n"
|
||||||
|
<< indent << indent << "and Environment.transition=init_0";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgent(const Process & proc) {
|
||||||
|
output << "\nAgent " << rs->processes_ids[proc] << "\n\n";
|
||||||
|
|
||||||
|
exportAgentVars(proc);
|
||||||
|
exportAgentProtocol(proc);
|
||||||
|
exportAgentEvolution(proc);
|
||||||
|
|
||||||
|
output << "end Agent\n" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgentVars(const Process & proc) {
|
||||||
|
output << "Vars:\n"
|
||||||
|
<< indent << "isActive: 0..1;\n";
|
||||||
|
|
||||||
|
for (const Entity & e : procInputs[proc]) {
|
||||||
|
output << indent << rs->entities_ids[e] << "_in: 0..1;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << indent << rs->entities_ids[e] << "_out: 0..1;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "end Vars\n\n";
|
||||||
|
|
||||||
|
output << "Actions = {\n";
|
||||||
|
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << indent << "produce_" << rs->entities_ids[e]
|
||||||
|
<< ", not_produce_" << rs->entities_ids[e] << ",\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "sleep\n};\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgentProtocol(const Process & proc) {
|
||||||
|
string procName = rs->processes_ids[proc];
|
||||||
|
|
||||||
|
output << "Protocol:\n";
|
||||||
|
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
string entityName = rs->entities_ids[e];
|
||||||
|
|
||||||
|
output << indent << entityName << "_out=1 and (Environment.mode=collect_" << procName << "_" << entityName
|
||||||
|
<< " and isActive=1): {produce_" << entityName << "};\n"
|
||||||
|
<< indent << entityName << "_out=0 and (Environment.mode=collect_" << procName << "_" << entityName
|
||||||
|
<< " and isActive=1): {not_produce_" << entityName << "};\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "Other: {sleep};\n"
|
||||||
|
<< "end Protocol\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgentEvolution(const Process & proc) {
|
||||||
|
string procName = rs->processes_ids[proc];
|
||||||
|
|
||||||
|
output << "Evolution:\n\n";
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Set the agent's activity status.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Set the agent's activity status.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n";
|
||||||
|
|
||||||
|
output << indent << "isActive=Environment.Active_" << procName << " ";
|
||||||
|
|
||||||
|
for (const Entity & e : procInputs[proc])
|
||||||
|
output << "and " << rs->entities_ids[e] << "_in=0 ";
|
||||||
|
|
||||||
|
output << "\n" << indent << indent << "if Environment.Action=activate_agents;\n\n";
|
||||||
|
|
||||||
|
bool first {true};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Synchronise with the environment state.
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
output << indent << "--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Synchronise with the environment state.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n";
|
||||||
|
|
||||||
|
for (const Entity & e : procInputs[proc]) {
|
||||||
|
string entityName = rs->entities_ids[e];
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
output << indent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
output << "and ";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << entityName << "_in=Environment." << procName << "_" << entityName << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << "\n" << indent << indent << "if isActive=1 and Environment.Action=distribute_global;\n\n";
|
||||||
|
|
||||||
|
exportAgentReactions(proc);
|
||||||
|
|
||||||
|
output << "end Evolution\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgentReactions(const Process & proc) {
|
||||||
|
output << indent <<"--------------------------------------------------------------------------------\n"
|
||||||
|
<< indent <<"-- Agent's reactions.\n"
|
||||||
|
<< indent <<"--------------------------------------------------------------------------------\n\n";
|
||||||
|
|
||||||
|
// For each entity produced accumulate all the ways it may be produced
|
||||||
|
|
||||||
|
map<string, string> sources;
|
||||||
|
|
||||||
|
for (const auto & reaction : rs->proc_reactions[proc]) {
|
||||||
|
string rctCond = reactionCondToStr(reaction);
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.prod) {
|
||||||
|
string rctProduct = rs->getEntityName(e);
|
||||||
|
|
||||||
|
if (sources.count(rctProduct))
|
||||||
|
sources[rctProduct] = appendCondition(sources[rctProduct], rctCond);
|
||||||
|
else
|
||||||
|
sources[rctProduct] = rctCond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output a single formula combining all the agent's reactions
|
||||||
|
|
||||||
|
bool moreReactions {false};
|
||||||
|
|
||||||
|
for (const auto & entry : sources) {
|
||||||
|
if (moreReactions)
|
||||||
|
output << indent << indent << "and\n";
|
||||||
|
else
|
||||||
|
moreReactions = true;
|
||||||
|
|
||||||
|
output << indent << entry.first << "_out = " << entry.second << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << indent << "if isActive=1 and Environment.Action=produce;\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportAgentInitState(const Process & proc) {
|
||||||
|
string procName = rs->processes_ids[proc];
|
||||||
|
|
||||||
|
output << "\n\n" << indent << indent << "and " << procName << ".isActive=0";
|
||||||
|
|
||||||
|
for (const Entity & e : procInputs[proc]) {
|
||||||
|
output << "\n" << indent << indent << "and " << procName << "." << rs->entities_ids[e] << "_in=0";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Entity & e : procOutputs[proc]) {
|
||||||
|
output << "\n" << indent << indent << "and " << procName << "." << rs->entities_ids[e] << "_out=0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::parseFormulas() {
|
||||||
|
for (const auto & prop : drv->properties) {
|
||||||
|
formulas.push_back(formulaToStr(prop.second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportEvaluation() {
|
||||||
|
output << "\nEvaluation\n";
|
||||||
|
|
||||||
|
for (const auto & a : atoms)
|
||||||
|
output << indent << a.second << " if " << a.first << ";\n";
|
||||||
|
|
||||||
|
output << "end Evaluation" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportInitStates() {
|
||||||
|
output << "\nInitStates\n";
|
||||||
|
|
||||||
|
exportEnvironmentInitState();
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc)
|
||||||
|
exportAgentInitState(proc);
|
||||||
|
|
||||||
|
output << ";\n"
|
||||||
|
<< "end InitStates" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportFormulae() {
|
||||||
|
output << "\nFormulae\n";
|
||||||
|
|
||||||
|
for (const string & fStr : formulas)
|
||||||
|
output << indent << fStr << ";\n";
|
||||||
|
|
||||||
|
output << "end Formulae" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* State constraints are required to be in conjunctive normal form. */
|
||||||
|
string RSExporter::stateConstrToStr(const StateConstr * guard) {
|
||||||
|
string expr;
|
||||||
|
|
||||||
|
switch (guard->oper) {
|
||||||
|
case STC_PV:
|
||||||
|
return guard->proc_name + "_" + guard->entity_name + "=1";
|
||||||
|
|
||||||
|
case STC_TF:
|
||||||
|
return guard->tf ? "true" : "false";
|
||||||
|
|
||||||
|
case STC_AND:
|
||||||
|
return "(" + stateConstrToStr(guard->arg[0]) + " and " + stateConstrToStr(guard->arg[1]) + ")";
|
||||||
|
|
||||||
|
case STC_OR:
|
||||||
|
return "(" + stateConstrToStr(guard->arg[0]) + " or " + stateConstrToStr(guard->arg[1]) + ")";
|
||||||
|
|
||||||
|
case STC_NOT:
|
||||||
|
expr = stateConstrToStr(guard->arg[0]);
|
||||||
|
return expr.substr(0, expr.length()-1) + "0";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "??";
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string RSExporter::reactionCondToStr(const Reaction & reaction) {
|
||||||
|
string cond;
|
||||||
|
|
||||||
|
bool moreRctts {false};
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.rctt) {
|
||||||
|
if (moreRctts)
|
||||||
|
cond += "*";
|
||||||
|
else
|
||||||
|
moreRctts = true;
|
||||||
|
|
||||||
|
cond += rs->getEntityName(e) + "_in";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.inhib)
|
||||||
|
cond += "*(1-" + rs->getEntityName(e) + "_in)";
|
||||||
|
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string RSExporter::appendCondition(string & oldCond, string & newCond) {
|
||||||
|
return "(" + oldCond + ") + " + newCond + " - (" + oldCond + ") * " + newCond;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string RSExporter::formulaToStr(const FormRSCTLK * form) {
|
||||||
|
string varStr;
|
||||||
|
string labelStr;
|
||||||
|
|
||||||
|
switch (form->oper) {
|
||||||
|
|
||||||
|
case RSCTLK_PV: // propositional variable
|
||||||
|
varStr = form->proc_name + "." + form->entity_name + "_out=1";
|
||||||
|
|
||||||
|
if (atoms.find(varStr) == atoms.end()) {
|
||||||
|
labelStr = "atomic_" + to_string(atoms.size());
|
||||||
|
atoms[varStr] = labelStr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
labelStr = atoms[varStr];
|
||||||
|
}
|
||||||
|
|
||||||
|
return labelStr;
|
||||||
|
|
||||||
|
case RSCTLK_AND:
|
||||||
|
return "(" + formulaToStr(form->arg[0]) + " and " + formulaToStr(form->arg[1]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_OR:
|
||||||
|
return "(" + formulaToStr(form->arg[0]) + " or " + formulaToStr(form->arg[1]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_XOR:
|
||||||
|
return "((" + formulaToStr(form->arg[0]) + " or " + formulaToStr(form->arg[1]) + ") and !(" +
|
||||||
|
formulaToStr(form->arg[0]) + " and " + formulaToStr(form->arg[1]) + "))";
|
||||||
|
|
||||||
|
case RSCTLK_NOT:
|
||||||
|
return "!(" + formulaToStr(form->arg[0]) +")";
|
||||||
|
|
||||||
|
case RSCTLK_IMPL:
|
||||||
|
return "(" + formulaToStr(form->arg[0]) + " -> " + formulaToStr(form->arg[1]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_EG: // Existential...
|
||||||
|
return "EG(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_EU:
|
||||||
|
return "E(" + formulaToStr(form->arg[0]) + " U " + formulaToStr(form->arg[1]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_EX:
|
||||||
|
return "EX(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_EF:
|
||||||
|
return "EF(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_AG: // Universal...
|
||||||
|
return "AG(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_AU:
|
||||||
|
return "A(" + formulaToStr(form->arg[0]) + " U " + formulaToStr(form->arg[1]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_AX:
|
||||||
|
return "AX(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_AF:
|
||||||
|
return "AF(" + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
case RSCTLK_UK: // Epistemic operators
|
||||||
|
return "K(" + form->getSingleAgent() + ", " + formulaToStr(form->arg[0]) + ")";
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
return "??";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RSExporter::exportToXML() {
|
||||||
|
output << "<xml version=\"1.0\">\n"
|
||||||
|
<< indent << "<reaction-system>\n";
|
||||||
|
|
||||||
|
for (Process proc=0; proc<rs->getNumberOfProcesses(); ++proc) {
|
||||||
|
output << indent << indent << "<process name=\"" << rs->processes_ids[proc] << "\">\n";
|
||||||
|
|
||||||
|
for (const auto & reaction : rs->proc_reactions[proc]) {
|
||||||
|
output << indent << indent << indent << "<reaction>\n";
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.rctt) {
|
||||||
|
output << indent << indent << indent << indent
|
||||||
|
<< "<reactant>" << rs->getEntityName(e) << "</reactant>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.inhib) {
|
||||||
|
output << indent << indent << indent << indent
|
||||||
|
<< "<inhibitor>" << rs->getEntityName(e) << "</inhibitor>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Entity & e : reaction.prod) {
|
||||||
|
output << indent << indent << indent << indent
|
||||||
|
<< "<product>" << rs->getEntityName(e) << "</product>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << indent << indent << "</reaction>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << indent << "</process>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "</reaction-system>\n";
|
||||||
|
|
||||||
|
output << indent << "<context-automaton>\n";
|
||||||
|
|
||||||
|
for (unsigned stId=0; stId<rs->ctx_aut->states_ids.size(); ++stId) {
|
||||||
|
if (rs->ctx_aut->states_ids[stId] == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
output << indent << indent << "<state id=\"" << stId + 1 << "\" name=\""
|
||||||
|
<< rs->ctx_aut->states_ids[stId] << "\" x=\"0\" y=\"0\"";
|
||||||
|
|
||||||
|
if (rs->ctx_aut->init_state_defined && stId == rs->ctx_aut->init_state_id)
|
||||||
|
output << " initial=\"true\"";
|
||||||
|
|
||||||
|
output << "/>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<map<State, vector<CtxAutTransition>>> edges(rs->ctx_aut->states_ids.size());
|
||||||
|
|
||||||
|
for (const CtxAutTransition & trans : rs->ctx_aut->transitions) {
|
||||||
|
if (rs->ctx_aut->states_ids[trans.src_state] == "T" || rs->ctx_aut->states_ids[trans.dst_state] == "T")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
edges[trans.src_state][trans.dst_state].push_back(trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned src=0; src<edges.size(); ++src) {
|
||||||
|
for (const auto &dst : edges[src]) {
|
||||||
|
output << indent << indent << "<edge from=\"" << rs->ctx_aut->getStateName(src)
|
||||||
|
<< "\" to=\"" << rs->ctx_aut->getStateName(dst.first) << "\">\n";
|
||||||
|
|
||||||
|
for (const CtxAutTransition &trans : dst.second) {
|
||||||
|
output << indent << indent << indent << "<transition context=\"" << rs->procEntitiesToStr(trans.ctx) << "\"";
|
||||||
|
|
||||||
|
if (trans.state_constr)
|
||||||
|
output << " guard=\"" << trans.state_constr->toStr() << "\"";
|
||||||
|
|
||||||
|
output << "/>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
output << indent << indent << "</edge>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "</context-automaton>\n";
|
||||||
|
|
||||||
|
output << indent << "<formulas>\n";
|
||||||
|
|
||||||
|
for (const auto & prop : drv->properties) {
|
||||||
|
string fStr = "";
|
||||||
|
|
||||||
|
for (const char ch : prop.second->toStr()) {
|
||||||
|
if (ch == '<')
|
||||||
|
fStr += "<";
|
||||||
|
else if (ch =='>')
|
||||||
|
fStr += ">";
|
||||||
|
else
|
||||||
|
fStr += ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << indent << indent << "<formula label=\"" << prop.first <<"\">"
|
||||||
|
<< fStr << "</formula>\n";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
output << indent << "</formulas>\n";
|
||||||
|
|
||||||
|
output << "</xml>" << endl;
|
||||||
|
}
|
||||||
57
reactics-bdd/export.hh
Normal file
57
reactics-bdd/export.hh
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
#ifndef EXPORT_HH
|
||||||
|
#define EXPORT_HH
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "types.hh"
|
||||||
|
#include "mc.hh"
|
||||||
|
#include "rs.hh"
|
||||||
|
#include "rsin_driver.hh"
|
||||||
|
|
||||||
|
|
||||||
|
class RSExporter {
|
||||||
|
public:
|
||||||
|
RSExporter(RctSys *rs, rsin_driver *drv, std::ostream & outStream = std::cout);
|
||||||
|
|
||||||
|
void exportToISPL();
|
||||||
|
void exportToXML();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RctSys *rs;
|
||||||
|
rsin_driver *drv;
|
||||||
|
string indent {" "};
|
||||||
|
std::ostream &output;
|
||||||
|
|
||||||
|
void exportEnvironment();
|
||||||
|
void exportAgent(const Process & proc);
|
||||||
|
|
||||||
|
void exportEnvironmentVars();
|
||||||
|
void exportEnvironmentActions();
|
||||||
|
void exportEnvironmentProtocol();
|
||||||
|
void exportEnvironmentEvolution();
|
||||||
|
void exportEnvironmentInitState();
|
||||||
|
|
||||||
|
void exportAgentVars(const Process & proc);
|
||||||
|
void exportAgentProtocol(const Process & proc);
|
||||||
|
void exportAgentEvolution(const Process & proc);
|
||||||
|
void exportAgentReactions(const Process & proc);
|
||||||
|
void exportAgentInitState(const Process & proc);
|
||||||
|
|
||||||
|
void parseFormulas();
|
||||||
|
void exportEvaluation();
|
||||||
|
void exportInitStates();
|
||||||
|
void exportFormulae();
|
||||||
|
|
||||||
|
std::string stateConstrToStr(const StateConstr * guard);
|
||||||
|
std::string reactionCondToStr(const Reaction & reaction);
|
||||||
|
std::string appendCondition(std::string & oldCond, std::string & newCond);
|
||||||
|
std::string formulaToStr(const FormRSCTLK * form);
|
||||||
|
|
||||||
|
EntitiesForProc procInputs;
|
||||||
|
EntitiesForProc procOutputs;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> atoms;
|
||||||
|
std::vector<std::string> formulas;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -172,39 +172,6 @@ bool FormRSCTLK::isERSCTLK(void) const
|
|||||||
|
|
||||||
std::string FormRSCTLK::getActionsStr(void) const
|
std::string FormRSCTLK::getActionsStr(void) const
|
||||||
{
|
{
|
||||||
// if (actions != nullptr) {
|
|
||||||
// std::string r = "[ ";
|
|
||||||
// bool firstact = true;
|
|
||||||
//
|
|
||||||
// for (ActionsVec_f::iterator act = actions->begin(); act != actions->end();
|
|
||||||
// ++act) {
|
|
||||||
// if (!firstact) {
|
|
||||||
// r += ",";
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// firstact = false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// r += "{";
|
|
||||||
// bool firstent = true;
|
|
||||||
//
|
|
||||||
// for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent) {
|
|
||||||
// if (!firstent) {
|
|
||||||
// r += ",";
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// firstent = false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// r += *ent;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// r += "}";
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// r += " ]";
|
|
||||||
// return r;
|
|
||||||
// }
|
|
||||||
if (boolCtx != nullptr) {
|
if (boolCtx != nullptr) {
|
||||||
return "< " + boolCtx->toStr() + " >";
|
return "< " + boolCtx->toStr() + " >";
|
||||||
}
|
}
|
||||||
@@ -222,22 +189,6 @@ void FormRSCTLK::encodeActions(const SymRS *srs)
|
|||||||
|
|
||||||
actions_bdd = new BDD(srs->getBDDfalse());
|
actions_bdd = new BDD(srs->getBDDfalse());
|
||||||
assert(boolCtx != nullptr);
|
assert(boolCtx != nullptr);
|
||||||
// assert(actions != nullptr || boolCtx != nullptr);
|
|
||||||
// assert(!(actions != nullptr && boolCtx != nullptr));
|
|
||||||
|
|
||||||
// if (actions != nullptr) {
|
|
||||||
// for (ActionsVec_f::iterator act = actions->begin(); act != actions->end();
|
|
||||||
// ++act) {
|
|
||||||
// BDD single_action = srs->getBDDtrue();
|
|
||||||
//
|
|
||||||
// for (Action_f::iterator ent = act->begin(); ent != act->end(); ++ent) {
|
|
||||||
// single_action *= srs->encActStrEntity(*ent);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// single_action = srs->compContext(single_action);
|
|
||||||
// *actions_bdd += single_action;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if (boolCtx != nullptr) {
|
if (boolCtx != nullptr) {
|
||||||
*actions_bdd = boolCtx->getBDDforContext(srs);
|
*actions_bdd = boolCtx->getBDDforContext(srs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
// #include "rs.hh"
|
|
||||||
#include "symrs.hh"
|
#include "symrs.hh"
|
||||||
#include "cudd.hh"
|
#include "cudd.hh"
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
@@ -56,22 +55,21 @@
|
|||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
|
|
||||||
// typedef std::string Entity_f;
|
|
||||||
// typedef std::set<Entity_f> Action_f;
|
|
||||||
// typedef vector<Action_f> ActionsVec_f;
|
|
||||||
typedef std::set<std::string> Agents_f;
|
typedef std::set<std::string> Agents_f;
|
||||||
|
|
||||||
class StateConstr;
|
class StateConstr;
|
||||||
|
class RSExporter;
|
||||||
|
|
||||||
class FormRSCTLK
|
class FormRSCTLK
|
||||||
{
|
{
|
||||||
|
friend class RSExporter;
|
||||||
|
|
||||||
Oper oper;
|
Oper oper;
|
||||||
FormRSCTLK *arg[2];
|
FormRSCTLK *arg[2];
|
||||||
std::string entity_name;
|
std::string entity_name;
|
||||||
std::string proc_name;
|
std::string proc_name;
|
||||||
bool tf;
|
bool tf;
|
||||||
BDD *bdd;
|
BDD *bdd;
|
||||||
// ActionsVec_f *actions;
|
|
||||||
BDD *actions_bdd;
|
BDD *actions_bdd;
|
||||||
StateConstr *boolCtx;
|
StateConstr *boolCtx;
|
||||||
Agents_f agents;
|
Agents_f agents;
|
||||||
@@ -90,7 +88,6 @@ class FormRSCTLK
|
|||||||
arg[0] = nullptr;
|
arg[0] = nullptr;
|
||||||
arg[1] = nullptr;
|
arg[1] = nullptr;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = nullptr;
|
boolCtx = nullptr;
|
||||||
}
|
}
|
||||||
@@ -107,7 +104,6 @@ class FormRSCTLK
|
|||||||
arg[0] = nullptr;
|
arg[0] = nullptr;
|
||||||
arg[1] = nullptr;
|
arg[1] = nullptr;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = nullptr;
|
boolCtx = nullptr;
|
||||||
}
|
}
|
||||||
@@ -123,28 +119,10 @@ class FormRSCTLK
|
|||||||
arg[0] = form1;
|
arg[0] = form1;
|
||||||
arg[1] = form2;
|
arg[1] = form2;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = nullptr;
|
boolCtx = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor for two-argument formula with action restrictions.
|
|
||||||
*/
|
|
||||||
// FormRSCTLK(Oper op, ActionsVec_f *acts, FormRSCTLK *form1, FormRSCTLK *form2)
|
|
||||||
// {
|
|
||||||
// assert(acts != nullptr);
|
|
||||||
// assert(RSCTLK_COND_2ARG(op));
|
|
||||||
// assert(RSCTLK_COND_ACT(op));
|
|
||||||
// oper = op;
|
|
||||||
// arg[0] = form1;
|
|
||||||
// arg[1] = form2;
|
|
||||||
// bdd = nullptr;
|
|
||||||
// actions = acts;
|
|
||||||
// actions_bdd = nullptr;
|
|
||||||
// boolCtx = nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor for two-argument formula with Boolean context restrictions.
|
* @brief Constructor for two-argument formula with Boolean context restrictions.
|
||||||
*/
|
*/
|
||||||
@@ -157,7 +135,6 @@ class FormRSCTLK
|
|||||||
arg[0] = form1;
|
arg[0] = form1;
|
||||||
arg[1] = form2;
|
arg[1] = form2;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = bctx;
|
boolCtx = bctx;
|
||||||
}
|
}
|
||||||
@@ -173,28 +150,10 @@ class FormRSCTLK
|
|||||||
arg[0] = form1;
|
arg[0] = form1;
|
||||||
arg[1] = nullptr;
|
arg[1] = nullptr;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = nullptr;
|
boolCtx = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor for one-argument formula with action restrictions.
|
|
||||||
*/
|
|
||||||
// FormRSCTLK(Oper op, ActionsVec_f *acts, FormRSCTLK *form1)
|
|
||||||
// {
|
|
||||||
// assert(acts != nullptr);
|
|
||||||
// assert(RSCTLK_COND_1ARG(op));
|
|
||||||
// assert(RSCTLK_COND_ACT(op));
|
|
||||||
// oper = op;
|
|
||||||
// arg[0] = form1;
|
|
||||||
// arg[1] = nullptr;
|
|
||||||
// bdd = nullptr;
|
|
||||||
// // actions = acts;
|
|
||||||
// actions_bdd = nullptr;
|
|
||||||
// boolCtx = nullptr;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor for one-argument formula with Boolean context restrictions.
|
* @brief Constructor for one-argument formula with Boolean context restrictions.
|
||||||
*/
|
*/
|
||||||
@@ -207,7 +166,6 @@ class FormRSCTLK
|
|||||||
arg[0] = form1;
|
arg[0] = form1;
|
||||||
arg[1] = nullptr;
|
arg[1] = nullptr;
|
||||||
bdd = nullptr;
|
bdd = nullptr;
|
||||||
// actions = nullptr;
|
|
||||||
actions_bdd = nullptr;
|
actions_bdd = nullptr;
|
||||||
boolCtx = bctx;
|
boolCtx = bctx;
|
||||||
}
|
}
|
||||||
@@ -231,7 +189,6 @@ class FormRSCTLK
|
|||||||
delete arg[0];
|
delete arg[0];
|
||||||
delete arg[1];
|
delete arg[1];
|
||||||
delete bdd;
|
delete bdd;
|
||||||
// delete actions;
|
|
||||||
delete actions_bdd;
|
delete actions_bdd;
|
||||||
delete boolCtx;
|
delete boolCtx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ for form in $forms; do
|
|||||||
|
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
|
|
||||||
./gen_bc.py $n $form > tmp.rs
|
./gen_bc.py $n $form > tmp.drs
|
||||||
|
|
||||||
echo "EXEC: $tool $options $popt tmp.rs"
|
echo "EXEC: $tool $options $popt tmp.drs"
|
||||||
$tool $options $popt tmp.rs >&1 >> $filename
|
$tool $options $popt tmp.drs >&1 >> $filename
|
||||||
|
|
||||||
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
||||||
if [ "$result" = "" ];then
|
if [ "$result" = "" ];then
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ for form in $forms; do
|
|||||||
|
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
|
|
||||||
./gen_mutex.py $n $form > tmp.rs
|
./gen_mutex.py $n $form > tmp.drs
|
||||||
|
|
||||||
echo "EXEC: $tool $options $popt tmp.rs"
|
echo "EXEC: $tool $options $popt tmp.drs"
|
||||||
|
|
||||||
$tool $options $popt tmp.rs >&1 >> $filename
|
$tool $options $popt tmp.drs >&1 >> $filename
|
||||||
|
|
||||||
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
||||||
if [ "$result" = "" ];then
|
if [ "$result" = "" ];then
|
||||||
|
|||||||
@@ -43,11 +43,11 @@ for form in $forms; do
|
|||||||
|
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
|
|
||||||
./gen_abstract1.py $n $form > tmp.rs
|
./gen_abstract1.py $n $form > tmp.drs
|
||||||
|
|
||||||
echo "EXEC: $tool $options $popt tmp.rs"
|
echo "EXEC: $tool $options $popt tmp.drs"
|
||||||
|
|
||||||
$tool $options $popt tmp.rs >&1 >> $filename
|
$tool $options $popt tmp.drs >&1 >> $filename
|
||||||
|
|
||||||
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
result="$(tail -1 $filename | grep -E '.*;.*;.*;.*'| sed "s/STAT/$n /")"
|
||||||
if [ "$result" = "" ];then
|
if [ "$result" = "" ];then
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 2 1 24`;do
|
|||||||
echo $y $x
|
echo $y $x
|
||||||
filename="results/f${y}_n${x}.out"
|
filename="results/f${y}_n${x}.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_bc.py $x $y > tmp.rs
|
./gen_bc.py $x $y > tmp.drs
|
||||||
../main -c -B tmp.rs >> $filename
|
../main -c -B tmp.drs >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_f${y}.out
|
echo $result >> results/summary_f${y}.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 2 1 24`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 1 60`;do
|
|||||||
echo $x
|
echo $x
|
||||||
filename="results/abs_v${y}_f0_n${x}.out"
|
filename="results/abs_v${y}_f0_n${x}.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_abstract1.py $x $y > tmp.rs
|
./gen_abstract1.py $x $y > tmp.drs
|
||||||
../main -z -c -p -v -B tmp.rs >&1 >> $filename
|
../main -z -c -p -v -B tmp.drs >&1 >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_v${y}_abs_f0.out
|
echo $result >> results/summary_v${y}_abs_f0.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 1 60`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 1 60`;do
|
|||||||
echo $x
|
echo $x
|
||||||
filename="results/abs_v${y}_f0_n${x}_PT.out"
|
filename="results/abs_v${y}_f0_n${x}_PT.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_abstract1.py $x $y > tmp.rs
|
./gen_abstract1.py $x $y > tmp.drs
|
||||||
../main -z -x -c -p -v -B tmp.rs >&1 >> $filename
|
../main -z -x -c -p -v -B tmp.drs >&1 >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_v${y}_abs_f0_PT.out
|
echo $result >> results/summary_v${y}_abs_f0_PT.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 1 60`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 1 50`;do
|
|||||||
echo $x $y
|
echo $x $y
|
||||||
filename="results/bc_f${y}_n${x}.out"
|
filename="results/bc_f${y}_n${x}.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_bc.py $x $y > tmp.rs
|
./gen_bc.py $x $y > tmp.drs
|
||||||
../main -z -c -v -B tmp.rs >&1 >> $filename
|
../main -z -c -v -B tmp.drs >&1 >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_bc_f${y}.out
|
echo $result >> results/summary_bc_f${y}.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 1 50`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 2 40`;do
|
|||||||
echo $x $y
|
echo $x $y
|
||||||
filename="results/mutex_f${y}_n${x}.out"
|
filename="results/mutex_f${y}_n${x}.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_mutex.py $x $y > tmp.rs
|
./gen_mutex.py $x $y > tmp.drs
|
||||||
../main -z -c -p -v -B tmp.rs >&1 >> $filename
|
../main -z -c -p -v -B tmp.drs >&1 >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_mutex_f${y}.out
|
echo $result >> results/summary_mutex_f${y}.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 2 40`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ for x in `seq 2 40`;do
|
|||||||
echo $x $y
|
echo $x $y
|
||||||
filename="results/mutex_f${y}_n${x}_PT.out"
|
filename="results/mutex_f${y}_n${x}_PT.out"
|
||||||
echo "$x" > $filename
|
echo "$x" > $filename
|
||||||
./gen_mutex.py $x $y > tmp.rs
|
./gen_mutex.py $x $y > tmp.drs
|
||||||
../main -zcpxvB tmp.rs >&1 >> $filename
|
../main -zcpxvB tmp.drs >&1 >> $filename
|
||||||
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
result="$(tail -1 $filename | sed "s/STAT/$x /")"
|
||||||
echo $result >> results/summary_mutex_f${y}_PT.out
|
echo $result >> results/summary_mutex_f${y}_PT.out
|
||||||
echo $result
|
echo $result
|
||||||
@@ -13,4 +13,4 @@ for x in `seq 2 40`;do
|
|||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
rm tmp.rs
|
rm tmp.drs
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from sys import argv,exit
|
|
||||||
|
|
||||||
if len(argv) < 3:
|
|
||||||
print "Usage:", argv[0], "<number of modules> <variant>"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
|
||||||
v = int(argv[2])
|
|
||||||
|
|
||||||
if not ( v > 0 and v < 3 ):
|
|
||||||
print "unsupported variant"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
print "reactions {"
|
|
||||||
s = "\t{ {x},{s} -> {a1} };\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
for i in range(1,n+1):
|
|
||||||
s = "\t{ {a" + str(i) + "},{s} -> {y" + str(i) + "} };\n"
|
|
||||||
s += "\t{ {a" + str(i) + "},{s} -> {b" + str(i) + "} };\n"
|
|
||||||
s += "\t{ {b" + str(i) + "},{s} -> {c" + str(i) + "} };\n"
|
|
||||||
s += "\t{ {c" + str(i) + "},{s} -> {d" + str(i) + "} };\n"
|
|
||||||
s += "\t{ {d" + str(i) + ",y" + str(i) + "},{s} -> {a" + str(i+1) + "} };\n"
|
|
||||||
s += "\t{ {y" + str(i) + "},{s} -> {y" + str(i) + "} };\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
s = "\t{ {a" + str(n+1)
|
|
||||||
for i in range(1,n+1):
|
|
||||||
s += ",y" + str(i)
|
|
||||||
s += "},{s} -> {r} };\n"
|
|
||||||
print s
|
|
||||||
print "}"
|
|
||||||
|
|
||||||
if v == 1:
|
|
||||||
print "context-entities { s }"
|
|
||||||
elif v == 2:
|
|
||||||
s = "context-entities { s"
|
|
||||||
for i in range(1,n+1):
|
|
||||||
if i % 2 == 0:
|
|
||||||
s += ",a" + str(i)
|
|
||||||
s += " }"
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "initial-contexts { {x} }"
|
|
||||||
print "rsctl-property { E[{}]F(r) }"
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from sys import argv,exit
|
|
||||||
|
|
||||||
OPTIONS_STR = """
|
|
||||||
options { use-context-automaton; make-progressive; };
|
|
||||||
"""
|
|
||||||
|
|
||||||
PROC_STR = """
|
|
||||||
proc{:d} {{
|
|
||||||
{{{{a}}, {{s}} -> {{y}}}};
|
|
||||||
{{{{y}}, {{s}} -> {{y}}}};
|
|
||||||
{{{{a}}, {{s}} -> {{b}}}};
|
|
||||||
{{{{b}}, {{s}} -> {{c}}}};
|
|
||||||
{{{{c}}, {{s}} -> {{d}}}};
|
|
||||||
{{{{d,y}}, {{s}} -> {{dy}}}};
|
|
||||||
}};
|
|
||||||
"""
|
|
||||||
|
|
||||||
FINAL_PROC = """
|
|
||||||
procFinal {
|
|
||||||
{{done}, {s} -> {done}};
|
|
||||||
};
|
|
||||||
"""
|
|
||||||
|
|
||||||
CA_STR = """
|
|
||||||
context-automaton {{
|
|
||||||
states {{ init, act }};
|
|
||||||
init-state {{ init }};
|
|
||||||
transitions {{
|
|
||||||
{:s}
|
|
||||||
}};
|
|
||||||
}};
|
|
||||||
"""
|
|
||||||
|
|
||||||
PROPERTY_STR = """
|
|
||||||
rsctlk-property {{ {:s} : {:s} }};
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
|
||||||
|
|
||||||
if len(argv) < 1:
|
|
||||||
print("Usage: {:s} <number of processes>".format(argv[0]))
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
|
||||||
|
|
||||||
assert n > 1, "number of proc must be > 1"
|
|
||||||
|
|
||||||
out = ""
|
|
||||||
|
|
||||||
out += OPTIONS_STR
|
|
||||||
out += "reactions {\n"
|
|
||||||
for i in range(1, n+1):
|
|
||||||
out += PROC_STR.format(i)
|
|
||||||
|
|
||||||
out += FINAL_PROC
|
|
||||||
out += "};\n"
|
|
||||||
|
|
||||||
transitions = ""
|
|
||||||
|
|
||||||
init_trans = 8*" " + "{ proc1={a} }: init -> act;\n"
|
|
||||||
transitions += init_trans
|
|
||||||
|
|
||||||
for i in range(1, n+1):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: act -> act : ~proc{:d}.dy;\n".format(8*" ", i, i, i)
|
|
||||||
|
|
||||||
for i in range(2, n+1):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{a}} }}: act -> act : proc{:d}.dy;\n".format(8*" ", i, i-1)
|
|
||||||
|
|
||||||
final_cond = "proc1.dy"
|
|
||||||
for i in range(2, n+1):
|
|
||||||
final_cond += " AND proc{:d}.dy".format(i)
|
|
||||||
|
|
||||||
transitions += "{:s}{{ procFinal={{done}} }}: act -> act : {:s};\n".format(8*" ", final_cond)
|
|
||||||
|
|
||||||
out += CA_STR.format(transitions)
|
|
||||||
|
|
||||||
# f1
|
|
||||||
formula = "EF( procFinal.done )"
|
|
||||||
out += PROPERTY_STR.format("f1",formula)
|
|
||||||
|
|
||||||
# f2
|
|
||||||
formula = "AG( proc{:d}.d IMPLIES K[proc{:d}]( proc{:d}.y ) )".format(n, n, n-1)
|
|
||||||
out += PROPERTY_STR.format("f2",formula)
|
|
||||||
|
|
||||||
# x1
|
|
||||||
formula = "EF( ~procFinal.done )"
|
|
||||||
out += PROPERTY_STR.format("x1",formula)
|
|
||||||
|
|
||||||
print(out)
|
|
||||||
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#!/usr/bin/env python2.7
|
|
||||||
|
|
||||||
from sys import argv,exit
|
|
||||||
|
|
||||||
|
|
||||||
if len(argv) < 3:
|
|
||||||
print "Usage:", argv[0], "<number of bits> <property>"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
|
||||||
property = int(argv[2])
|
|
||||||
|
|
||||||
K = 8
|
|
||||||
if property == 3:
|
|
||||||
if n < K+1:
|
|
||||||
print "too small n"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
if not ( property >= 1 and property < 5 ):
|
|
||||||
print "property: 1-4"
|
|
||||||
exit(101)
|
|
||||||
|
|
||||||
print "reactions {"
|
|
||||||
|
|
||||||
# (1) no dec, no inc
|
|
||||||
print "\t# (1) no decrement, no increment"
|
|
||||||
for j in range(0,n):
|
|
||||||
print "\t{{p" + str(j) + "},{dec,inc} -> {p" + str(j) + "}};"
|
|
||||||
|
|
||||||
# (2) increment
|
|
||||||
s = "\n\t# (2) increment operation\n"
|
|
||||||
s += "\t{{inc},{dec,p0} -> {p0}};\n"
|
|
||||||
for j in range(1,n):
|
|
||||||
s += "\t{{inc,"
|
|
||||||
for k in range(0,j):
|
|
||||||
s += "p" + str(k)
|
|
||||||
if k < j-1:
|
|
||||||
s += ","
|
|
||||||
s += "},{dec,p" + str(j) + "} -> {p" + str(j) + "}};\n"
|
|
||||||
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "\t# the more significant bits remain (inc)"
|
|
||||||
s = ""
|
|
||||||
for j in range(0,n):
|
|
||||||
for k in range(j+1,n):
|
|
||||||
s += "\t{{inc,p" + str(k) + "},{dec,p" + str(j) + "} -> {p" + str(k) + "}};\n"
|
|
||||||
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "\t# (3) decrement operation"
|
|
||||||
s = ""
|
|
||||||
for j in range(0,n):
|
|
||||||
s += "\t{{dec},{inc,"
|
|
||||||
for k in range(0,j+1):
|
|
||||||
s += "p" + str(k)
|
|
||||||
if k < j:
|
|
||||||
s += ","
|
|
||||||
s += "} -> {p" + str(j) + "}};\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "\t# the more significant bits remain (dec)"
|
|
||||||
s = ""
|
|
||||||
for j in range(0,n):
|
|
||||||
for k in range(j+1,n):
|
|
||||||
s += "\t{{dec,p" + str(j) + ",p" + str(k) + "},{inc} -> {p" + str(k) + "}};\n"
|
|
||||||
|
|
||||||
s += "}\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "context-entities { inc,dec }"
|
|
||||||
print "initial-contexts { {} }"
|
|
||||||
|
|
||||||
if property == 4:
|
|
||||||
print "rsctl-property { AG( p" + str(n-1) + " IMPLIES EF ~p" + str(n-1) + " ) }"
|
|
||||||
elif property == 1:
|
|
||||||
s = "rsctl-property { AG(("
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "~p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
s += ") IMPLIES E[{inc},{dec}]F("
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
|
|
||||||
s += ")) }"
|
|
||||||
print s
|
|
||||||
elif property == 2:
|
|
||||||
s = "rsctl-property { AG(("
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
s += ") IMPLIES A[{inc}]X("
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "~p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
|
|
||||||
s += ")) }"
|
|
||||||
print s
|
|
||||||
|
|
||||||
elif property == 3:
|
|
||||||
s = "rsctl-property { E[{inc}]F("
|
|
||||||
for i in range(0,n-K):
|
|
||||||
s += "p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
for i in range(n-K,n):
|
|
||||||
s += "~p" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += " AND "
|
|
||||||
s += ") }"
|
|
||||||
print s
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from sys import argv,exit
|
|
||||||
|
|
||||||
|
|
||||||
if len(argv) < 3:
|
|
||||||
print "Usage:", argv[0], "<number of processes> <formula>"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
|
||||||
f = int(argv[2])
|
|
||||||
|
|
||||||
if not ( f>0 and f<4 ):
|
|
||||||
print "unsupported formula"
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
print "reactions {"
|
|
||||||
for i in range(0,n):
|
|
||||||
s = "\t{{out" + str(i) + ",act" + str(i) + "},{} -> {request" + str(i) + "}};\n"
|
|
||||||
s += "\t{{out" + str(i) + "},{act" + str(i) + "} -> {out" + str(i) + "}};\n"
|
|
||||||
for j in range(0,n):
|
|
||||||
if i != j:
|
|
||||||
s += "\t{{request" + str(i) + ",act" + str(i) + ",act" + str(j) + "},{} -> {request" + str(i) + "}};\n"
|
|
||||||
#s += "\t{{request" + str(i) + "},{"
|
|
||||||
#for j in range(0,n):
|
|
||||||
# s += "act" + str(j)
|
|
||||||
# if j < n-1:
|
|
||||||
# s += ","
|
|
||||||
#s += "} -> {request" + str(i) + "}};\n"
|
|
||||||
s += "\t{{request" + str(i) + "},{act" + str(i) + "} -> {request" + str(i) + "}};\n"
|
|
||||||
s += "\t{{request" + str(i) + ",act" + str(i) + "},{"
|
|
||||||
for j in range(0,n):
|
|
||||||
if i != j:
|
|
||||||
s += "act" + str(j) + ","
|
|
||||||
s += "lock} -> {in" + str(i) + ",lock}};\n"
|
|
||||||
s += "\t{{in" + str(i) + ",act" + str(i) + "},{} -> {out" + str(i) + ",done}};\n"
|
|
||||||
s += "\t{{in" + str(i) + "},{act" + str(i) + "} -> {in" + str(i) + "}};\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
print "\t{{lock},{done} -> {lock}};"
|
|
||||||
|
|
||||||
print "}"
|
|
||||||
|
|
||||||
s = "context-entities {"
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "act" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += ","
|
|
||||||
s += "}\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
s = "initial-contexts { {"
|
|
||||||
for i in range(0,n):
|
|
||||||
s += "out" + str(i)
|
|
||||||
if i < n-1:
|
|
||||||
s += ","
|
|
||||||
s += "} }\n"
|
|
||||||
print s
|
|
||||||
|
|
||||||
#print "rsctl-property { A[{act1}]G(A[{act1}]F(in1)) }"
|
|
||||||
if f == 1:
|
|
||||||
print "rsctl-property { A[{act1}]F(in1) }"
|
|
||||||
elif f == 2:
|
|
||||||
print "rsctl-property { E[{act1}]F(in1) }"
|
|
||||||
elif f == 3:
|
|
||||||
s = "rsctl-property { AG("
|
|
||||||
for i in range(0,n):
|
|
||||||
for j in range(i+1,n):
|
|
||||||
s += "~(in" + str(i) + " AND in" + str(j) + ")"
|
|
||||||
if i < n-2:
|
|
||||||
s += " AND "
|
|
||||||
s += ") }"
|
|
||||||
print s
|
|
||||||
else:
|
|
||||||
exit(111)
|
|
||||||
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from sys import argv,exit
|
|
||||||
|
|
||||||
OPTIONS_STR = """
|
|
||||||
options { use-context-automaton; make-progressive; };
|
|
||||||
"""
|
|
||||||
|
|
||||||
PROC_STR = """
|
|
||||||
proc{:d} {{
|
|
||||||
{{{{out}}, {{}} -> {{approach}}}};
|
|
||||||
{{{{approach}}, {{req}} -> {{req}}}};
|
|
||||||
{{{{allowed}}, {{}} -> {{in}}}};
|
|
||||||
{{{{in}}, {{}} -> {{out,leave}}}};
|
|
||||||
{{{{req}}, {{in}} -> {{req}}}};
|
|
||||||
}};
|
|
||||||
"""
|
|
||||||
|
|
||||||
CA_STR = """
|
|
||||||
context-automaton {{
|
|
||||||
states {{ init, green, red }};
|
|
||||||
init-state {{ init }};
|
|
||||||
transitions {{
|
|
||||||
{:s}
|
|
||||||
}};
|
|
||||||
}};
|
|
||||||
"""
|
|
||||||
|
|
||||||
PROPERTY_STR = """
|
|
||||||
rsctlk-property {{ {:s} : {:s} }};
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
|
||||||
|
|
||||||
if len(argv) < 1:
|
|
||||||
print("Usage: {:s} <number of processes>".format(argv[0]))
|
|
||||||
exit(100)
|
|
||||||
|
|
||||||
n = int(argv[1])
|
|
||||||
|
|
||||||
assert n > 1, "number of proc must be > 1"
|
|
||||||
|
|
||||||
out = ""
|
|
||||||
|
|
||||||
out += OPTIONS_STR
|
|
||||||
out += "reactions {\n"
|
|
||||||
for i in range(n):
|
|
||||||
out += PROC_STR.format(i)
|
|
||||||
out += "};\n"
|
|
||||||
|
|
||||||
transitions = ""
|
|
||||||
|
|
||||||
init_trans = 8*" " + "{ "
|
|
||||||
for i in range(n):
|
|
||||||
init_trans += "proc{:d}={{out}} ".format(i)
|
|
||||||
init_trans += "}: init -> green;\n"
|
|
||||||
transitions += init_trans
|
|
||||||
|
|
||||||
for i in range(n):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{allowed}} }}: green -> red : proc{:d}.req;\n".format(8*" ", i, i)
|
|
||||||
|
|
||||||
no_req_cond = "~proc0.req"
|
|
||||||
for i in range(1, n):
|
|
||||||
no_req_cond += " AND ~proc{:d}.req".format(i)
|
|
||||||
|
|
||||||
for i in range(n):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: green -> green : {:s};\n".format(8*" ", i, no_req_cond)
|
|
||||||
|
|
||||||
for i in range(n):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: red -> green : proc{:d}.leave;\n".format(8*" ", i, i)
|
|
||||||
|
|
||||||
no_leave_cond = "~proc0.leave"
|
|
||||||
for i in range(1, n):
|
|
||||||
no_leave_cond += " AND ~proc{:d}.leave".format(i)
|
|
||||||
|
|
||||||
for i in range(n):
|
|
||||||
transitions += "{:s}{{ proc{:d}={{}} }}: red -> red : {:s};\n".format(8*" ", i, no_leave_cond)
|
|
||||||
|
|
||||||
out += CA_STR.format(transitions)
|
|
||||||
|
|
||||||
## f1
|
|
||||||
#formula = "EF( proc0.in )"
|
|
||||||
#out += PROPERTY_STR.format("f1",formula)
|
|
||||||
|
|
||||||
# f1
|
|
||||||
formula = "EF( E<proc0.allowed>X( proc0.in ) )"
|
|
||||||
for i in range(1, n):
|
|
||||||
formula += " AND EF( E<proc{:d}.allowed>X( proc{:d}.in ) )".format(i, i)
|
|
||||||
out += PROPERTY_STR.format("f1",formula)
|
|
||||||
|
|
||||||
# f2
|
|
||||||
formula = "EF( proc0.approach"
|
|
||||||
for i in range(1, n):
|
|
||||||
formula += " AND proc{:d}.approach".format(i)
|
|
||||||
formula += " )"
|
|
||||||
out += PROPERTY_STR.format("f2",formula)
|
|
||||||
|
|
||||||
# f3
|
|
||||||
subf = "~proc1.in"
|
|
||||||
for i in range(2, n):
|
|
||||||
subf += " AND ~proc{:d}.in".format(i)
|
|
||||||
formula = "AG( proc0.in IMPLIES K[proc0]({:s}) )".format(subf)
|
|
||||||
out += PROPERTY_STR.format("f3",formula)
|
|
||||||
|
|
||||||
# f4
|
|
||||||
subf = "~proc1.in"
|
|
||||||
for i in range(2, n):
|
|
||||||
subf += " AND ~proc{:d}.in".format(i)
|
|
||||||
all_agents = "proc0"
|
|
||||||
for i in range(1, n):
|
|
||||||
all_agents += ",proc{:d}".format(i)
|
|
||||||
formula = "AG( proc0.in IMPLIES C[{:s}]({:s}) )".format(all_agents,subf)
|
|
||||||
out += PROPERTY_STR.format("f4",formula)
|
|
||||||
|
|
||||||
print(out)
|
|
||||||
|
|
||||||
@@ -198,8 +198,15 @@ void ModelChecker::printReachWithSucc(void)
|
|||||||
while (!unproc.IsZero()) {
|
while (!unproc.IsZero()) {
|
||||||
BDD t;
|
BDD t;
|
||||||
t = unproc.PickOneMinterm(*pv);
|
t = unproc.PickOneMinterm(*pv);
|
||||||
cout << "Successors of " << srs->decodedRctSysStateToStr(t) << ":" << endl;
|
if (opts->backend_mode)
|
||||||
srs->printDecodedRctSysStates(getSucc(t));
|
{
|
||||||
|
cout << "G " << srs->decodedRctSysStateWithCtxAutToStr(t) << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "Successors of " << srs->decodedRctSysStateWithCtxAutToStr(t) << ":" << endl;
|
||||||
|
}
|
||||||
|
srs->printDecodedRctSysWithCtxAutStates(getSucc(t));
|
||||||
unproc -= t;
|
unproc -= t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,9 +517,9 @@ BDD ModelChecker::getIthOnly(Process proc_id)
|
|||||||
/* nothing has been found in the cache */
|
/* nothing has been found in the cache */
|
||||||
BDD bdd = BDD_TRUE;
|
BDD bdd = BDD_TRUE;
|
||||||
|
|
||||||
for (auto i = 0; i < pv_drs_E->size(); ++i) {
|
for (size_t i = 0; i < pv_drs_E->size(); ++i) {
|
||||||
|
|
||||||
if (i == proc_id) {
|
if (i == static_cast<size_t>(proc_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,18 +591,16 @@ bool ModelChecker::checkRSCTLKfull(FormRSCTLK *form)
|
|||||||
|
|
||||||
VERB("Checking the formula");
|
VERB("Checking the formula");
|
||||||
|
|
||||||
//if (*initStates * getStatesRSCTLK(form) != cuddMgr->bddZero())
|
result = (*initStates * getStatesRSCTLK(form) == *initStates);
|
||||||
if (*initStates * getStatesRSCTLK(form) == *initStates) {
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
cout << "Formula " << form->toStr() << (result ? " holds" : " does not hold")
|
if (opts->backend_mode) {
|
||||||
<< endl;
|
cout << "Result:" << result << endl;
|
||||||
|
} else {
|
||||||
|
cout << "Formula " << form->toStr() << (result ? " holds" : " does not hold")
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->measure) {
|
if (opts->measure) {
|
||||||
opts->ver_time = cpuTime() - opts->ver_time;
|
opts->ver_time = cpuTime() - opts->ver_time;
|
||||||
@@ -658,8 +663,12 @@ bool ModelChecker::checkRSCTLKbmc(FormRSCTLK *form)
|
|||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
cout << "Formula " << form->toStr() << " " << (result ? "holds" :
|
if (opts->backend_mode) {
|
||||||
"does not hold") << endl;
|
cout << "result:" << result << endl;
|
||||||
|
} else {
|
||||||
|
cout << "Formula " << form->toStr() << " " << (result ? "holds" :
|
||||||
|
"does not hold") << endl;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->measure) {
|
if (opts->measure) {
|
||||||
opts->ver_time = cpuTime() - opts->ver_time;
|
opts->ver_time = cpuTime() - opts->ver_time;
|
||||||
|
|||||||
@@ -5,7 +5,12 @@
|
|||||||
#define __MEMTIME_H__
|
#define __MEMTIME_H__
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#ifdef __WIN32__
|
||||||
|
#include <windows.h>
|
||||||
|
#include <psapi.h>
|
||||||
|
#else
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <malloc/malloc.h>
|
#include <malloc/malloc.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -17,6 +22,25 @@ using namespace std;
|
|||||||
|
|
||||||
typedef long long int64;
|
typedef long long int64;
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
|
|
||||||
|
static inline double cpuTime()
|
||||||
|
{
|
||||||
|
FILETIME createTime, exitTime, kernelTime, userTime;
|
||||||
|
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime)) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULARGE_INTEGER u;
|
||||||
|
u.LowPart = userTime.dwLowDateTime;
|
||||||
|
u.HighPart = userTime.dwHighDateTime;
|
||||||
|
|
||||||
|
return (double)u.QuadPart / 10e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static inline double cpuTime(void)
|
static inline double cpuTime(void)
|
||||||
{
|
{
|
||||||
struct rusage ru;
|
struct rusage ru;
|
||||||
@@ -24,6 +48,8 @@ static inline double cpuTime(void)
|
|||||||
return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000;
|
return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline int memReadStat(void)
|
static inline int memReadStat(void)
|
||||||
{
|
{
|
||||||
char name[256];
|
char name[256];
|
||||||
@@ -47,11 +73,28 @@ static inline int memReadStat(void)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __WIN32__
|
||||||
|
|
||||||
|
static inline int64 memUsedInt64()
|
||||||
|
{
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
|
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
|
||||||
|
return (int64) pmc.WorkingSetSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static inline int64 memUsedInt64()
|
static inline int64 memUsedInt64()
|
||||||
{
|
{
|
||||||
return (int64)memReadStat() * (int64)getpagesize();
|
return (int64)memReadStat() * (int64)getpagesize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
|
||||||
static inline double memUsed()
|
static inline double memUsed()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class Options
|
|||||||
bool part_tr_rel;
|
bool part_tr_rel;
|
||||||
bool reorder_reach;
|
bool reorder_reach;
|
||||||
bool reorder_trans;
|
bool reorder_trans;
|
||||||
|
bool backend_mode;
|
||||||
|
|
||||||
double enc_time;
|
double enc_time;
|
||||||
double enc_mem;
|
double enc_mem;
|
||||||
@@ -23,10 +24,12 @@ class Options
|
|||||||
show_progress = false;
|
show_progress = false;
|
||||||
measure = false;
|
measure = false;
|
||||||
|
|
||||||
part_tr_rel = false;
|
part_tr_rel = true;
|
||||||
|
|
||||||
reorder_reach = false;
|
reorder_reach = true;
|
||||||
reorder_trans = false;
|
reorder_trans = true;
|
||||||
|
|
||||||
|
backend_mode = false;
|
||||||
|
|
||||||
enc_time = 0;
|
enc_time = 0;
|
||||||
enc_mem = 0;
|
enc_mem = 0;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ int main(int argc, char **argv)
|
|||||||
bool rstl_model_checking = false;
|
bool rstl_model_checking = false;
|
||||||
bool reach_states = false;
|
bool reach_states = false;
|
||||||
bool reach_states_succ = false;
|
bool reach_states_succ = false;
|
||||||
|
bool export_to_ispl = false;
|
||||||
|
bool export_to_xml = false;
|
||||||
bool bmc = true;
|
bool bmc = true;
|
||||||
bool benchmarking = false;
|
bool benchmarking = false;
|
||||||
bool dump_help_message = false;
|
bool dump_help_message = false;
|
||||||
@@ -31,17 +33,17 @@ int main(int argc, char **argv)
|
|||||||
int c;
|
int c;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "c:bBmpPrsStTvxzh", long_options,
|
while ((c = getopt_long(argc, argv, "c:bBmpPrsStTvXheyEG", long_options,
|
||||||
&option_index)) != -1) {
|
&option_index)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
printf("option %s", long_options[option_index].name);
|
cout << "option " << long_options[option_index].name;
|
||||||
|
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
printf(" with arg %s", optarg);
|
cout << " with arg " << optarg;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
cout << endl;
|
||||||
|
|
||||||
if (strcmp(long_options[option_index].name, "trace-parsing")) {
|
if (strcmp(long_options[option_index].name, "trace-parsing")) {
|
||||||
driver.trace_parsing = true;
|
driver.trace_parsing = true;
|
||||||
@@ -52,6 +54,14 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
export_to_ispl = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
export_to_xml = true;
|
||||||
|
break;
|
||||||
|
|
||||||
//case 'b':
|
//case 'b':
|
||||||
// printf("-b with %s\n", optarg);
|
// printf("-b with %s\n", optarg);
|
||||||
// break;
|
// break;
|
||||||
@@ -97,13 +107,17 @@ int main(int argc, char **argv)
|
|||||||
opts->verbose++;
|
opts->verbose++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'E':
|
||||||
opts->part_tr_rel = true;
|
opts->reorder_reach = false;
|
||||||
|
opts->reorder_trans = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'z':
|
case 'G':
|
||||||
opts->reorder_reach = true;
|
opts->part_tr_rel = false;
|
||||||
opts->reorder_trans = true;
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
opts->backend_mode = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
@@ -132,8 +146,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(reach_states || reach_states_succ || rstl_model_checking
|
if (!(reach_states || reach_states_succ || rstl_model_checking
|
||||||
|| show_reactions || print_parsed_sys)) {
|
|| show_reactions || print_parsed_sys || export_to_ispl || export_to_xml)) {
|
||||||
FERROR("No task specified: -c, -P, -r, or -s needs to be used");
|
FERROR("No task specified: -c, -P, -r, -s, or -e needs to be used");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts->verbose > 0) {
|
if (opts->verbose > 0) {
|
||||||
@@ -167,7 +181,7 @@ int main(int argc, char **argv)
|
|||||||
rs.printSystem();
|
rs.printSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reach_states || reach_states_succ || rstl_model_checking) {
|
if (reach_states || reach_states_succ || rstl_model_checking || export_to_ispl || export_to_xml) {
|
||||||
SymRS srs(&rs, opts);
|
SymRS srs(&rs, opts);
|
||||||
|
|
||||||
ModelChecker mc(&srs, opts);
|
ModelChecker mc(&srs, opts);
|
||||||
@@ -180,6 +194,16 @@ int main(int argc, char **argv)
|
|||||||
mc.printReachWithSucc();
|
mc.printReachWithSucc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (export_to_ispl) {
|
||||||
|
RSExporter exp(&rs, &driver);
|
||||||
|
exp.exportToISPL();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (export_to_xml) {
|
||||||
|
RSExporter exp(&rs, &driver);
|
||||||
|
exp.exportToXML();
|
||||||
|
}
|
||||||
|
|
||||||
if (rstl_model_checking) {
|
if (rstl_model_checking) {
|
||||||
if (bmc) {
|
if (bmc) {
|
||||||
cout << "Using BDD-based Bounded Model Checking" << endl;
|
cout << "Using BDD-based Bounded Model Checking" << endl;
|
||||||
@@ -212,16 +236,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
delete opts;
|
delete opts;
|
||||||
|
|
||||||
int ret_val;
|
return result ? 0 : 1;
|
||||||
|
|
||||||
if (result) {
|
|
||||||
ret_val = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ret_val = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_help(std::string path_str)
|
void print_help(std::string path_str)
|
||||||
@@ -252,16 +267,20 @@ void print_help(std::string path_str)
|
|||||||
<< endl
|
<< endl
|
||||||
<< endl << " OTHER:" << endl
|
<< endl << " OTHER:" << endl
|
||||||
<< " -b -- disable bounded model checking (BMC) heuristic" << endl
|
<< " -b -- disable bounded model checking (BMC) heuristic" << endl
|
||||||
<< " -x -- use partitioned transition relation" <<
|
<< " -v -- verbose (use more than once to increase verbosity)" << endl
|
||||||
endl
|
|
||||||
<< " -z -- use reordering of the BDD variables" << endl
|
|
||||||
<< " -v -- verbose (use more than once to increase verbosity)" <<
|
|
||||||
endl
|
|
||||||
<< " -p -- show progress (where possible)" << endl
|
<< " -p -- show progress (where possible)" << endl
|
||||||
|
<< " -X -- backend mode (makes output parsing easier)" << endl
|
||||||
|
<< " -y -- export to XML (for GUI tool)" << endl
|
||||||
|
<< endl
|
||||||
|
<< " Optimisations:" << endl
|
||||||
|
<< " -E -- disable auto-reordering optimisation of BDDs" << endl
|
||||||
|
<< " -G -- disable partitioned transition relation optimisation" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< " Benchmarking options:" << endl
|
<< " Benchmarking options:" << endl
|
||||||
<< " -m -- measure and display time and memory usage" << endl
|
<< " -m -- measure and display time and memory usage" << endl
|
||||||
<< " -B -- display an easy to parse summary (enables -m)" << endl
|
<< " -B -- display an easy to parse summary (enables -m)" << endl
|
||||||
|
<< " -e -- exports to ISPL (MCMAS input format)" << endl
|
||||||
|
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "rsin_driver.hh"
|
#include "rsin_driver.hh"
|
||||||
#include "options.hh"
|
#include "options.hh"
|
||||||
#include "memtime.hh"
|
#include "memtime.hh"
|
||||||
|
#include "export.hh"
|
||||||
|
|
||||||
#define VERSION "2.0"
|
#define VERSION "2.0"
|
||||||
//#define AUTHOR "Artur Meski <artur.meski@gmail.com>"
|
//#define AUTHOR "Artur Meski <artur.meski@gmail.com>"
|
||||||
|
|||||||
@@ -14,12 +14,7 @@ RctSys::RctSys(void)
|
|||||||
|
|
||||||
bool RctSys::hasEntity(std::string name)
|
bool RctSys::hasEntity(std::string name)
|
||||||
{
|
{
|
||||||
if (entities_names.find(name) == entities_names.end()) {
|
return entities_names.find(name) != entities_names.end();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RctSys::addEntity(std::string name)
|
void RctSys::addEntity(std::string name)
|
||||||
@@ -84,21 +79,12 @@ void RctSys::addProcess(std::string processName)
|
|||||||
|
|
||||||
bool RctSys::hasProcess(std::string processName)
|
bool RctSys::hasProcess(std::string processName)
|
||||||
{
|
{
|
||||||
if (processes_names.find(processName) == processes_names.end()) {
|
return processes_names.find(processName) != processes_names.end();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RctSys::hasProcess(Process processID)
|
bool RctSys::hasProcess(Process processID)
|
||||||
{
|
{
|
||||||
if (processID >= processes_ids.size()) {
|
return processID < processes_ids.size();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process RctSys::getProcessID(std::string processName)
|
Process RctSys::getProcessID(std::string processName)
|
||||||
@@ -120,28 +106,26 @@ std::string RctSys::getProcessName(Process processID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RctSys::pushReactant(std::string entityName)
|
void RctSys::ensureEntity(std::string entityName)
|
||||||
{
|
{
|
||||||
if (!hasEntity(entityName)) {
|
if (!hasEntity(entityName)) {
|
||||||
addEntity(entityName);
|
addEntity(entityName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RctSys::pushReactant(std::string entityName)
|
||||||
|
{
|
||||||
|
ensureEntity(entityName);
|
||||||
tmpReactants.insert(getEntityID(entityName));
|
tmpReactants.insert(getEntityID(entityName));
|
||||||
}
|
}
|
||||||
void RctSys::pushInhibitor(std::string entityName)
|
void RctSys::pushInhibitor(std::string entityName)
|
||||||
{
|
{
|
||||||
if (!hasEntity(entityName)) {
|
ensureEntity(entityName);
|
||||||
addEntity(entityName);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpInhibitors.insert(getEntityID(entityName));
|
tmpInhibitors.insert(getEntityID(entityName));
|
||||||
}
|
}
|
||||||
void RctSys::pushProduct(std::string entityName)
|
void RctSys::pushProduct(std::string entityName)
|
||||||
{
|
{
|
||||||
if (!hasEntity(entityName)) {
|
ensureEntity(entityName);
|
||||||
addEntity(entityName);
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpProducts.insert(getEntityID(entityName));
|
tmpProducts.insert(getEntityID(entityName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,10 +216,7 @@ void RctSys::commitInitState(void)
|
|||||||
|
|
||||||
void RctSys::addActionEntity(std::string entityName)
|
void RctSys::addActionEntity(std::string entityName)
|
||||||
{
|
{
|
||||||
if (!hasEntity(entityName)) {
|
ensureEntity(entityName);
|
||||||
addEntity(entityName);
|
|
||||||
}
|
|
||||||
|
|
||||||
actionEntities.insert(getEntityID(entityName));
|
actionEntities.insert(getEntityID(entityName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,12 +229,7 @@ void RctSys::addActionEntity(Entity entity)
|
|||||||
|
|
||||||
bool RctSys::isActionEntity(Entity entity)
|
bool RctSys::isActionEntity(Entity entity)
|
||||||
{
|
{
|
||||||
if (actionEntities.count(entity) > 0) {
|
return actionEntities.count(entity) > 0;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RctSys::showActionEntities(void)
|
void RctSys::showActionEntities(void)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class RctSys
|
|||||||
{
|
{
|
||||||
friend class SymRS;
|
friend class SymRS;
|
||||||
friend class SymRSstate;
|
friend class SymRSstate;
|
||||||
|
friend class RSExporter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RctSys(void);
|
RctSys(void);
|
||||||
@@ -49,6 +50,7 @@ class RctSys
|
|||||||
|
|
||||||
void addReactionForCurrentProcess(Reaction reaction);
|
void addReactionForCurrentProcess(Reaction reaction);
|
||||||
|
|
||||||
|
void ensureEntity(std::string entityName);
|
||||||
void pushReactant(std::string entityName);
|
void pushReactant(std::string entityName);
|
||||||
void pushInhibitor(std::string entityName);
|
void pushInhibitor(std::string entityName);
|
||||||
void pushProduct(std::string entityName);
|
void pushProduct(std::string entityName);
|
||||||
|
|||||||
@@ -23,9 +23,12 @@
|
|||||||
#define STC_IS_VALID(a) (STC_COND_1ARG(a) || STC_COND_2ARG(a) || (a) == STC_PV || (a) == STC_TF)
|
#define STC_IS_VALID(a) (STC_COND_1ARG(a) || STC_COND_2ARG(a) || (a) == STC_PV || (a) == STC_TF)
|
||||||
|
|
||||||
class SymRS;
|
class SymRS;
|
||||||
|
class RSExporter;
|
||||||
|
|
||||||
class StateConstr
|
class StateConstr
|
||||||
{
|
{
|
||||||
|
friend class RSExporter;
|
||||||
|
|
||||||
Oper oper;
|
Oper oper;
|
||||||
StateConstr *arg[2];
|
StateConstr *arg[2];
|
||||||
std::string entity_name;
|
std::string entity_name;
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ SymRS::SymRS(RctSys *rs, Options *opts)
|
|||||||
|
|
||||||
totalEntities = rs->getEntitiesSize();
|
totalEntities = rs->getEntitiesSize();
|
||||||
|
|
||||||
// TODO: remove
|
|
||||||
totalActions = 0;
|
|
||||||
|
|
||||||
totalRctSysStateVars = getTotalProductVariables();
|
totalRctSysStateVars = getTotalProductVariables();
|
||||||
totalCtxEntities = getTotalCtxEntitiesVariables();
|
totalCtxEntities = getTotalCtxEntitiesVariables();
|
||||||
|
|
||||||
@@ -404,39 +401,19 @@ BDD SymRS::encCtxEntity(Process proc_id, Entity entity) const
|
|||||||
|
|
||||||
bool SymRS::productEntityExists(Process proc_id, Entity entity) const
|
bool SymRS::productEntityExists(Process proc_id, Entity entity) const
|
||||||
{
|
{
|
||||||
if (prod_ent_local_idx.count(proc_id) == 0) {
|
return prod_ent_local_idx.count(proc_id) != 0 &&
|
||||||
return false;
|
prod_ent_local_idx.at(proc_id).count(entity) == 1;
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (prod_ent_local_idx.at(proc_id).count(entity) == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymRS::ctxEntityExists(Process proc_id, Entity entity) const
|
bool SymRS::ctxEntityExists(Process proc_id, Entity entity) const
|
||||||
{
|
{
|
||||||
if (ctx_ent_local_idx.count(proc_id) == 0) {
|
return ctx_ent_local_idx.count(proc_id) != 0 &&
|
||||||
return false;
|
ctx_ent_local_idx.at(proc_id).count(entity) == 1;
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (ctx_ent_local_idx.at(proc_id).count(entity) == 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymRS::processUsesEntity(Process proc_id, Entity entity_id) const
|
bool SymRS::processUsesEntity(Process proc_id, Entity entity_id) const
|
||||||
{
|
{
|
||||||
if (productEntityExists(proc_id, entity_id) || ctxEntityExists(proc_id, entity_id)) {
|
return productEntityExists(proc_id, entity_id) || ctxEntityExists(proc_id, entity_id);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BDD SymRS::encEntitiesConj_raw(Process proc_id, const Entities &entities, bool succ)
|
BDD SymRS::encEntitiesConj_raw(Process proc_id, const Entities &entities, bool succ)
|
||||||
@@ -511,20 +488,6 @@ BDD SymRS::encContext(const EntitiesForProc &proc_entities)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
BDD SymRS::compState(const BDD &state) const
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
BDD s = state;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < totalRctSysStateVars; ++i) {
|
|
||||||
if (!(*pv)[i] * state != cuddMgr->bddZero()) {
|
|
||||||
s *= !(*pv)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
BDD SymRS::compContext(const BDD &context) const
|
BDD SymRS::compContext(const BDD &context) const
|
||||||
{
|
{
|
||||||
BDD c = context;
|
BDD c = context;
|
||||||
@@ -567,13 +530,35 @@ std::string SymRS::decodedRctSysStateToStr(const BDD &state)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SymRS::decodedRctSysStateWithCtxAutToStr(const BDD &state)
|
||||||
|
{
|
||||||
|
std::string s = "( ";
|
||||||
|
s += decodedRctSysStateToStr(state) + " ";
|
||||||
|
for (const auto &aut_state : rs->ctx_aut->states_ids) {
|
||||||
|
const auto state_id = rs->ctx_aut->getStateID(aut_state);
|
||||||
|
if (!(encCtxAutState(state_id) * state).IsZero()) {
|
||||||
|
s += aut_state + " ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s += ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void SymRS::printDecodedRctSysStates(const BDD &states)
|
void SymRS::printDecodedRctSysStates(const BDD &states)
|
||||||
{
|
{
|
||||||
BDD unproc = states;
|
BDD unproc = states;
|
||||||
|
|
||||||
while (!unproc.IsZero()) {
|
while (!unproc.IsZero()) {
|
||||||
BDD t = unproc.PickOneMinterm(*pv_drs_flat);
|
BDD t = unproc.PickOneMinterm(*pv_drs_flat);
|
||||||
cout << decodedRctSysStateToStr(t) << endl;
|
if (opts->backend_mode)
|
||||||
|
{
|
||||||
|
cout << "s " << decodedRctSysStateToStr(t) << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << decodedRctSysStateToStr(t) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
if (opts->verbose > 9) {
|
if (opts->verbose > 9) {
|
||||||
BDD_PRINT(t);
|
BDD_PRINT(t);
|
||||||
@@ -584,6 +569,31 @@ void SymRS::printDecodedRctSysStates(const BDD &states)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SymRS::printDecodedRctSysWithCtxAutStates(const BDD &states)
|
||||||
|
{
|
||||||
|
BDD unproc = states;
|
||||||
|
|
||||||
|
while (!unproc.IsZero()) {
|
||||||
|
BDD t = unproc.PickOneMinterm(*pv);
|
||||||
|
if (opts->backend_mode)
|
||||||
|
{
|
||||||
|
cout << "s " << decodedRctSysStateWithCtxAutToStr(t) << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << decodedRctSysStateWithCtxAutToStr(t) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->verbose > 9) {
|
||||||
|
BDD_PRINT(t);
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
unproc -= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DecompReactions SymRS::getProductionConditions(Process proc_id)
|
DecompReactions SymRS::getProductionConditions(Process proc_id)
|
||||||
{
|
{
|
||||||
DecompReactions dr;
|
DecompReactions dr;
|
||||||
@@ -678,65 +688,6 @@ BDD SymRS::encEnabledness(Process prod_proc_id, Entity entity_id)
|
|||||||
return enab;
|
return enab;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BDD SymRS::encEnabledness(Process prod_proc_id, Entity entity_id)
|
|
||||||
// {
|
|
||||||
// assert(prod_conds.size() > prod_proc_id);
|
|
||||||
|
|
||||||
// BDD enab = BDD_FALSE;
|
|
||||||
|
|
||||||
// auto production_conditions = prod_conds[prod_proc_id][entity_id];
|
|
||||||
|
|
||||||
// VERB_LN(5, "| Produce " << rs->getEntityName(entity_id) << " in " << rs->getProcessName(prod_proc_id) << ":");
|
|
||||||
|
|
||||||
// for (const auto &cond : production_conditions) {
|
|
||||||
|
|
||||||
// BDD reactants = BDD_TRUE;
|
|
||||||
// BDD inhibitors = BDD_TRUE;
|
|
||||||
|
|
||||||
// for (const auto &reactant : cond.rctt) {
|
|
||||||
// BDD proc_reactants = BDD_FALSE;
|
|
||||||
|
|
||||||
// for (unsigned int proc_id = 0; proc_id < numberOfProc; ++proc_id) {
|
|
||||||
// if (processUsesEntity(proc_id, reactant)) {
|
|
||||||
// proc_reactants += encProcEnabled(proc_id) * encEntityCondition(proc_id, reactant);
|
|
||||||
|
|
||||||
// VERB_LN(5, "| - if process " << rs->getProcessName(proc_id) << " is enabled and has " << rs->getEntityName(reactant));
|
|
||||||
|
|
||||||
// }
|
|
||||||
// } // END FOR: prod_id
|
|
||||||
|
|
||||||
// reactants *= proc_reactants;
|
|
||||||
// } // END FOR: reactant
|
|
||||||
|
|
||||||
// // For inhibitors, we take all the processes first and then we iterate over the inhibitors
|
|
||||||
// for (unsigned int proc_id = 0; proc_id < numberOfProc; ++proc_id) {
|
|
||||||
// BDD proc_inhibitors = BDD_TRUE;
|
|
||||||
|
|
||||||
// for (const auto &inhibitor : cond.inhib) {
|
|
||||||
// if (processUsesEntity(proc_id, inhibitor)) {
|
|
||||||
// proc_inhibitors *= !encEntityCondition(proc_id, inhibitor);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (proc_inhibitors != BDD_TRUE) { // just an optimisation
|
|
||||||
// proc_inhibitors += !encProcEnabled(proc_id);
|
|
||||||
// inhibitors *= proc_inhibitors;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// enab += reactants * inhibitors;
|
|
||||||
|
|
||||||
// } // END FOR: cond
|
|
||||||
|
|
||||||
// if (opts->reorder_trans) {
|
|
||||||
// VERB_L2("Reordering");
|
|
||||||
// Cudd_ReduceHeap(cuddMgr->getManager(), CUDD_REORDER_SIFT, 10000);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return enab;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
BDD SymRS::encEntitySameSuccessor(Process proc_id, Entity entity_id)
|
BDD SymRS::encEntitySameSuccessor(Process proc_id, Entity entity_id)
|
||||||
{
|
{
|
||||||
return BDD_IFF(encEntity(proc_id, entity_id), encEntitySucc(proc_id, entity_id));
|
return BDD_IFF(encEntity(proc_id, entity_id), encEntitySucc(proc_id, entity_id));
|
||||||
@@ -763,7 +714,7 @@ void SymRS::encodeTransitions(void)
|
|||||||
|
|
||||||
prod_conds.resize(numberOfProc);
|
prod_conds.resize(numberOfProc);
|
||||||
|
|
||||||
for (auto proc_id = 0; proc_id < numberOfProc; ++proc_id) {
|
for (unsigned int proc_id = 0; proc_id < numberOfProc; ++proc_id) {
|
||||||
prod_conds[proc_id] = getProductionConditions(proc_id);
|
prod_conds[proc_id] = getProductionConditions(proc_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
#include "macro.hh"
|
#include "macro.hh"
|
||||||
#include "bdd_macro.hh"
|
#include "bdd_macro.hh"
|
||||||
// #include "rs.hh"
|
|
||||||
#include "options.hh"
|
#include "options.hh"
|
||||||
#include "memtime.hh"
|
#include "memtime.hh"
|
||||||
|
|
||||||
@@ -240,16 +239,11 @@ class SymRS
|
|||||||
vector<BDDvec> *pv_proc_ctx;
|
vector<BDDvec> *pv_proc_ctx;
|
||||||
BDDvec *pv_proc_ctx_E;
|
BDDvec *pv_proc_ctx_E;
|
||||||
|
|
||||||
// TODO: remove
|
|
||||||
BDDvec *pv_act;
|
|
||||||
BDD *pv_act_E;
|
|
||||||
|
|
||||||
unsigned int totalEntities;
|
unsigned int totalEntities;
|
||||||
unsigned int numberOfProc; /*!< The number of DRS processes */
|
unsigned int numberOfProc; /*!< The number of DRS processes */
|
||||||
unsigned int totalStateVars;
|
unsigned int totalStateVars;
|
||||||
unsigned int totalRctSysStateVars; /*!< Total number of different entities produced by reactions */
|
unsigned int totalRctSysStateVars; /*!< Total number of different entities produced by reactions */
|
||||||
unsigned int totalCtxEntities; /*!< Total number of different (process,context) entities used */
|
unsigned int totalCtxEntities; /*!< Total number of different (process,context) entities used */
|
||||||
unsigned int totalActions;
|
|
||||||
unsigned int totalCtxAutStateVars;
|
unsigned int totalCtxAutStateVars;
|
||||||
|
|
||||||
EntitiesForProc usedProducts; /*!< Entities used in products (per process) */
|
EntitiesForProc usedProducts; /*!< Entities used in products (per process) */
|
||||||
@@ -309,17 +303,12 @@ class SymRS
|
|||||||
|
|
||||||
BDD encContext(const EntitiesForProc &proc_entities);
|
BDD encContext(const EntitiesForProc &proc_entities);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Complements an encoding of a given state by negating all the variables that are not set to true
|
|
||||||
*
|
|
||||||
* @return Returns the encoded state
|
|
||||||
*/
|
|
||||||
BDD compState(const BDD &state) const;
|
|
||||||
|
|
||||||
BDD compContext(const BDD &context) const;
|
BDD compContext(const BDD &context) const;
|
||||||
|
|
||||||
std::string decodedRctSysStateToStr(const BDD &state);
|
std::string decodedRctSysStateToStr(const BDD &state);
|
||||||
|
std::string decodedRctSysStateWithCtxAutToStr(const BDD &state);
|
||||||
void printDecodedRctSysStates(const BDD &states);
|
void printDecodedRctSysStates(const BDD &states);
|
||||||
|
void printDecodedRctSysWithCtxAutStates(const BDD &states);
|
||||||
|
|
||||||
DecompReactions getProductionConditions(Process proc_id);
|
DecompReactions getProductionConditions(Process proc_id);
|
||||||
|
|
||||||
|
|||||||
BIN
reactics-gui/resources/help/img/ctx-automaton-edge-details.png
Normal file
BIN
reactics-gui/resources/help/img/ctx-automaton-edge-details.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
BIN
reactics-gui/resources/help/img/ctx-automaton-panel.png
Normal file
BIN
reactics-gui/resources/help/img/ctx-automaton-panel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
BIN
reactics-gui/resources/help/img/ctx-automaton-state.png
Normal file
BIN
reactics-gui/resources/help/img/ctx-automaton-state.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
321
reactics-gui/resources/help/index.html
Normal file
321
reactics-gui/resources/help/index.html
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>ReactICS GUI Help</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<center><a name="top"><h1>ReactICS - Distributed Reaction Systems Model Checker</h1></a></center>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
<b>ReactICS</b> is a toolkit that allows for verification of Reaction Systems.
|
||||||
|
The toolkit consists of two separate modules implementing:
|
||||||
|
<ul>
|
||||||
|
<li>Methods using binary decision diagrams (BDD)
|
||||||
|
for storing and manipulating the state space of the verified system.</li>
|
||||||
|
<li>Methods translating the verification problems into satisfiability modulo theories (SMT).</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p align="justify">
|
||||||
|
<b>ReactICS GUI</b> offers a graphical user interface allowing for editing the reaction system details
|
||||||
|
and model checking using BDD module.
|
||||||
|
</p>
|
||||||
|
<p align="justify">
|
||||||
|
More on <b>ReactICS</b> can be found at <a href="https://reactics.org">The Reactics Webpage</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<hr/>
|
||||||
|
<h2>Table of contents</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#reaction-systems">Reaction systems</a><br/></li>
|
||||||
|
<li><a href="#gui">Application functions</a><br/></li>
|
||||||
|
<li><a href="#rs-edit">Reaction system editor</a><br/></li>
|
||||||
|
<li><a href="#ctx-edit">Context automaton editor</a><br/></li>
|
||||||
|
<li><a href="#trs-view">Transition system viewer</a><br/></li>
|
||||||
|
<li><a href="#model-checking">Model checking</a><br/></li>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="reaction-systems"><h2>Reaction Systems</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
<b>Reaction Systems</b> are a formalism inspired by the functioning of living cells.
|
||||||
|
They allow for specifying and analysing computational processes in which reactions operate on sets of molecules.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The behaviour of a reaction system is determined by the interactions of its reactions, which are based on
|
||||||
|
the mechanisms of facilitation and inhibition.
|
||||||
|
The formal treatment of reaction systems is qualitative and there is no direct representation of the number
|
||||||
|
of molecules involved in reactions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
A <b>Distributed Reaction System</b> is a computational model in which multiple autonomous processes (aka. agents)
|
||||||
|
interact locally through rule-based reactions.
|
||||||
|
Each agent operates independently (without any central controller—coordination),
|
||||||
|
processing inputs and producing outputs based on predefined reactions,
|
||||||
|
and their collective behavior leads to complex system dynamics.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
More on reaction system can be found at <a href="https://www.reactionsystems.org">The Reaction System Webpage</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="gui"><h2>Application functions</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
<b>ReactICS GUI</b> allows to:
|
||||||
|
<ul>
|
||||||
|
<li>Edit the reaction system structure (the number of processes/agents, reactions for each process/agent, etc.)</li>
|
||||||
|
<li>Edit the context automaton structure (adding/removing states and transitions,
|
||||||
|
edit context for active processes/agents, setting guards for transitions, etc.). </li>
|
||||||
|
<li>Preview of the state space represented as a transition system.</li>
|
||||||
|
<li>Verification of properties defined by formulas using rsCTLK semantics.</li>
|
||||||
|
<li>Save/load the reaction system structure to/from XML file.</li>
|
||||||
|
<li>Export/import the reaction system to/from RSSL file.</li>
|
||||||
|
<li>Export the reaction system structure and behaviour to ISPL file.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="rs-edit"><h2>Distributed reaction system editor</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The structure of distributed reaction system can be edited using the following buttons from the distributed reaction system control panel:
|
||||||
|
<center><img src="img/rs-ctrl-buttons.png"/></center>
|
||||||
|
<ul>
|
||||||
|
<li><b>New process</b> - Creates a new empty process.</li>
|
||||||
|
<li><b>Remove</b> - Removes selected processes.</li>
|
||||||
|
<li><b>Copy</b> - Makes copies of selected processes (together with all reactions).</li>
|
||||||
|
<li><b>Rename</b> - Renames a selected process. Note that process names should be unique.</li>
|
||||||
|
<li><b>Move up</b> - Moves selected process up the list of all processes.</li>
|
||||||
|
<li><b>Move down</b> - Moves selected process down the list of all processes.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The details of a single process can be edited using the following buttons in the process panel:
|
||||||
|
<center><img src="img/process-edit-button.png"/></center>
|
||||||
|
<ul>
|
||||||
|
<li><b>Add reaction</b> - Creates a new reaction. The details of the reaction should be specified in dialog shown below.</li>
|
||||||
|
<li><b>Edit reaction</b> - Allows to edit the details of a selected reaction using dialog shown below.</li>
|
||||||
|
<li><b>Remove reaction</b> - Removes a selected reaction.</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<center><img src="img/reaction-details.png"/></center>
|
||||||
|
<p align="justify">
|
||||||
|
Verification of formulas against a system specification is done after selecting desired formulas
|
||||||
|
and clicking <b>Evaluate</b> button.
|
||||||
|
The result of the verification (<b>True</b>/<b>False</b>), as well as time and memory used are presented next to each verified formula.
|
||||||
|
</p>
|
||||||
|
<center><img src="img/model-checking.png"/></center>
|
||||||
|
<p align="justify">
|
||||||
|
Clicking the <b>Reset</b> button resets the status of the model checking.
|
||||||
|
Note that updating the reaction system specification (the list of processes, details of the reactions or the content automaton structure)
|
||||||
|
the results of model checking, if any, are reset automatically.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="ctx-edit"><h2>Context automaton editor</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
To create or edit the context automaton structure a proper edit mode should be set using the <b>edit mode panel</b>.
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<center><img src="img/ctx-automaton-panel.png"/></center>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The type of the newly created object (state or edge) is set by checking the proper toggle button.
|
||||||
|
With no button checked, one can transform the net by moving states around, etc.
|
||||||
|
(see below for more details).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h3>States</h3>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
A new state is created by left-clicking the edit area (the main part of the component).
|
||||||
|
As it is customary in automata theory, states are numbered separately starting from 1.
|
||||||
|
The types of states are distinguished by shape and colour:
|
||||||
|
the initial state is depicted as a square, all other states are depicted as circles.
|
||||||
|
Moreover, hovering the mouse above a state allows to see its full description containing both
|
||||||
|
its name and its (distinct) number.
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<center><img src="img/ctx-automaton-state.png"/></center>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The details of a state can be edited by right-clicking the existing
|
||||||
|
state and choosing the right option from the popup menu:
|
||||||
|
<ul>
|
||||||
|
<li><b>Set as initial</b> - Makes the selected state the initial state of the context automaton.</li>
|
||||||
|
<li><b>Set label</b> - Allows to set the custom label for the selected state. Note that state labels have to be unique.</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<br/>
|
||||||
|
<center><img src="img/ctx-automaton-state.png"/></center>
|
||||||
|
|
||||||
|
<h3>Edges</h3>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
A directed edge between two states is created by left-clicking both its endpoints in correct order.
|
||||||
|
Each edge may contain several transitions, each of them defined by a <i>context</i> (additional entities
|
||||||
|
provided for active processes/agents) and a <i>guard</i> (a condition required by the transition to execute).
|
||||||
|
The list of transitions may be edited by right-clicking the existing
|
||||||
|
edge and choosing the <b>Nondeterministic transitions</b> popup menu.
|
||||||
|
</p>
|
||||||
|
<center><img src="img/ctx-automaton-transition-edit.png"/></center>
|
||||||
|
<p align="justify">
|
||||||
|
Hovering the mouse above an edge allows to see the full list of transitions
|
||||||
|
including context and guards.
|
||||||
|
</p>
|
||||||
|
<center><img src="img/ctx-automaton-edge-details.png"/></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h3>Removing context automaton elements</h3>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Switching the toggle button <b>Delete</b> on allows removing context automaton elements.
|
||||||
|
Each left-clicked element is removed from the automaton grapn.
|
||||||
|
Moreover, the entire context automaton graph may be deleted by clicking the <b>Clear</b> button.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h3>Transforming the context automaton graph</h3>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Any state of the automaton may be picked and dragged around the edit area to obtain the desired graph shape.
|
||||||
|
It is also possible to select multiple states and move them together at the same time.
|
||||||
|
After <b>CTRL + left-click</b> on a particular state the entire automaton graph is shifted to be centered
|
||||||
|
on the clicked state.
|
||||||
|
Checking the <b>Lock relative nodes positions</b> checkbox locks the relative positions of the states.
|
||||||
|
In that case, dragging a single state moves the entire automaton graph.
|
||||||
|
Moreover, using mouse scroll the automaton graph view can be zoomed in and out.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="trs-view"><h2>Transition system viewer</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The component offers the visualisation of the transition system representing the state space of the reaction systems.
|
||||||
|
The initial state is depicted as a square, all other states are depicted as circles.
|
||||||
|
There is a directed edge connecting the state S<sub>i</sub> to the state S<sub>j</sub>
|
||||||
|
if S<sub>f</sub> is reachable from S<sub>i</sub> by a single computation step of the reaction system.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
The component has two separate instances represented by two separate tabs in the application window.
|
||||||
|
The first visualises the complete state space of the reaction system,
|
||||||
|
where each state is represented by sets of entities possessed by each agent and the current context automaton state.
|
||||||
|
The second visualises the compressed state space, where context automaton states are ignored
|
||||||
|
(states are represented only by the sets of entities possessed by each agent).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Computation is done by pressing <b>Update transition system</b> button.
|
||||||
|
The reaction system structure should be loaded from the file or edited manually for the computation to be possible.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Note that no matter in which component the <b>Update transition system</b> button
|
||||||
|
is pressed, the transition system structure will be updated in both.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Hovering the mouse above a state allows to see its full description: entities possessed by each process/agent
|
||||||
|
and the context automaton state (not present in the case of the compressed graph).
|
||||||
|
</p>
|
||||||
|
<center><img src="img/ctx-automaton-edge-details.png"/></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<h3>Transforming the transition system graph</h3>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Any state of the transition system may be picked and dragged around the edit area to obtain the desired graph shape.
|
||||||
|
It is also possible to select multiple states and move them together at the same time.
|
||||||
|
After <b>CTRL + left-click</b> on a particular state the entire transition system graph is shifted to be centered
|
||||||
|
on the clicked state.
|
||||||
|
Checking the <b>Lock relative nodes positions</b> checkbox locks the relative positions of the states.
|
||||||
|
In that case, dragging a single state moves the entire transition system graph.
|
||||||
|
Moreover, using mouse scroll the transition system graph view can be zoomed in and out.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<a name="model-checking"><h2>Model checking</h2></a>
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<p align="justify">
|
||||||
|
Model checking is handled by the component at the bottom of the application window.
|
||||||
|
The properties of the analysed system are expressed as formulas following <b>rsCTLK</b> syntax.
|
||||||
|
</p>
|
||||||
|
<p align="justify">
|
||||||
|
The list of formulas may be modified using the following buttons:
|
||||||
|
<ul>
|
||||||
|
<li><b>Add formula</b> - Creates an empty formula. The details of the formula should be specified in dialog shown below.</li>
|
||||||
|
<li><b>Edit formula</b> - Allows to edit the details of a selected formula using dialog shown below.</li>
|
||||||
|
<li><b>Remove formulas</b> - Removes selected formulas.</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<center><img src="img/formula-details.png"/></center>
|
||||||
|
<p align="justify">
|
||||||
|
Verification of formulas against a system specification is done after selecting desired formulas
|
||||||
|
and clicking <b>Evaluate</b> button.
|
||||||
|
The result of the verification (<b>True</b>/<b>False</b>), as well as time and memory used are presented next to each verified formula.
|
||||||
|
</p>
|
||||||
|
<center><img src="img/model-checking.png"/></center>
|
||||||
|
<p align="justify">
|
||||||
|
Clicking the <b>Reset</b> button resets the status of the model checking.
|
||||||
|
Note that updating the reaction system specification (the list of processes, details of the reactions or the content automaton structure)
|
||||||
|
the results of model checking, if any, are reset automatically.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<center><a href="#top">Back to top</a></center>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3
reactics-gui/src/META-INF/MANIFEST.MF
Normal file
3
reactics-gui/src/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: pl.umk.mat.martinp.reactics.ReacticsGUI
|
||||||
|
|
||||||
@@ -0,0 +1,693 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.FRLayout;
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.Layout;
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.util.Relaxer;
|
||||||
|
import edu.uci.ics.jung.graph.Graph;
|
||||||
|
import edu.uci.ics.jung.graph.util.Context;
|
||||||
|
import edu.uci.ics.jung.graph.util.Pair;
|
||||||
|
import edu.uci.ics.jung.visualization.VisualizationViewer;
|
||||||
|
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
|
||||||
|
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
|
||||||
|
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
|
||||||
|
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
|
||||||
|
import edu.uci.ics.jung.visualization.picking.PickedState;
|
||||||
|
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
||||||
|
import org.apache.commons.collections15.Transformer;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.EtchedBorder;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
public class ContextAutomatonEditor extends JPanel implements RSObserver {
|
||||||
|
private enum EditorState {STATE, EDGE, DELETE, CLEAR, NONE}
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private ReactionSystem rs;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Visual configuration settings
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
private static final Color pickedNodeColor = Color.yellow;
|
||||||
|
//private static final Color pickedEdgeColor = Color.red;
|
||||||
|
private static final Color pickedEdgeColor = Color.black;
|
||||||
|
private static final Color edgeColor = Color.black;
|
||||||
|
private static final Color emptyEdgeColor = Color.lightGray;
|
||||||
|
private static final Font nodeLabelFont = new Font("Helvetica", Font.BOLD, 20);
|
||||||
|
private static final Font edgeLabelFont = new Font("Helvetica", Font.BOLD, 15);
|
||||||
|
private static final Font toolTipFont = new Font("Helvetica", Font.PLAIN, 14);
|
||||||
|
private static final float[] dash = {10.0f, 10.0f};
|
||||||
|
private static final Stroke basicEdgeStroke = new BasicStroke(3.0f,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
|
||||||
|
private static final Stroke emptyEdgeStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, dash, 0.f);
|
||||||
|
private static final Stroke basicEdgeArrow = new BasicStroke(3.0f);
|
||||||
|
private static final Stroke emptyEdgeArrow = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 10.0f, dash, 10.0f);
|
||||||
|
|
||||||
|
private static Dimension initialEditorSize;
|
||||||
|
|
||||||
|
private VisualizationViewer<CAState, CAEdge> graphViewer;
|
||||||
|
private Layout<CAState, CAEdge> gLayout;
|
||||||
|
DefaultModalGraphMouse graphMouse;
|
||||||
|
private ContextAutomatonGraph graph;
|
||||||
|
|
||||||
|
// Context menus for transitions, places and edges
|
||||||
|
private JPopupMenu stateContextMenu;
|
||||||
|
private JPopupMenu edgeContextMenu;
|
||||||
|
private TransitionEditor transitionEditor = null;
|
||||||
|
|
||||||
|
private EditorState edtState;
|
||||||
|
private Vector<EditorModeButton> modeButtons;
|
||||||
|
|
||||||
|
private CAState lastPickedNode = null;
|
||||||
|
|
||||||
|
|
||||||
|
public ContextAutomatonEditor(Dimension size) {
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
initialEditorSize = size;
|
||||||
|
|
||||||
|
edtState = EditorState.NONE;
|
||||||
|
graph = new ContextAutomatonGraph();
|
||||||
|
|
||||||
|
createGraphEditor();
|
||||||
|
createModeButtonsPanel();
|
||||||
|
createContextMenus();
|
||||||
|
|
||||||
|
rs = ReactionSystem.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModified() { return graph.isModified(); }
|
||||||
|
|
||||||
|
public void clearModificationStatus() { graph.clearModificationStatus(); }
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
return graph.toRSSLString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
updateNodesLocations();
|
||||||
|
graph.exportToXML(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFromXML(Document input) throws ContextAutomatonStructureError {
|
||||||
|
clear();
|
||||||
|
graph.loadFromXML(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void recalculateCoordinates() {
|
||||||
|
Layout<CAState, CAEdge> autoLayout = new FRLayout<CAState, CAEdge>(graph, graphViewer.getSize());
|
||||||
|
autoLayout.initialize();
|
||||||
|
|
||||||
|
for (CAState state : graph.getVertices()) {
|
||||||
|
Point2D pos = autoLayout.transform(state);
|
||||||
|
state.updateLocation(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
graph.clear();
|
||||||
|
|
||||||
|
for (EditorModeButton emb : modeButtons)
|
||||||
|
emb.setSelected(false);
|
||||||
|
|
||||||
|
graphViewer.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lockNodesPositions(boolean lock) {
|
||||||
|
if (lock)
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
|
||||||
|
else
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReactantsSet() { return graph.getReactantsSet(); }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Creates visualization viewer for context automaton graph display/edition
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
private void createGraphEditor() {
|
||||||
|
gLayout = new StaticLayout<CAState, CAEdge>(graph,
|
||||||
|
new Transformer<CAState, Point2D>() {
|
||||||
|
public Point2D transform(CAState node) {
|
||||||
|
return node.getLocation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer = new VisualizationViewer<CAState, CAEdge>(gLayout, initialEditorSize) {
|
||||||
|
public JToolTip createToolTip() {
|
||||||
|
JToolTip tooltip = super.createToolTip();
|
||||||
|
tooltip.setFont(toolTipFont);
|
||||||
|
return tooltip;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Nodes labels
|
||||||
|
graphViewer.getRenderContext().setVertexLabelTransformer(
|
||||||
|
new ToStringLabeller<CAState>());
|
||||||
|
graphViewer.getRenderer().getVertexLabelRenderer()
|
||||||
|
.setPosition(Renderer.VertexLabel.Position.CNTR);
|
||||||
|
graphViewer.getRenderContext().setVertexFontTransformer(
|
||||||
|
new Transformer<CAState,Font>() {
|
||||||
|
public Font transform(CAState v) {
|
||||||
|
return nodeLabelFont;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nodes colour, background, etc.
|
||||||
|
graphViewer.getRenderContext().setVertexIconTransformer(new Transformer<CAState,Icon>() {
|
||||||
|
public Icon transform(final CAState v) {
|
||||||
|
Color nodeColor = null;
|
||||||
|
|
||||||
|
if(graphViewer.getPickedVertexState().isPicked(v))
|
||||||
|
nodeColor = pickedNodeColor;
|
||||||
|
else
|
||||||
|
nodeColor = v.getFillColor();
|
||||||
|
|
||||||
|
return (v.isInitial() ? new SquareIcon(nodeColor, v.getWidth()) : new CircleIcon(nodeColor, v.getWidth()));
|
||||||
|
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Edge color, shape and weight
|
||||||
|
graphViewer.getRenderContext().setEdgeDrawPaintTransformer(new Transformer<CAEdge, Paint>() {
|
||||||
|
public Paint transform(CAEdge e) {
|
||||||
|
return edgeColor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setEdgeStrokeTransformer(new Transformer<CAEdge, Stroke>() {
|
||||||
|
public Stroke transform(CAEdge e) {
|
||||||
|
return basicEdgeStroke;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setEdgeArrowStrokeTransformer(new Transformer<CAEdge, Stroke>() {
|
||||||
|
public Stroke transform(CAEdge e) {
|
||||||
|
return basicEdgeArrow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setArrowFillPaintTransformer(new Transformer<CAEdge, Paint>() {
|
||||||
|
public Paint transform(CAEdge caEdge) {
|
||||||
|
if (caEdge.hasTransition())
|
||||||
|
return edgeColor;
|
||||||
|
else
|
||||||
|
return emptyEdgeColor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setEdgeShapeTransformer(new ConditionalEdgeShape<>(1.5f));
|
||||||
|
|
||||||
|
// Edge labels
|
||||||
|
graphViewer.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<CAEdge>());
|
||||||
|
graphViewer.getRenderContext().getEdgeLabelRenderer().setRotateEdgeLabels(true);
|
||||||
|
graphViewer.getRenderContext().setLabelOffset(20);
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setEdgeFontTransformer(new Transformer<CAEdge, Font>() {
|
||||||
|
public Font transform(CAEdge CAEdge) {
|
||||||
|
return edgeLabelFont;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// For interactive graph editing
|
||||||
|
graphMouse = new DefaultModalGraphMouse();
|
||||||
|
graphViewer.setGraphMouse(graphMouse);
|
||||||
|
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
|
||||||
|
|
||||||
|
graphViewer.setVertexToolTipTransformer(new Transformer<CAState, String>() {
|
||||||
|
public String transform(CAState caState) {
|
||||||
|
return caState.getTooltipText();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.setEdgeToolTipTransformer(new Transformer<CAEdge, String>() {
|
||||||
|
public String transform(CAEdge caEdge) {
|
||||||
|
return caEdge.getTooltipText();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.setBackground(Color.white);
|
||||||
|
graphViewer.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
|
||||||
|
graphViewer.addMouseListener(new EditorMouseListener());
|
||||||
|
|
||||||
|
add(graphViewer,BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Create panel with buttons alowing editing mode choice
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
private void createModeButtonsPanel() {
|
||||||
|
modeButtons = new Vector<EditorModeButton>();
|
||||||
|
modeButtons.add(new EditorModeButton("STATE",new CircleIcon(CAState.baseFillColor, 15), EditorState.STATE, 0));
|
||||||
|
modeButtons.add(new EditorModeButton("EDGE", EditorState.EDGE, 1));
|
||||||
|
modeButtons.add(new EditorModeButton("DELETE", EditorState.DELETE, 2));
|
||||||
|
modeButtons.add(new EditorModeButton("CLEAR", EditorState.CLEAR, 3));
|
||||||
|
|
||||||
|
ModeButtonsListener mbListener = new ModeButtonsListener();
|
||||||
|
|
||||||
|
for(int i=0;i<modeButtons.size();++i)
|
||||||
|
modeButtons.elementAt(i).addActionListener(mbListener);
|
||||||
|
|
||||||
|
JPanel btnPanel = new JPanel();
|
||||||
|
btnPanel.setLayout(new FlowLayout());
|
||||||
|
|
||||||
|
for(int i=0;i<modeButtons.size();++i)
|
||||||
|
btnPanel.add(modeButtons.elementAt(i));
|
||||||
|
|
||||||
|
JCheckBox posLockCBox = new JCheckBox("Lock relative nodes positions");
|
||||||
|
posLockCBox.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
lockNodesPositions(posLockCBox.isSelected());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
btnPanel.add(posLockCBox);
|
||||||
|
|
||||||
|
add(btnPanel,BorderLayout.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Create context menus for transitions, places and edges
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
private void createContextMenus() {
|
||||||
|
stateContextMenu = new JPopupMenu();
|
||||||
|
|
||||||
|
JMenuItem stateInitialItem = new JMenuItem("Set as initial");
|
||||||
|
stateInitialItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
PickedState<CAState> pickedVertexState = graphViewer.getPickedVertexState();
|
||||||
|
Set<CAState> pickedNodes = pickedVertexState.getPicked();
|
||||||
|
Iterator<CAState> it = pickedNodes.iterator();
|
||||||
|
|
||||||
|
if(!it.hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAState editedNode = it.next();
|
||||||
|
pickedVertexState.clear();
|
||||||
|
|
||||||
|
graph.setInitialState(editedNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JMenuItem setLabelItem = new JMenuItem("Set label");
|
||||||
|
setLabelItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
PickedState<CAState> pickedVertexState = graphViewer.getPickedVertexState();
|
||||||
|
Set<CAState> pickedNodes = pickedVertexState.getPicked();
|
||||||
|
Iterator<CAState> it = pickedNodes.iterator();
|
||||||
|
|
||||||
|
if(!it.hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAState state = it.next();
|
||||||
|
pickedVertexState.clear();
|
||||||
|
|
||||||
|
showStateLabelEditDialog(state);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stateContextMenu.add(stateInitialItem);
|
||||||
|
stateContextMenu.add(setLabelItem);
|
||||||
|
stateContextMenu.setVisible(false);
|
||||||
|
|
||||||
|
edgeContextMenu = new JPopupMenu();
|
||||||
|
JMenuItem edgeLabelEditItem = new JMenuItem("Nondeterministic transitions");
|
||||||
|
edgeLabelEditItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
PickedState<CAEdge> pickedEdgeState = graphViewer.getPickedEdgeState();
|
||||||
|
Set<CAEdge> pickedEdges = pickedEdgeState.getPicked();
|
||||||
|
Iterator<CAEdge> it = pickedEdges.iterator();
|
||||||
|
|
||||||
|
if(!it.hasNext()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAEdge editedEdge = it.next();
|
||||||
|
pickedEdgeState.clear();
|
||||||
|
showEdgeLabelEditDialog(editedEdge);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
edgeContextMenu.add(edgeLabelEditItem);
|
||||||
|
edgeContextMenu.setVisible(false);
|
||||||
|
|
||||||
|
transitionEditor = new TransitionEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showStateLabelEditDialog(CAState state) {
|
||||||
|
String idRegex = "[a-zA-Z][a-zA-Z_0-9:-]*";
|
||||||
|
boolean idOk = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
String newLabel = JOptionPane.showInputDialog(this, "State label", state.getLabel());
|
||||||
|
|
||||||
|
if (newLabel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
newLabel = newLabel.trim();
|
||||||
|
|
||||||
|
if (!newLabel.matches(idRegex)) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"<html>State label should start with a letter and may contain only:<br/>" +
|
||||||
|
"letters, numbers, colons (:), underscores (_) and hyphens (-)</html>",
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idOk = true;
|
||||||
|
state.setLabel(newLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!idOk);
|
||||||
|
|
||||||
|
graph.markAsModified();
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Creates a simple dialog window for editing edge labels
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
private void showEdgeLabelEditDialog(CAEdge edge) {
|
||||||
|
Pair<CAState> endPoints = graph.getEndpoints(edge);
|
||||||
|
transitionEditor.showTransitionEditDialog(this, edge.getTransitions(), endPoints.getFirst().getLabel(), endPoints.getSecond().getLabel());
|
||||||
|
graph.markAsModified();
|
||||||
|
graphViewer.repaint();
|
||||||
|
rs.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates coordinates stored in each graph node (eg. after interactive graph modification).
|
||||||
|
* Called before each storing net structure to the file. */
|
||||||
|
private void updateNodesLocations() {
|
||||||
|
Collection<CAState> nodes = graph.getVertices();
|
||||||
|
|
||||||
|
for(CAState n : nodes) {
|
||||||
|
n.updateLocation(gLayout.transform(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** For better vertex placement */
|
||||||
|
private void relax() {
|
||||||
|
Layout<CAState, CAEdge> layout = graphViewer.getGraphLayout();
|
||||||
|
layout.initialize();
|
||||||
|
layout.setSize(graphViewer.getSize());
|
||||||
|
Relaxer relaxer = graphViewer.getModel().getRelaxer();
|
||||||
|
if (relaxer != null) {
|
||||||
|
relaxer.stop();
|
||||||
|
relaxer.prerelax();
|
||||||
|
relaxer.relax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRSUpdate() {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
static class EditorModeButton extends JToggleButton {
|
||||||
|
private EditorState mode;
|
||||||
|
int seqNum;
|
||||||
|
|
||||||
|
public EditorModeButton(String label, EditorState mode) {
|
||||||
|
super(label);
|
||||||
|
|
||||||
|
this.mode = mode;
|
||||||
|
seqNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorModeButton(String label, EditorState mode, int seqNum) {
|
||||||
|
super(label);
|
||||||
|
|
||||||
|
this.mode = mode;
|
||||||
|
this.seqNum = seqNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorModeButton(String label, Icon icon, EditorState mode, int seqNum) {
|
||||||
|
super(label, icon);
|
||||||
|
|
||||||
|
this.mode = mode;
|
||||||
|
this.seqNum = seqNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditorState getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSeqNum() {
|
||||||
|
return seqNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class ModeButtonsListener implements ActionListener {
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent changeEvent) {
|
||||||
|
EditorModeButton emb = (EditorModeButton) changeEvent.getSource();
|
||||||
|
|
||||||
|
if(emb.isSelected()) {
|
||||||
|
int num = emb.getSeqNum();
|
||||||
|
|
||||||
|
for(int i=0;i<modeButtons.size();++i)
|
||||||
|
if(i != num || emb.mode == EditorState.CLEAR)
|
||||||
|
modeButtons.elementAt(i).setSelected(false);
|
||||||
|
|
||||||
|
edtState = emb.getMode();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
edtState = EditorState.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edtState == EditorState.CLEAR) {
|
||||||
|
graph.clear();
|
||||||
|
repaint();
|
||||||
|
edtState = EditorState.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// Mouse event handler. To allow interactive net editing
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
class EditorMouseListener extends MouseAdapter {
|
||||||
|
|
||||||
|
public void mouseClicked(MouseEvent me) {
|
||||||
|
int btnClicked = me.getButton();
|
||||||
|
|
||||||
|
if(btnClicked == MouseEvent.BUTTON1)
|
||||||
|
leftButtonClicked(me);
|
||||||
|
else if(btnClicked == MouseEvent.BUTTON3)
|
||||||
|
rightButtonClicked(me);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leftButtonClicked(MouseEvent me) {
|
||||||
|
Point clickPt = me.getPoint();
|
||||||
|
GraphElementAccessor<CAState, CAEdge> pickSupport = null;
|
||||||
|
Layout<CAState, CAEdge> layout = null;
|
||||||
|
CAState node = null;
|
||||||
|
CAEdge edge = null;
|
||||||
|
|
||||||
|
switch(edtState) {
|
||||||
|
case STATE:
|
||||||
|
try {
|
||||||
|
// Transform screen coordinates to layout coordinates.
|
||||||
|
// Necessary for possible automaton structure viewer scaling.
|
||||||
|
Point2D nodeLocation = graphViewer.getRenderContext().getMultiLayerTransformer().inverseTransform(clickPt);
|
||||||
|
graph.addState(new CAState(nodeLocation));
|
||||||
|
} catch (ContextAutomatonStructureError e) {
|
||||||
|
JOptionPane.showMessageDialog(null,
|
||||||
|
e.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EDGE:
|
||||||
|
PickedState<CAState> pickedVertexState = graphViewer.getPickedVertexState();
|
||||||
|
|
||||||
|
pickSupport = graphViewer.getPickSupport();
|
||||||
|
layout = graphViewer.getGraphLayout();
|
||||||
|
node = pickSupport.getVertex(layout, clickPt.getX(), clickPt.getY());
|
||||||
|
|
||||||
|
if (node != null) {
|
||||||
|
if (lastPickedNode == null) {
|
||||||
|
lastPickedNode = node;
|
||||||
|
} else {
|
||||||
|
graph.addEdge(lastPickedNode, node);
|
||||||
|
lastPickedNode = null;
|
||||||
|
pickedVertexState.pick(node,false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lastPickedNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DELETE:
|
||||||
|
pickSupport = graphViewer.getPickSupport();
|
||||||
|
layout = graphViewer.getGraphLayout();
|
||||||
|
node = pickSupport.getVertex(layout, clickPt.getX(), clickPt.getY());
|
||||||
|
edge = pickSupport.getEdge(layout, clickPt.getX(), clickPt.getY());
|
||||||
|
|
||||||
|
if (node != null) {
|
||||||
|
Collection<CAEdge> edges = graph.getIncidentEdges(node);
|
||||||
|
|
||||||
|
for (CAEdge e : edges)
|
||||||
|
rs.removeCAEdge(e);
|
||||||
|
|
||||||
|
graph.removeState(node);
|
||||||
|
}
|
||||||
|
else if (edge != null) {
|
||||||
|
graph.removeEdge(edge);
|
||||||
|
rs.removeCAEdge(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
me.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rightButtonClicked(MouseEvent me) {
|
||||||
|
GraphElementAccessor<CAState, CAEdge> pickSupport = graphViewer.getPickSupport();
|
||||||
|
Layout<CAState, CAEdge> layout = graphViewer.getGraphLayout();
|
||||||
|
CAState node = pickSupport.getVertex(layout, me.getX(), me.getY());
|
||||||
|
CAEdge edge = pickSupport.getEdge(layout, me.getX(), me.getY());
|
||||||
|
|
||||||
|
if (node != null) {
|
||||||
|
PickedState<CAState> pickedVertexState = graphViewer.getPickedVertexState();
|
||||||
|
pickedVertexState.clear();
|
||||||
|
pickedVertexState.pick(node,true);
|
||||||
|
stateContextMenu.show(graphViewer, me.getX(), me.getY());
|
||||||
|
}
|
||||||
|
else if (edge != null) {
|
||||||
|
PickedState<CAEdge> pickedEdgeState = graphViewer.getPickedEdgeState();
|
||||||
|
pickedEdgeState.clear();
|
||||||
|
pickedEdgeState.pick(edge, true);
|
||||||
|
edgeContextMenu.show(graphViewer, me.getX(), me.getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
me.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// For drawing the initial state
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static class SquareIcon implements Icon {
|
||||||
|
private Color fillColor;
|
||||||
|
private int width;
|
||||||
|
|
||||||
|
public SquareIcon(Color fColor, int width) {
|
||||||
|
fillColor = fColor;
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(fillColor);
|
||||||
|
g.fillRect(x, y, width, width);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.drawRect(x, y, width, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconHeight() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// For drawing all non-initial states
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static class CircleIcon implements Icon {
|
||||||
|
private Color fillColor;
|
||||||
|
private int radius;
|
||||||
|
|
||||||
|
public CircleIcon(Color fColor, int radius) {
|
||||||
|
fillColor = fColor;
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(fillColor);
|
||||||
|
g.fillOval(x, y, radius, radius);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.drawOval(x, y, radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconWidth() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconHeight() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConditionalEdgeShape<V, E> implements Transformer<Context<Graph<V, E>, E>, Shape> {
|
||||||
|
|
||||||
|
private final EdgeShape.Loop<V, E> loopShape;
|
||||||
|
private final Transformer<Context<Graph<V, E>, E>, Shape> defaultShape;
|
||||||
|
private final float loopScale;
|
||||||
|
|
||||||
|
public ConditionalEdgeShape(float loopScale) {
|
||||||
|
this.loopShape = new EdgeShape.Loop<>();
|
||||||
|
this.defaultShape = new EdgeShape.QuadCurve<>(); // or Line<>
|
||||||
|
this.loopScale = loopScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape transform(Context<Graph<V, E>, E> context) {
|
||||||
|
Graph<V, E> graph = context.graph;
|
||||||
|
E edge = context.element;
|
||||||
|
V src = graph.getSource(edge);
|
||||||
|
V dst = graph.getDest(edge);
|
||||||
|
|
||||||
|
if (src.equals(dst)) {
|
||||||
|
// Scale the self-loop
|
||||||
|
Shape baseLoop = loopShape.transform(context);
|
||||||
|
|
||||||
|
Rectangle bounds = baseLoop.getBounds();
|
||||||
|
double centerX = bounds.getCenterX();
|
||||||
|
double centerY = bounds.getCenterY();
|
||||||
|
|
||||||
|
AffineTransform at = new AffineTransform();
|
||||||
|
at.translate(centerX, centerY);
|
||||||
|
at.scale(loopScale, loopScale);
|
||||||
|
at.translate(-centerX, -centerY);
|
||||||
|
|
||||||
|
return at.createTransformedShape(baseLoop);
|
||||||
|
} else {
|
||||||
|
return defaultShape.transform(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,438 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
|
||||||
|
import edu.uci.ics.jung.graph.DirectedSparseGraph;
|
||||||
|
import edu.uci.ics.jung.graph.util.Pair;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
class ContextAutomatonGraph extends DirectedSparseGraph<CAState, CAEdge> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
HashMap<Integer, CAState> states = new HashMap<>();
|
||||||
|
private CAState initialState = null;
|
||||||
|
boolean modified = false;
|
||||||
|
|
||||||
|
public ContextAutomatonGraph() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModified() { return modified; }
|
||||||
|
|
||||||
|
public void markAsModified() { modified = true; }
|
||||||
|
|
||||||
|
public void clearModificationStatus() { modified = false; }
|
||||||
|
|
||||||
|
String toRSSLString() {
|
||||||
|
StringBuilder rsslString = new StringBuilder("context-automaton {\n");
|
||||||
|
|
||||||
|
rsslString.append(" states { ");
|
||||||
|
Collection<CAState> allStates = states.values();
|
||||||
|
Iterator<CAState> it = allStates.iterator();
|
||||||
|
if (it.hasNext()) {
|
||||||
|
rsslString.append(it.next().getLabel());
|
||||||
|
}
|
||||||
|
while (it.hasNext()) {
|
||||||
|
rsslString.append(", ").append(it.next().getLabel());
|
||||||
|
}
|
||||||
|
rsslString.append(" };\n");
|
||||||
|
|
||||||
|
rsslString.append(" init-state { ").append(initialState != null ? initialState.getLabel() : "").append(" };\n");
|
||||||
|
rsslString.append(" transitions {\n");
|
||||||
|
|
||||||
|
for (CAEdge edge : this.getEdges()) {
|
||||||
|
for (Transition tr : edge.getTransitions()) {
|
||||||
|
rsslString.append(" { ").append(tr.context).append(" }: ");
|
||||||
|
rsslString.append(this.getSource(edge).label).append(" -> ").append(this.getDest(edge).label);
|
||||||
|
|
||||||
|
String guard = tr.guard;
|
||||||
|
|
||||||
|
if (guard.length() > 0) {
|
||||||
|
rsslString.append(" : ").append(guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
rsslString.append(";\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rsslString.append(" };\n");
|
||||||
|
|
||||||
|
rsslString.append("};\n");
|
||||||
|
|
||||||
|
return rsslString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
output.println(" <context-automaton>");
|
||||||
|
|
||||||
|
for (CAState state : states.values()) {
|
||||||
|
Point2D pos = state.getLocation();
|
||||||
|
output.print(" <state");
|
||||||
|
output.print(" id=\"" + state.getId() + "\"");
|
||||||
|
output.print(" name=\"" + state.getLabel() + "\"");
|
||||||
|
output.print(" x=\"" + pos.getX() + "\"");
|
||||||
|
output.print(" y=\"" + pos.getY() + "\"");
|
||||||
|
|
||||||
|
if (state.isInitial())
|
||||||
|
output.print(" initial=\"true\"");
|
||||||
|
|
||||||
|
output.println("/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CAEdge edge : edges.keySet()) {
|
||||||
|
Pair<CAState> endPts = this.getEndpoints(edge);
|
||||||
|
output.print(" <edge");
|
||||||
|
output.print(" from=\"" + endPts.getFirst().getLabel() + "\"");
|
||||||
|
output.print(" to=\"" + endPts.getSecond().getLabel() + "\"");
|
||||||
|
output.println(">");
|
||||||
|
|
||||||
|
for (Transition tr : edge.getTransitions()) {
|
||||||
|
output.print(" <transition");
|
||||||
|
output.print(" context=\"" + tr.context + "\"");
|
||||||
|
output.print(" guard=\"" + tr.guard + "\"");
|
||||||
|
output.println("/>");
|
||||||
|
}
|
||||||
|
output.println(" </edge>");
|
||||||
|
}
|
||||||
|
|
||||||
|
output.println(" </context-automaton>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the context automaton structure from the XML file.
|
||||||
|
*
|
||||||
|
* @param input An XML file containing a valid description of a context automaton.
|
||||||
|
* @throws ContextAutomatonStructureError In the case of <b>inputFile</b> structure error, eg. \
|
||||||
|
* more than one context-automaton section, more than one \
|
||||||
|
* initial state, repeating state identifiers, \
|
||||||
|
* edge between non-existing nodes, etc.
|
||||||
|
*/
|
||||||
|
public void loadFromXML(Document input) throws ContextAutomatonStructureError {
|
||||||
|
NodeList caSections = input.getElementsByTagName("context-automaton");
|
||||||
|
|
||||||
|
if (caSections.getLength() == 0 || caSections.getLength() > 1) {
|
||||||
|
throw new ContextAutomatonStructureError("An XML file should contain a single context automaton description.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
// Retrieve the states
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
HashMap<String, CAState> states = new HashMap<String, CAState>();
|
||||||
|
NodeList stateList = input.getElementsByTagName("state");
|
||||||
|
boolean hasInitialState = false;
|
||||||
|
|
||||||
|
for (int idx = 0; idx < stateList.getLength(); ++idx) {
|
||||||
|
Node stateNode = stateList.item(idx);
|
||||||
|
|
||||||
|
if (stateNode.getNodeType() != Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element stateElement = (Element) stateNode;
|
||||||
|
|
||||||
|
int id = Integer.parseInt(stateElement.getAttribute("id"));
|
||||||
|
double x = Double.parseDouble(stateElement.getAttribute("x"));
|
||||||
|
double y = Double.parseDouble(stateElement.getAttribute("y"));
|
||||||
|
String name = stateElement.getAttribute("name");
|
||||||
|
String initial = stateElement.getAttribute("initial");
|
||||||
|
|
||||||
|
if (states.containsKey(name)) {
|
||||||
|
throw new ContextAutomatonStructureError("State name <" + name + "> already used.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CAState newState = new CAState(id, name, new Point2D.Double(x, y));
|
||||||
|
this.addState(newState);
|
||||||
|
states.put(name, newState);
|
||||||
|
|
||||||
|
if (initial.equals("true")) {
|
||||||
|
if (hasInitialState)
|
||||||
|
throw new ContextAutomatonStructureError("There should not be more than one initial state.");
|
||||||
|
|
||||||
|
hasInitialState = true;
|
||||||
|
this.setInitialState(newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
// Retrieve the edges
|
||||||
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NodeList edgeList = input.getElementsByTagName("edge");
|
||||||
|
|
||||||
|
for (int idx = 0; idx < edgeList.getLength(); ++idx) {
|
||||||
|
Node edgeNode = edgeList.item(idx);
|
||||||
|
|
||||||
|
if (edgeNode.getNodeType() != Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element edgeElement = (Element) edgeNode;
|
||||||
|
|
||||||
|
String from = edgeElement.getAttribute("from");
|
||||||
|
String to = edgeElement.getAttribute("to");
|
||||||
|
|
||||||
|
// Retrieve all child nodes describing nondeterministic transitions related to this edge
|
||||||
|
NodeList childNodeList = edgeNode.getChildNodes();
|
||||||
|
Vector<Transition> transitionList = new Vector<Transition>();
|
||||||
|
|
||||||
|
for (int cIdx=0; cIdx < childNodeList.getLength(); ++ cIdx) {
|
||||||
|
Node childNode = childNodeList.item(cIdx);
|
||||||
|
|
||||||
|
if (childNode.getNodeType() != Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element transElement = (Element) childNode;
|
||||||
|
transitionList.add(new Transition(transElement.getAttribute("context"), transElement.getAttribute("guard")));
|
||||||
|
}
|
||||||
|
|
||||||
|
CAState stateFrom = states.get(from);
|
||||||
|
CAState stateTo = states.get(to);
|
||||||
|
|
||||||
|
if (stateFrom == null || stateTo == null)
|
||||||
|
throw new ContextAutomatonStructureError("An edge may be created only between existing nodes.");
|
||||||
|
|
||||||
|
this.addEdge(stateFrom, stateTo, transitionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReactantsSet() {
|
||||||
|
Set<String> reactants = new HashSet<String>();
|
||||||
|
|
||||||
|
for (CAEdge edge : getEdges()) {
|
||||||
|
for (Transition trans : edge.getTransitions()) {
|
||||||
|
int start = trans.context.indexOf("{");
|
||||||
|
int end = trans.context.indexOf("}");
|
||||||
|
|
||||||
|
if (start != -1 && end != -1 && start < end) {
|
||||||
|
reactants.addAll(Arrays.asList(trans.context.substring(start + 1, end).split("\\s*,\\s*")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reactants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialState(CAState state) {
|
||||||
|
if (initialState != null)
|
||||||
|
initialState.setInitial(false);
|
||||||
|
|
||||||
|
state.setInitial(true);
|
||||||
|
initialState = state;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CAState getInitialState() {
|
||||||
|
return initialState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the entire automaton structure structure
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
for (CAState st : states.values())
|
||||||
|
removeVertex(st);
|
||||||
|
|
||||||
|
states.clear();
|
||||||
|
CAState.resetIdCounter();
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean addEdge(CAState from, CAState to) {
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
return this.addEdge(new CAEdge(), from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEdge(CAState from, CAState to, Collection<Transition> transitionList) {
|
||||||
|
CAEdge edge = this.findEdge(from, to);
|
||||||
|
|
||||||
|
if (edge == null) {
|
||||||
|
CAEdge caEdge = ReactionSystem.getInstance().createCAEdge();
|
||||||
|
caEdge.addTransitions(transitionList);
|
||||||
|
this.addEdge(caEdge, from, to);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
edge.addTransitions(transitionList);
|
||||||
|
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addState(CAState state) throws ContextAutomatonStructureError {
|
||||||
|
int stateId = state.getId();
|
||||||
|
|
||||||
|
if (states.get(stateId) != null)
|
||||||
|
throw new ContextAutomatonStructureError("State id " + stateId + " already in use.");
|
||||||
|
|
||||||
|
states.put(stateId, state);
|
||||||
|
this.addVertex(state);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeState(CAState state) {
|
||||||
|
if (states.get(state.getId()) != null) {
|
||||||
|
states.remove(state.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
modified = true;
|
||||||
|
|
||||||
|
// Remove the state with all connected edges
|
||||||
|
return this.removeVertex(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Single node of the context automaton graph
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CAState {
|
||||||
|
public final static Color baseFillColor = Color.lightGray;
|
||||||
|
public final static Color selectedFillColor = Color.lightGray;
|
||||||
|
public final static Color initStateFillColor = new Color(102, 178, 255);
|
||||||
|
|
||||||
|
private static final int nodeWidth = 30;
|
||||||
|
private static final int nodeHeight = 30;
|
||||||
|
protected static int nextId = 1;
|
||||||
|
|
||||||
|
/** Unique auto incremented identifier of the node */
|
||||||
|
protected int id;
|
||||||
|
|
||||||
|
/** User defined label of the node displayed as a tool tip and used in RSSL and XML files */
|
||||||
|
protected String label;
|
||||||
|
|
||||||
|
protected Point2D location;
|
||||||
|
private boolean isInitial = false;
|
||||||
|
|
||||||
|
/** A state created from the description stored in a file. */
|
||||||
|
public CAState(int id, String label, Point2D location) {
|
||||||
|
this.id = id;
|
||||||
|
this.label = label;
|
||||||
|
this.location = location;
|
||||||
|
|
||||||
|
// To avoid duplicate node identifiers
|
||||||
|
if (id >= nextId)
|
||||||
|
nextId = id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A state created by clicking in graphical component. */
|
||||||
|
public CAState(Point2D location) {
|
||||||
|
this.id = nextId;
|
||||||
|
this.label = "q" + id;
|
||||||
|
this.location = location;
|
||||||
|
++nextId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getLocation() { return location; }
|
||||||
|
public void updateLocation(Point2D location) { this.location = location; }
|
||||||
|
|
||||||
|
public boolean isInitial() { return isInitial; }
|
||||||
|
public void setInitial(boolean status) { isInitial = status; }
|
||||||
|
|
||||||
|
public int getWidth() { return nodeWidth; }
|
||||||
|
public int getHeight() { return nodeHeight; }
|
||||||
|
|
||||||
|
public String getLabel() { return label; }
|
||||||
|
public void setLabel(String newLabel) { label = newLabel; }
|
||||||
|
|
||||||
|
public int getId() { return id; }
|
||||||
|
|
||||||
|
static void resetIdCounter() { nextId = 1; }
|
||||||
|
|
||||||
|
public String toString() { return Integer.toString(id); }
|
||||||
|
|
||||||
|
public String getTooltipText() {
|
||||||
|
return "<html>"+
|
||||||
|
"<b>State</b> " + id + "<br/><hr>" + getLabel() + //"<hr>"+
|
||||||
|
"</html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getFillColor() {
|
||||||
|
return isInitial ? initStateFillColor : baseFillColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Single edge of the context automaton graph.
|
||||||
|
// Each edge can represent a number of single transitions between the same pair of automaton states.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CAEdge {
|
||||||
|
protected static int nextId = 0;
|
||||||
|
|
||||||
|
protected int id;
|
||||||
|
|
||||||
|
// The list of all nondeterministic transitions represented by this edge
|
||||||
|
private Vector<Transition> transitions = new Vector<Transition>();
|
||||||
|
|
||||||
|
public boolean hasTransition() { return transitions.size() > 0; }
|
||||||
|
|
||||||
|
|
||||||
|
public CAEdge() {
|
||||||
|
this.id = nextId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public CAEdge(Collection<Transition> transitionList) {
|
||||||
|
// this.transitions.addAll(transitionList);
|
||||||
|
// }
|
||||||
|
|
||||||
|
Vector<Transition> getTransitions() {
|
||||||
|
return transitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
// Update this if you need any label displayed together with graph edge
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooltipText() {
|
||||||
|
StringBuilder tooTip = new StringBuilder("<html><hr/><center><b>Context <font color=\"red\">:</font> Guard</b></center><hr/>");
|
||||||
|
|
||||||
|
for (Transition tr : transitions) {
|
||||||
|
tooTip.append(tr.context).append(" <b><font color=\"red\">:</font></b> ").append(tr.guard).append("<br/><hr/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
tooTip.append("</html>");
|
||||||
|
|
||||||
|
return tooTip.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTransitions(Collection<Transition> transitionList) {
|
||||||
|
transitions.addAll(transitionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Single transition. To be included in a multiedge.
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Transition {
|
||||||
|
String context;
|
||||||
|
String guard;
|
||||||
|
|
||||||
|
public Transition(String ctx, String grd) {
|
||||||
|
context = ctx;
|
||||||
|
guard = grd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ContextAutomatonStructureError extends FileStructureError {
|
||||||
|
public ContextAutomatonStructureError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class CumulatedReactionsViewer extends JPanel {
|
||||||
|
|
||||||
|
public CumulatedReactionsViewer() {
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
this.add(new JLabel("Cumulate Reactions Viewer", SwingConstants.CENTER), BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
410
reactics-gui/src/pl/umk/mat/martinp/reactics/FormulaEditor.java
Normal file
410
reactics-gui/src/pl/umk/mat/martinp/reactics/FormulaEditor.java
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.Border;
|
||||||
|
import javax.swing.border.EtchedBorder;
|
||||||
|
import javax.swing.event.TableModelEvent;
|
||||||
|
import javax.swing.event.TableModelListener;
|
||||||
|
import javax.swing.table.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
public class FormulaEditor extends JPanel implements RSObserver {
|
||||||
|
private FormulaTableModel ftModel;
|
||||||
|
private JTable formTable;
|
||||||
|
private ReactionSystem rs;
|
||||||
|
private Vector<Formula> formulaList;
|
||||||
|
|
||||||
|
boolean modified = false;
|
||||||
|
|
||||||
|
static final Color TableHeaderBackgroundColor = Color.gray;
|
||||||
|
static final Color TableHeaderFontColor = Color.white;
|
||||||
|
static final Color BaseFormulaBackgroundColor = Color.white;
|
||||||
|
static final Color TrueFormulaBackgroundColor = new Color(138, 242, 183);
|
||||||
|
static final Color FalseFormulaBackgroundColor = new Color(240, 141, 141);
|
||||||
|
static final Color InvalidFormulaBackgroundColor = new Color(124, 124, 124);
|
||||||
|
static final Border emptyBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1);
|
||||||
|
static final Border selectedBorder = BorderFactory.createLineBorder(Color.RED, 2);
|
||||||
|
|
||||||
|
|
||||||
|
public FormulaEditor(ReactionSystem rs) {
|
||||||
|
this.rs = rs;
|
||||||
|
formulaList = rs.formulas;
|
||||||
|
|
||||||
|
// Create the table for displaying formulas. Prevent default selection modes.
|
||||||
|
ftModel = new FormulaTableModel();
|
||||||
|
formTable = new JTable(ftModel, new FormulaColumnModel());
|
||||||
|
formTable.setCellSelectionEnabled(false);
|
||||||
|
formTable.setRowSelectionAllowed(true);
|
||||||
|
|
||||||
|
Font headerFont = formTable.getTableHeader().getFont();
|
||||||
|
Font cellFont = formTable.getFont();
|
||||||
|
JTableHeader formHeader = formTable.getTableHeader();
|
||||||
|
formTable.setFont(new Font("Monospaced", Font.PLAIN, cellFont.getSize() + 2));
|
||||||
|
formHeader.setFont(new Font(headerFont.getFamily(), Font.BOLD, headerFont.getSize() + 2));
|
||||||
|
formHeader.setBackground(TableHeaderBackgroundColor);
|
||||||
|
formHeader.setForeground(TableHeaderFontColor);
|
||||||
|
formHeader.setReorderingAllowed(false);
|
||||||
|
formHeader.setResizingAllowed(true);
|
||||||
|
formHeader.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
|
||||||
|
|
||||||
|
FormulaTableCellRenderer renderer = new FormulaTableCellRenderer();
|
||||||
|
formTable.setDefaultRenderer(Object.class, renderer);
|
||||||
|
formTable.createDefaultColumnsFromModel();
|
||||||
|
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(new JScrollPane(formTable), BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModified() { return modified; }
|
||||||
|
|
||||||
|
public void clearModificationStatus() { modified = false; }
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
StringBuilder rsslString = new StringBuilder();
|
||||||
|
|
||||||
|
for (Formula f: formulaList)
|
||||||
|
rsslString.append(f.toRSSLString()).append("\n");
|
||||||
|
|
||||||
|
return rsslString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
output.println(" <formulas>");
|
||||||
|
|
||||||
|
for (Formula f : formulaList)
|
||||||
|
output.println(" " + f.toXMLString());
|
||||||
|
|
||||||
|
output.println(" </formulas>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFromXML(Document input) {
|
||||||
|
formulaList.clear();
|
||||||
|
|
||||||
|
NodeList formulaTags = input.getElementsByTagName("formula");
|
||||||
|
|
||||||
|
for (int idx = 0; idx < formulaTags.getLength(); ++idx) {
|
||||||
|
Node formulaNode = formulaTags.item(idx);
|
||||||
|
|
||||||
|
if (formulaNode.getNodeType() != Node.ELEMENT_NODE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element formulaElement = (Element) formulaNode;
|
||||||
|
|
||||||
|
String label = formulaElement.getAttribute("label");
|
||||||
|
String formula = formulaElement.getTextContent();
|
||||||
|
formulaList.add(new Formula(label, formula));
|
||||||
|
}
|
||||||
|
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean showFormulaEditDialog(JFrame parent, Formula ff) {
|
||||||
|
final int Select = 0;
|
||||||
|
final int Approve = 1;
|
||||||
|
|
||||||
|
JTextField labelInput = new JTextField(30);
|
||||||
|
JTextField formulaInput = new JTextField(30);
|
||||||
|
|
||||||
|
String labelStr = "";
|
||||||
|
String formulaStr = "";
|
||||||
|
|
||||||
|
labelStr = ff.label;
|
||||||
|
formulaStr = ff.formula;
|
||||||
|
|
||||||
|
labelInput.setToolTipText("<html>A unique label of the formula</html>");
|
||||||
|
formulaInput.setToolTipText("<html>Formula to be evaluated</html>");
|
||||||
|
|
||||||
|
JPanel myPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints cs = new GridBagConstraints();
|
||||||
|
|
||||||
|
cs.insets = new Insets(5, 5, 5, 5);
|
||||||
|
cs.anchor = GridBagConstraints.WEST;
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(new JLabel("Label"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(labelInput, cs);
|
||||||
|
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(new JLabel("Formula"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(formulaInput, cs);
|
||||||
|
|
||||||
|
int opStatus = Select;
|
||||||
|
|
||||||
|
do {
|
||||||
|
labelInput.setText(labelStr);
|
||||||
|
formulaInput.setText(formulaStr);
|
||||||
|
|
||||||
|
int result = JOptionPane.showConfirmDialog(parent, myPanel,
|
||||||
|
"Formula details", JOptionPane.OK_CANCEL_OPTION);
|
||||||
|
|
||||||
|
if (result != JOptionPane.OK_OPTION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
labelStr = labelInput.getText();
|
||||||
|
formulaStr = formulaInput.getText();
|
||||||
|
|
||||||
|
ff.label = labelStr;
|
||||||
|
ff.formula = formulaStr;
|
||||||
|
|
||||||
|
opStatus = Approve;
|
||||||
|
}
|
||||||
|
while(opStatus == Select);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFormula(JFrame parent) {
|
||||||
|
Formula ff = new Formula();
|
||||||
|
|
||||||
|
if (showFormulaEditDialog(parent, ff)) {
|
||||||
|
formulaList.add(ff);
|
||||||
|
modified = true;
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If more than one formula is selected throw an exception only the first can be edited
|
||||||
|
public void editFormula(JFrame parent) {
|
||||||
|
int[] selected = formTable.getSelectedRows();
|
||||||
|
|
||||||
|
if (selected.length != 1) {
|
||||||
|
JOptionPane.showMessageDialog(parent, "Select a single formula to edit.", "Select formula", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Formula fEdt = formulaList.get(formTable.convertRowIndexToModel(selected[0]));
|
||||||
|
|
||||||
|
if (fEdt == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
showFormulaEditDialog(parent, fEdt);
|
||||||
|
fEdt.status = Formula.FormulaStatus.None;
|
||||||
|
modified = true;
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFormulas() {
|
||||||
|
int[] viewRows = formTable.getSelectedRows();
|
||||||
|
|
||||||
|
// Remove formulas starting from the last to avoid indexes updates
|
||||||
|
for (int vIdx = viewRows.length - 1; vIdx>=0; --vIdx) {
|
||||||
|
int mr = formTable.convertRowIndexToModel(viewRows[vIdx]);
|
||||||
|
formulaList.remove(mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
modified = true;
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Formula> getSelectedFormulas() {
|
||||||
|
Vector<Formula> selected = new Vector<Formula>();
|
||||||
|
int[] viewRows = formTable.getSelectedRows();
|
||||||
|
|
||||||
|
for (int vr : viewRows) {
|
||||||
|
int mr = formTable.convertRowIndexToModel(vr);
|
||||||
|
selected.add(formulaList.get(mr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed to repaint JTable. Called after content modification by an external object.
|
||||||
|
public void refreshStatus() {
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetFormulasStatus() {
|
||||||
|
for (Formula ff : formulaList) {
|
||||||
|
ff.status = Formula.FormulaStatus.None;
|
||||||
|
ff.mcTime = ff.totalTime = ff.memory = "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
ftModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRSUpdate() {
|
||||||
|
resetFormulasStatus();
|
||||||
|
refreshStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FormulaColumnModel extends DefaultTableColumnModel {
|
||||||
|
int colno = 0;
|
||||||
|
|
||||||
|
public void addColumn(TableColumn tc) {
|
||||||
|
switch (colno) {
|
||||||
|
case 0 -> {
|
||||||
|
tc.setMinWidth(60);
|
||||||
|
tc.setMaxWidth(Integer.MAX_VALUE / 10);
|
||||||
|
tc.setPreferredWidth(100);
|
||||||
|
}
|
||||||
|
case 1 -> {
|
||||||
|
tc.setMinWidth(100);
|
||||||
|
tc.setMaxWidth(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
case 2, 3, 4, 5 -> {
|
||||||
|
tc.setMinWidth(50);
|
||||||
|
tc.setPreferredWidth(50);
|
||||||
|
tc.setMaxWidth(Integer.MAX_VALUE / 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.addColumn(tc);
|
||||||
|
++colno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FormulaTableModel extends AbstractTableModel implements TableModelListener {
|
||||||
|
private final String[] columnNames = {"Label", "Formula", "Status", "MC Time (s)", "Total Time (s)", "Memory (MB)"};
|
||||||
|
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return columnNames[colIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRowCount() {
|
||||||
|
return formulaList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return columnNames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(int row, int column) {
|
||||||
|
Formula ff = formulaList.get(row);
|
||||||
|
|
||||||
|
return switch (column) {
|
||||||
|
case 0 -> ff.label;
|
||||||
|
case 1 -> ff.formula;
|
||||||
|
case 2 -> ff.status;
|
||||||
|
case 3 -> ff.mcTime;
|
||||||
|
case 4 -> ff.totalTime;
|
||||||
|
case 5 -> ff.memory;
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueAt(Object value, int row, int column) {
|
||||||
|
// fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int rowIndex, int columnIndex) { return false; }
|
||||||
|
|
||||||
|
public Class getColumnClass(int column) {
|
||||||
|
return getValueAt(0, column).getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tableChanged(TableModelEvent tableModelEvent) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// To properly display the content of the table containing formulas
|
||||||
|
class FormulaTableCellRenderer extends JLabel implements TableCellRenderer {
|
||||||
|
|
||||||
|
public FormulaTableCellRenderer() {
|
||||||
|
// Allows background to be visible
|
||||||
|
setOpaque(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
|
String statusStr = "";
|
||||||
|
Formula ff = formulaList.get(row);
|
||||||
|
|
||||||
|
setForeground(Color.black);
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
setBorder(selectedBorder);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setBorder(emptyBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cell background and formula evaluation status
|
||||||
|
if (column == 2) {
|
||||||
|
switch (ff.status) {
|
||||||
|
case None -> {
|
||||||
|
statusStr = "?";
|
||||||
|
setBackground(BaseFormulaBackgroundColor);
|
||||||
|
}
|
||||||
|
case True -> {
|
||||||
|
statusStr = "True";
|
||||||
|
setBackground(TrueFormulaBackgroundColor);
|
||||||
|
}
|
||||||
|
case False -> {
|
||||||
|
statusStr = "False";
|
||||||
|
setBackground(FalseFormulaBackgroundColor);
|
||||||
|
}
|
||||||
|
case Invalid -> {
|
||||||
|
statusStr = "Invalid";
|
||||||
|
setBackground(InvalidFormulaBackgroundColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setText(statusStr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setText((String) value);
|
||||||
|
setBackground(BaseFormulaBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column > 2) {
|
||||||
|
setHorizontalAlignment(SwingConstants.RIGHT);
|
||||||
|
} else {
|
||||||
|
setHorizontalAlignment(SwingConstants.LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Formula {
|
||||||
|
public enum FormulaStatus {None, True, False, Invalid};
|
||||||
|
|
||||||
|
String label;
|
||||||
|
String formula;
|
||||||
|
FormulaStatus status;
|
||||||
|
String mcTime;
|
||||||
|
String totalTime;
|
||||||
|
String memory;
|
||||||
|
|
||||||
|
public Formula() {
|
||||||
|
this("", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Formula(String label, String formula) {
|
||||||
|
this.label = label;
|
||||||
|
this.formula = formula;
|
||||||
|
this.status = FormulaStatus.None;
|
||||||
|
this.mcTime = this.totalTime = this.memory = "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
return "rsctlk-property { " + label + " : " + formula + " };";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toXMLString() {
|
||||||
|
return "<formula label=\"" + label +"\">" +
|
||||||
|
formula.replaceAll("<", "<").replaceAll(">", ">") +
|
||||||
|
"</formula>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
125
reactics-gui/src/pl/umk/mat/martinp/reactics/HelpWindow.java
Normal file
125
reactics-gui/src/pl/umk/mat/martinp/reactics/HelpWindow.java
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
public class HelpWindow extends JFrame {
|
||||||
|
private static final long serialVersionUID = 327019113533268901L;
|
||||||
|
private static final String startDocument = "index.html";
|
||||||
|
private static final String docPath = "/help/";
|
||||||
|
|
||||||
|
private static HelpWindow instance = null;
|
||||||
|
private static JTextPane helpPane = new JTextPane();;
|
||||||
|
|
||||||
|
public static synchronized HelpWindow getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new HelpWindow();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HelpWindow() {
|
||||||
|
super("ReactICS GUI Help");
|
||||||
|
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel mainPanel = new JPanel();
|
||||||
|
mainPanel.setLayout(new BorderLayout());
|
||||||
|
EtchedBorder panelBorder = new EtchedBorder(EtchedBorder.LOWERED);
|
||||||
|
mainPanel.setBorder(panelBorder);
|
||||||
|
|
||||||
|
helpPane.setEditable(false);
|
||||||
|
helpPane.addHyperlinkListener(new HyperlinkListener() {
|
||||||
|
public void hyperlinkUpdate(HyperlinkEvent hle) {
|
||||||
|
if (hle.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
|
String target = hle.getDescription();
|
||||||
|
|
||||||
|
if (target.startsWith("#")) {
|
||||||
|
helpPane.scrollToReference(target.substring(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL helpUrl = this.getClass().getResource(docPath + startDocument);
|
||||||
|
helpPane.setPage(helpUrl);
|
||||||
|
|
||||||
|
helpPane.revalidate();
|
||||||
|
helpPane.repaint();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
System.out.println("Exception: " + e.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(null, "Can not load help content",
|
||||||
|
"Help", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
JScrollPane helpScroller = new JScrollPane();
|
||||||
|
JViewport helpVp = new JViewport();
|
||||||
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
helpVp.setPreferredSize(new Dimension(screenSize.width/2, screenSize.height-200));
|
||||||
|
helpVp.add(helpPane);
|
||||||
|
helpScroller.setViewport(helpVp);
|
||||||
|
mainPanel.add(helpScroller, BorderLayout.CENTER);
|
||||||
|
getContentPane().add(mainPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(Component parent) {
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AboutWindow extends JFrame {
|
||||||
|
private static AboutWindow instance = null;
|
||||||
|
|
||||||
|
public static synchronized AboutWindow getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new AboutWindow();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AboutWindow() {
|
||||||
|
super("About ...");
|
||||||
|
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel infoPanel = new JPanel();
|
||||||
|
infoPanel.add(new JLabel("<html><h1>" + ReacticsGUI.ApplicationName + "</h1>"
|
||||||
|
+ "<h2>version " + ReacticsGUI.ApplicationVersion + " (" + ReacticsGUI.ApplicationReleaseDate + ")</h2>"
|
||||||
|
+ "<h3>Model Checker for Reaction Systems</h3>"
|
||||||
|
+ "<h3>ReactICS Research Team (CC BY 4.0)</h3>"
|
||||||
|
+ "<h3><a href=\"https://reactics.org\">https://reactics.org</a></h3></html>"));
|
||||||
|
getContentPane().add(infoPanel, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JButton closeButton = new JButton("Close");
|
||||||
|
closeButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JPanel ctrlPanel = new JPanel();
|
||||||
|
ctrlPanel.add(closeButton);
|
||||||
|
ctrlPanel.setAlignmentX(SwingConstants.RIGHT);
|
||||||
|
getContentPane().add(ctrlPanel, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
setSize(new Dimension(400, 250));
|
||||||
|
setResizable(false);
|
||||||
|
this.setAlwaysOnTop(true);
|
||||||
|
this.setUndecorated(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(Component parent) {
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
427
reactics-gui/src/pl/umk/mat/martinp/reactics/ProcessEditor.java
Normal file
427
reactics-gui/src/pl/umk/mat/martinp/reactics/ProcessEditor.java
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.*;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Graphical component for editing a single process (list of reactions)
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ProcessEditor extends JPanel {
|
||||||
|
private JTable reactionList;
|
||||||
|
private RSTableModel reactionsModel;
|
||||||
|
|
||||||
|
private RSProcess rsProcess;
|
||||||
|
private boolean modified = false;
|
||||||
|
|
||||||
|
private JCheckBox selectBox;
|
||||||
|
private TitledBorder outBorder;
|
||||||
|
private ReactionSystem rs;
|
||||||
|
|
||||||
|
private final Color borderColor = new Color(24, 104, 92);;
|
||||||
|
private final Color selectedBorderColor = new Color(150, 10, 10);
|
||||||
|
private static final int borderThickness = 4;
|
||||||
|
|
||||||
|
public ProcessEditor(RSProcess rsProc) {
|
||||||
|
rsProcess = rsProc;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RSProcess getProcess() { return rsProcess; }
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selectBox.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModified() { return modified; }
|
||||||
|
|
||||||
|
public void clearModificationStatus() { modified = false; }
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return rsProcess.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
// Create border for the component
|
||||||
|
outBorder = BorderFactory.createTitledBorder(rsProcess.label);
|
||||||
|
Font font = outBorder.getTitleFont();
|
||||||
|
Font newFont = new Font (font.getFamily(), Font.BOLD, font.getSize() + 2);
|
||||||
|
outBorder.setTitleFont(new Font (font.getFamily(), Font.BOLD, font.getSize() + 2));
|
||||||
|
outBorder.setTitleColor(borderColor);
|
||||||
|
outBorder.setBorder(new LineBorder(borderColor, borderThickness, true));
|
||||||
|
setBorder(outBorder);
|
||||||
|
|
||||||
|
// Create reactions list component
|
||||||
|
reactionsModel = new RSTableModel();
|
||||||
|
reactionList = new JTable(reactionsModel);
|
||||||
|
|
||||||
|
Font cellFont = reactionList.getFont();
|
||||||
|
Font headerFont = reactionList.getTableHeader().getFont();
|
||||||
|
|
||||||
|
reactionList.setFont(new Font("Monospaced", 0, cellFont.getSize() + 2));
|
||||||
|
reactionList.getTableHeader().setFont(new Font(headerFont.getFamily(), Font.BOLD, headerFont.getSize() + 2));
|
||||||
|
reactionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
|
||||||
|
JButton addButton = new JButton("Add reaction");
|
||||||
|
addButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { addReaction(); }
|
||||||
|
});
|
||||||
|
buttonPanel.add(addButton);
|
||||||
|
|
||||||
|
JButton edtButton = new JButton("Edit reaction");
|
||||||
|
edtButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
editReaction();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttonPanel.add(edtButton);
|
||||||
|
|
||||||
|
JButton rmButton = new JButton("Remove reaction");
|
||||||
|
rmButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
removeReactions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttonPanel.add(rmButton);
|
||||||
|
|
||||||
|
selectBox = new JCheckBox("Select");
|
||||||
|
selectBox.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
toggleSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttonPanel.add(selectBox);
|
||||||
|
|
||||||
|
add(buttonPanel);
|
||||||
|
|
||||||
|
add(new JScrollPane(reactionList));
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(-1, 200));
|
||||||
|
|
||||||
|
rs = ReactionSystem.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean showReactionEditDialog(JComponent parent, Reaction rr) {
|
||||||
|
final int Select = 0;
|
||||||
|
final int Approve = 1;
|
||||||
|
|
||||||
|
JTextField reactantsInput = new JTextField(30);
|
||||||
|
JTextField inhibitorsInput = new JTextField(30);
|
||||||
|
JTextField productsInput = new JTextField(30);
|
||||||
|
|
||||||
|
String reactantsStr = "";
|
||||||
|
String inhibitorsStr = "";
|
||||||
|
String productsStr = "";
|
||||||
|
|
||||||
|
Iterator<?> it = rr.reactants.iterator();
|
||||||
|
StringBuilder dataStr = new StringBuilder();
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
dataStr.append(it.next()).append(" ");
|
||||||
|
|
||||||
|
reactantsStr = dataStr.toString();
|
||||||
|
|
||||||
|
it = rr.inhibitors.iterator();
|
||||||
|
dataStr.setLength(0);
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
dataStr.append(it.next()).append(" ");
|
||||||
|
|
||||||
|
inhibitorsStr = dataStr.toString();
|
||||||
|
|
||||||
|
it = rr.products.iterator();
|
||||||
|
dataStr.setLength(0);
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
dataStr.append(it.next()).append(" ");
|
||||||
|
|
||||||
|
productsStr = dataStr.toString();
|
||||||
|
|
||||||
|
reactantsInput.setToolTipText("<html>Space separated list of reactants</html>");
|
||||||
|
inhibitorsInput.setToolTipText("<html>Space separated list of inhibitors</html>");
|
||||||
|
productsInput.setToolTipText("<html>Space separated list of products</html>");
|
||||||
|
|
||||||
|
JPanel myPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints cs = new GridBagConstraints();
|
||||||
|
|
||||||
|
cs.insets = new Insets(5, 5, 5, 5);
|
||||||
|
cs.anchor = GridBagConstraints.WEST;
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(new JLabel("Reactants"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(reactantsInput, cs);
|
||||||
|
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(new JLabel("Inhibitors"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(inhibitorsInput, cs);
|
||||||
|
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 2;
|
||||||
|
myPanel.add(new JLabel("Products"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 2;
|
||||||
|
myPanel.add(productsInput, cs);
|
||||||
|
|
||||||
|
int opStatus = Select;
|
||||||
|
|
||||||
|
do {
|
||||||
|
reactantsInput.setText(reactantsStr);
|
||||||
|
inhibitorsInput.setText(inhibitorsStr);
|
||||||
|
productsInput.setText(productsStr);
|
||||||
|
|
||||||
|
int result = JOptionPane.showConfirmDialog(parent, myPanel,
|
||||||
|
"Reaction details", JOptionPane.OK_CANCEL_OPTION);
|
||||||
|
|
||||||
|
if (result != JOptionPane.OK_OPTION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reactantsStr = reactantsInput.getText();
|
||||||
|
inhibitorsStr = inhibitorsInput.getText();
|
||||||
|
productsStr = productsInput.getText();
|
||||||
|
|
||||||
|
HashSet<String> reactantsSet = new HashSet<String>(Arrays.asList(reactantsStr.trim().split("\\s+")));
|
||||||
|
HashSet<String> inhibitorsSet = new HashSet<String>(Arrays.asList(inhibitorsStr.trim().split("\\s+")));
|
||||||
|
HashSet<String> productsSet = new HashSet<String>(Arrays.asList(productsStr.trim().split("\\s+")));
|
||||||
|
|
||||||
|
// Verify that reactant and inhibitor sets have empty intersection
|
||||||
|
boolean intersection = false;
|
||||||
|
|
||||||
|
for (String entity : inhibitorsSet) {
|
||||||
|
if (reactantsSet.contains(entity)) {
|
||||||
|
intersection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intersection) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Reactant and inhibitor sets have to be disjoint.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rr.reactants.clear();
|
||||||
|
rr.reactants.addAll(reactantsSet);
|
||||||
|
rr.inhibitors.clear();
|
||||||
|
rr.inhibitors.addAll(inhibitorsSet);
|
||||||
|
rr.products.clear();
|
||||||
|
rr.products.addAll(productsSet);
|
||||||
|
|
||||||
|
opStatus = Approve;
|
||||||
|
}
|
||||||
|
while(opStatus == Select);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReactantsSet() {
|
||||||
|
HashSet<String> rset = new HashSet<String>();
|
||||||
|
|
||||||
|
for (Reaction rr : rsProcess.reactions)
|
||||||
|
rset.addAll(rr.getReactantsSet());
|
||||||
|
|
||||||
|
return rset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
output.println(" <process name=\"" + rsProcess.label + "\">");
|
||||||
|
|
||||||
|
for (Reaction rr : rsProcess.reactions)
|
||||||
|
rr.exportToXML(output);
|
||||||
|
|
||||||
|
output.println(" </process>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
StringBuilder rsslString = new StringBuilder(" " + rsProcess.label + " {\n");
|
||||||
|
|
||||||
|
for (Reaction rr : rsProcess.reactions) {
|
||||||
|
rsslString.append(rr.toRSSLString());
|
||||||
|
}
|
||||||
|
|
||||||
|
rsslString.append(" };\n");
|
||||||
|
|
||||||
|
return rsslString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rename(String newLabel) {
|
||||||
|
rsProcess.label = newLabel;
|
||||||
|
outBorder.setTitle(rsProcess.label);
|
||||||
|
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new reaction
|
||||||
|
public void addReaction(Reaction rr) {
|
||||||
|
rsProcess.reactions.add(rr);
|
||||||
|
reactionsModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addReaction() {
|
||||||
|
Reaction rr = new Reaction();
|
||||||
|
if (!showReactionEditDialog(this, rr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
rsProcess.reactions.add(rr);
|
||||||
|
modified = true;
|
||||||
|
reactionsModel.fireTableDataChanged();
|
||||||
|
rs.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit details of an existing reaction
|
||||||
|
private void editReaction() {
|
||||||
|
int rIdx = reactionList.getSelectedRow();
|
||||||
|
|
||||||
|
if (rIdx == -1) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Select the reaction to edit.", "Select reaction", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reaction rr = new Reaction(rsProcess.reactions.get(rIdx));
|
||||||
|
reactionList.clearSelection();
|
||||||
|
if (!showReactionEditDialog(this, rr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsProcess.reactions.setElementAt(rr, rIdx);
|
||||||
|
modified = true;
|
||||||
|
reactionsModel.fireTableDataChanged();
|
||||||
|
rs.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove an existing reaction
|
||||||
|
private void removeReactions() {
|
||||||
|
int rIdx = reactionList.getSelectedRow();
|
||||||
|
|
||||||
|
if (rIdx == -1) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Select the reaction to be removed.", "Select reaction", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsProcess.reactions.remove(rIdx);
|
||||||
|
reactionList.clearSelection();
|
||||||
|
reactionsModel.fireTableDataChanged();
|
||||||
|
modified = true;
|
||||||
|
this.repaint();
|
||||||
|
rs.notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleSelection() {
|
||||||
|
if (selectBox.isSelected()) {
|
||||||
|
outBorder.setTitleColor(selectedBorderColor);
|
||||||
|
outBorder.setBorder(new LineBorder(selectedBorderColor, borderThickness, true));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
outBorder.setTitleColor(borderColor);
|
||||||
|
outBorder.setBorder(new LineBorder(borderColor, borderThickness, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
class RSTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private String columnNames[] = {"Reactants", "Inhibitors", "Results"};
|
||||||
|
private Vector<String>[] data;
|
||||||
|
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return columnNames[colIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRowCount() {
|
||||||
|
return rsProcess.reactions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return columnNames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(int row, int column) {
|
||||||
|
Reaction rr = rsProcess.reactions.get(row);
|
||||||
|
|
||||||
|
return switch (column) {
|
||||||
|
case 0 -> rr.reactants;
|
||||||
|
case 1 -> rr.inhibitors;
|
||||||
|
case 2 -> rr.products;
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Object representing a single reaction
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Reaction {
|
||||||
|
LinkedList<String> reactants;
|
||||||
|
LinkedList<String> inhibitors;
|
||||||
|
LinkedList<String> products;
|
||||||
|
|
||||||
|
public Reaction() {
|
||||||
|
reactants = new LinkedList<String>();
|
||||||
|
inhibitors = new LinkedList<String>();
|
||||||
|
products = new LinkedList<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Reaction(Reaction rr) {
|
||||||
|
reactants = new LinkedList<String>(rr.reactants);
|
||||||
|
inhibitors = new LinkedList<String>(rr.inhibitors);
|
||||||
|
products = new LinkedList<String>(rr.products);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReactantsSet() {
|
||||||
|
Set<String> rset = new HashSet<String>();
|
||||||
|
rset.addAll(reactants);
|
||||||
|
rset.addAll(inhibitors);
|
||||||
|
rset.addAll(products);
|
||||||
|
|
||||||
|
return rset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
return " {" + "{" + reactants.toString().replace("[", "").replace("]", "") + "}, " +
|
||||||
|
"{" + inhibitors.toString().replace("[", "").replace("]", "") + "} -> " +
|
||||||
|
"{" + products.toString().replace("[", "").replace("]", "") + "}" +
|
||||||
|
"};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
output.println(" <reaction>");
|
||||||
|
|
||||||
|
for (String str : reactants)
|
||||||
|
output.println(" <reactant>" + str + "</reactant>");
|
||||||
|
|
||||||
|
for (String str : inhibitors)
|
||||||
|
output.println(" <inhibitor>" + str + "</inhibitor>");
|
||||||
|
|
||||||
|
for (String str : products)
|
||||||
|
output.println(" <product>" + str + "</product>");
|
||||||
|
|
||||||
|
output.println(" </reaction>");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.LineBorder;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
public class ReactantSetPanel extends JPanel implements RSObserver {
|
||||||
|
private final int borderThickness = 2;
|
||||||
|
|
||||||
|
JTextArea textArea = new JTextArea();
|
||||||
|
|
||||||
|
public ReactantSetPanel() {
|
||||||
|
textArea.setEditable(false);
|
||||||
|
textArea.setLineWrap(true);
|
||||||
|
textArea.setWrapStyleWord(false);
|
||||||
|
Font textFont = textArea.getFont();
|
||||||
|
textArea.setFont(new Font(textFont.getFamily(), Font.BOLD, textFont.getSize()+2));
|
||||||
|
|
||||||
|
this.setPreferredSize(new Dimension(-1, 75));
|
||||||
|
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
this.add(new JScrollPane(textArea), BorderLayout.CENTER);
|
||||||
|
|
||||||
|
TitledBorder outBorder = BorderFactory.createTitledBorder("Reactants");
|
||||||
|
Font borderFont = outBorder.getTitleFont();
|
||||||
|
outBorder.setTitleFont(new Font (borderFont.getFamily(), Font.BOLD, borderFont.getSize()+2));
|
||||||
|
outBorder.setBorder(new LineBorder(Color.black, borderThickness, true));
|
||||||
|
setBorder(outBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateReactants(Set<String> reactantsSet) {
|
||||||
|
textArea.setText("");
|
||||||
|
// textArea.setText(Arrays.toString(reactantsSet.toArray()));
|
||||||
|
textArea.setText(Arrays.stream(reactantsSet.toArray()).map(String::valueOf).collect(Collectors.joining(" ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
textArea.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRSUpdate() {
|
||||||
|
ReactionSystem rs = ReactionSystem.getInstance();
|
||||||
|
updateReactants(rs.getReactants());
|
||||||
|
}
|
||||||
|
}
|
||||||
791
reactics-gui/src/pl/umk/mat/martinp/reactics/ReacticsGUI.java
Normal file
791
reactics-gui/src/pl/umk/mat/martinp/reactics/ReacticsGUI.java
Normal file
@@ -0,0 +1,791 @@
|
|||||||
|
/** Main application window */
|
||||||
|
|
||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
|
||||||
|
public class ReacticsGUI extends JFrame {
|
||||||
|
public final static String ApplicationName = "ReactICS GUI";
|
||||||
|
public final static String ApplicationVersion = "0.1";
|
||||||
|
public final static String ApplicationReleaseDate = "2025";
|
||||||
|
|
||||||
|
private static final String defaultConfigFileName = "reactics.conf";
|
||||||
|
|
||||||
|
private JFrame window;
|
||||||
|
private JTabbedPane modulePane;
|
||||||
|
private ReactantSetPanel reactantSetPanel;
|
||||||
|
private ReactionSystemEditor reactionSystemEditor;
|
||||||
|
private ContextAutomatonEditor contextAutomatonEditor;
|
||||||
|
private TransitionSystemViewer transitionSystemViewer;
|
||||||
|
private TransitionSystemViewer compressedTransitionSystemViewer;
|
||||||
|
private FormulaEditor formulaEditor;
|
||||||
|
|
||||||
|
private FileSelector fileSelector;
|
||||||
|
|
||||||
|
private ReactionSystem reactionSystem;
|
||||||
|
private ReacticsRuntime reactics;
|
||||||
|
|
||||||
|
|
||||||
|
public ReacticsGUI() {
|
||||||
|
super(ApplicationName);
|
||||||
|
|
||||||
|
reactionSystem = ReactionSystem.getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
|
reactics = ReacticsRuntime.getInstance();
|
||||||
|
}
|
||||||
|
catch (ReacticsRuntimeException rre) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
rre.getMessage(),
|
||||||
|
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||||
|
setSize(new Dimension(screenSize.width-200, screenSize.height-200));
|
||||||
|
createMenuBar();
|
||||||
|
createContentPane();
|
||||||
|
|
||||||
|
fileSelector = FileSelector.getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
|
reactics.loadConfig(defaultConfigFileName);
|
||||||
|
}
|
||||||
|
catch (ConfigReadingError cre) {
|
||||||
|
System.err.println("[ReactICS] Error reading configuration: " + cre.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Could not read configuration\n" + cre.getMessage(),
|
||||||
|
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
catch (InvalidRuntimeException ire) {
|
||||||
|
System.err.println("[ReactICS] ReactICS runtime cannot be executed" + ire.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Invalid ReactICS runtime patn\n" + ire.getMessage() +
|
||||||
|
"\nYou may proceed with editing reaction system structure," +
|
||||||
|
"however not model checking will be possible.",
|
||||||
|
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
window = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createMenuBar() {
|
||||||
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
|
||||||
|
JMenu fileMenu = new JMenu("File");
|
||||||
|
menuBar.add(fileMenu);
|
||||||
|
|
||||||
|
JMenuItem xmlLoadItem = new JMenuItem("Load from XML file");
|
||||||
|
xmlLoadItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
loadFromXML();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileMenu.add(xmlLoadItem);
|
||||||
|
|
||||||
|
JMenuItem xmlsaveItem = new JMenuItem("Save to XML file");
|
||||||
|
xmlsaveItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
saveAsXML();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileMenu.add(xmlsaveItem);
|
||||||
|
|
||||||
|
JMenuItem rsslImportItem = new JMenuItem("Import from RSSL file");
|
||||||
|
rsslImportItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
importFromRSSL();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileMenu.add(rsslImportItem);
|
||||||
|
|
||||||
|
JMenuItem rsslExportItem = new JMenuItem("Save to RSSL file");
|
||||||
|
rsslExportItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
exportToRSSLFile();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileMenu.add(rsslExportItem);
|
||||||
|
|
||||||
|
JMenuItem isplExportItem = new JMenuItem("Export to ISPL file");
|
||||||
|
isplExportItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { exportToISPLFile(); }
|
||||||
|
});
|
||||||
|
fileMenu.add(isplExportItem);
|
||||||
|
|
||||||
|
JMenuItem exitItem = new JMenuItem("Exit");
|
||||||
|
exitItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fileMenu.addSeparator();
|
||||||
|
fileMenu.add(exitItem);
|
||||||
|
|
||||||
|
JMenu helpMenu = new JMenu("Help");
|
||||||
|
menuBar.add(helpMenu);
|
||||||
|
|
||||||
|
JMenuItem helpItem = new JMenuItem("Help");
|
||||||
|
helpItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { showHelpWindow(); }
|
||||||
|
});
|
||||||
|
helpMenu.add(helpItem);
|
||||||
|
|
||||||
|
JMenuItem aboutItem = new JMenuItem("About");
|
||||||
|
aboutItem.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { showAboutWindow(); }
|
||||||
|
});
|
||||||
|
helpMenu.add(aboutItem);
|
||||||
|
|
||||||
|
setJMenuBar(menuBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createContentPane() {
|
||||||
|
modulePane = new JTabbedPane();
|
||||||
|
modulePane.setTabPlacement(JTabbedPane.NORTH);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Reaction System Editor
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
reactionSystemEditor = new ReactionSystemEditor();
|
||||||
|
modulePane.addTab("Reaction System", reactionSystemEditor);
|
||||||
|
reactionSystem.addObserver(reactionSystemEditor);
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Context Automaton Editor
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
contextAutomatonEditor = new ContextAutomatonEditor(getSize());
|
||||||
|
modulePane.addTab("Context Automaton", contextAutomatonEditor);
|
||||||
|
reactionSystem.addObserver(contextAutomatonEditor);
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Transition System Viewer
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JPanel transitionSystemPanel = new JPanel(new BorderLayout());
|
||||||
|
transitionSystemViewer = new TransitionSystemViewer(getSize(), false);
|
||||||
|
transitionSystemPanel.add(transitionSystemViewer, BorderLayout.CENTER);
|
||||||
|
reactionSystem.addObserver(transitionSystemViewer);
|
||||||
|
|
||||||
|
JPanel tsCtrlPanel = new JPanel();
|
||||||
|
JButton tsUpdateBtn = new JButton("Update transition system");
|
||||||
|
tsUpdateBtn.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { updateTransitionSystem(); }
|
||||||
|
});
|
||||||
|
tsCtrlPanel.add(tsUpdateBtn);
|
||||||
|
|
||||||
|
JCheckBox tsLockCBox = new JCheckBox("Lock relative nodes positions");
|
||||||
|
tsLockCBox.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
transitionSystemViewer.lockNodesPositions(tsLockCBox.isSelected());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tsCtrlPanel.add(tsLockCBox);
|
||||||
|
|
||||||
|
transitionSystemPanel.add(tsCtrlPanel, BorderLayout.NORTH);
|
||||||
|
modulePane.addTab("Transition System", transitionSystemPanel);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Compressed Transition System Viewer
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JPanel compressedTransitionSystemPanel = new JPanel(new BorderLayout());
|
||||||
|
compressedTransitionSystemViewer = new TransitionSystemViewer(getSize(), true);
|
||||||
|
compressedTransitionSystemPanel.add(compressedTransitionSystemViewer, BorderLayout.CENTER);
|
||||||
|
reactionSystem.addObserver(compressedTransitionSystemViewer);
|
||||||
|
|
||||||
|
JPanel ctsCtrlPanel = new JPanel();
|
||||||
|
JButton ctsUpdateBtn = new JButton("Update transition system");
|
||||||
|
ctsUpdateBtn.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { updateTransitionSystem(); }
|
||||||
|
});
|
||||||
|
ctsCtrlPanel.add(ctsUpdateBtn);
|
||||||
|
|
||||||
|
JCheckBox ctsLockCBox = new JCheckBox("Lock relative nodes positions");
|
||||||
|
ctsLockCBox.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
compressedTransitionSystemViewer.lockNodesPositions(ctsLockCBox.isSelected());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ctsCtrlPanel.add(ctsLockCBox);
|
||||||
|
|
||||||
|
compressedTransitionSystemPanel.add(ctsCtrlPanel, BorderLayout.NORTH);
|
||||||
|
modulePane.addTab("Compressed Transition System", compressedTransitionSystemPanel);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Formula Editor
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JPanel formulaEditorPanel = new JPanel();
|
||||||
|
formulaEditorPanel.setLayout(new BorderLayout());
|
||||||
|
formulaEditor = new FormulaEditor(reactionSystem);
|
||||||
|
reactionSystem.addObserver(formulaEditor);
|
||||||
|
formulaEditorPanel.add(formulaEditor, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel formulaCtrlPanel = new JPanel();
|
||||||
|
JButton addButton = new JButton("Add formula");
|
||||||
|
addButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { formulaEditor.addFormula(window); }
|
||||||
|
});
|
||||||
|
formulaCtrlPanel.add(addButton);
|
||||||
|
|
||||||
|
JButton edtButton = new JButton("Edit formula");
|
||||||
|
edtButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
formulaEditor.editFormula(window);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formulaCtrlPanel.add(edtButton);
|
||||||
|
|
||||||
|
JButton rmButton = new JButton("Remove formulas");
|
||||||
|
rmButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
formulaEditor.removeFormulas();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formulaCtrlPanel.add(rmButton);
|
||||||
|
|
||||||
|
JButton evalButton = new JButton("Evaluate");
|
||||||
|
evalButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
evaluateFormulas();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formulaCtrlPanel.add(evalButton);
|
||||||
|
|
||||||
|
JButton resetButton = new JButton("Reset");
|
||||||
|
resetButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
formulaEditor.resetFormulasStatus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
formulaCtrlPanel.add(resetButton);
|
||||||
|
|
||||||
|
formulaEditorPanel.add(formulaCtrlPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Split the main window into two parts. The upper one contains details of the reaction
|
||||||
|
// system. The bottom part contains the list of formulas for model checking.
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, modulePane, formulaEditorPanel);
|
||||||
|
splitPane.setResizeWeight(0.75);
|
||||||
|
// splitPane.setOneTouchExpandable(true);
|
||||||
|
splitPane.setDividerSize(8);
|
||||||
|
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
getContentPane().add(splitPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
// Update button + Reactant Set Viewer
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JPanel topPanel = new JPanel();
|
||||||
|
topPanel.setLayout(new BorderLayout());
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JButton updateButton = new JButton("<html><center>Update<br>Reaction System</center></html>");
|
||||||
|
updateButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
updateReactionSystem();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttonPanel.add(updateButton);
|
||||||
|
topPanel.add(buttonPanel, BorderLayout.WEST);
|
||||||
|
reactantSetPanel = new ReactantSetPanel();
|
||||||
|
reactionSystem.addObserver(reactantSetPanel);
|
||||||
|
topPanel.add(reactantSetPanel, BorderLayout.CENTER);
|
||||||
|
getContentPane().add(topPanel, BorderLayout.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isModified() {
|
||||||
|
return reactionSystemEditor.isModified() || contextAutomatonEditor.isModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearModificationStatus() {
|
||||||
|
reactionSystemEditor.clearModificationStatus();
|
||||||
|
contextAutomatonEditor.clearModificationStatus();
|
||||||
|
transitionSystemViewer.clearModificationStatus();
|
||||||
|
compressedTransitionSystemViewer.clearModificationStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateReactionSystem() {
|
||||||
|
System.out.println("[ReactICS] Update reaction system structure");
|
||||||
|
|
||||||
|
Path rsslFile = reactics.getRSSLFile();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.writeString(rsslFile, "");
|
||||||
|
|
||||||
|
PrintWriter rsslStream = new PrintWriter(Files.newBufferedWriter(rsslFile));
|
||||||
|
printRSStructure(rsslStream);
|
||||||
|
rsslStream.close();
|
||||||
|
}
|
||||||
|
catch (IOException ie) {
|
||||||
|
System.err.println("[ReactICS] Could not read transition system structure: " + ie.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Could not read transition system structure\n" + ie.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
reactionSystem.notifyObservers();
|
||||||
|
updateReactantSet();
|
||||||
|
clearModificationStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateReactantSet() {
|
||||||
|
TreeSet<String> rset = new TreeSet<String>();
|
||||||
|
|
||||||
|
rset.addAll(reactionSystemEditor.getReactantsSet());
|
||||||
|
rset.addAll(contextAutomatonEditor.getReactantsSet());
|
||||||
|
rset.remove("");
|
||||||
|
reactantSetPanel.updateReactants(rset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTransitionSystem() {
|
||||||
|
if (isModified()) {
|
||||||
|
updateReactionSystem();
|
||||||
|
}
|
||||||
|
else if (transitionSystemViewer.isComputed()) {
|
||||||
|
// Skip re-computing transition system structure
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String tsStructure = reactics.getTransitionSystemStructure();
|
||||||
|
transitionSystemViewer.updateTransitionSystemStructure(tsStructure);
|
||||||
|
compressedTransitionSystemViewer.updateTransitionSystemStructure(tsStructure);
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
System.out.println("[ReactICS] I/O Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Could not write reaction system structure to a temporary file\n" + ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
catch (ReacticsRuntimeException rre) {
|
||||||
|
System.out.println("[ReactICS] Runtime Error: " + rre.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
rre.getMessage(),
|
||||||
|
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evaluateFormulas() {
|
||||||
|
Collection<Formula> formulas = formulaEditor.getSelectedFormulas();
|
||||||
|
|
||||||
|
if (isModified())
|
||||||
|
updateReactionSystem();
|
||||||
|
|
||||||
|
Path rsslFile = reactics.getRSSLFile();
|
||||||
|
long originalSize = -1;
|
||||||
|
|
||||||
|
try {
|
||||||
|
originalSize = Files.size(rsslFile);
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Formula ff : formulas) {
|
||||||
|
try {
|
||||||
|
System.out.println("[ReactICS] Evaluate formula: " + ff.label);
|
||||||
|
|
||||||
|
Files.writeString(rsslFile, ff.toRSSLString() + "\n", StandardCharsets.UTF_8, StandardOpenOption.APPEND);
|
||||||
|
|
||||||
|
ReacticsRuntime.EvalResult result = reactics.evaluateFormula(ff.label);
|
||||||
|
ff.status = result.result();
|
||||||
|
ff.mcTime = result.mcTime() + " s";
|
||||||
|
ff.totalTime = result.totalTime() + " s";
|
||||||
|
ff.memory = result.memory() + " MB";
|
||||||
|
formulaEditor.refreshStatus();
|
||||||
|
}
|
||||||
|
catch(IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
catch(ReacticsRuntimeException rre) {
|
||||||
|
System.err.println("[ReactICS] Runtime error: " + rre.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
rre.getMessage(),
|
||||||
|
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
ff.status = Formula.FormulaStatus.Invalid;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
RandomAccessFile raf = new RandomAccessFile(rsslFile.toFile(), "rw");
|
||||||
|
raf.setLength(originalSize);
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAsXML() {
|
||||||
|
File outFile = fileSelector.selectOutputFile(this, new File(System.getProperty("user.dir")),
|
||||||
|
new FileNameExtensionFilter("Reaction System (XML)", "xml"));
|
||||||
|
|
||||||
|
if(outFile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
System.out.println("[ReactICS] Save to XML file: " + outFile.getName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
PrintWriter xmlOut = new PrintWriter(new FileWriter(outFile));
|
||||||
|
xmlOut.println("<xml version=\"1.0\">");
|
||||||
|
reactionSystemEditor.exportToXML(xmlOut);
|
||||||
|
contextAutomatonEditor.exportToXML(xmlOut);
|
||||||
|
formulaEditor.exportToXML(xmlOut);
|
||||||
|
xmlOut.println("</xml>");
|
||||||
|
xmlOut.flush();
|
||||||
|
xmlOut.close();
|
||||||
|
}
|
||||||
|
catch(IOException ioe) {
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFromXML() {
|
||||||
|
FileNameExtensionFilter fileTypeFilter = new FileNameExtensionFilter("Reaction System (XML)", "xml");
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.addChoosableFileFilter(fileTypeFilter);
|
||||||
|
fc.setAcceptAllFileFilterUsed(true);
|
||||||
|
fc.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||||
|
|
||||||
|
|
||||||
|
if(fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File xmlFile = fc.getSelectedFile();
|
||||||
|
loadFromXMLFile(xmlFile);
|
||||||
|
setTitle("ReactICS GUI : " + xmlFile.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
modulePane.setSelectedIndex(0);
|
||||||
|
clearModificationStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void loadFromXMLFile(File xmlFile) {
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
transitionSystemViewer.clear();
|
||||||
|
compressedTransitionSystemViewer.clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||||
|
Document doc = dBuilder.parse(xmlFile);
|
||||||
|
doc.getDocumentElement().normalize();
|
||||||
|
reactionSystemEditor.loadFromXML(doc);
|
||||||
|
contextAutomatonEditor.loadFromXML(doc);
|
||||||
|
formulaEditor.loadFromXML(doc);
|
||||||
|
updateReactionSystem();
|
||||||
|
}
|
||||||
|
catch(IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, "Error reading file: " + xmlFile.getName() + "\n" + ioe.getMessage(),
|
||||||
|
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
}
|
||||||
|
catch(ParserConfigurationException pce) {
|
||||||
|
System.err.println("[ReactICS] Parse Configuration Error: " + pce.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, pce.getMessage(),
|
||||||
|
"Parse Configuration Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
}
|
||||||
|
catch(SAXException se) {
|
||||||
|
System.err.println("[ReactICS] SAXException: " + se.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, se.getMessage(),
|
||||||
|
"Parse error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
}
|
||||||
|
catch(FileStructureError err) {
|
||||||
|
System.err.println("[ReactICS]: File Structure Error: " + err.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, err.getMessage(),
|
||||||
|
"XML file structure error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
System.out.println("[ReactICS] Error: " + e.getMessage());
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, "Unexpected error reading file: " + xmlFile.getName() +
|
||||||
|
" " + e.getMessage(),
|
||||||
|
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
||||||
|
reactionSystemEditor.clear();
|
||||||
|
contextAutomatonEditor.clear();
|
||||||
|
reactantSetPanel.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void importFromRSSL() {
|
||||||
|
FileNameExtensionFilter fileTypeFilter = new FileNameExtensionFilter("Reaction System Specification Language (rs)", "rs");
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.addChoosableFileFilter(fileTypeFilter);
|
||||||
|
fc.setAcceptAllFileFilterUsed(true);
|
||||||
|
fc.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||||
|
|
||||||
|
|
||||||
|
if(fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
File rsslFile = fc.getSelectedFile();
|
||||||
|
|
||||||
|
try {
|
||||||
|
File xmlFile = reactics.convertToXMLFile(rsslFile);
|
||||||
|
loadFromXMLFile(xmlFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("IOException: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ReacticsRuntimeException e) {
|
||||||
|
System.err.println("ReacticsRuntimeException: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
setTitle("ReactICS GUI : " + rsslFile.getName());
|
||||||
|
contextAutomatonEditor.recalculateCoordinates();
|
||||||
|
}
|
||||||
|
|
||||||
|
modulePane.setSelectedIndex(0);
|
||||||
|
clearModificationStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void exportToRSSLFile() {
|
||||||
|
File outFile = fileSelector.selectOutputFile(this, new File(System.getProperty("user.dir")),
|
||||||
|
new FileNameExtensionFilter("Reaction System Specification Language (RSSL)", "rs"));
|
||||||
|
|
||||||
|
if(outFile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
System.out.println("[ReactICS] Export to RSSL file: " + outFile.getName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
PrintWriter rsslOut = new PrintWriter(new FileWriter(outFile));
|
||||||
|
printRSStructure(rsslOut);
|
||||||
|
rsslOut.close();
|
||||||
|
}
|
||||||
|
catch(IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void exportToISPLFile() {
|
||||||
|
updateReactionSystem();
|
||||||
|
|
||||||
|
if (!reactionSystem.isplTranslationAllowed()) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Context automaton contains guards for some transitions.\n" +
|
||||||
|
"Current version of ReactICS does not support translation to ISPL format in this case.\n",
|
||||||
|
"Translation is not possible", JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File outFile = fileSelector.selectOutputFile(this, new File(System.getProperty("user.dir")),
|
||||||
|
new FileNameExtensionFilter("Interpreted System Programming Language (ISPL)", "ispl"));
|
||||||
|
|
||||||
|
if (outFile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
System.out.println("[ReactICS] Export to ISPL file: " + outFile.getAbsolutePath());
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!outFile.exists() && !outFile.createNewFile()) {
|
||||||
|
System.err.println("[ReactICS] Error: The file "+ outFile.getName() + " could not be created.");
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"The file " + outFile.getName() + " could not be created.",
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outFile.canWrite()){
|
||||||
|
System.err.println("[ReactICS] Error: Cannot write to the file " + outFile.getName());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"Cannot write to the file " + outFile.getName(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reactics.exportToISPLFile(outFile);
|
||||||
|
}
|
||||||
|
catch(IOException ioe) {
|
||||||
|
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
catch(ReacticsRuntimeException rre) {
|
||||||
|
System.err.println("[ReactICS] Runtime error: " + rre.getMessage());
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
rre.getMessage(),
|
||||||
|
"ReactICS Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printRSStructure(PrintWriter outStream) {
|
||||||
|
outStream.println("options { use-context-automaton; make-progressive; };\n");
|
||||||
|
outStream.println(reactionSystemEditor.toRSSLString());
|
||||||
|
outStream.println(contextAutomatonEditor.toRSSLString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAboutWindow() {
|
||||||
|
AboutWindow awin = AboutWindow.getInstance();
|
||||||
|
awin.show(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showHelpWindow() {
|
||||||
|
HelpWindow hwin = HelpWindow.getInstance();
|
||||||
|
hwin.show(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
ReacticsGUI wnd = new ReacticsGUI();
|
||||||
|
wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
wnd.setLocationRelativeTo(null);
|
||||||
|
wnd.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Class responsible for selecting a file to load / save the reaction system structure
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FileSelector {
|
||||||
|
private enum Status {SELECT, APPROVE, CANCEL}
|
||||||
|
|
||||||
|
private static FileSelector instance = null;
|
||||||
|
|
||||||
|
public static synchronized FileSelector getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new FileSelector();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileSelector() { }
|
||||||
|
|
||||||
|
public File selecInputFile(Component parent, File rootDir, FileNameExtensionFilter filter) {
|
||||||
|
Status opStatus = Status.SELECT;
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.addChoosableFileFilter(filter);
|
||||||
|
fc.setAcceptAllFileFilterUsed(true);
|
||||||
|
fc.setCurrentDirectory(rootDir);
|
||||||
|
File outFile = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (fc.showOpenDialog(parent) != JFileChooser.APPROVE_OPTION) {
|
||||||
|
opStatus = Status.CANCEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile = fc.getSelectedFile();
|
||||||
|
opStatus = Status.APPROVE;
|
||||||
|
|
||||||
|
if(outFile.exists()) {
|
||||||
|
if (JOptionPane.showConfirmDialog(parent,
|
||||||
|
"The file " + outFile.getName() + " already exists.\n" +
|
||||||
|
"Do you wish to overwrite it?", "Warning",
|
||||||
|
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) {
|
||||||
|
opStatus = Status.SELECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(opStatus == Status.SELECT);
|
||||||
|
|
||||||
|
if(opStatus != Status.APPROVE)
|
||||||
|
outFile = null;
|
||||||
|
|
||||||
|
return outFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File selectOutputFile(Component parent, File rootDir, FileNameExtensionFilter filter) {
|
||||||
|
Status opStatus = Status.SELECT;
|
||||||
|
JFileChooser fc = new JFileChooser();
|
||||||
|
fc.addChoosableFileFilter(filter);
|
||||||
|
fc.setAcceptAllFileFilterUsed(true);
|
||||||
|
fc.setCurrentDirectory(rootDir);
|
||||||
|
File outFile = null;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (fc.showSaveDialog(parent) != JFileChooser.APPROVE_OPTION) {
|
||||||
|
opStatus = Status.CANCEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile = fc.getSelectedFile();
|
||||||
|
opStatus = Status.APPROVE;
|
||||||
|
|
||||||
|
if(outFile.exists()) {
|
||||||
|
if (JOptionPane.showConfirmDialog(parent,
|
||||||
|
"The file " + outFile.getName() + " already exists.\n" +
|
||||||
|
"Do you wish to overwrite it?", "Warning",
|
||||||
|
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.NO_OPTION) {
|
||||||
|
opStatus = Status.SELECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(opStatus == Status.SELECT);
|
||||||
|
|
||||||
|
if(opStatus != Status.APPROVE)
|
||||||
|
outFile = null;
|
||||||
|
|
||||||
|
return outFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General exception class for any error related to input XML file
|
||||||
|
*/
|
||||||
|
class FileStructureError extends Exception {
|
||||||
|
public FileStructureError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
|
||||||
|
public class ReacticsRuntime {
|
||||||
|
private static ReacticsRuntime instance = null;
|
||||||
|
|
||||||
|
private String rctPath = "./";
|
||||||
|
private String rctRuntime = "reactics";
|
||||||
|
private Path rsslFile;
|
||||||
|
|
||||||
|
public static synchronized ReacticsRuntime getInstance() throws ReacticsRuntimeException {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new ReacticsRuntime();
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReacticsRuntime() throws ReacticsRuntimeException {
|
||||||
|
try {
|
||||||
|
rsslFile = Files.createTempFile("reaction_system_", ".rs");
|
||||||
|
rsslFile.toFile().deleteOnExit();
|
||||||
|
System.out.println("[ReactICS] Created temporary file: " + rsslFile.toAbsolutePath());
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
System.err.println("[ReactICS] Problem creating temporary file: + e.getMessage()");
|
||||||
|
throw new ReacticsRuntimeException("Problem creating temporary file:\n" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getRSSLFile() {
|
||||||
|
return rsslFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadConfig(String configFileName) throws ConfigReadingError, InvalidRuntimeException {
|
||||||
|
System.out.println("[ReactICS] Loading configuration from: " + configFileName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedReader inputStream = new BufferedReader(new FileReader(configFileName));
|
||||||
|
String line;
|
||||||
|
|
||||||
|
while ((line = inputStream.readLine()) != null) {
|
||||||
|
if (line.startsWith("runtime")) {
|
||||||
|
line = line.replaceAll("\\s", "");
|
||||||
|
rctRuntime = line.substring(line.indexOf(":") + 1);
|
||||||
|
}
|
||||||
|
else if (line.startsWith("path")) {
|
||||||
|
line = line.replaceAll("\\s", "");
|
||||||
|
rctPath = line.substring(line.indexOf(":") + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new ConfigReadingError(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
File rctRntFile = new File(rctPath + rctRuntime);
|
||||||
|
|
||||||
|
if (! (rctRntFile.exists() && rctRntFile.canExecute()) ) {
|
||||||
|
throw new InvalidRuntimeException(rctPath + rctRuntime + " cannot be executed");
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("[ReactICS] Using runtime: " + rctPath + rctRuntime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EvalResult evaluateFormula(String fLabel) throws IOException, ReacticsRuntimeException {
|
||||||
|
// Drop "-B" option if verification time should not be measured
|
||||||
|
Process proc = Runtime.getRuntime().exec(rctPath + rctRuntime + " -B -c " + fLabel + " " + rsslFile.toAbsolutePath(),
|
||||||
|
null, new File(rctPath));
|
||||||
|
|
||||||
|
BufferedReader formResultStream = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||||
|
String line;
|
||||||
|
Formula.FormulaStatus result = Formula.FormulaStatus.None;
|
||||||
|
String mcTime = "";
|
||||||
|
String totalTime = "";
|
||||||
|
String memory = "";
|
||||||
|
|
||||||
|
while ((line = formResultStream.readLine()) != null) {
|
||||||
|
if (line.contains("holds")) {
|
||||||
|
result = Formula.FormulaStatus.True;
|
||||||
|
}
|
||||||
|
else if (line.contains("not hold")) {
|
||||||
|
result = Formula.FormulaStatus.False;
|
||||||
|
}
|
||||||
|
else if (line.startsWith("STAT")) {
|
||||||
|
String[] tokens = line.split(";");
|
||||||
|
mcTime = tokens[2];
|
||||||
|
totalTime = tokens[5];
|
||||||
|
memory = tokens[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Handle incorrect formulas
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder errMsg = new StringBuilder();
|
||||||
|
BufferedReader procErrStr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
|
||||||
|
while ((line = procErrStr.readLine()) != null) {
|
||||||
|
errMsg.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errMsg.isEmpty())
|
||||||
|
throw new ReacticsRuntimeException(errMsg.toString());
|
||||||
|
|
||||||
|
return new EvalResult(result, mcTime, totalTime, memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Complete Transition System. Context automaton state included. */
|
||||||
|
public String getTransitionSystemStructure() throws IOException, ReacticsRuntimeException {
|
||||||
|
Process proc = Runtime.getRuntime().exec(rctPath + rctRuntime + " -t -X " + rsslFile.toAbsolutePath(),
|
||||||
|
null, new File(rctPath));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
StringBuilder tsString = new StringBuilder();
|
||||||
|
BufferedReader procOutStr = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||||
|
while ((line = procOutStr.readLine()) != null) {
|
||||||
|
tsString.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder errMsg = new StringBuilder();
|
||||||
|
BufferedReader procErrStr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
|
||||||
|
while ((line = procErrStr.readLine()) != null) {
|
||||||
|
errMsg.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errMsg.isEmpty())
|
||||||
|
throw new ReacticsRuntimeException(errMsg.toString());
|
||||||
|
|
||||||
|
return tsString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToISPLFile(File outFile) throws IOException, ReacticsRuntimeException {
|
||||||
|
Process proc = Runtime.getRuntime().exec(rctPath + rctRuntime + " -e " + rsslFile.toAbsolutePath() + " > " + outFile.getAbsolutePath(),
|
||||||
|
null, new File(rctPath));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
BufferedReader procOutStr = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||||
|
PrintWriter isplOutStr = new PrintWriter(new FileWriter(outFile));
|
||||||
|
while ((line = procOutStr.readLine()) != null) {
|
||||||
|
isplOutStr.println(line);
|
||||||
|
}
|
||||||
|
isplOutStr.close();
|
||||||
|
|
||||||
|
StringBuilder errMsg = new StringBuilder();
|
||||||
|
BufferedReader procErrStr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
|
||||||
|
while ((line = procErrStr.readLine()) != null) {
|
||||||
|
errMsg.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errMsg.isEmpty())
|
||||||
|
throw new ReacticsRuntimeException(errMsg.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public File convertToXMLFile(File rsslInputFile) throws IOException, ReacticsRuntimeException {
|
||||||
|
File xmlFile = Files.createTempFile("_" + rsslInputFile.getName(), ".xml").toFile();
|
||||||
|
xmlFile.deleteOnExit();
|
||||||
|
|
||||||
|
ProcessBuilder procBuilder = new ProcessBuilder(rctPath + rctRuntime, "-y", rsslInputFile.getAbsolutePath());
|
||||||
|
procBuilder.redirectOutput(new File(xmlFile.getAbsolutePath()));
|
||||||
|
Process proc = procBuilder.start();
|
||||||
|
|
||||||
|
String line;
|
||||||
|
StringBuilder errMsg = new StringBuilder();
|
||||||
|
BufferedReader procErrStr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
|
||||||
|
while ((line = procErrStr.readLine()) != null) {
|
||||||
|
errMsg.append(line).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errMsg.isEmpty())
|
||||||
|
throw new ReacticsRuntimeException(errMsg.toString());
|
||||||
|
|
||||||
|
return xmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
record EvalResult(Formula.FormulaStatus result, String mcTime, String totalTime, String memory) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigReadingError extends Exception {
|
||||||
|
public ConfigReadingError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidRuntimeException extends Exception {
|
||||||
|
public InvalidRuntimeException(String description) {
|
||||||
|
super(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReacticsRuntimeException extends Exception {
|
||||||
|
public ReacticsRuntimeException(String description) {
|
||||||
|
super(description);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,409 @@
|
|||||||
|
/** A component for editing the reaction system details */
|
||||||
|
|
||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
/** A graphical component allowing edition and display of a distributed reaction system.
|
||||||
|
* A distributed reaction system contains a number of processes.
|
||||||
|
* Each process contains a list of reactions.
|
||||||
|
*/
|
||||||
|
public class ReactionSystemEditor extends JPanel implements RSObserver {
|
||||||
|
ReactionSystem rs;
|
||||||
|
private Vector<ProcessEditor> procEditors = new Vector<ProcessEditor>();
|
||||||
|
private JPanel processPanel = new JPanel();
|
||||||
|
|
||||||
|
|
||||||
|
public ReactionSystemEditor() {
|
||||||
|
rs = ReactionSystem.getInstance();
|
||||||
|
|
||||||
|
processPanel.setLayout(new BoxLayout(processPanel, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
final Dimension buttonSize = new Dimension(150, 25);
|
||||||
|
|
||||||
|
JButton addButton = new JButton("New process");
|
||||||
|
addButton.setMaximumSize(buttonSize);
|
||||||
|
addButton.setPreferredSize(buttonSize);
|
||||||
|
addButton.setMaximumSize(buttonSize);
|
||||||
|
addButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
createProcess();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton rmButton = new JButton("Remove");
|
||||||
|
rmButton.setMaximumSize(buttonSize);
|
||||||
|
rmButton.setPreferredSize(buttonSize);
|
||||||
|
rmButton.setMaximumSize(buttonSize);
|
||||||
|
rmButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
removeProcesses();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton copyButton = new JButton("Copy");
|
||||||
|
copyButton.setMaximumSize(buttonSize);
|
||||||
|
copyButton.setPreferredSize(buttonSize);
|
||||||
|
copyButton.setMaximumSize(buttonSize);
|
||||||
|
copyButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
copyProcesses();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton renameButton = new JButton("Rename");
|
||||||
|
renameButton.setMaximumSize(buttonSize);
|
||||||
|
renameButton.setPreferredSize(buttonSize);
|
||||||
|
renameButton.setMaximumSize(buttonSize);
|
||||||
|
renameButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
renameProcess();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton upButton = new JButton("Move up");
|
||||||
|
upButton.setMaximumSize(buttonSize);
|
||||||
|
upButton.setPreferredSize(buttonSize);
|
||||||
|
upButton.setMaximumSize(buttonSize);
|
||||||
|
upButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
moveSelectedUp();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton downButton = new JButton("Move down");
|
||||||
|
downButton.setMaximumSize(buttonSize);
|
||||||
|
downButton.setPreferredSize(buttonSize);
|
||||||
|
downButton.setMaximumSize(buttonSize);
|
||||||
|
downButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
moveSelectedDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
buttonPanel.add(addButton);
|
||||||
|
buttonPanel.add(rmButton);
|
||||||
|
buttonPanel.add(copyButton);
|
||||||
|
buttonPanel.add(renameButton);
|
||||||
|
buttonPanel.add(upButton);
|
||||||
|
buttonPanel.add(downButton);
|
||||||
|
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
this.add(new JScrollPane(processPanel), BorderLayout.CENTER);
|
||||||
|
this.add(buttonPanel, BorderLayout.WEST);
|
||||||
|
|
||||||
|
createProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isModified() {
|
||||||
|
boolean procModified = false;
|
||||||
|
|
||||||
|
for (ProcessEditor pe : procEditors)
|
||||||
|
procModified |= pe.isModified();
|
||||||
|
|
||||||
|
return rs.modified | procModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearModificationStatus() {
|
||||||
|
for (ProcessEditor pe : procEditors)
|
||||||
|
pe.clearModificationStatus();
|
||||||
|
|
||||||
|
rs.modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getReactantsSet() {
|
||||||
|
HashSet<String> rset = new HashSet<String>();
|
||||||
|
|
||||||
|
for (ProcessEditor pe : procEditors)
|
||||||
|
rset.addAll(pe.getReactantsSet());
|
||||||
|
|
||||||
|
return rset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void exportToXML(PrintWriter output) {
|
||||||
|
output.println(" <reaction-system>");
|
||||||
|
|
||||||
|
for (ProcessEditor process : procEditors)
|
||||||
|
process.exportToXML(output);
|
||||||
|
|
||||||
|
output.println(" </reaction-system>");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadFromXML(Document input) throws ReactionSystemStructureError {
|
||||||
|
NodeList rsSections = input.getElementsByTagName("reaction-system");
|
||||||
|
|
||||||
|
if (rsSections.getLength() == 0 || rsSections.getLength() > 1) {
|
||||||
|
throw new ReactionSystemStructureError("An XML file should contain a single reaction system description.");
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeList processList = rsSections.item(0).getChildNodes();
|
||||||
|
|
||||||
|
for (int idx=0; idx<processList.getLength(); ++idx) {
|
||||||
|
Node processNode = processList.item(idx);
|
||||||
|
|
||||||
|
if (processNode.getNodeType() != Node.ELEMENT_NODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String procName = processNode.getAttributes().getNamedItem("name").getNodeValue();
|
||||||
|
ProcessEditor processEditor = new ProcessEditor(rs.createProcess(procName));
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------------
|
||||||
|
// Reactions details
|
||||||
|
//----------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
NodeList reactionList = processNode.getChildNodes();
|
||||||
|
|
||||||
|
for (int rIdx=0; rIdx<reactionList.getLength(); ++rIdx) {
|
||||||
|
Node reactionNode = reactionList.item(rIdx);
|
||||||
|
|
||||||
|
if (reactionNode.getNodeType() != Node.ELEMENT_NODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Reaction reaction = new Reaction();
|
||||||
|
|
||||||
|
NodeList substrateNodes = reactionNode.getChildNodes();
|
||||||
|
|
||||||
|
for (int sIdx=0; sIdx<substrateNodes.getLength(); ++sIdx) {
|
||||||
|
Node sNode = substrateNodes.item(sIdx);
|
||||||
|
|
||||||
|
if (sNode.getNodeType() != Node.ELEMENT_NODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String nodeName = sNode.getNodeName();
|
||||||
|
String nodeContent = sNode.getTextContent();
|
||||||
|
|
||||||
|
switch (nodeName) {
|
||||||
|
case "reactant":
|
||||||
|
reaction.reactants.add(nodeContent);
|
||||||
|
break;
|
||||||
|
case "inhibitor":
|
||||||
|
reaction.inhibitors.add(nodeContent);
|
||||||
|
break;
|
||||||
|
case "product":
|
||||||
|
reaction.products.add(nodeContent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ReactionSystemStructureError("Unexpected node type: " + nodeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processEditor.addReaction(reaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
procEditors.add(processEditor);
|
||||||
|
processPanel.add(processEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toRSSLString() {
|
||||||
|
StringBuilder rsString = new StringBuilder("reactions {\n");
|
||||||
|
|
||||||
|
for (ProcessEditor pe : procEditors) {
|
||||||
|
rsString.append(pe.toRSSLString());
|
||||||
|
}
|
||||||
|
|
||||||
|
rsString.append("};\n");
|
||||||
|
|
||||||
|
return rsString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
processPanel.removeAll();
|
||||||
|
procEditors.clear();
|
||||||
|
rs.clearProcesses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcess() {
|
||||||
|
ProcessEditor newProcEdt = new ProcessEditor(rs.createProcess());
|
||||||
|
procEditors.add(newProcEdt);
|
||||||
|
processPanel.add(newProcEdt);
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcess(String label) {
|
||||||
|
ProcessEditor newProcEdt = new ProcessEditor(rs.createProcess(label));
|
||||||
|
procEditors.add(newProcEdt);
|
||||||
|
processPanel.add(newProcEdt);
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeProcesses() {
|
||||||
|
Vector<ProcessEditor> toRemove = new Vector<ProcessEditor>();
|
||||||
|
for (ProcessEditor edt : procEditors) {
|
||||||
|
if (edt.isSelected()) {
|
||||||
|
toRemove.add(edt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toRemove.size() == procEditors.size()) {
|
||||||
|
JOptionPane.showMessageDialog(this, "There should be at least a single process in the system.",
|
||||||
|
"Warning", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ProcessEditor edt : toRemove) {
|
||||||
|
if (rs.removeProcess(edt.getProcess())) {
|
||||||
|
processPanel.remove(edt);
|
||||||
|
procEditors.remove(edt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JOptionPane.showMessageDialog(this, "Process " + edt.getLabel() +
|
||||||
|
" appears in a formula or a context automaton guard.\n" +
|
||||||
|
"Update them before removing the process.",
|
||||||
|
"Warning", JOptionPane.WARNING_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyProcesses() {
|
||||||
|
Vector<ProcessEditor> toBeCopied = new Vector<ProcessEditor>();
|
||||||
|
|
||||||
|
for (ProcessEditor edt : procEditors) {
|
||||||
|
if (edt.isSelected()) {
|
||||||
|
toBeCopied.add(edt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ProcessEditor edt : toBeCopied) {
|
||||||
|
ProcessEditor newEdt = new ProcessEditor(rs.copyProcess(edt.getProcess()));
|
||||||
|
processPanel.add(newEdt);
|
||||||
|
procEditors.add(newEdt);
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renameProcess() {
|
||||||
|
ProcessEditor toRename = null;
|
||||||
|
boolean fail = false;
|
||||||
|
|
||||||
|
for (ProcessEditor edt : procEditors) {
|
||||||
|
if (edt.isSelected()) {
|
||||||
|
if (toRename == null) {
|
||||||
|
toRename = edt;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail || toRename == null) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Select a single process to rename.", "Select process", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String idRegex = "[a-zA-Z][a-zA-Z_0-9:-]*";
|
||||||
|
boolean idOk = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
String newLabel = JOptionPane.showInputDialog(this, "Process name", toRename.getProcess().label);
|
||||||
|
if (newLabel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
newLabel = newLabel.trim();
|
||||||
|
|
||||||
|
if (!newLabel.matches(idRegex)) {
|
||||||
|
JOptionPane.showMessageDialog(this,
|
||||||
|
"<html>Process name should start with a letter and may contain only:<br/>" +
|
||||||
|
"letters, numbers, colons (:), underscores (_) and hyphens (-)</html>",
|
||||||
|
"Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
idOk = true;
|
||||||
|
rs.renameProcess(toRename.getProcess(), newLabel);
|
||||||
|
toRename.rename(newLabel);
|
||||||
|
rs.notifyObservers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!idOk);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveSelectedUp() {
|
||||||
|
Vector<Integer> toBeMovedIds = new Vector<Integer>();
|
||||||
|
for (int i = 0; i< procEditors.size(); ++i) {
|
||||||
|
if (procEditors.elementAt(i).isSelected())
|
||||||
|
toBeMovedIds.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int pos : toBeMovedIds) {
|
||||||
|
if (pos == 0 || procEditors.elementAt(pos-1).isSelected())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Collections.swap(procEditors, pos, pos-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
processPanel.removeAll();
|
||||||
|
|
||||||
|
for (ProcessEditor edt : procEditors) {
|
||||||
|
processPanel.add(edt);
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveSelectedDown() {
|
||||||
|
Vector<Integer> toBeMovedIds = new Vector<Integer>();
|
||||||
|
|
||||||
|
for (int i = procEditors.size()-1; i>=0; --i) {
|
||||||
|
if (procEditors.elementAt(i).isSelected())
|
||||||
|
toBeMovedIds.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int pos : toBeMovedIds) {
|
||||||
|
if (pos == procEditors.size()-1 || procEditors.elementAt(pos+1).isSelected())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Collections.swap(procEditors, pos, pos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
processPanel.removeAll();
|
||||||
|
|
||||||
|
for (ProcessEditor edt : procEditors) {
|
||||||
|
processPanel.add(edt);
|
||||||
|
}
|
||||||
|
|
||||||
|
rs.modified = true;
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRSUpdate() {
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ReactionSystemStructureError extends FileStructureError {
|
||||||
|
public ReactionSystemStructureError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
class TransitionEditor extends JDialog {
|
||||||
|
private JTable transitionsList;
|
||||||
|
private TransitionTableModel transitionsModel;
|
||||||
|
private Vector<Transition> transitions;
|
||||||
|
|
||||||
|
public TransitionEditor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// Create reactions list component
|
||||||
|
transitionsModel = new TransitionTableModel();
|
||||||
|
transitionsList = new JTable(transitionsModel);
|
||||||
|
|
||||||
|
Font cellFont = transitionsList.getFont();
|
||||||
|
Font headerFont = transitionsList.getTableHeader().getFont();
|
||||||
|
|
||||||
|
transitionsList.setFont(new Font("Monospaced", 0, cellFont.getSize() + 2));
|
||||||
|
transitionsList.getTableHeader().setFont(new Font(headerFont.getFamily(), Font.BOLD, headerFont.getSize() + 2));
|
||||||
|
transitionsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
|
|
||||||
|
getContentPane().setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JButton addButton = new JButton("Add transition");
|
||||||
|
addButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { addTransition(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton edtButton = new JButton("Edit transition");
|
||||||
|
edtButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { editTransition(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton rmButton = new JButton("Remove transition");
|
||||||
|
rmButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { removeTransitions(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton closeButton = new JButton("Close");
|
||||||
|
closeButton.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) { setVisible(false); }
|
||||||
|
});
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
buttonPanel.add(addButton);
|
||||||
|
buttonPanel.add(edtButton);
|
||||||
|
buttonPanel.add(rmButton);
|
||||||
|
buttonPanel.add(closeButton);
|
||||||
|
|
||||||
|
getContentPane().add(buttonPanel, BorderLayout.NORTH);
|
||||||
|
getContentPane().add(new JScrollPane(transitionsList), BorderLayout.CENTER);
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(-1, 200));
|
||||||
|
setSize(new Dimension(600, 200));
|
||||||
|
setTitle("Transitions");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showTransitionEditDialog(Component parent, Collection<Transition> trans, String from, String to) {
|
||||||
|
setTitle("Transitions for (" + from + " -> " + to + ")");
|
||||||
|
transitions = (Vector<Transition>) trans;
|
||||||
|
transitionsModel.fireTableDataChanged();
|
||||||
|
setLocationRelativeTo(parent);
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTransition() {
|
||||||
|
Transition tr = new Transition("", "");
|
||||||
|
|
||||||
|
if (!showTransitionEditDialog(tr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
transitions.add(tr);
|
||||||
|
transitionsModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editTransition() {
|
||||||
|
int[] selected = transitionsList.getSelectedRows();
|
||||||
|
|
||||||
|
if (selected.length != 1) {
|
||||||
|
JOptionPane.showMessageDialog(this, "Select a single transition to edit.", "Select transition", JOptionPane.WARNING_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Transition tr = transitions.get(selected[0]);
|
||||||
|
transitionsList.clearSelection();
|
||||||
|
if (!showTransitionEditDialog(tr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transitions.setElementAt(tr, selected[0]);
|
||||||
|
transitionsModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeTransitions() {
|
||||||
|
int[] selected = transitionsList.getSelectedRows();
|
||||||
|
|
||||||
|
for (int trIdx : selected) {
|
||||||
|
transitions.remove(trIdx);
|
||||||
|
transitionsList.clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
transitionsModel.fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean showTransitionEditDialog(Transition tr) {
|
||||||
|
final int Select = 0;
|
||||||
|
final int Approve = 1;
|
||||||
|
|
||||||
|
JTextField contextInput = new JTextField(30);
|
||||||
|
JTextField guardInput = new JTextField(30);
|
||||||
|
|
||||||
|
String contextStr = tr.context;
|
||||||
|
String guardStr = tr.guard;
|
||||||
|
|
||||||
|
contextInput.setToolTipText("<html>Additional entities for processes</html>");
|
||||||
|
guardInput.setToolTipText("<html>Initial conditions for the transition in rsCTL format.</html>");
|
||||||
|
|
||||||
|
JPanel myPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints cs = new GridBagConstraints();
|
||||||
|
|
||||||
|
cs.insets = new Insets(5, 5, 5, 5);
|
||||||
|
cs.anchor = GridBagConstraints.WEST;
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(new JLabel("Context"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 0;
|
||||||
|
myPanel.add(contextInput, cs);
|
||||||
|
|
||||||
|
cs.gridx = 0;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(new JLabel("Guards"), cs);
|
||||||
|
|
||||||
|
cs.gridx = 1;
|
||||||
|
cs.gridy = 1;
|
||||||
|
myPanel.add(guardInput, cs);
|
||||||
|
|
||||||
|
int opStatus = Select;
|
||||||
|
|
||||||
|
do {
|
||||||
|
contextInput.setText(contextStr);
|
||||||
|
guardInput.setText(guardStr);
|
||||||
|
|
||||||
|
int result = JOptionPane.showConfirmDialog(null, myPanel,
|
||||||
|
"Reaction details", JOptionPane.OK_CANCEL_OPTION);
|
||||||
|
|
||||||
|
if (result != JOptionPane.OK_OPTION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
contextStr = contextInput.getText();
|
||||||
|
guardStr = guardInput.getText();
|
||||||
|
|
||||||
|
//TODO: Validate the data entered to the text fields
|
||||||
|
tr.context = contextStr;
|
||||||
|
tr.guard = guardStr;
|
||||||
|
|
||||||
|
opStatus = Approve;
|
||||||
|
}
|
||||||
|
while(opStatus == Select);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TransitionTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private final String[] columnNames = {"Context", "Guard"};
|
||||||
|
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return columnNames[colIdx];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRowCount() {
|
||||||
|
return transitions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return columnNames.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object getValueAt(int row, int column) {
|
||||||
|
Transition tr = transitions.get(row);
|
||||||
|
|
||||||
|
return switch (column) {
|
||||||
|
case 0 -> tr.context;
|
||||||
|
case 1 -> tr.guard;
|
||||||
|
default -> "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
package pl.umk.mat.martinp.reactics;
|
||||||
|
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.*;
|
||||||
|
import edu.uci.ics.jung.algorithms.layout.util.Relaxer;
|
||||||
|
import edu.uci.ics.jung.graph.DirectedSparseGraph;
|
||||||
|
import edu.uci.ics.jung.visualization.VisualizationViewer;
|
||||||
|
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
|
||||||
|
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
|
||||||
|
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
|
||||||
|
import edu.uci.ics.jung.visualization.renderers.Renderer;
|
||||||
|
import org.apache.commons.collections15.Transformer;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JToolTip;
|
||||||
|
import javax.swing.Icon;
|
||||||
|
import javax.swing.border.EtchedBorder;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
|
public class TransitionSystemViewer extends JPanel implements RSObserver {
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Visual configuration settings
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
private static final Color pickedNodeColor = Color.yellow;
|
||||||
|
private static final Color edgeColor = Color.black;
|
||||||
|
private static final Font nodeLabelFont = new Font("Helvetica", Font.BOLD, 20);
|
||||||
|
private static final Font toolTipFont = new Font("Helvetica", Font.PLAIN, 14);
|
||||||
|
private static final Stroke basicEdgeArrow = new BasicStroke(3.0f);
|
||||||
|
|
||||||
|
private static Dimension initialEditorSize;
|
||||||
|
|
||||||
|
private VisualizationViewer<TSState, TSTransition> graphViewer;
|
||||||
|
private Layout<TSState, TSTransition> graphLayout;
|
||||||
|
DefaultModalGraphMouse graphMouse;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Transition system graph
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
|
private DirectedSparseGraph<TSState, TSTransition> tsGraph;
|
||||||
|
private boolean isCompressed;
|
||||||
|
|
||||||
|
// Is transition system already computed?
|
||||||
|
// Used to avoid unnecessary computation of the same graph.
|
||||||
|
private boolean computed = false;
|
||||||
|
|
||||||
|
// compressed == true => context automaton state is not taken into account.
|
||||||
|
public TransitionSystemViewer(Dimension size, boolean compressed) {
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
tsGraph = new DirectedSparseGraph<TSState, TSTransition>();
|
||||||
|
this.isCompressed = compressed;
|
||||||
|
initialEditorSize = size;
|
||||||
|
|
||||||
|
createGraphViever();
|
||||||
|
lockNodesPositions(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is transition system graph already computed?
|
||||||
|
boolean isComputed() { return computed; }
|
||||||
|
|
||||||
|
void clearModificationStatus() { computed = false; }
|
||||||
|
|
||||||
|
private void createGraphViever() {
|
||||||
|
graphLayout = new FRLayout<TSState, TSTransition>(tsGraph);
|
||||||
|
|
||||||
|
graphViewer = new VisualizationViewer<TSState, TSTransition>(graphLayout, initialEditorSize) {
|
||||||
|
public JToolTip createToolTip() {
|
||||||
|
JToolTip tooltip = super.createToolTip();
|
||||||
|
tooltip.setFont(toolTipFont);
|
||||||
|
return tooltip;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Nodes labels
|
||||||
|
graphViewer.getRenderContext().setVertexLabelTransformer(
|
||||||
|
new ToStringLabeller<TSState>());
|
||||||
|
graphViewer.getRenderer().getVertexLabelRenderer()
|
||||||
|
.setPosition(Renderer.VertexLabel.Position.CNTR);
|
||||||
|
graphViewer.getRenderContext().setVertexFontTransformer(
|
||||||
|
new Transformer<TSState,Font>() {
|
||||||
|
public Font transform(TSState st) {
|
||||||
|
return nodeLabelFont;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nodes colour, background, etc.
|
||||||
|
graphViewer.getRenderContext().setVertexIconTransformer(new Transformer<TSState,Icon>() {
|
||||||
|
public Icon transform(final TSState v) {
|
||||||
|
Color nodeColor = null;
|
||||||
|
|
||||||
|
if(graphViewer.getPickedVertexState().isPicked(v))
|
||||||
|
nodeColor = pickedNodeColor;
|
||||||
|
else
|
||||||
|
nodeColor = v.getFillColor();
|
||||||
|
|
||||||
|
return (v.isInitial() ? new SquareIcon(nodeColor, v.getWidth()) : new CircleIcon(nodeColor, v.getWidth()));
|
||||||
|
|
||||||
|
}});
|
||||||
|
|
||||||
|
graphViewer.getRenderContext().setEdgeShapeTransformer(new ConditionalEdgeShape<>(1.5f));
|
||||||
|
|
||||||
|
// Edges
|
||||||
|
graphViewer.getRenderContext().setEdgeArrowStrokeTransformer(new Transformer<TSTransition, Stroke>() {
|
||||||
|
public Stroke transform(TSTransition tr) {
|
||||||
|
return basicEdgeArrow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// For interactive graph editing
|
||||||
|
graphMouse = new DefaultModalGraphMouse();
|
||||||
|
graphViewer.setGraphMouse(graphMouse);
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
|
||||||
|
|
||||||
|
graphViewer.setVertexToolTipTransformer(new Transformer<TSState, String>() {
|
||||||
|
public String transform(TSState st) {
|
||||||
|
return st.getTooltipText();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
graphViewer.setBackground(Color.white);
|
||||||
|
graphViewer.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
|
||||||
|
|
||||||
|
add(graphViewer, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateTransitionSystemStructure(String tsString) {
|
||||||
|
// Clear graph
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// Load graph structure
|
||||||
|
int nextId = 1;
|
||||||
|
|
||||||
|
HashMap<String, TSState> nodes = new HashMap<>();
|
||||||
|
TSState src = null;
|
||||||
|
|
||||||
|
for (String line : tsString.split("\\R")) {
|
||||||
|
char type = line.charAt(0);
|
||||||
|
line = line.substring(2).strip();
|
||||||
|
int end = line.lastIndexOf('}');
|
||||||
|
String automatonState = line.substring(end + 1, line.length() - 1).strip();
|
||||||
|
String stateStr = line.substring(line.indexOf('{'), end + 1);
|
||||||
|
TSState state = nodes.get( isCompressed ? stateStr : line);
|
||||||
|
|
||||||
|
if (state == null) {
|
||||||
|
state = new TSState(nextId++, stateStr, isCompressed ? null : automatonState);
|
||||||
|
nodes.put(isCompressed ? stateStr : line, state);
|
||||||
|
tsGraph.addVertex(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == 'G') {
|
||||||
|
src = state;
|
||||||
|
}
|
||||||
|
else if (type == 's') {
|
||||||
|
tsGraph.addEdge(new TSTransition(), src, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the initial state
|
||||||
|
for (TSState state : tsGraph.getVertices()) {
|
||||||
|
if (tsGraph.getInEdges(state).size() == 0) {
|
||||||
|
state.setAsInitial();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relax();
|
||||||
|
graphViewer.repaint();
|
||||||
|
computed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void lockNodesPositions(boolean lock) {
|
||||||
|
if (lock)
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
|
||||||
|
else
|
||||||
|
graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
for (TSState st : new java.util.ArrayList<TSState>(tsGraph.getVertices())) {
|
||||||
|
tsGraph.removeVertex(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** For better vertex placement */
|
||||||
|
private void relax() {
|
||||||
|
graphLayout.initialize();
|
||||||
|
graphLayout.setSize(graphViewer.getSize());
|
||||||
|
Relaxer relaxer = graphViewer.getModel().getRelaxer();
|
||||||
|
|
||||||
|
if (relaxer != null) {
|
||||||
|
relaxer.stop();
|
||||||
|
relaxer.prerelax();
|
||||||
|
relaxer.relax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// For drawing the initial state
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static class SquareIcon implements Icon {
|
||||||
|
private final Color fillColor;
|
||||||
|
private final int width;
|
||||||
|
|
||||||
|
public SquareIcon(Color fColor, int width) {
|
||||||
|
fillColor = fColor;
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(fillColor);
|
||||||
|
g.fillRect(x, y, width, width);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.drawRect(x, y, width, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconHeight() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
// For drawing all non-initial states
|
||||||
|
//---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static class CircleIcon implements Icon {
|
||||||
|
private final Color fillColor;
|
||||||
|
private final int radius;
|
||||||
|
|
||||||
|
public CircleIcon(Color fColor, int radius) {
|
||||||
|
fillColor = fColor;
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||||
|
g.setColor(fillColor);
|
||||||
|
g.fillOval(x, y, radius, radius);
|
||||||
|
g.setColor(Color.black);
|
||||||
|
g.drawOval(x, y, radius, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconWidth() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIconHeight() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRSUpdate() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Single node of the Transition system graph
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TSState {
|
||||||
|
|
||||||
|
public final static Color fillColor = Color.lightGray;
|
||||||
|
public final static Color initialColor = new Color(102, 178, 255);
|
||||||
|
|
||||||
|
private static final int nodeWidth = 30;
|
||||||
|
private static final int nodeHeight = 30;
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
private final String rsDetails;
|
||||||
|
private final String toolTipText;
|
||||||
|
private final String aState;
|
||||||
|
private boolean initial = false;
|
||||||
|
|
||||||
|
public TSState(int id, String stateStr) {
|
||||||
|
this.id = id;
|
||||||
|
this.rsDetails = formatRSDetails(stateStr.substring(1, stateStr.length() - 1).strip());
|
||||||
|
this.aState = null;
|
||||||
|
this.toolTipText = formatToolTipText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TSState(int id, String stateStr, String aState) {
|
||||||
|
this.id = id;
|
||||||
|
this.rsDetails = formatRSDetails(stateStr.substring(1, stateStr.length() - 1).strip());
|
||||||
|
this.aState = aState;
|
||||||
|
this.toolTipText = formatToolTipText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitial() {
|
||||||
|
return initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsInitial() {
|
||||||
|
initial = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return nodeWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return nodeHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color getFillColor() {
|
||||||
|
return initial ? initialColor : fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTooltipText() {
|
||||||
|
return toolTipText;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatRSDetails(String rsDetails) {
|
||||||
|
return rsDetails.replaceAll("\\} (proc\\d+=\\{)", "}<br/>$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatToolTipText() {
|
||||||
|
Pattern pattern = Pattern.compile("\\w+=\\{[^}]*\\}");
|
||||||
|
Matcher matcher = pattern.matcher(rsDetails);
|
||||||
|
|
||||||
|
ArrayList<String> blocks = new ArrayList<String>();
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
blocks.add(matcher.group());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aState != null)
|
||||||
|
return "<html>" +
|
||||||
|
"<b>CA</b> " + aState+ "<br/><hr>" +
|
||||||
|
String.join("<br/>", blocks) +
|
||||||
|
"</html>";
|
||||||
|
else
|
||||||
|
return "<html>" +
|
||||||
|
String.join("<br/>", blocks) +
|
||||||
|
"</html>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
// Single edge of the Transition system graph
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TSTransition { }
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
C_HEADER = '\033[95m'
|
C_HEADER = "\033[95m"
|
||||||
C_BLUE = '\033[94m'
|
C_BLUE = "\033[94m"
|
||||||
C_GREEN = '\033[92m'
|
C_GREEN = "\033[92m"
|
||||||
C_SOMEOTHER = '\033[93m'
|
C_SOMEOTHER = "\033[93m"
|
||||||
C_RED = '\033[91m'
|
C_RED = "\033[91m"
|
||||||
C_ENDC = '\033[0m'
|
C_ENDC = "\033[0m"
|
||||||
C_BOLD = '\033[1m'
|
C_BOLD = "\033[1m"
|
||||||
C_UNDERLINE = '\033[4m'
|
C_UNDERLINE = "\033[4m"
|
||||||
|
|
||||||
C_MARK_INFO = C_BOLD + "[" + C_GREEN + "*" + C_ENDC + C_BOLD + "]" + C_ENDC
|
C_MARK_INFO = C_BOLD + "[" + C_GREEN + "*" + C_ENDC + C_BOLD + "]" + C_ENDC
|
||||||
C_MARK_ERROR = C_BOLD + "[" + C_RED + "!" + C_ENDC + C_BOLD + "]" + C_ENDC
|
C_MARK_ERROR = C_BOLD + "[" + C_RED + "!" + C_ENDC + C_BOLD + "]" + C_ENDC
|
||||||
@@ -30,4 +30,5 @@ def print_info(s):
|
|||||||
def print_positive(s):
|
def print_positive(s):
|
||||||
print("[" + colour_str(C_BOLD, "+") + "] {:s}".format(s))
|
print("[" + colour_str(C_BOLD, "+") + "] {:s}".format(s))
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -5,26 +5,26 @@ from smt import *
|
|||||||
from logics import *
|
from logics import *
|
||||||
from rsltl_shortcuts import *
|
from rsltl_shortcuts import *
|
||||||
|
|
||||||
|
|
||||||
def ex():
|
def ex():
|
||||||
|
|
||||||
prs = ReactionSystemWithConcentrationsParam()
|
prs = ReactionSystemWithConcentrationsParam()
|
||||||
|
|
||||||
ent_with_conc = [("a", 3), ("b",2), ("c",1), ("h",1)]
|
ent_with_conc = [("a", 3), ("b", 2), ("c", 1), ("h", 1)]
|
||||||
|
|
||||||
for ec in ent_with_conc:
|
for ec in ent_with_conc:
|
||||||
prs.add_bg_set_entity(ec)
|
prs.add_bg_set_entity(ec)
|
||||||
|
|
||||||
lda = prs.get_param("lda")
|
lda = prs.get_param("lda")
|
||||||
|
|
||||||
prs.add_reaction([("a",1)],[("h",1)],[("b", 2)])
|
prs.add_reaction([("a", 1)], [("h", 1)], [("b", 2)])
|
||||||
prs.add_reaction(lda,[("h",1)],[("c",1)])
|
prs.add_reaction(lda, [("h", 1)], [("c", 1)])
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
||||||
ca = ContextAutomatonWithConcentrations(prs)
|
ca = ContextAutomatonWithConcentrations(prs)
|
||||||
ca.add_init_state("0")
|
ca.add_init_state("0")
|
||||||
ca.add_state("1")
|
ca.add_state("1")
|
||||||
|
|
||||||
ca.add_transition("0", [("a", 3)], "1")
|
ca.add_transition("0", [("a", 3)], "1")
|
||||||
ca.add_transition("1", [], "1")
|
ca.add_transition("1", [], "1")
|
||||||
ca.add_transition("1", [("h", 1)], "1")
|
ca.add_transition("1", [("h", 1)], "1")
|
||||||
@@ -37,8 +37,9 @@ def ex():
|
|||||||
|
|
||||||
checker = SmtCheckerRSCParam(crprs, optimise=True)
|
checker = SmtCheckerRSCParam(crprs, optimise=True)
|
||||||
checker.check_rsltl(formulae_list=[f], param_constr=pc)
|
checker.check_rsltl(formulae_list=[f], param_constr=pc)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
ex()
|
ex()
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
BagDesc_oper = Enum(
|
|
||||||
'BagDesc_oper', 'entity true l_and l_or l_not lt le eq ge gt')
|
BagDesc_oper = Enum("BagDesc_oper", "entity true l_and l_or l_not lt le eq ge gt")
|
||||||
|
|
||||||
|
|
||||||
class BagDescription(object):
|
class BagDescription(object):
|
||||||
|
|
||||||
def __init__(self, f_type, L_oper=None, R_oper=None, entity=""):
|
def __init__(self, f_type, L_oper=None, R_oper=None, entity=""):
|
||||||
self.f_type = f_type
|
self.f_type = f_type
|
||||||
self.left_operand = L_oper
|
self.left_operand = L_oper
|
||||||
@@ -19,9 +18,13 @@ class BagDescription(object):
|
|||||||
if self.f_type == BagDesc_oper.true:
|
if self.f_type == BagDesc_oper.true:
|
||||||
return "TRUE"
|
return "TRUE"
|
||||||
if self.f_type == BagDesc_oper.l_and:
|
if self.f_type == BagDesc_oper.l_and:
|
||||||
return "(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == BagDesc_oper.l_or:
|
if self.f_type == BagDesc_oper.l_or:
|
||||||
return "(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == BagDesc_oper.l_not:
|
if self.f_type == BagDesc_oper.l_not:
|
||||||
return "~(" + repr(self.left_operand) + ")"
|
return "~(" + repr(self.left_operand) + ")"
|
||||||
if self.f_type == BagDesc_oper.lt:
|
if self.f_type == BagDesc_oper.lt:
|
||||||
@@ -39,12 +42,14 @@ class BagDescription(object):
|
|||||||
"""Sanity checks"""
|
"""Sanity checks"""
|
||||||
for operand in (self.left_operand, self.right_operand):
|
for operand in (self.left_operand, self.right_operand):
|
||||||
if operand:
|
if operand:
|
||||||
if not(
|
if not (
|
||||||
isinstance(operand, BagDescription)
|
isinstance(operand, BagDescription) or isinstance(operand, int)
|
||||||
or isinstance(operand, int)):
|
):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Unexpected operand type for a bag: {:s} (type: {:s})".format(
|
"Unexpected operand type for a bag: {:s} (type: {:s})".format(
|
||||||
str(operand), str(type(operand))))
|
str(operand), str(type(operand))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_entity(cls, entity_name):
|
def f_entity(cls, entity_name):
|
||||||
@@ -86,4 +91,5 @@ class BagDescription(object):
|
|||||||
def __invert__(self):
|
def __invert__(self):
|
||||||
return BagDescription(BagDesc_oper.l_not, L_oper=self)
|
return BagDescription(BagDesc_oper.l_not, L_oper=self)
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
ParamConstraint_oper = Enum(
|
ParamConstraint_oper = Enum(
|
||||||
'ParamConstraint_oper',
|
"ParamConstraint_oper", "param_entity true l_and l_or l_not lt le eq ge gt"
|
||||||
'param_entity true l_and l_or l_not lt le eq ge gt')
|
)
|
||||||
|
|
||||||
|
|
||||||
class ParamConstraint(object):
|
class ParamConstraint(object):
|
||||||
|
|
||||||
def __init__(self, f_type, L_oper=None, R_oper=None, param=None, entity=""):
|
def __init__(self, f_type, L_oper=None, R_oper=None, param=None, entity=""):
|
||||||
self.f_type = f_type
|
self.f_type = f_type
|
||||||
self.left_operand = L_oper
|
self.left_operand = L_oper
|
||||||
@@ -21,9 +21,13 @@ class ParamConstraint(object):
|
|||||||
if self.f_type == ParamConstraint_oper.true:
|
if self.f_type == ParamConstraint_oper.true:
|
||||||
return "TRUE"
|
return "TRUE"
|
||||||
if self.f_type == ParamConstraint_oper.l_and:
|
if self.f_type == ParamConstraint_oper.l_and:
|
||||||
return "(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == ParamConstraint_oper.l_or:
|
if self.f_type == ParamConstraint_oper.l_or:
|
||||||
return "(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == ParamConstraint_oper.l_not:
|
if self.f_type == ParamConstraint_oper.l_not:
|
||||||
return "~(" + repr(self.left_operand) + ")"
|
return "~(" + repr(self.left_operand) + ")"
|
||||||
if self.f_type == ParamConstraint_oper.lt:
|
if self.f_type == ParamConstraint_oper.lt:
|
||||||
@@ -41,17 +45,18 @@ class ParamConstraint(object):
|
|||||||
"""Sanity checks"""
|
"""Sanity checks"""
|
||||||
for operand in (self.left_operand, self.right_operand):
|
for operand in (self.left_operand, self.right_operand):
|
||||||
if operand:
|
if operand:
|
||||||
if not(
|
if not (
|
||||||
isinstance(operand, ParamConstraint)
|
isinstance(operand, ParamConstraint) or isinstance(operand, int)
|
||||||
or isinstance(operand, int)):
|
):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Unexpected operand type for a bag: {:s} (type: {:s})".format(
|
"Unexpected operand type for a bag: {:s} (type: {:s})".format(
|
||||||
str(operand), str(type(operand))))
|
str(operand), str(type(operand))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_param_ent(cls, param, entity_name):
|
def f_param_ent(cls, param, entity_name):
|
||||||
return cls(ParamConstraint_oper.param_entity, param=param,
|
return cls(ParamConstraint_oper.param_entity, param=param, entity=entity_name)
|
||||||
entity=entity_name)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_TRUE(cls):
|
def f_TRUE(cls):
|
||||||
@@ -66,34 +71,28 @@ class ParamConstraint(object):
|
|||||||
return cls(ParamConstraint_oper.l_not, L_oper=arg)
|
return cls(ParamConstraint_oper.l_not, L_oper=arg)
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.lt, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.lt, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __le__(self, other):
|
def __le__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.le, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.le, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.eq, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.eq, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.ge, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.ge, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.gt, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.gt, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __and__(self, other):
|
def __and__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.l_and, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.l_and, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __or__(self, other):
|
def __or__(self, other):
|
||||||
return ParamConstraint(
|
return ParamConstraint(ParamConstraint_oper.l_or, L_oper=self, R_oper=other)
|
||||||
ParamConstraint_oper.l_or, L_oper=self, R_oper=other)
|
|
||||||
|
|
||||||
def __invert__(self):
|
def __invert__(self):
|
||||||
return ParamConstraint(ParamConstraint_oper.l_not, L_oper=self)
|
return ParamConstraint(ParamConstraint_oper.l_not, L_oper=self)
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -14,57 +14,60 @@ class ParamConstr_Encoder(object):
|
|||||||
# self.loop_position = None
|
# self.loop_position = None
|
||||||
|
|
||||||
def load_variables(self, var_rs, var_ctx, var_loop_pos):
|
def load_variables(self, var_rs, var_ctx, var_loop_pos):
|
||||||
|
|
||||||
self.v = var_rs
|
self.v = var_rs
|
||||||
self.v_ctx = var_ctx
|
self.v_ctx = var_ctx
|
||||||
self.loop_position = var_loop_pos
|
self.loop_position = var_loop_pos
|
||||||
|
|
||||||
def encode(self, param_constr):
|
def encode(self, param_constr):
|
||||||
|
|
||||||
if not param_constr:
|
if not param_constr:
|
||||||
raise RuntimeError("param_constr is None")
|
raise RuntimeError("param_constr is None")
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.param_entity:
|
if param_constr.f_type == ParamConstraint_oper.param_entity:
|
||||||
return self.smt_checker.get_enc_param(
|
return self.smt_checker.get_enc_param(
|
||||||
param_constr.param.name, param_constr.entity)
|
param_constr.param.name, param_constr.entity
|
||||||
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.true:
|
if param_constr.f_type == ParamConstraint_oper.true:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.l_and:
|
if param_constr.f_type == ParamConstraint_oper.l_and:
|
||||||
return And(self.encode(param_constr.left_operand),
|
return And(
|
||||||
self.encode(param_constr.right_operand))
|
self.encode(param_constr.left_operand),
|
||||||
|
self.encode(param_constr.right_operand),
|
||||||
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.l_or:
|
if param_constr.f_type == ParamConstraint_oper.l_or:
|
||||||
return Or(self.encode(param_constr.left_operand),
|
return Or(
|
||||||
self.encode(param_constr.right_operand))
|
self.encode(param_constr.left_operand),
|
||||||
|
self.encode(param_constr.right_operand),
|
||||||
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.l_not:
|
if param_constr.f_type == ParamConstraint_oper.l_not:
|
||||||
return Not(self.encode(param_constr.left_operand))
|
return Not(self.encode(param_constr.left_operand))
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.lt:
|
if param_constr.f_type == ParamConstraint_oper.lt:
|
||||||
return self.encode(
|
return self.encode(param_constr.left_operand) < int(
|
||||||
param_constr.left_operand) < int(
|
param_constr.right_operand
|
||||||
param_constr.right_operand)
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.le:
|
if param_constr.f_type == ParamConstraint_oper.le:
|
||||||
return self.encode(
|
return self.encode(param_constr.left_operand) <= int(
|
||||||
param_constr.left_operand) <= int(
|
param_constr.right_operand
|
||||||
param_constr.right_operand)
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.eq:
|
if param_constr.f_type == ParamConstraint_oper.eq:
|
||||||
return self.encode(
|
return self.encode(param_constr.left_operand) == int(
|
||||||
param_constr.left_operand) == int(
|
param_constr.right_operand
|
||||||
param_constr.right_operand)
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.ge:
|
if param_constr.f_type == ParamConstraint_oper.ge:
|
||||||
return self.encode(
|
return self.encode(param_constr.left_operand) >= int(
|
||||||
param_constr.left_operand) >= int(
|
param_constr.right_operand
|
||||||
param_constr.right_operand)
|
)
|
||||||
|
|
||||||
if param_constr.f_type == ParamConstraint_oper.gt:
|
if param_constr.f_type == ParamConstraint_oper.gt:
|
||||||
return self.encode(
|
return self.encode(param_constr.left_operand) > int(
|
||||||
param_constr.left_operand) > int(
|
param_constr.right_operand
|
||||||
param_constr.right_operand)
|
)
|
||||||
|
|
||||||
assert False, "Unsupported case {:s}".format(param_constr.f_type)
|
assert False, "Unsupported case {:s}".format(param_constr.f_type)
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ from enum import Enum
|
|||||||
from logics.bags import *
|
from logics.bags import *
|
||||||
|
|
||||||
rsLTL_form_type = Enum(
|
rsLTL_form_type = Enum(
|
||||||
'rsLTL_form_type',
|
"rsLTL_form_type",
|
||||||
'bag l_and l_or l_not l_implies t_globally t_finally t_next t_until t_release')
|
"bag l_and l_or l_not l_implies t_globally t_finally t_next t_until t_release",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Formula_rsLTL(object):
|
class Formula_rsLTL(object):
|
||||||
|
def __init__(self, f_type, L_oper=None, R_oper=None, sub_oper=None, bag=None):
|
||||||
def __init__(
|
|
||||||
self, f_type, L_oper=None, R_oper=None, sub_oper=None, bag=None):
|
|
||||||
self.f_type = f_type
|
self.f_type = f_type
|
||||||
self.left_operand = L_oper
|
self.left_operand = L_oper
|
||||||
self.right_operand = R_oper
|
self.right_operand = R_oper
|
||||||
@@ -21,7 +20,10 @@ class Formula_rsLTL(object):
|
|||||||
# it's silly, but it's a frequent mistake
|
# it's silly, but it's a frequent mistake
|
||||||
if callable(sub_oper):
|
if callable(sub_oper):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"sub_oper should not be a function. Missing () for {0}?".format(sub_oper))
|
"sub_oper should not be a function. Missing () for {0}?".format(
|
||||||
|
sub_oper
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if isinstance(self.left_operand, BagDescription):
|
if isinstance(self.left_operand, BagDescription):
|
||||||
self.left_operand = Formula_rsLTL.f_bag(self.left_operand)
|
self.left_operand = Formula_rsLTL.f_bag(self.left_operand)
|
||||||
@@ -43,21 +45,37 @@ class Formula_rsLTL(object):
|
|||||||
if self.f_type == rsLTL_form_type.t_next:
|
if self.f_type == rsLTL_form_type.t_next:
|
||||||
return "X[" + repr(self.sub_operand) + "](" + repr(self.left_operand) + ")"
|
return "X[" + repr(self.sub_operand) + "](" + repr(self.left_operand) + ")"
|
||||||
if self.f_type == rsLTL_form_type.l_and:
|
if self.f_type == rsLTL_form_type.l_and:
|
||||||
return "(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " & " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == rsLTL_form_type.l_or:
|
if self.f_type == rsLTL_form_type.l_or:
|
||||||
return "(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " | " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == rsLTL_form_type.l_implies:
|
if self.f_type == rsLTL_form_type.l_implies:
|
||||||
return "(" + repr(self.left_operand) + " => " + repr(self.right_operand) + ")"
|
return (
|
||||||
|
"(" + repr(self.left_operand) + " => " + repr(self.right_operand) + ")"
|
||||||
|
)
|
||||||
if self.f_type == rsLTL_form_type.t_until:
|
if self.f_type == rsLTL_form_type.t_until:
|
||||||
return "(" + repr(
|
return (
|
||||||
self.left_operand) + " U[" + repr(
|
"("
|
||||||
self.sub_operand) + "] " + repr(
|
+ repr(self.left_operand)
|
||||||
self.right_operand) + ")"
|
+ " U["
|
||||||
|
+ repr(self.sub_operand)
|
||||||
|
+ "] "
|
||||||
|
+ repr(self.right_operand)
|
||||||
|
+ ")"
|
||||||
|
)
|
||||||
if self.f_type == rsLTL_form_type.t_release:
|
if self.f_type == rsLTL_form_type.t_release:
|
||||||
return "(" + repr(
|
return (
|
||||||
self.left_operand) + " R[" + repr(
|
"("
|
||||||
self.sub_operand) + "] " + repr(
|
+ repr(self.left_operand)
|
||||||
self.right_operand) + ")"
|
+ " R["
|
||||||
|
+ repr(self.sub_operand)
|
||||||
|
+ "] "
|
||||||
|
+ repr(self.right_operand)
|
||||||
|
+ ")"
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_bag(self):
|
def is_bag(self):
|
||||||
@@ -93,8 +111,7 @@ class Formula_rsLTL(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_U(cls, sub, arg_L, arg_R):
|
def f_U(cls, sub, arg_L, arg_R):
|
||||||
return cls(
|
return cls(rsLTL_form_type.t_until, L_oper=arg_L, R_oper=arg_R, sub_oper=sub)
|
||||||
rsLTL_form_type.t_until, L_oper=arg_L, R_oper=arg_R, sub_oper=sub)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_F(cls, sub, arg_L):
|
def f_F(cls, sub, arg_L):
|
||||||
@@ -102,9 +119,7 @@ class Formula_rsLTL(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def f_R(cls, sub, arg_L, arg_R):
|
def f_R(cls, sub, arg_L, arg_R):
|
||||||
return cls(
|
return cls(rsLTL_form_type.t_release, L_oper=arg_L, R_oper=arg_R, sub_oper=sub)
|
||||||
rsLTL_form_type.t_release, L_oper=arg_L, R_oper=arg_R,
|
|
||||||
sub_oper=sub)
|
|
||||||
|
|
||||||
def __and__(self, other):
|
def __and__(self, other):
|
||||||
return Formula_rsLTL(rsLTL_form_type.l_and, L_oper=self, R_oper=other)
|
return Formula_rsLTL(rsLTL_form_type.l_and, L_oper=self, R_oper=other)
|
||||||
|
|||||||
@@ -24,13 +24,11 @@ class rsLTL_Encoder(object):
|
|||||||
self.init_ncalls()
|
self.init_ncalls()
|
||||||
|
|
||||||
def load_variables(self, var_rs, var_ctx, var_loop_pos):
|
def load_variables(self, var_rs, var_ctx, var_loop_pos):
|
||||||
|
|
||||||
self.v = var_rs
|
self.v = var_rs
|
||||||
self.v_ctx = var_ctx
|
self.v_ctx = var_ctx
|
||||||
self.loop_position = var_loop_pos
|
self.loop_position = var_loop_pos
|
||||||
|
|
||||||
def get_encoding(self, formula, bound):
|
def get_encoding(self, formula, bound):
|
||||||
|
|
||||||
assert self.v is not None
|
assert self.v is not None
|
||||||
assert self.v_ctx is not None
|
assert self.v_ctx is not None
|
||||||
assert self.loop_position is not None
|
assert self.loop_position is not None
|
||||||
@@ -49,8 +47,8 @@ class rsLTL_Encoder(object):
|
|||||||
Cache for formulae encodings
|
Cache for formulae encodings
|
||||||
"""
|
"""
|
||||||
self.cache_hits = 0
|
self.cache_hits = 0
|
||||||
self.enc_fcache = [{} for level in range(0, bound+1)]
|
self.enc_fcache = [{} for level in range(0, bound + 1)]
|
||||||
self.enc_fcache_approx = [{} for level in range(0, bound+1)]
|
self.enc_fcache_approx = [{} for level in range(0, bound + 1)]
|
||||||
|
|
||||||
def cache_save(self, formula, level, formula_encoding):
|
def cache_save(self, formula, level, formula_encoding):
|
||||||
self.enc_fcache[level][formula] = formula_encoding
|
self.enc_fcache[level][formula] = formula_encoding
|
||||||
@@ -83,7 +81,6 @@ class rsLTL_Encoder(object):
|
|||||||
return (self.ncalls_encode, self.ncalls_encode_approx)
|
return (self.ncalls_encode, self.ncalls_encode_approx)
|
||||||
|
|
||||||
def encode_bag(self, bag_formula, level, context=False):
|
def encode_bag(self, bag_formula, level, context=False):
|
||||||
|
|
||||||
if not bag_formula:
|
if not bag_formula:
|
||||||
raise RuntimeError("bag_formula is None")
|
raise RuntimeError("bag_formula is None")
|
||||||
|
|
||||||
@@ -100,41 +97,42 @@ class rsLTL_Encoder(object):
|
|||||||
if bag_formula.f_type == BagDesc_oper.l_and:
|
if bag_formula.f_type == BagDesc_oper.l_and:
|
||||||
return And(
|
return And(
|
||||||
self.encode_bag(bag_formula.left_operand, level, context),
|
self.encode_bag(bag_formula.left_operand, level, context),
|
||||||
self.encode_bag(bag_formula.right_operand, level, context))
|
self.encode_bag(bag_formula.right_operand, level, context),
|
||||||
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.l_or:
|
if bag_formula.f_type == BagDesc_oper.l_or:
|
||||||
return Or(
|
return Or(
|
||||||
self.encode_bag(bag_formula.left_operand, level, context),
|
self.encode_bag(bag_formula.left_operand, level, context),
|
||||||
self.encode_bag(bag_formula.right_operand, level, context))
|
self.encode_bag(bag_formula.right_operand, level, context),
|
||||||
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.l_not:
|
if bag_formula.f_type == BagDesc_oper.l_not:
|
||||||
return Not(self.encode_bag(
|
return Not(self.encode_bag(bag_formula.left_operand, level, context))
|
||||||
bag_formula.left_operand, level, context))
|
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.lt:
|
if bag_formula.f_type == BagDesc_oper.lt:
|
||||||
return self.encode_bag(
|
return self.encode_bag(bag_formula.left_operand, level, context) < int(
|
||||||
bag_formula.left_operand, level, context) < int(
|
bag_formula.right_operand
|
||||||
bag_formula.right_operand)
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.le:
|
if bag_formula.f_type == BagDesc_oper.le:
|
||||||
return self.encode_bag(
|
return self.encode_bag(bag_formula.left_operand, level, context) <= int(
|
||||||
bag_formula.left_operand, level, context) <= int(
|
bag_formula.right_operand
|
||||||
bag_formula.right_operand)
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.eq:
|
if bag_formula.f_type == BagDesc_oper.eq:
|
||||||
return self.encode_bag(
|
return self.encode_bag(bag_formula.left_operand, level, context) == int(
|
||||||
bag_formula.left_operand, level, context) == int(
|
bag_formula.right_operand
|
||||||
bag_formula.right_operand)
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.ge:
|
if bag_formula.f_type == BagDesc_oper.ge:
|
||||||
return self.encode_bag(
|
return self.encode_bag(bag_formula.left_operand, level, context) >= int(
|
||||||
bag_formula.left_operand, level, context) >= int(
|
bag_formula.right_operand
|
||||||
bag_formula.right_operand)
|
)
|
||||||
|
|
||||||
if bag_formula.f_type == BagDesc_oper.gt:
|
if bag_formula.f_type == BagDesc_oper.gt:
|
||||||
return self.encode_bag(
|
return self.encode_bag(bag_formula.left_operand, level, context) > int(
|
||||||
bag_formula.left_operand, level, context) > int(
|
bag_formula.right_operand
|
||||||
bag_formula.right_operand)
|
)
|
||||||
|
|
||||||
assert False, "Unsupported case {:s}".format(bag_formula.f_type)
|
assert False, "Unsupported case {:s}".format(bag_formula.f_type)
|
||||||
|
|
||||||
@@ -149,7 +147,6 @@ class rsLTL_Encoder(object):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
def encode(self, formula, level, bound):
|
def encode(self, formula, level, bound):
|
||||||
|
|
||||||
self.ncalls_encode += 1
|
self.ncalls_encode += 1
|
||||||
|
|
||||||
from_cache = self.cache_query(formula, level)
|
from_cache = self.cache_query(formula, level)
|
||||||
@@ -159,12 +156,12 @@ class rsLTL_Encoder(object):
|
|||||||
enc = None
|
enc = None
|
||||||
|
|
||||||
if not isinstance(formula, Formula_rsLTL):
|
if not isinstance(formula, Formula_rsLTL):
|
||||||
raise NotImplementedError(
|
raise NotImplementedError("Unsupported formula type: " + str(type(formula)))
|
||||||
"Unsupported formula type: " + str(type(formula)))
|
|
||||||
|
|
||||||
if level > bound:
|
if level > bound:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"level > bound. Unexpected behaviour. The encoding does not support levels higher than a bound.")
|
"level > bound. Unexpected behaviour. The encoding does not support levels higher than a bound."
|
||||||
|
)
|
||||||
|
|
||||||
if formula.f_type == rsLTL_form_type.bag:
|
if formula.f_type == rsLTL_form_type.bag:
|
||||||
enc = self.encode_bag_state(formula.bag_descr, level)
|
enc = self.encode_bag_state(formula.bag_descr, level)
|
||||||
@@ -179,33 +176,40 @@ class rsLTL_Encoder(object):
|
|||||||
elif formula.f_type == rsLTL_form_type.l_and:
|
elif formula.f_type == rsLTL_form_type.l_and:
|
||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode(formula.right_operand, level, bound)
|
self.encode(formula.right_operand, level, bound),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif formula.f_type == rsLTL_form_type.l_or:
|
elif formula.f_type == rsLTL_form_type.l_or:
|
||||||
enc = Or(
|
enc = Or(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode(formula.right_operand, level, bound)
|
self.encode(formula.right_operand, level, bound),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif formula.f_type == rsLTL_form_type.l_implies:
|
elif formula.f_type == rsLTL_form_type.l_implies:
|
||||||
enc = Implies(
|
enc = Implies(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode(formula.right_operand, level, bound)
|
self.encode(formula.right_operand, level, bound),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif formula.f_type == rsLTL_form_type.t_next:
|
elif formula.f_type == rsLTL_form_type.t_next:
|
||||||
if level < bound:
|
if level < bound:
|
||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.left_operand, level + 1, bound),
|
self.encode(formula.left_operand, level + 1, bound),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
enc = False
|
enc = False
|
||||||
for loop_level in range(1, bound+1):
|
for loop_level in range(1, bound + 1):
|
||||||
enc = simplify(Or(enc, And(self.loop_position == loop_level, self.encode(
|
enc = simplify(
|
||||||
formula.left_operand, loop_level, bound))))
|
Or(
|
||||||
|
enc,
|
||||||
|
And(
|
||||||
|
self.loop_position == loop_level,
|
||||||
|
self.encode(formula.left_operand, loop_level, bound),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
enc = And(enc, self.encode_bag_ctx(formula.sub_operand, level))
|
enc = And(enc, self.encode_bag_ctx(formula.sub_operand, level))
|
||||||
enc = simplify(enc)
|
enc = simplify(enc)
|
||||||
|
|
||||||
@@ -214,22 +218,25 @@ class rsLTL_Encoder(object):
|
|||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level),
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
self.encode(formula, level + 1, bound)
|
self.encode(formula, level + 1, bound),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
enc_loops = False
|
enc_loops = False
|
||||||
for loop_level in range(1, bound+1):
|
for loop_level in range(1, bound + 1):
|
||||||
enc_loops = simplify(Or(enc_loops,
|
enc_loops = simplify(
|
||||||
And(
|
Or(
|
||||||
self.loop_position == loop_level,
|
enc_loops,
|
||||||
self.encode_approx(formula, loop_level, bound),
|
And(
|
||||||
)
|
self.loop_position == loop_level,
|
||||||
))
|
self.encode_approx(formula, loop_level, bound),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.left_operand, bound, bound),
|
self.encode(formula.left_operand, bound, bound),
|
||||||
enc_loops,
|
enc_loops,
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
)
|
)
|
||||||
enc = simplify(enc)
|
enc = simplify(enc)
|
||||||
|
|
||||||
@@ -239,25 +246,26 @@ class rsLTL_Encoder(object):
|
|||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
And(
|
And(
|
||||||
self.encode_bag_ctx(formula.sub_operand, level),
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
self.encode(formula, level + 1, bound)
|
self.encode(formula, level + 1, bound),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
enc_loops = False
|
enc_loops = False
|
||||||
for loop_level in range(1, bound+1):
|
for loop_level in range(1, bound + 1):
|
||||||
enc_loops = simplify(Or(enc_loops,
|
enc_loops = simplify(
|
||||||
And(
|
Or(
|
||||||
self.loop_position == loop_level,
|
enc_loops,
|
||||||
self.encode_approx(formula, loop_level, bound),
|
And(
|
||||||
)
|
self.loop_position == loop_level,
|
||||||
))
|
self.encode_approx(formula, loop_level, bound),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
# print(enc)
|
# print(enc)
|
||||||
enc = Or(self.encode(formula.left_operand, bound, bound),
|
enc = Or(
|
||||||
And(
|
self.encode(formula.left_operand, bound, bound),
|
||||||
enc_loops,
|
And(enc_loops, self.encode_bag_ctx(formula.sub_operand, level)),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
enc = simplify(enc)
|
enc = simplify(enc)
|
||||||
@@ -268,21 +276,24 @@ class rsLTL_Encoder(object):
|
|||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
inner_enc = False
|
inner_enc = False
|
||||||
for loop_level in range(1, bound+1):
|
for loop_level in range(1, bound + 1):
|
||||||
inner_enc = simplify(Or(inner_enc,
|
inner_enc = simplify(
|
||||||
And(
|
Or(
|
||||||
self.loop_position == loop_level,
|
inner_enc,
|
||||||
self.encode_approx(formula, loop_level, bound)
|
And(
|
||||||
)
|
self.loop_position == loop_level,
|
||||||
))
|
self.encode_approx(formula, loop_level, bound),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
enc = Or(
|
enc = Or(
|
||||||
self.encode(formula.right_operand, level, bound),
|
self.encode(formula.right_operand, level, bound),
|
||||||
And(
|
And(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
inner_enc,
|
inner_enc,
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
elif formula.f_type == rsLTL_form_type.t_release:
|
elif formula.f_type == rsLTL_form_type.t_release:
|
||||||
@@ -291,23 +302,23 @@ class rsLTL_Encoder(object):
|
|||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
inner_enc = False
|
inner_enc = False
|
||||||
for loop_level in range(1, bound+1):
|
for loop_level in range(1, bound + 1):
|
||||||
inner_enc = simplify(Or(inner_enc,
|
inner_enc = simplify(
|
||||||
And(
|
Or(
|
||||||
self.loop_position == loop_level,
|
inner_enc,
|
||||||
self.encode_approx(formula, loop_level, bound)
|
And(
|
||||||
)
|
self.loop_position == loop_level,
|
||||||
))
|
self.encode_approx(formula, loop_level, bound),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.right_operand, level, bound),
|
self.encode(formula.right_operand, level, bound),
|
||||||
Or(
|
Or(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
And(
|
And(inner_enc, self.encode_bag_ctx(formula.sub_operand, level)),
|
||||||
inner_enc,
|
),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -341,8 +352,8 @@ class rsLTL_Encoder(object):
|
|||||||
And(
|
And(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode_approx(formula, level + 1, bound),
|
self.encode_approx(formula, level + 1, bound),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
@@ -356,9 +367,9 @@ class rsLTL_Encoder(object):
|
|||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
And(
|
And(
|
||||||
self.encode_approx(formula, level + 1, bound),
|
self.encode_approx(formula, level + 1, bound),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level)
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
@@ -369,7 +380,7 @@ class rsLTL_Encoder(object):
|
|||||||
enc = And(
|
enc = And(
|
||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
self.encode_bag_ctx(formula.sub_operand, level),
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
self.encode_approx(formula, level + 1, bound)
|
self.encode_approx(formula, level + 1, bound),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
@@ -381,16 +392,15 @@ class rsLTL_Encoder(object):
|
|||||||
self.encode(formula.left_operand, level, bound),
|
self.encode(formula.left_operand, level, bound),
|
||||||
And(
|
And(
|
||||||
self.encode_bag_ctx(formula.sub_operand, level),
|
self.encode_bag_ctx(formula.sub_operand, level),
|
||||||
self.encode_approx(formula, level + 1, bound)
|
self.encode_approx(formula, level + 1, bound),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# level == bound
|
# level == bound
|
||||||
enc = self.encode(formula.left_operand, bound, bound)
|
enc = self.encode(formula.left_operand, bound, bound)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError("Unsupported operator in approximation encoding")
|
||||||
"Unsupported operator in approximation encoding")
|
|
||||||
|
|
||||||
if enc is None:
|
if enc is None:
|
||||||
raise RuntimeError("Encoding is NONE. Should never happen")
|
raise RuntimeError("Encoding is NONE. Should never happen")
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ from rs.reaction_system import ReactionSystem
|
|||||||
from rs.context_automaton import ContextAutomaton
|
from rs.context_automaton import ContextAutomaton
|
||||||
|
|
||||||
from rs.reaction_system_with_concentrations import ReactionSystemWithConcentrations
|
from rs.reaction_system_with_concentrations import ReactionSystemWithConcentrations
|
||||||
from rs.reaction_system_with_concentrations_param import ReactionSystemWithConcentrationsParam, ParameterObj, is_param
|
from rs.reaction_system_with_concentrations_param import (
|
||||||
|
ReactionSystemWithConcentrationsParam,
|
||||||
|
ParameterObj,
|
||||||
|
is_param,
|
||||||
|
)
|
||||||
from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations
|
from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations
|
||||||
|
|
||||||
from rs.extended_context_automaton import ExtendedContextAutomaton
|
from rs.extended_context_automaton import ExtendedContextAutomaton
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from colour import *
|
|||||||
|
|
||||||
|
|
||||||
class ContextAutomaton(object):
|
class ContextAutomaton(object):
|
||||||
|
|
||||||
def __init__(self, reaction_system):
|
def __init__(self, reaction_system):
|
||||||
self._states = []
|
self._states = []
|
||||||
self._transitions = []
|
self._transitions = []
|
||||||
@@ -40,7 +39,7 @@ class ContextAutomaton(object):
|
|||||||
if name not in self._states:
|
if name not in self._states:
|
||||||
self._states.append(name)
|
self._states.append(name)
|
||||||
else:
|
else:
|
||||||
print("\'%s\' already added. skipping..." % (name,))
|
print("'%s' already added. skipping..." % (name,))
|
||||||
|
|
||||||
def add_states(self, states_set):
|
def add_states(self, states_set):
|
||||||
for st in states_set:
|
for st in states_set:
|
||||||
@@ -56,10 +55,7 @@ class ContextAutomaton(object):
|
|||||||
return self._states[self._init_state]
|
return self._states[self._init_state]
|
||||||
|
|
||||||
def is_state(self, name):
|
def is_state(self, name):
|
||||||
if name in self._states:
|
return name in self._states
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_state_id(self, name):
|
def get_state_id(self, name):
|
||||||
try:
|
try:
|
||||||
@@ -79,10 +75,7 @@ class ContextAutomaton(object):
|
|||||||
print(state)
|
print(state)
|
||||||
|
|
||||||
def is_valid_rs_set(self, elements):
|
def is_valid_rs_set(self, elements):
|
||||||
if set(elements).issubset(self._reaction_system.background_set):
|
return set(elements).issubset(self._reaction_system.background_set)
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_valid_context(self, context):
|
def is_valid_context(self, context):
|
||||||
return self.is_valid_rs_set(context)
|
return self.is_valid_rs_set(context)
|
||||||
@@ -96,20 +89,19 @@ class ContextAutomaton(object):
|
|||||||
return new_set
|
return new_set
|
||||||
|
|
||||||
def add_transition(self, src, context_set, dst):
|
def add_transition(self, src, context_set, dst):
|
||||||
if not type(context_set) is set and not type(context_set) is list:
|
if not isinstance(context_set, (set, list)):
|
||||||
print("Contexts set must be of type set or list")
|
print("Contexts set must be of type set or list")
|
||||||
|
|
||||||
if not self.is_valid_context(context_set):
|
if not self.is_valid_context(context_set):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"one of the entities in the context set is unknown (undefined)!")
|
"one of the entities in the context set is unknown (undefined)!"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.is_state(src):
|
if not self.is_state(src):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + src + '" is an unknown (undefined) state')
|
||||||
"\"" + src + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
if not self.is_state(dst):
|
if not self.is_state(dst):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + dst + '" is an unknown (undefined) state')
|
||||||
"\"" + dst + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
new_context_set = set()
|
new_context_set = set()
|
||||||
for e in set(context_set):
|
for e in set(context_set):
|
||||||
@@ -118,8 +110,8 @@ class ContextAutomaton(object):
|
|||||||
self._prod_entities |= new_context_set
|
self._prod_entities |= new_context_set
|
||||||
|
|
||||||
self._transitions.append(
|
self._transitions.append(
|
||||||
(self.get_state_id(src),
|
(self.get_state_id(src), new_context_set, self.get_state_id(dst))
|
||||||
new_context_set, self.get_state_id(dst)))
|
)
|
||||||
|
|
||||||
def rsset2str(self, elements):
|
def rsset2str(self, elements):
|
||||||
"""Converts the set of entities ids into the string with their names"""
|
"""Converts the set of entities ids into the string with their names"""
|
||||||
@@ -168,4 +160,5 @@ class ContextAutomaton(object):
|
|||||||
self.show_transitions()
|
self.show_transitions()
|
||||||
self.show_prod_entities()
|
self.show_prod_entities()
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -5,18 +5,13 @@ from rs.context_automaton import ContextAutomaton
|
|||||||
|
|
||||||
|
|
||||||
class ContextAutomatonWithConcentrations(ContextAutomaton):
|
class ContextAutomatonWithConcentrations(ContextAutomaton):
|
||||||
|
|
||||||
def __init__(self, reaction_system):
|
def __init__(self, reaction_system):
|
||||||
super(ContextAutomatonWithConcentrations,
|
super(ContextAutomatonWithConcentrations, self).__init__(reaction_system)
|
||||||
self).__init__(reaction_system)
|
|
||||||
|
|
||||||
def is_valid_context(self, context):
|
def is_valid_context(self, context):
|
||||||
if set(
|
return set(e for e, lvl in context).issubset(
|
||||||
[e for e, lvl in context]).issubset(
|
self._reaction_system.background_set
|
||||||
self._reaction_system.background_set):
|
)
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def context2str(self, ctx):
|
def context2str(self, ctx):
|
||||||
if len(ctx) == 0:
|
if len(ctx) == 0:
|
||||||
@@ -28,50 +23,43 @@ class ContextAutomatonWithConcentrations(ContextAutomaton):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
def add_transition(self, src, context_set, dst):
|
def add_transition(self, src, context_set, dst):
|
||||||
if not type(context_set) is set and not type(context_set) is list:
|
if not isinstance(context_set, (set, list)):
|
||||||
print("Contexts set must be of type set or list")
|
print("Contexts set must be of type set or list")
|
||||||
|
|
||||||
if not self.is_valid_context(context_set):
|
if not self.is_valid_context(context_set):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"one of the entities in the context set is unknown (undefined)!")
|
"one of the entities in the context set is unknown (undefined)!"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.is_state(src):
|
if not self.is_state(src):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + src + '" is an unknown (undefined) state')
|
||||||
"\"" + src + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
if not self.is_state(dst):
|
if not self.is_state(dst):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + dst + '" is an unknown (undefined) state')
|
||||||
"\"" + dst + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
new_context_set = set()
|
new_context_set = set()
|
||||||
for ent, lvl in set(context_set):
|
for ent, lvl in set(context_set):
|
||||||
new_context_set.add(
|
new_context_set.add((self._reaction_system.get_entity_id(ent), lvl))
|
||||||
(self._reaction_system.get_entity_id(ent), lvl))
|
|
||||||
|
|
||||||
self._transitions.append(
|
self._transitions.append(
|
||||||
(self.get_state_id(src),
|
(self.get_state_id(src), new_context_set, self.get_state_id(dst))
|
||||||
new_context_set, self.get_state_id(dst)))
|
)
|
||||||
|
|
||||||
def get_automaton_with_flat_contexts(self, ordinary_reaction_system):
|
def get_automaton_with_flat_contexts(self, ordinary_reaction_system):
|
||||||
|
|
||||||
ca = ContextAutomaton(ordinary_reaction_system)
|
ca = ContextAutomaton(ordinary_reaction_system)
|
||||||
ca._states = self._states
|
ca._states = self._states
|
||||||
ca._init_state = self._init_state
|
ca._init_state = self._init_state
|
||||||
|
|
||||||
for src, ctx, dst in self._transitions:
|
for src, ctx, dst in self._transitions:
|
||||||
|
|
||||||
new_ctx = set()
|
new_ctx = set()
|
||||||
|
|
||||||
for ent, conc in ctx:
|
for ent, conc in ctx:
|
||||||
for i in range(1, conc+1):
|
for i in range(1, conc + 1):
|
||||||
n = self._reaction_system.get_entity_name(
|
n = self._reaction_system.get_entity_name(ent) + "#" + str(i)
|
||||||
ent) + "#" + str(i)
|
|
||||||
ca._reaction_system.ensure_bg_set_entity(n)
|
ca._reaction_system.ensure_bg_set_entity(n)
|
||||||
new_ctx.add(n)
|
new_ctx.add(n)
|
||||||
|
|
||||||
ca.add_transition(
|
ca.add_transition(ca.get_state_name(src), new_ctx, ca.get_state_name(dst))
|
||||||
ca.get_state_name(src),
|
|
||||||
new_ctx, ca.get_state_name(dst))
|
|
||||||
|
|
||||||
return ca
|
return ca
|
||||||
|
|
||||||
@@ -80,4 +68,5 @@ class ContextAutomatonWithConcentrations(ContextAutomaton):
|
|||||||
self.show_states()
|
self.show_states()
|
||||||
self.show_transitions()
|
self.show_transitions()
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -70,28 +70,29 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
|
|
||||||
ctx_reactants, ctx_inhibitors, ctx_products = ctx_reaction
|
ctx_reactants, ctx_inhibitors, ctx_products = ctx_reaction
|
||||||
|
|
||||||
if not type(ctx_products) is set and not type(ctx_products) is list:
|
if not isinstance(ctx_products, (set, list)):
|
||||||
print("Contexts set (context products) must be of type set or list")
|
print("Contexts set (context products) must be of type set or list")
|
||||||
|
|
||||||
if not self.is_valid_rs_set(ctx_reactants):
|
if not self.is_valid_rs_set(ctx_reactants):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"one of the entities in the reactants set is unknown (undefined)!")
|
"one of the entities in the reactants set is unknown (undefined)!"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.is_valid_rs_set(ctx_inhibitors):
|
if not self.is_valid_rs_set(ctx_inhibitors):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"one of the entities in the inhibitors set is unknown (undefined)!")
|
"one of the entities in the inhibitors set is unknown (undefined)!"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.is_valid_rs_set(ctx_products):
|
if not self.is_valid_rs_set(ctx_products):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"one of the entities in the context set is unknown (undefined)!")
|
"one of the entities in the context set is unknown (undefined)!"
|
||||||
|
)
|
||||||
|
|
||||||
if not self.is_state(src):
|
if not self.is_state(src):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + src + '" is an unknown (undefined) state')
|
||||||
"\"" + src + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
if not self.is_state(dst):
|
if not self.is_state(dst):
|
||||||
raise RuntimeError(
|
raise RuntimeError('"' + dst + '" is an unknown (undefined) state')
|
||||||
"\"" + dst + "\" is an unknown (undefined) state")
|
|
||||||
|
|
||||||
src_id = self.get_state_id(src)
|
src_id = self.get_state_id(src)
|
||||||
dst_id = self.get_state_id(dst)
|
dst_id = self.get_state_id(dst)
|
||||||
@@ -119,8 +120,15 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
for src_id, act_id, reaction, dst_id in self._transitions:
|
for src_id, act_id, reaction, dst_id in self._transitions:
|
||||||
str_transition = self.get_state_name(src_id) + " --( "
|
str_transition = self.get_state_name(src_id) + " --( "
|
||||||
str_transition += "<" + self.get_actions_str(act_id) + "> | "
|
str_transition += "<" + self.get_actions_str(act_id) + "> | "
|
||||||
str_transition += "( " + self.rsset2str(reaction[0]) + "," + self.rsset2str(
|
str_transition += (
|
||||||
reaction[1]) + "," + self.rsset2str(reaction[2]) + " )"
|
"( "
|
||||||
|
+ self.rsset2str(reaction[0])
|
||||||
|
+ ","
|
||||||
|
+ self.rsset2str(reaction[1])
|
||||||
|
+ ","
|
||||||
|
+ self.rsset2str(reaction[2])
|
||||||
|
+ " )"
|
||||||
|
)
|
||||||
str_transition += " )--> " + self.get_state_name(dst_id)
|
str_transition += " )--> " + self.get_state_name(dst_id)
|
||||||
print(" - " + str_transition)
|
print(" - " + str_transition)
|
||||||
|
|
||||||
@@ -130,7 +138,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
if action_name not in self._actions:
|
if action_name not in self._actions:
|
||||||
self._actions.append(action_name)
|
self._actions.append(action_name)
|
||||||
else:
|
else:
|
||||||
print("\'%s\' already added. skipping..." % (action_name,))
|
print("'%s' already added. skipping..." % (action_name,))
|
||||||
|
|
||||||
def get_action_id(self, action_name):
|
def get_action_id(self, action_name):
|
||||||
"""For an action name returns its id"""
|
"""For an action name returns its id"""
|
||||||
@@ -138,8 +146,7 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
try:
|
try:
|
||||||
return self._actions.index(action_name)
|
return self._actions.index(action_name)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print_error("Undefined context automaton action: " +
|
print_error("Undefined context automaton action: " + repr(action_name))
|
||||||
repr(action_name))
|
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def get_action_name(self, action_id):
|
def get_action_name(self, action_id):
|
||||||
@@ -173,4 +180,5 @@ class ExtendedContextAutomaton(ContextAutomaton):
|
|||||||
super(ExtendedContextAutomaton, self).show()
|
super(ExtendedContextAutomaton, self).show()
|
||||||
self.show_actions()
|
self.show_actions()
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ from colour import *
|
|||||||
|
|
||||||
|
|
||||||
class NetworkOfContextAutomata(object):
|
class NetworkOfContextAutomata(object):
|
||||||
|
|
||||||
def __init__(self, reaction_system, context_automata):
|
def __init__(self, reaction_system, context_automata):
|
||||||
self.automata = []
|
self.automata = []
|
||||||
self._reaction_system = reaction_system
|
self._reaction_system = reaction_system
|
||||||
@@ -44,14 +43,14 @@ class NetworkOfContextAutomata(object):
|
|||||||
for automaton in self.automata:
|
for automaton in self.automata:
|
||||||
if automaton.reaction_system != self._reaction_system:
|
if automaton.reaction_system != self._reaction_system:
|
||||||
print_error(
|
print_error(
|
||||||
"Mismatching reaction system used in \"" +
|
'Mismatching reaction system used in "'
|
||||||
str(automaton.name) + "\"!!!")
|
+ str(automaton.name)
|
||||||
|
+ '"!!!'
|
||||||
|
)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def show_prod_entities(self):
|
def show_prod_entities(self):
|
||||||
print(
|
print(C_MARK_INFO + " Possible context-products for the network of automata:")
|
||||||
C_MARK_INFO +
|
|
||||||
" Possible context-products for the network of automata:")
|
|
||||||
for entity in self.prod_entities:
|
for entity in self.prod_entities:
|
||||||
print(" - " + self._reaction_system.get_entity_name(entity))
|
print(" - " + self._reaction_system.get_entity_name(entity))
|
||||||
|
|
||||||
@@ -96,7 +95,8 @@ class NetworkOfContextAutomata(object):
|
|||||||
for entity in aut.prod_entities:
|
for entity in aut.prod_entities:
|
||||||
self._actions_for_products.setdefault(entity, set())
|
self._actions_for_products.setdefault(entity, set())
|
||||||
self._actions_for_products[entity] |= aut.get_actions_producing_entity(
|
self._actions_for_products[entity] |= aut.get_actions_producing_entity(
|
||||||
entity)
|
entity
|
||||||
|
)
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
print()
|
print()
|
||||||
@@ -108,4 +108,5 @@ class NetworkOfContextAutomata(object):
|
|||||||
self.show_prod_entities()
|
self.show_prod_entities()
|
||||||
self.show_actions()
|
self.show_actions()
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ from colour import *
|
|||||||
|
|
||||||
|
|
||||||
class ReactionSystem(object):
|
class ReactionSystem(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.reactions = []
|
self.reactions = []
|
||||||
self.background_set = []
|
self.background_set = []
|
||||||
|
|
||||||
@@ -30,8 +28,7 @@ class ReactionSystem(object):
|
|||||||
|
|
||||||
def assume_not_in_bgset(self, name):
|
def assume_not_in_bgset(self, name):
|
||||||
if self.is_in_background_set(name):
|
if self.is_in_background_set(name):
|
||||||
raise RuntimeError(
|
raise RuntimeError("The entity " + name + " is already on the list")
|
||||||
"The entity " + name + " is already on the list")
|
|
||||||
|
|
||||||
def add_bg_set_entity(self, name):
|
def add_bg_set_entity(self, name):
|
||||||
self.assume_not_in_bgset(name)
|
self.assume_not_in_bgset(name)
|
||||||
@@ -46,11 +43,8 @@ class ReactionSystem(object):
|
|||||||
self.add_bg_set_entity(e)
|
self.add_bg_set_entity(e)
|
||||||
|
|
||||||
def is_in_background_set(self, entity):
|
def is_in_background_set(self, entity):
|
||||||
"""Checks if the given name is valid wrt the background set="""
|
"""Checks if the given name is valid wrt the background set"""
|
||||||
if entity in self.background_set:
|
return entity in self.background_set
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_entity_id(self, name):
|
def get_entity_id(self, name):
|
||||||
try:
|
try:
|
||||||
@@ -106,7 +100,6 @@ class ReactionSystem(object):
|
|||||||
self.init_contexts.append(integers)
|
self.init_contexts.append(integers)
|
||||||
|
|
||||||
def set_context_entities(self, entities):
|
def set_context_entities(self, entities):
|
||||||
|
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
entity_id = self.get_entity_id(entity)
|
entity_id = self.get_entity_id(entity)
|
||||||
self.context_entities.append(entity_id)
|
self.context_entities.append(entity_id)
|
||||||
@@ -131,20 +124,36 @@ class ReactionSystem(object):
|
|||||||
def show_reactions(self, soft=False):
|
def show_reactions(self, soft=False):
|
||||||
print(C_MARK_INFO + " Reactions:")
|
print(C_MARK_INFO + " Reactions:")
|
||||||
if soft and len(self.reactions) > 50:
|
if soft and len(self.reactions) > 50:
|
||||||
print(" -> there are more than 50 reactions (" +
|
print(
|
||||||
str(len(self.reactions)) + ")")
|
" -> there are more than 50 reactions ("
|
||||||
|
+ str(len(self.reactions))
|
||||||
|
+ ")"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
" "*4 + "{0: ^35}{1: ^25}{2: ^15}".format("reactants", " inhibitors", " products"))
|
" " * 4
|
||||||
|
+ "{0: ^35}{1: ^25}{2: ^15}".format(
|
||||||
|
"reactants", " inhibitors", " products"
|
||||||
|
)
|
||||||
|
)
|
||||||
for reaction in self.reactions:
|
for reaction in self.reactions:
|
||||||
# print("\t( R={" + self.state_to_str(reaction[0]) + "}, I={" + self.state_to_str(reaction[1]) + "}, P={" + self.state_to_str(reaction[2]) + "} )")
|
# print("\t( R={" + self.state_to_str(reaction[0]) + "}, I={" + self.state_to_str(reaction[1]) + "}, P={" + self.state_to_str(reaction[2]) + "} )")
|
||||||
print(" " + "- {0: ^35}{1: ^25}{2: ^15}".format("{ " + self.state_to_str(reaction[0]) + " }",
|
print(
|
||||||
" { " + self.state_to_str(reaction[1]) + " }",
|
" "
|
||||||
" { " + self.state_to_str(reaction[2]) + " }"))
|
+ "- {0: ^35}{1: ^25}{2: ^15}".format(
|
||||||
|
"{ " + self.state_to_str(reaction[0]) + " }",
|
||||||
|
" { " + self.state_to_str(reaction[1]) + " }",
|
||||||
|
" { " + self.state_to_str(reaction[2]) + " }",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def show_background_set(self):
|
def show_background_set(self):
|
||||||
print(
|
print(
|
||||||
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
|
C_MARK_INFO
|
||||||
|
+ " Background set: {"
|
||||||
|
+ self.entities_names_set_to_str(self.background_set)
|
||||||
|
+ "}"
|
||||||
|
)
|
||||||
|
|
||||||
def show_initial_contexts(self):
|
def show_initial_contexts(self):
|
||||||
if len(self.init_contexts) > 0:
|
if len(self.init_contexts) > 0:
|
||||||
@@ -155,10 +164,12 @@ class ReactionSystem(object):
|
|||||||
def show_context_entities(self):
|
def show_context_entities(self):
|
||||||
if len(self.context_entities) > 0:
|
if len(self.context_entities) > 0:
|
||||||
print(
|
print(
|
||||||
C_MARK_INFO + " Context entities: " + self.entities_ids_set_to_str(self.context_entities))
|
C_MARK_INFO
|
||||||
|
+ " Context entities: "
|
||||||
|
+ self.entities_ids_set_to_str(self.context_entities)
|
||||||
|
)
|
||||||
|
|
||||||
def show(self, soft=False):
|
def show(self, soft=False):
|
||||||
|
|
||||||
self.show_background_set()
|
self.show_background_set()
|
||||||
self.show_initial_contexts()
|
self.show_initial_contexts()
|
||||||
self.show_reactions(soft)
|
self.show_reactions(soft)
|
||||||
@@ -181,8 +192,7 @@ class ReactionSystem(object):
|
|||||||
reactions_by_prod[prod_entity] = []
|
reactions_by_prod[prod_entity] = []
|
||||||
for reaction in self.reactions:
|
for reaction in self.reactions:
|
||||||
if prod_entity in reaction[2]:
|
if prod_entity in reaction[2]:
|
||||||
reactions_by_prod[prod_entity].append(
|
reactions_by_prod[prod_entity].append([reaction[0], reaction[1]])
|
||||||
[reaction[0], reaction[1]])
|
|
||||||
|
|
||||||
# save in cache
|
# save in cache
|
||||||
self.reactions_by_prod = reactions_by_prod
|
self.reactions_by_prod = reactions_by_prod
|
||||||
@@ -200,4 +210,5 @@ class ReactionSystem(object):
|
|||||||
print("Empty background set")
|
print("Empty background set")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
|
|
||||||
class ReactionSystemWithNetworkOfAutomata(object):
|
class ReactionSystemWithNetworkOfAutomata(object):
|
||||||
|
|
||||||
def __init__(self, reaction_system, context_automata):
|
def __init__(self, reaction_system, context_automata):
|
||||||
self.rs = reaction_system
|
self.rs = reaction_system
|
||||||
self.cas = context_automata
|
self.cas = context_automata
|
||||||
@@ -9,4 +7,5 @@ class ReactionSystemWithNetworkOfAutomata(object):
|
|||||||
self.rs.show(soft)
|
self.rs.show(soft)
|
||||||
self.cas.show()
|
self.cas.show()
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from rs.reaction_system_with_concentrations import ReactionSystemWithConcentrations
|
from rs.reaction_system_with_concentrations import ReactionSystemWithConcentrations
|
||||||
from rs.reaction_system_with_concentrations_param import ReactionSystemWithConcentrationsParam
|
from rs.reaction_system_with_concentrations_param import (
|
||||||
|
ReactionSystemWithConcentrationsParam,
|
||||||
|
)
|
||||||
from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations
|
from rs.context_automaton_with_concentrations import ContextAutomatonWithConcentrations
|
||||||
|
|
||||||
|
|
||||||
class ReactionSystemWithAutomaton(object):
|
class ReactionSystemWithAutomaton(object):
|
||||||
|
|
||||||
def __init__(self, reaction_system, context_automaton):
|
def __init__(self, reaction_system, context_automaton):
|
||||||
self.rs = reaction_system
|
self.rs = reaction_system
|
||||||
self.ca = context_automaton
|
self.ca = context_automaton
|
||||||
@@ -15,7 +16,7 @@ class ReactionSystemWithAutomaton(object):
|
|||||||
|
|
||||||
def is_concentr_and_param_compatible(self):
|
def is_concentr_and_param_compatible(self):
|
||||||
"""
|
"""
|
||||||
Checks if the underlying RS/CA are compatible
|
Checks if the underlying RS/CA are compatible
|
||||||
with parameters and concentrations
|
with parameters and concentrations
|
||||||
"""
|
"""
|
||||||
if not isinstance(self.rs, ReactionSystemWithConcentrationsParam):
|
if not isinstance(self.rs, ReactionSystemWithConcentrationsParam):
|
||||||
@@ -35,7 +36,6 @@ class ReactionSystemWithAutomaton(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_ordinary_reaction_system_with_automaton(self):
|
def get_ordinary_reaction_system_with_automaton(self):
|
||||||
|
|
||||||
if not self.is_with_concentrations():
|
if not self.is_with_concentrations():
|
||||||
raise RuntimeError("Not RS/CA with concentrations")
|
raise RuntimeError("Not RS/CA with concentrations")
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ from rs.reaction_system import ReactionSystem
|
|||||||
|
|
||||||
|
|
||||||
class ReactionSystemWithConcentrations(ReactionSystem):
|
class ReactionSystemWithConcentrations(ReactionSystem):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.reactions = []
|
self.reactions = []
|
||||||
self.meta_reactions = dict()
|
self.meta_reactions = dict()
|
||||||
self.permanent_entities = dict()
|
self.permanent_entities = dict()
|
||||||
@@ -20,14 +18,13 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
def add_bg_set_entity(self, e):
|
def add_bg_set_entity(self, e):
|
||||||
name = ""
|
name = ""
|
||||||
def_max_conc = -1
|
def_max_conc = -1
|
||||||
if type(e) is tuple and len(e) == 2:
|
if isinstance(e, tuple) and len(e) == 2:
|
||||||
name, def_max_conc = e
|
name, def_max_conc = e
|
||||||
elif type(e) is str:
|
elif isinstance(e, str):
|
||||||
name = e
|
name = e
|
||||||
print("\nWARNING: no maximal concentration level specified for:", e, "\n")
|
print("\nWARNING: no maximal concentration level specified for:", e, "\n")
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Bad entity type when adding background set element")
|
||||||
"Bad entity type when adding background set element")
|
|
||||||
|
|
||||||
self.assume_not_in_bgset(name)
|
self.assume_not_in_bgset(name)
|
||||||
self.background_set.append(name)
|
self.background_set.append(name)
|
||||||
@@ -41,7 +38,6 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
self.max_concentration = def_max_conc
|
self.max_concentration = def_max_conc
|
||||||
|
|
||||||
def get_max_concentration_level(self, e):
|
def get_max_concentration_level(self, e):
|
||||||
|
|
||||||
if e in self.max_conc_per_ent:
|
if e in self.max_conc_per_ent:
|
||||||
return self.max_conc_per_ent[e]
|
return self.max_conc_per_ent[e]
|
||||||
else:
|
else:
|
||||||
@@ -50,18 +46,10 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
def is_valid_entity_with_concentration(self, e):
|
def is_valid_entity_with_concentration(self, e):
|
||||||
"""Sanity check for entities with concentration"""
|
"""Sanity check for entities with concentration"""
|
||||||
|
|
||||||
if type(e) is tuple:
|
if isinstance(e, (tuple, list)) and len(e) == 2 and isinstance(e[1], int):
|
||||||
if len(e) == 2 and type(e[1]) is int:
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
if type(e) is list:
|
raise RuntimeError("Invalid entity+concentration: " + repr(e))
|
||||||
if len(e) == 2 and type(e[1]) is int:
|
|
||||||
return True
|
|
||||||
|
|
||||||
print("FATAL. Invalid entity+concentration: {:s}".format(e))
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_state_ids(self, state):
|
def get_state_ids(self, state):
|
||||||
"""Returns entities of the given state without levels"""
|
"""Returns entities of the given state without levels"""
|
||||||
@@ -69,8 +57,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
|
|
||||||
def has_non_zero_concentration(self, elem):
|
def has_non_zero_concentration(self, elem):
|
||||||
if elem[1] < 1:
|
if elem[1] < 1:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Unexpected concentration level in state: " + str(elem))
|
||||||
"Unexpected concentration level in state: " + str(elem))
|
|
||||||
|
|
||||||
def process_rip(self, R, I, P, ignore_empty_R=False):
|
def process_rip(self, R, I, P, ignore_empty_R=False):
|
||||||
"""Chcecks concentration levels and converts entities names into their ids"""
|
"""Chcecks concentration levels and converts entities names into their ids"""
|
||||||
@@ -123,21 +110,25 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
"""Adds a macro/meta reaction for increasing the value of incr_entity"""
|
"""Adds a macro/meta reaction for increasing the value of incr_entity"""
|
||||||
|
|
||||||
reactants, inhibitors, products = self.process_rip(
|
reactants, inhibitors, products = self.process_rip(
|
||||||
R, I, [], ignore_empty_R=True)
|
R, I, [], ignore_empty_R=True
|
||||||
|
)
|
||||||
incr_entity_id = self.get_entity_id(incr_entity)
|
incr_entity_id = self.get_entity_id(incr_entity)
|
||||||
self.meta_reactions.setdefault(incr_entity_id, [])
|
self.meta_reactions.setdefault(incr_entity_id, [])
|
||||||
self.meta_reactions[incr_entity_id].append(
|
self.meta_reactions[incr_entity_id].append(
|
||||||
("inc", self.get_entity_id(incrementer), reactants, inhibitors))
|
("inc", self.get_entity_id(incrementer), reactants, inhibitors)
|
||||||
|
)
|
||||||
|
|
||||||
def add_reaction_dec(self, decr_entity, decrementer, R, I):
|
def add_reaction_dec(self, decr_entity, decrementer, R, I):
|
||||||
"""Adds a macro/meta reaction for decreasing the value of incr_entity"""
|
"""Adds a macro/meta reaction for decreasing the value of incr_entity"""
|
||||||
|
|
||||||
reactants, inhibitors, products = self.process_rip(
|
reactants, inhibitors, products = self.process_rip(
|
||||||
R, I, [], ignore_empty_R=True)
|
R, I, [], ignore_empty_R=True
|
||||||
|
)
|
||||||
decr_entity_id = self.get_entity_id(decr_entity)
|
decr_entity_id = self.get_entity_id(decr_entity)
|
||||||
self.meta_reactions.setdefault(decr_entity_id, [])
|
self.meta_reactions.setdefault(decr_entity_id, [])
|
||||||
self.meta_reactions[decr_entity_id].append(
|
self.meta_reactions[decr_entity_id].append(
|
||||||
("dec", self.get_entity_id(decrementer), reactants, inhibitors))
|
("dec", self.get_entity_id(decrementer), reactants, inhibitors)
|
||||||
|
)
|
||||||
|
|
||||||
def add_permanency(self, ent, I):
|
def add_permanency(self, ent, I):
|
||||||
"""Sets entity to be permanent unless it is inhibited"""
|
"""Sets entity to be permanent unless it is inhibited"""
|
||||||
@@ -145,8 +136,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
ent_id = self.get_entity_id(ent)
|
ent_id = self.get_entity_id(ent)
|
||||||
|
|
||||||
if ent_id in self.permanent_entities:
|
if ent_id in self.permanent_entities:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Permanency for {0} already defined.".format(ent))
|
||||||
"Permanency for {0} already defined.".format(ent))
|
|
||||||
|
|
||||||
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
|
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
|
||||||
self.permanent_entities[ent_id] = inhibitors
|
self.permanent_entities[ent_id] = inhibitors
|
||||||
@@ -177,31 +167,50 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
|
|
||||||
def show_background_set(self):
|
def show_background_set(self):
|
||||||
print(
|
print(
|
||||||
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
|
C_MARK_INFO
|
||||||
|
+ " Background set: {"
|
||||||
|
+ self.entities_names_set_to_str(self.background_set)
|
||||||
|
+ "}"
|
||||||
|
)
|
||||||
|
|
||||||
def show_meta_reactions(self):
|
def show_meta_reactions(self):
|
||||||
print(C_MARK_INFO + " Meta reactions:")
|
print(C_MARK_INFO + " Meta reactions:")
|
||||||
for param_ent, reactions in self.meta_reactions.items():
|
for param_ent, reactions in self.meta_reactions.items():
|
||||||
for r_type, command, reactants, inhibitors in reactions:
|
for r_type, command, reactants, inhibitors in reactions:
|
||||||
if r_type == "inc" or r_type == "dec":
|
if r_type == "inc" or r_type == "dec":
|
||||||
print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + " ) Command=( " + self.get_entity_name(
|
print(
|
||||||
command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )")
|
" - [ Type="
|
||||||
|
+ repr(r_type)
|
||||||
|
+ " Operand=( "
|
||||||
|
+ self.get_entity_name(param_ent)
|
||||||
|
+ " ) Command=( "
|
||||||
|
+ self.get_entity_name(command)
|
||||||
|
+ " ) ] -- ( R={"
|
||||||
|
+ self.state_to_str(reactants)
|
||||||
|
+ "}, I={"
|
||||||
|
+ self.state_to_str(inhibitors)
|
||||||
|
+ "} )"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type))
|
||||||
"Unknown meta-reaction type: " + repr(r_type))
|
|
||||||
|
|
||||||
def show_max_concentrations(self):
|
def show_max_concentrations(self):
|
||||||
print(
|
print(
|
||||||
C_MARK_INFO +
|
C_MARK_INFO
|
||||||
" Maximal allowed concentration levels (for optimized translation to RS):")
|
+ " Maximal allowed concentration levels (for optimized translation to RS):"
|
||||||
|
)
|
||||||
for e, max_conc in self.max_conc_per_ent.items():
|
for e, max_conc in self.max_conc_per_ent.items():
|
||||||
print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e), max_conc))
|
print(" - {0:^20} = {1:<6}".format(self.get_entity_name(e), max_conc))
|
||||||
|
|
||||||
def show_permanent_entities(self):
|
def show_permanent_entities(self):
|
||||||
print(C_MARK_INFO + " Permanent entities:")
|
print(C_MARK_INFO + " Permanent entities:")
|
||||||
for e, inhibitors in self.permanent_entities.items():
|
for e, inhibitors in self.permanent_entities.items():
|
||||||
print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ",
|
print(
|
||||||
"I={" + self.state_to_str(inhibitors) + "}"))
|
" - {0:^20}{1:<6}".format(
|
||||||
|
self.get_entity_name(e) + ": ",
|
||||||
|
"I={" + self.state_to_str(inhibitors) + "}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def show(self, soft=False):
|
def show(self, soft=False):
|
||||||
self.show_background_set()
|
self.show_background_set()
|
||||||
@@ -220,8 +229,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
|
|
||||||
for reaction in self.reactions:
|
for reaction in self.reactions:
|
||||||
product_entities = [e for e, c in reaction[2]]
|
product_entities = [e for e, c in reaction[2]]
|
||||||
producible_entities = producible_entities.union(
|
producible_entities = producible_entities.union(set(product_entities))
|
||||||
set(product_entities))
|
|
||||||
|
|
||||||
reactions_by_prod = {}
|
reactions_by_prod = {}
|
||||||
|
|
||||||
@@ -242,18 +250,20 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
|
|
||||||
# we need to order the reactions w.r.t. the concentration levels produced (increasing order)
|
# we need to order the reactions w.r.t. the concentration levels produced (increasing order)
|
||||||
for i in range(0, len(rcts_for_p_e)):
|
for i in range(0, len(rcts_for_p_e)):
|
||||||
|
|
||||||
checked_conc = rcts_for_p_e[i][2][0][1]
|
checked_conc = rcts_for_p_e[i][2][0][1]
|
||||||
if prod_conc <= checked_conc:
|
if prod_conc <= checked_conc:
|
||||||
insert_place = i
|
insert_place = i
|
||||||
break
|
break
|
||||||
|
|
||||||
if insert_place == None: # empty or the is only one element which is smaller than the element being added
|
if (
|
||||||
|
insert_place == None
|
||||||
|
): # empty or the is only one element which is smaller than the element being added
|
||||||
# we append (to the end)
|
# we append (to the end)
|
||||||
rcts_for_p_e.append((reactants, inhibitors, products))
|
rcts_for_p_e.append((reactants, inhibitors, products))
|
||||||
else:
|
else:
|
||||||
rcts_for_p_e.insert(
|
rcts_for_p_e.insert(
|
||||||
insert_place, (reactants, inhibitors, products))
|
insert_place, (reactants, inhibitors, products)
|
||||||
|
)
|
||||||
|
|
||||||
# save in cache
|
# save in cache
|
||||||
self.reactions_by_prod = reactions_by_prod
|
self.reactions_by_prod = reactions_by_prod
|
||||||
@@ -261,11 +271,9 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
return reactions_by_prod
|
return reactions_by_prod
|
||||||
|
|
||||||
def get_reaction_system(self):
|
def get_reaction_system(self):
|
||||||
|
|
||||||
rs = ReactionSystem()
|
rs = ReactionSystem()
|
||||||
|
|
||||||
for reactants, inhibitors, products in self.reactions:
|
for reactants, inhibitors, products in self.reactions:
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
new_inhibitors = []
|
new_inhibitors = []
|
||||||
new_products = []
|
new_products = []
|
||||||
@@ -281,7 +289,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
new_inhibitors.append(n)
|
new_inhibitors.append(n)
|
||||||
|
|
||||||
for ent, conc in products:
|
for ent, conc in products:
|
||||||
for i in range(1, conc+1):
|
for i in range(1, conc + 1):
|
||||||
n = self.get_entity_name(ent) + "#" + str(i)
|
n = self.get_entity_name(ent) + "#" + str(i)
|
||||||
rs.ensure_bg_set_entity(n)
|
rs.ensure_bg_set_entity(n)
|
||||||
new_products.append(n)
|
new_products.append(n)
|
||||||
@@ -290,7 +298,6 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
|
|
||||||
for param_ent, reactions in self.meta_reactions.items():
|
for param_ent, reactions in self.meta_reactions.items():
|
||||||
for r_type, command, reactants, inhibitors in reactions:
|
for r_type, command, reactants, inhibitors in reactions:
|
||||||
|
|
||||||
param_ent_name = self.get_entity_name(param_ent)
|
param_ent_name = self.get_entity_name(param_ent)
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
@@ -312,16 +319,15 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
"WARNING:\n\tThere is no maximal concentration level defined for "
|
"WARNING:\n\tThere is no maximal concentration level defined for "
|
||||||
+ self.get_entity_name(command))
|
+ self.get_entity_name(command)
|
||||||
|
)
|
||||||
print("\tThis is a very bad idea -- expect degraded performance\n")
|
print("\tThis is a very bad idea -- expect degraded performance\n")
|
||||||
|
|
||||||
for l in range(1, max_cmd_c+1):
|
for l in range(1, max_cmd_c + 1):
|
||||||
|
|
||||||
cmd_ent = self.get_entity_name(command) + "#" + str(l)
|
cmd_ent = self.get_entity_name(command) + "#" + str(l)
|
||||||
rs.ensure_bg_set_entity(cmd_ent)
|
rs.ensure_bg_set_entity(cmd_ent)
|
||||||
|
|
||||||
if r_type == "inc":
|
if r_type == "inc":
|
||||||
|
|
||||||
# pre_conc -- predecessor concentration
|
# pre_conc -- predecessor concentration
|
||||||
# succ_conc -- successor concentration concentration
|
# succ_conc -- successor concentration concentration
|
||||||
|
|
||||||
@@ -329,8 +335,8 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
pre_conc = param_ent_name + "#" + str(i)
|
pre_conc = param_ent_name + "#" + str(i)
|
||||||
rs.ensure_bg_set_entity(pre_conc)
|
rs.ensure_bg_set_entity(pre_conc)
|
||||||
new_products = []
|
new_products = []
|
||||||
succ_value = i+l
|
succ_value = i + l
|
||||||
for j in range(1, succ_value+1):
|
for j in range(1, succ_value + 1):
|
||||||
if j > self.max_concentration:
|
if j > self.max_concentration:
|
||||||
break
|
break
|
||||||
new_p = param_ent_name + "#" + str(j)
|
new_p = param_ent_name + "#" + str(j)
|
||||||
@@ -340,15 +346,16 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
rs.add_reaction(
|
rs.add_reaction(
|
||||||
set(new_reactants + [pre_conc, cmd_ent]),
|
set(new_reactants + [pre_conc, cmd_ent]),
|
||||||
set(new_inhibitors),
|
set(new_inhibitors),
|
||||||
set(new_products))
|
set(new_products),
|
||||||
|
)
|
||||||
|
|
||||||
elif r_type == "dec":
|
elif r_type == "dec":
|
||||||
for i in range(1, self.max_concentration+1):
|
for i in range(1, self.max_concentration + 1):
|
||||||
pre_conc = param_ent_name + "#" + str(i)
|
pre_conc = param_ent_name + "#" + str(i)
|
||||||
rs.ensure_bg_set_entity(pre_conc)
|
rs.ensure_bg_set_entity(pre_conc)
|
||||||
new_products = []
|
new_products = []
|
||||||
succ_value = i-l
|
succ_value = i - l
|
||||||
for j in range(1, succ_value+1):
|
for j in range(1, succ_value + 1):
|
||||||
if j > self.max_concentration:
|
if j > self.max_concentration:
|
||||||
break
|
break
|
||||||
new_p = param_ent_name + "#" + str(j)
|
new_p = param_ent_name + "#" + str(j)
|
||||||
@@ -358,28 +365,29 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
rs.add_reaction(
|
rs.add_reaction(
|
||||||
set(new_reactants + [pre_conc, cmd_ent]),
|
set(new_reactants + [pre_conc, cmd_ent]),
|
||||||
set(new_inhibitors),
|
set(new_inhibitors),
|
||||||
set(new_products))
|
set(new_products),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Unknown meta-reaction type: " + repr(r_type))
|
"Unknown meta-reaction type: " + repr(r_type)
|
||||||
|
)
|
||||||
|
|
||||||
for ent, inhibitors in self.permanent_entities.items():
|
for ent, inhibitors in self.permanent_entities.items():
|
||||||
|
|
||||||
max_c = self.max_concentration
|
max_c = self.max_concentration
|
||||||
if ent in self.max_conc_per_ent:
|
if ent in self.max_conc_per_ent:
|
||||||
max_c = self.max_conc_per_ent[ent]
|
max_c = self.max_conc_per_ent[ent]
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
"WARNING:\n\tThere is no maximal concentration level defined for "
|
"WARNING:\n\tThere is no maximal concentration level defined for "
|
||||||
+ self.get_entity_name(ent))
|
+ self.get_entity_name(ent)
|
||||||
|
)
|
||||||
print("\tThis is a very bad idea -- expect degraded performance\n")
|
print("\tThis is a very bad idea -- expect degraded performance\n")
|
||||||
|
|
||||||
def e_value(i):
|
def e_value(i):
|
||||||
return self.get_entity_name(ent) + "#" + str(i)
|
return self.get_entity_name(ent) + "#" + str(i)
|
||||||
|
|
||||||
for value in range(1, max_c+1):
|
for value in range(1, max_c + 1):
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
new_inhibitors = []
|
new_inhibitors = []
|
||||||
new_products = []
|
new_products = []
|
||||||
@@ -391,7 +399,7 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
rs.ensure_bg_set_entity(n)
|
rs.ensure_bg_set_entity(n)
|
||||||
new_inhibitors.append(n)
|
new_inhibitors.append(n)
|
||||||
|
|
||||||
for i in range(1, value+1):
|
for i in range(1, value + 1):
|
||||||
new_products.append(e_value(i))
|
new_products.append(e_value(i))
|
||||||
|
|
||||||
rs.add_reaction(new_reactants, new_inhibitors, new_products)
|
rs.add_reaction(new_reactants, new_inhibitors, new_products)
|
||||||
@@ -399,35 +407,4 @@ class ReactionSystemWithConcentrations(ReactionSystem):
|
|||||||
return rs
|
return rs
|
||||||
|
|
||||||
|
|
||||||
class ReactionSystemWithAutomaton(object):
|
|
||||||
|
|
||||||
def __init__(self, reaction_system, context_automaton):
|
|
||||||
self.rs = reaction_system
|
|
||||||
self.ca = context_automaton
|
|
||||||
|
|
||||||
def show(self, soft=False):
|
|
||||||
self.rs.show(soft)
|
|
||||||
self.ca.show()
|
|
||||||
|
|
||||||
def is_with_concentrations(self):
|
|
||||||
if not isinstance(self.rs, ReactionSystemWithConcentrations):
|
|
||||||
return False
|
|
||||||
if not isinstance(self.ca, ContextAutomatonWithConcentrations):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def sanity_check(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_ordinary_reaction_system_with_automaton(self):
|
|
||||||
|
|
||||||
if not self.is_with_concentrations():
|
|
||||||
raise RuntimeError("Not RS/CA with concentrations")
|
|
||||||
|
|
||||||
ors = self.rs.get_reaction_system()
|
|
||||||
oca = self.ca.get_automaton_with_flat_contexts(ors)
|
|
||||||
|
|
||||||
return ReactionSystemWithAutomaton(ors, oca)
|
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from rs.reaction_system import ReactionSystem
|
|||||||
|
|
||||||
|
|
||||||
class ParameterObj(object):
|
class ParameterObj(object):
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
@@ -21,9 +20,7 @@ def is_param(some_object):
|
|||||||
|
|
||||||
|
|
||||||
class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.reactions = []
|
self.reactions = []
|
||||||
self.parameters = dict()
|
self.parameters = dict()
|
||||||
self.meta_reactions = dict()
|
self.meta_reactions = dict()
|
||||||
@@ -37,14 +34,13 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
def add_bg_set_entity(self, e):
|
def add_bg_set_entity(self, e):
|
||||||
name = ""
|
name = ""
|
||||||
def_max_conc = -1
|
def_max_conc = -1
|
||||||
if type(e) is tuple and len(e) == 2:
|
if isinstance(e, tuple) and len(e) == 2:
|
||||||
name, def_max_conc = e
|
name, def_max_conc = e
|
||||||
elif type(e) is str:
|
elif isinstance(e, str):
|
||||||
name = e
|
name = e
|
||||||
print("\nWARNING: no maximal concentration level specified for:", e, "\n")
|
print("\nWARNING: no maximal concentration level specified for:", e, "\n")
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Bad entity type when adding background set element")
|
||||||
"Bad entity type when adding background set element")
|
|
||||||
|
|
||||||
self.assume_not_in_bgset(name)
|
self.assume_not_in_bgset(name)
|
||||||
self.background_set.append(name)
|
self.background_set.append(name)
|
||||||
@@ -76,7 +72,6 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
self.parameters[param_key].idx = len(self.parameters)
|
self.parameters[param_key].idx = len(self.parameters)
|
||||||
|
|
||||||
def get_max_concentration_level(self, e):
|
def get_max_concentration_level(self, e):
|
||||||
|
|
||||||
if e in self.max_conc_per_ent:
|
if e in self.max_conc_per_ent:
|
||||||
return self.max_conc_per_ent[e]
|
return self.max_conc_per_ent[e]
|
||||||
else:
|
else:
|
||||||
@@ -85,18 +80,10 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
def is_valid_entity_with_concentration(self, e):
|
def is_valid_entity_with_concentration(self, e):
|
||||||
"""Sanity check for entities with concentration"""
|
"""Sanity check for entities with concentration"""
|
||||||
|
|
||||||
if type(e) is tuple:
|
if isinstance(e, (tuple, list)) and len(e) == 2 and isinstance(e[1], int):
|
||||||
if len(e) == 2 and type(e[1]) is int:
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
if type(e) is list:
|
raise RuntimeError("Invalid entity+concentration: " + repr(e))
|
||||||
if len(e) == 2 and type(e[1]) is int:
|
|
||||||
return True
|
|
||||||
|
|
||||||
print("FATAL. Invalid entity+concentration: {:s}".format(e))
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def is_valid_concentration_for_entity(self, entity, level):
|
def is_valid_concentration_for_entity(self, entity, level):
|
||||||
"""Checks the concentration level for entity"""
|
"""Checks the concentration level for entity"""
|
||||||
@@ -113,17 +100,18 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
def terminate_on_invalid_concentration(self, entity, level):
|
def terminate_on_invalid_concentration(self, entity, level):
|
||||||
if not self.is_valid_concentration_for_entity(entity, level):
|
if not self.is_valid_concentration_for_entity(entity, level):
|
||||||
print("FATAL. Invalid entity concentration: {:s}={:d}".format(entity, level))
|
print(
|
||||||
|
"FATAL. Invalid entity concentration: {:s}={:d}".format(entity, level)
|
||||||
|
)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def get_state_ids(self, state):
|
def get_state_ids(self, state):
|
||||||
"""Returns entities of the given state without levels"""
|
"""Returns entities of the given state without levels"""
|
||||||
return [self.get_entity_id(e) for e in state]
|
return [self.get_entity_id(e) for e in state]
|
||||||
|
|
||||||
def has_non_zero_concentration(self, elem):
|
def has_non_zero_concentration(self, elem):
|
||||||
if elem[1] < 1:
|
if elem[1] < 1:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Unexpected concentration level in state: " + str(elem))
|
||||||
"Unexpected concentration level in state: " + str(elem))
|
|
||||||
|
|
||||||
def process_rip(self, R, I, P, ignore_empty_R=False):
|
def process_rip(self, R, I, P, ignore_empty_R=False):
|
||||||
"""Chcecks concentration levels and converts entities names into their ids"""
|
"""Chcecks concentration levels and converts entities names into their ids"""
|
||||||
@@ -207,21 +195,25 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
"""Adds a macro/meta reaction for increasing the value of incr_entity"""
|
"""Adds a macro/meta reaction for increasing the value of incr_entity"""
|
||||||
|
|
||||||
reactants, inhibitors, products = self.process_rip(
|
reactants, inhibitors, products = self.process_rip(
|
||||||
R, I, [], ignore_empty_R=True)
|
R, I, [], ignore_empty_R=True
|
||||||
|
)
|
||||||
incr_entity_id = self.get_entity_id(incr_entity)
|
incr_entity_id = self.get_entity_id(incr_entity)
|
||||||
self.meta_reactions.setdefault(incr_entity_id, [])
|
self.meta_reactions.setdefault(incr_entity_id, [])
|
||||||
self.meta_reactions[incr_entity_id].append(
|
self.meta_reactions[incr_entity_id].append(
|
||||||
("inc", self.get_entity_id(incrementer), reactants, inhibitors))
|
("inc", self.get_entity_id(incrementer), reactants, inhibitors)
|
||||||
|
)
|
||||||
|
|
||||||
def add_reaction_dec(self, decr_entity, decrementer, R, I):
|
def add_reaction_dec(self, decr_entity, decrementer, R, I):
|
||||||
"""Adds a macro/meta reaction for decreasing the value of incr_entity"""
|
"""Adds a macro/meta reaction for decreasing the value of incr_entity"""
|
||||||
|
|
||||||
reactants, inhibitors, products = self.process_rip(
|
reactants, inhibitors, products = self.process_rip(
|
||||||
R, I, [], ignore_empty_R=True)
|
R, I, [], ignore_empty_R=True
|
||||||
|
)
|
||||||
decr_entity_id = self.get_entity_id(decr_entity)
|
decr_entity_id = self.get_entity_id(decr_entity)
|
||||||
self.meta_reactions.setdefault(decr_entity_id, [])
|
self.meta_reactions.setdefault(decr_entity_id, [])
|
||||||
self.meta_reactions[decr_entity_id].append(
|
self.meta_reactions[decr_entity_id].append(
|
||||||
("dec", self.get_entity_id(decrementer), reactants, inhibitors))
|
("dec", self.get_entity_id(decrementer), reactants, inhibitors)
|
||||||
|
)
|
||||||
|
|
||||||
def add_permanency(self, ent, I):
|
def add_permanency(self, ent, I):
|
||||||
"""Sets entity to be permanent unless it is inhibited"""
|
"""Sets entity to be permanent unless it is inhibited"""
|
||||||
@@ -229,8 +221,7 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
ent_id = self.get_entity_id(ent)
|
ent_id = self.get_entity_id(ent)
|
||||||
|
|
||||||
if ent_id in self.permanent_entities:
|
if ent_id in self.permanent_entities:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Permanency for {0} already defined.".format(ent))
|
||||||
"Permanency for {0} already defined.".format(ent))
|
|
||||||
|
|
||||||
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
|
inhibitors = self.process_rip([], I, [], ignore_empty_R=True)[1]
|
||||||
self.permanent_entities[ent_id] = inhibitors
|
self.permanent_entities[ent_id] = inhibitors
|
||||||
@@ -269,18 +260,32 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
def show_background_set(self):
|
def show_background_set(self):
|
||||||
print(
|
print(
|
||||||
C_MARK_INFO + " Background set: {" + self.entities_names_set_to_str(self.background_set) + "}")
|
C_MARK_INFO
|
||||||
|
+ " Background set: {"
|
||||||
|
+ self.entities_names_set_to_str(self.background_set)
|
||||||
|
+ "}"
|
||||||
|
)
|
||||||
|
|
||||||
def show_meta_reactions(self):
|
def show_meta_reactions(self):
|
||||||
print(C_MARK_INFO + " Meta reactions:")
|
print(C_MARK_INFO + " Meta reactions:")
|
||||||
for param_ent, reactions in self.meta_reactions.items():
|
for param_ent, reactions in self.meta_reactions.items():
|
||||||
for r_type, command, reactants, inhibitors in reactions:
|
for r_type, command, reactants, inhibitors in reactions:
|
||||||
if r_type == "inc" or r_type == "dec":
|
if r_type == "inc" or r_type == "dec":
|
||||||
print(" - [ Type=" + repr(r_type) + " Operand=( " + self.get_entity_name(param_ent) + " ) Command=( " + self.get_entity_name(
|
print(
|
||||||
command) + " ) ] -- ( R={" + self.state_to_str(reactants) + "}, I={" + self.state_to_str(inhibitors) + "} )")
|
" - [ Type="
|
||||||
|
+ repr(r_type)
|
||||||
|
+ " Operand=( "
|
||||||
|
+ self.get_entity_name(param_ent)
|
||||||
|
+ " ) Command=( "
|
||||||
|
+ self.get_entity_name(command)
|
||||||
|
+ " ) ] -- ( R={"
|
||||||
|
+ self.state_to_str(reactants)
|
||||||
|
+ "}, I={"
|
||||||
|
+ self.state_to_str(inhibitors)
|
||||||
|
+ "} )"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError("Unknown meta-reaction type: " + repr(r_type))
|
||||||
"Unknown meta-reaction type: " + repr(r_type))
|
|
||||||
|
|
||||||
def show_max_concentrations(self):
|
def show_max_concentrations(self):
|
||||||
print(C_MARK_INFO + " Maximal allowed concentration levels:")
|
print(C_MARK_INFO + " Maximal allowed concentration levels:")
|
||||||
@@ -290,8 +295,12 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
def show_permanent_entities(self):
|
def show_permanent_entities(self):
|
||||||
print(C_MARK_INFO + " Permanent entities:")
|
print(C_MARK_INFO + " Permanent entities:")
|
||||||
for e, inhibitors in self.permanent_entities.items():
|
for e, inhibitors in self.permanent_entities.items():
|
||||||
print(" - {0:^20}{1:<6}".format(self.get_entity_name(e) + ": ",
|
print(
|
||||||
"I={" + self.state_to_str(inhibitors) + "}"))
|
" - {0:^20}{1:<6}".format(
|
||||||
|
self.get_entity_name(e) + ": ",
|
||||||
|
"I={" + self.state_to_str(inhibitors) + "}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def show(self, soft=False):
|
def show(self, soft=False):
|
||||||
self.show_background_set()
|
self.show_background_set()
|
||||||
@@ -303,7 +312,7 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
def get_producible_entities(self):
|
def get_producible_entities(self):
|
||||||
"""
|
"""
|
||||||
Returns the set of entities that appear as products of
|
Returns the set of entities that appear as products of
|
||||||
reactions.
|
reactions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -311,8 +320,7 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
for reaction in self.reactions:
|
for reaction in self.reactions:
|
||||||
product_entities = [e for e, c in reaction[2] if c > 0]
|
product_entities = [e for e, c in reaction[2] if c > 0]
|
||||||
producible_entities = producible_entities.union(
|
producible_entities = producible_entities.union(set(product_entities))
|
||||||
set(product_entities))
|
|
||||||
|
|
||||||
return producible_entities
|
return producible_entities
|
||||||
|
|
||||||
@@ -324,7 +332,6 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
rs = ReactionSystem()
|
rs = ReactionSystem()
|
||||||
|
|
||||||
for reactants, inhibitors, products in self.reactions:
|
for reactants, inhibitors, products in self.reactions:
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
new_inhibitors = []
|
new_inhibitors = []
|
||||||
new_products = []
|
new_products = []
|
||||||
@@ -349,7 +356,6 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
for param_ent, reactions in self.meta_reactions.items():
|
for param_ent, reactions in self.meta_reactions.items():
|
||||||
for r_type, command, reactants, inhibitors in reactions:
|
for r_type, command, reactants, inhibitors in reactions:
|
||||||
|
|
||||||
param_ent_name = self.get_entity_name(param_ent)
|
param_ent_name = self.get_entity_name(param_ent)
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
@@ -371,16 +377,15 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
"WARNING:\n\tThere is no maximal concentration level defined for "
|
"WARNING:\n\tThere is no maximal concentration level defined for "
|
||||||
+ self.get_entity_name(command))
|
+ self.get_entity_name(command)
|
||||||
|
)
|
||||||
print("\tThis is a very bad idea -- expect degraded performance\n")
|
print("\tThis is a very bad idea -- expect degraded performance\n")
|
||||||
|
|
||||||
for l in range(1, max_cmd_c + 1):
|
for l in range(1, max_cmd_c + 1):
|
||||||
|
|
||||||
cmd_ent = self.get_entity_name(command) + "#" + str(l)
|
cmd_ent = self.get_entity_name(command) + "#" + str(l)
|
||||||
rs.ensure_bg_set_entity(cmd_ent)
|
rs.ensure_bg_set_entity(cmd_ent)
|
||||||
|
|
||||||
if r_type == "inc":
|
if r_type == "inc":
|
||||||
|
|
||||||
# pre_conc -- predecessor concentration
|
# pre_conc -- predecessor concentration
|
||||||
# succ_conc -- successor concentration concentration
|
# succ_conc -- successor concentration concentration
|
||||||
|
|
||||||
@@ -399,7 +404,8 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
rs.add_reaction(
|
rs.add_reaction(
|
||||||
set(new_reactants + [pre_conc, cmd_ent]),
|
set(new_reactants + [pre_conc, cmd_ent]),
|
||||||
set(new_inhibitors),
|
set(new_inhibitors),
|
||||||
set(new_products))
|
set(new_products),
|
||||||
|
)
|
||||||
|
|
||||||
elif r_type == "dec":
|
elif r_type == "dec":
|
||||||
for i in range(1, self.max_concentration + 1):
|
for i in range(1, self.max_concentration + 1):
|
||||||
@@ -417,28 +423,29 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
rs.add_reaction(
|
rs.add_reaction(
|
||||||
set(new_reactants + [pre_conc, cmd_ent]),
|
set(new_reactants + [pre_conc, cmd_ent]),
|
||||||
set(new_inhibitors),
|
set(new_inhibitors),
|
||||||
set(new_products))
|
set(new_products),
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Unknown meta-reaction type: " + repr(r_type))
|
"Unknown meta-reaction type: " + repr(r_type)
|
||||||
|
)
|
||||||
|
|
||||||
for ent, inhibitors in self.permanent_entities.items():
|
for ent, inhibitors in self.permanent_entities.items():
|
||||||
|
|
||||||
max_c = self.max_concentration
|
max_c = self.max_concentration
|
||||||
if ent in self.max_conc_per_ent:
|
if ent in self.max_conc_per_ent:
|
||||||
max_c = self.max_conc_per_ent[ent]
|
max_c = self.max_conc_per_ent[ent]
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
"WARNING:\n\tThere is no maximal concentration level defined for "
|
"WARNING:\n\tThere is no maximal concentration level defined for "
|
||||||
+ self.get_entity_name(ent))
|
+ self.get_entity_name(ent)
|
||||||
|
)
|
||||||
print("\tThis is a very bad idea -- expect degraded performance\n")
|
print("\tThis is a very bad idea -- expect degraded performance\n")
|
||||||
|
|
||||||
def e_value(i):
|
def e_value(i):
|
||||||
return self.get_entity_name(ent) + "#" + str(i)
|
return self.get_entity_name(ent) + "#" + str(i)
|
||||||
|
|
||||||
for value in range(1, max_c + 1):
|
for value in range(1, max_c + 1):
|
||||||
|
|
||||||
new_reactants = []
|
new_reactants = []
|
||||||
new_inhibitors = []
|
new_inhibitors = []
|
||||||
new_products = []
|
new_products = []
|
||||||
@@ -457,4 +464,5 @@ class ReactionSystemWithConcentrationsParam(ReactionSystem):
|
|||||||
|
|
||||||
return rs
|
return rs
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
from rs import *
|
from rs import *
|
||||||
from smt import *
|
from smt import *
|
||||||
import rs_examples
|
|
||||||
from logics import *
|
from logics import *
|
||||||
from rsltl_shortcuts import *
|
from rsltl_shortcuts import *
|
||||||
|
|
||||||
from itertools import chain, combinations
|
from itertools import chain, combinations
|
||||||
|
|
||||||
import sys
|
|
||||||
import resource
|
import resource
|
||||||
|
|
||||||
def powerset(iterable,N=None):
|
def powerset(iterable,N=None):
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user