diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a9bd496..6cc2a53 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.10', '3.11', '3.12'] clingo-version: ['5.6'] steps: @@ -20,6 +20,7 @@ jobs: - name: Install dependencies run: | python -m pip install "clingo==${{ matrix.clingo-version }}.*" + python -m pip install biodivine_aeon python -m pip install . - name: Test with pytest run: | diff --git a/bonesis/aeon.py b/bonesis/aeon.py index 0c57965..ab05f94 100644 --- a/bonesis/aeon.py +++ b/bonesis/aeon.py @@ -66,7 +66,7 @@ def __repr__(self): def asp_of_AEONReg(dom, boenc, n, acting_n=None, regs=None, ns=""): - regs = dom.rg.regulators(n) if regs is None else regs + regs = dom.am.predecessors(n) if regs is None else regs acting_n = n if acting_n is None else acting_n d = len(regs) boenc.load_template_domain(ns=ns, allow_externals=ns) @@ -76,24 +76,27 @@ def asp_of_AEONReg(dom, boenc, n, acting_n=None, regs=None, ns=""): nbc = dom.get_maxclause(d) rules.append(clingo.Function(f"{ns}maxC", symbols(n, nbc))) for m in regs: - reg = dom.rg.find_regulation(m, acting_n) - m = dom.rg.get_variable_name(m) + reg = dom.am.find_regulation(m, acting_n) + m = dom.am.get_variable_name(m) args = symbols(m, n) - monotonicity = reg.get("monotonicity") - if monotonicity == "activation": + monotonicity = reg.get("sign") + if monotonicity in [True, "positive", "+"]: sign = 1 - elif monotonicity == "inhibition": + elif monotonicity in [False, "negative", "-"]: sign = -1 else: sign = "(-1;1)" rules.append("{}in({},{},{})".format(ns, *args, sign)) - if reg["observable"]: + if reg.get("essential"): boenc.load_template_edge(ns=ns) rules.append(":- not {}edge({},{},_)".format(ns, *args)) return rules def asp_of_AEONFunction(dom, n, func): rules = [] + if isinstance(func.struct, bool): + rules.append(clingo.Function("constant", symbols(n, s2v(func.struct)))) + return rules for cid, c in enumerate(func.struct): if isinstance(c, bool): rules.append(clingo.Function("constant", symbols(n, s2v(c)))) @@ -167,7 +170,6 @@ class AEONDomain(BonesisDomain, dict): def __init__(self, aeon_model, maxclause=None, canonic=True): super().__init__() self.am = aeon_model - self.rg = self.am.graph() self.ba = boolean.BooleanAlgebra(NOT_class=NOT) self.maxclause = maxclause self.canonic = canonic # canonicty is ensured only for parameters and free functions @@ -176,7 +178,7 @@ def __init__(self, aeon_model, maxclause=None, canonic=True): self._f = bonesis.BooleanNetwork({}) for i in self.am.variables(): - name = self.rg.get_variable_name(i) + name = self.am.get_variable_name(i) func = self.am.get_update_function(i) self[name] = func @@ -201,7 +203,7 @@ def register_parameter(g): else: assert self.params[name] == args return name - func = func.to_string(self.am) if not isinstance(func, str) else func + func = str(func) if not isinstance(func, str) else func f = self.ba.parse(RE_PARAMETER.sub(register_parameter, func)) self._f[node] = f f = self._f[node] diff --git a/tests/test_aeon.py b/tests/test_aeon.py new file mode 100644 index 0000000..5da947b --- /dev/null +++ b/tests/test_aeon.py @@ -0,0 +1,34 @@ +import unittest + +import os +import tempfile +import shutil + +import bonesis +import bonesis.aeon + +class TestAEONImport(unittest.TestCase): + def setUp(self): + self.test_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.test_dir) + + + def test_import_with_constant(self): + """ + Source: https://github.com/bnediction/bonesis/issues/6 + """ + fpath = os.path.join(self.test_dir, "test1.aeon") + with open(fpath, "w") as fp: + fp.write("""#name:aeon_test +$A:A & T +A -> A +T -> A +A ->? B +$T:true +""") + + dom = bonesis.aeon.AEONDomain.from_aeon_file(fpath) + bo = bonesis.BoNesis(dom) + self.assertEqual(bo.boolean_networks().count(), 3)