bnediction/bonesis

Incomplete enumeration of local functions fails

daemontus opened this issue · 1 comments

Hi! One more small bug we ran into: If one uses bo.local_functions() to get a per-variable view of the inferred update functions, one has to always enumerate all functions, because otherwise the __exit__ method on the ProjectedBooleanNetworksContext will just crash with Program updates not supported!.

This can be reproduced by the following Python script:

import bonesis

influences = [
	("Pax6","Pax6",dict(sign=1)),
	("Pax6","Hes5",dict(sign=1)),
	("Pax6","Mash1",dict(sign=1)),
	("Hes5","Mash1",dict(sign=-1)),
	("Hes5","Scl",dict(sign=1)),
	("Hes5","Olig2",dict(sign=1)),
	("Hes5","Stat3",dict(sign=1)),
	("Mash1","Hes5",dict(sign=-1)),
	("Mash1","Zic1",dict(sign=1)),
	("Mash1","Brn2",dict(sign=1)),
	("Zic1","Tuj1",dict(sign=1)),
	("Brn2","Tuj1",dict(sign=1)),
	("Scl","Olig2",dict(sign=-1)),
	("Scl","Stat3",dict(sign=1)),
	("Olig2","Scl",dict(sign=-1)),
	("Olig2","Myt1L",dict(sign=1)),
	("Olig2","Sox8",dict(sign=1)),
	("Olig2","Brn2",dict(sign=-1)),
	("Stat3","Aldh1L1",dict(sign=1)),
	("Myt1L","Tuj1",dict(sign=1)),
]

dom = bonesis.InfluenceGraph(influences)

data = {
    "fMS": {"Pax6": 1, "Tuj1": 0, "Zic1": 0, "Brn2": 0, "Aldh1L1": 0, "Sox8": 1},
    "fA": {"Pax6": 1, "Tuj1": 0, "Zic1": 0, "Brn2": 0, "Aldh1L1": 1, "Sox8": 0},
}

bo = bonesis.BoNesis(dom, data)
bo.fixed(~bo.obs("fA"))
bo.fixed(~bo.obs("fMS"));

print(" >> Enumerating unrestricted.")
funs = bo.local_functions()
for node in dom.nodes():	
	with funs.view(node) as view:
		f = [f for f in view]
		print(f"Enumerated {len(f)} functions for node {node}.")

print(" >> Enumerating with limit.")
funs = bo.local_functions(limit=2)
for node in dom.nodes():	
	with funs.view(node) as view:
		f = [f for f in view]
		print(f"Enumerated {len(f)} functions for node {node}.")

At the moment, this is the output we are getting:

 >> Enumerating unrestricted.
Grounding...done in 0.1s
Enumerated 2 functions for node Pax6.
Enumerated 6 functions for node Hes5.
Enumerated 6 functions for node Mash1.
Enumerated 4 functions for node Scl.
Enumerated 4 functions for node Olig2.
Enumerated 4 functions for node Stat3.
Enumerated 2 functions for node Zic1.
Enumerated 3 functions for node Brn2.
Enumerated 19 functions for node Tuj1.
Enumerated 3 functions for node Myt1L.
Enumerated 1 functions for node Sox8.
Enumerated 1 functions for node Aldh1L1.
 >> Enumerating with limit.
Grounding...done in 0.0s
Enumerated 2 functions for node Pax6.
Traceback (most recent call last):
  File "/Users/daemontus/Downloads/test.py", line 47, in <module>
    with funs.view(node) as view:
  File "/opt/homebrew/lib/python3.11/site-packages/bonesis/views.py", line 271, in __exit__
    self.parent.control.assign_external(e, False)
  File "/opt/homebrew/lib/python3.11/site-packages/bonesis0/proxy_control.py", line 88, in assign_external
    return self.control.assign_external(*args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.11/site-packages/clingo/control.py", line 368, in assign_external
    _handle_error(
  File "/opt/homebrew/lib/python3.11/site-packages/clingo/_internal.py", line 75, in _handle_error
    raise RuntimeError(msg)
RuntimeError: Program updates not supported!

We can work around this by not using the with environment, but this probably leaks some memory/process.

Thanks for the report! It should be fixed with the latest commit.