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]:
[input layer:]
Categorical Smoothed Node id: 38 scope: frozenset({0})
            var: 0 val: 2 [[9, 2]] [[-0.20763936477824441, -1.6739764335716714]]
Categorical Smoothed Node id: 39 scope: frozenset({1})
            var: 1 val: 2 [[1, 9]] [[-2.2270775404859005, -0.11411330676742093]]
Categorical Smoothed Node id: 40 scope: frozenset({2})
            var: 2 val: 2 [[7, 7]] [[-0.69314718055994518, -0.69314718055994518]]
Categorical Smoothed Node id: 41 scope: frozenset({3})
            var: 3 val: 2 [[6, 2]] [[-0.29584538309094199, -1.3621968095408301]]
**********************************************************

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]:
False

In [24]:
spn._layers[2]._nodes[0].log_weights


Out[24]:
[-0.6733445532637656, -0.7133498878774648]