CASCI-lab / CANA

CANAlization: Control & Redundancy in Boolean Networks
https://casci-lab.github.io/CANA/
MIT License
22 stars 15 forks source link

wrong attractors for networks with constants #23

Closed stas-g closed 1 year ago

stas-g commented 2 years ago

as per the title, i get wrong attractors with any constants in the network. consider two simple networks, L and N, respectively:

x *= 1
y *= x
z *= y

and

x *= x
y *= x
z *= y

read in:

#constant setup: 1 -> x -> y -> z    
L = boolean_network.BooleanNetwork.from_file("xxx.txt", type = 'logical', name = "test", keep_constants = True)
#self-feeding setup: x -> x -> y -> z
N = boolean_network.BooleanNetwork.from_file("yyy.txt", type = 'logical', name = "test", keep_constants = True)  

now, L has only one attractor, "111", whilst N has two, "111" and "000". however

att_L = L.attractors()    
att_N = N.attractors()    

att_L
Out[11]: [[3]]

att_N
Out[12]: [[0], [7]]

cutils.statenum_to_binstate(att_L[0][0], len(L.nodes))
Out[14]: '011'  

[cutils.statenum_to_binstate(att_N[i][0], len(N.nodes)) for i in range(len(att_N))]
Out[15]: ['000', '111']

to get the correct (kind of, assuming value of 1 is implied for x) attractor for L, one needs to account for constants:

cutils.statenum_to_binstate(att_L[0][0], len(L.nodes) - 1)
Out[16]: '11'

one can get the correct trajectory to an attractor though + correct attractor:

L.trajectory_to_attractor('000', return_attractor = True)    
Out[19]: (['000', '100', '110', '111'], [3])
austin-marcus commented 1 year ago

Actually, the attractors are being computed correctly. The output of attractors() is not the decimal version of the binary representing the state of the network. Rather, it is the key into the nodes of the networkx graph of the STG (L._stg.nodes[3] = {"label": "111"}). It just so happens that, for N, the keys match the network state they map to.

You can obtain the network states from those dictionary indicies like this:

>>> [set(L._stg.nodes[nid]["label"] for nid in att) for att in L.attractors()]
[{'111'}]
>>> [set(N._stg.nodes[nid]["label"] for nid in att) for att in N.attractors()]
[{'000'}, {'111'}]

Hope this helps!

stas-g commented 1 year ago

@austin-marcus thank you for your help!