In [1]:
from spn.factory import SpnFactory
from spn.linked.spn import Spn as SpnLinked
from spn.linked.layers import SumLayer as SumLayerLinked
from spn.linked.layers import ProductLayer as ProductLayerLinked
from spn.linked.layers import CategoricalIndicatorLayer
from spn.linked.layers import CategoricalSmoothedLayer
from spn.linked.nodes import SumNode
from spn.linked.nodes import ProductNode
from spn.linked.nodes import CategoricalIndicatorNode
from spn.linked.nodes import CategoricalSmoothedNode
from spn.linked.nodes import CLTreeNode
from spn import MARG_IND
from spn import LOG_ZERO
import numpy
from math import log
from math import exp
import dataset
import logging
import dataset
import algo.learnspn
from algo.dataslice import DataSlice
import spn.linked.tests.test_spn as test
from pyomo.opt import ProblemFormat
In [5]:
dicts = [{'var': 0, 'freqs': [9, 2]},
{'var': 1, 'freqs': [1, 9]},
{'var': 2, 'freqs': [7, 7]},
{'var': 3, 'freqs': [6, 2]}]
In [6]:
def create_valid_toy_spn():
# root layer
whole_scope = frozenset({0, 1, 2, 3})
root_node = SumNode(var_scope=whole_scope)
root_layer = SumLayerLinked([root_node])
# prod layer
prod_node_1 = ProductNode(var_scope=whole_scope)
prod_node_2 = ProductNode(var_scope=whole_scope)
prod_layer_1 = ProductLayerLinked([prod_node_1, prod_node_2])
root_node.add_child(prod_node_1, 0.2)
root_node.add_child(prod_node_2, 0.8)
# sum layer
scope_1 = frozenset({0, 1})
scope_2 = frozenset({2})
scope_3 = frozenset({3})
scope_4 = frozenset({2, 3})
sum_node_1 = SumNode(var_scope=scope_1)
sum_node_2 = SumNode(var_scope=scope_2)
sum_node_3 = SumNode(var_scope=scope_3)
sum_node_4 = SumNode(var_scope=scope_4)
prod_node_1.add_child(sum_node_1)
prod_node_1.add_child(sum_node_2)
prod_node_1.add_child(sum_node_3)
prod_node_2.add_child(sum_node_1)
prod_node_2.add_child(sum_node_4)
sum_layer_1 = SumLayerLinked([sum_node_1, sum_node_2,
sum_node_3, sum_node_4])
# another product layer
prod_node_3 = ProductNode(var_scope=scope_1)
prod_node_4 = ProductNode(var_scope=scope_1)
prod_node_5 = ProductNode(var_scope=scope_4)
prod_node_6 = ProductNode(var_scope=scope_4)
sum_node_1.add_child(prod_node_3, 0.51)
sum_node_1.add_child(prod_node_4, 0.49)
sum_node_4.add_child(prod_node_5, 0.45)
sum_node_4.add_child(prod_node_6, 0.55)
prod_layer_2 = ProductLayerLinked([prod_node_3, prod_node_4,
prod_node_5, prod_node_6])
# last sum one
scope_5 = frozenset({0})
scope_6 = frozenset({1})
sum_node_5 = SumNode(var_scope=scope_5)
sum_node_6 = SumNode(var_scope=scope_6)
sum_node_7 = SumNode(var_scope=scope_5)
sum_node_8 = SumNode(var_scope=scope_6)
sum_node_9 = SumNode(var_scope=scope_2)
sum_node_10 = SumNode(var_scope=scope_3)
sum_node_11 = SumNode(var_scope=scope_2)
sum_node_12 = SumNode(var_scope=scope_3)
prod_node_3.add_child(sum_node_5)
prod_node_3.add_child(sum_node_6)
prod_node_4.add_child(sum_node_7)
prod_node_4.add_child(sum_node_8)
prod_node_5.add_child(sum_node_9)
prod_node_5.add_child(sum_node_10)
prod_node_6.add_child(sum_node_11)
prod_node_6.add_child(sum_node_12)
sum_layer_2 = SumLayerLinked([sum_node_5, sum_node_6,
sum_node_7, sum_node_8,
sum_node_9, sum_node_10,
sum_node_11, sum_node_12])
# input layer
vars = [2, 2, 2, 2]
input_layer = CategoricalSmoothedLayer(vars=vars, node_dicts=dicts)
last_sum_nodes = [sum_node_2, sum_node_3,
sum_node_5, sum_node_6,
sum_node_7, sum_node_8,
sum_node_9, sum_node_10,
sum_node_11, sum_node_12]
for sum_node in last_sum_nodes:
(var_scope,) = sum_node.var_scope
for input_node in input_layer.nodes():
if input_node.var == var_scope:
sum_node.add_child(input_node, 1.0)
spn = SpnLinked(input_layer=input_layer,
layers=[sum_layer_2, prod_layer_2,
sum_layer_1, prod_layer_1,
root_layer])
# print(spn)
return spn
In [7]:
spn = create_valid_toy_spn()
In [9]:
spn._input_layer
Out[9]:
In [ ]:
In [ ]:
In [2]:
def get_variables_and_constraints(self, c):
"""
function used to scroll through the SPN and get variables and constraints in order the compute the MPE thanks
to the nonlinear solver COUENNE and to the PYOMO library
"""
var_node = []
var_indic = []
print("scrolling through the graph")
constraints = []
l = len(self._layers)
print('there are {} layers to visit'.format(l))
for ith_layer in range(l):
for jth_node in range(self._layers[l-ith_layer-1]._n_nodes):
node = self._layers[l-ith_layer-1]._nodes[jth_node]
var_node.append(node.id)
equation="model.x[{}] <= ".format(node.id)
if node.node_type_str() == '*':
not_first = False
for child in node.children:
if child.node_type_str() == '+' or \
child.node_type_str() == '*' or \
child.node_type_str() == 'd':
equation += '{}model.x[{}]'.format('+'*not_first, child.id)
else :
print("Child is neither a '+', a '*' or a 'd' ")
not_first = True
elif node.node_type_str() == '+':
not_first = False
for ith_child in range(len(node.children)):
w = node.log_weights[ith_child]
child = node.children[ith_child]
if child.node_type_str() == '+' or \
child.node_type_str() == '*' or \
child.node_type_str() == 'd':
equation += '{}{}math.exp({}+model.x[{}])'.format('math.log('*(not not_first),'+'*not_first, w, child.id)
else:
print("Child is neither a '+', a '*' or a 'd' ")
not_first = True
equation +=')'
else:
print("Warning, there is an interior node which is neither '*' neither a '+'")
constraints.append(equation)
for node in self._input_layer._nodes:
var_node.append(node.id)
equation = "model.x[{}] <= ".format(node.id)
equation += '{w0}*(1-model.l[{v}])+{w1}*model.l[{v}]'.format(w0 = math.exp(node._var_probs[0]),
w1 = math.exp(node._var_probs[1]),
v= node.var)
constraints.append(equation)
print("end of scrolling through the graph")
var_indic = list(self._root_layer._nodes[0].var_scope)
return var_node, var_indic, constraints
In [13]:
not (2==2)
Out[13]:
In [24]:
spn._layers[2]._nodes[0].log_weights
Out[24]: