Пример #1
0
        def generate_scopes_from_inputs(node, inputs, num_or_size_sums, ivs=False):
            # Create a flat list of scopes, where the scope elements of a single input
            # node are subsequent in the list
            flat_scopes = []
            size = 0
            for inp in inputs:
                if isinstance(inp, tuple) and inp[1]:
                    input_indices = [inp[1]] if isinstance(inp[1], int) else inp[1]
                    for i in input_indices:
                        flat_scopes.append(scopes_per_node[inp[0]][i])
                    size += len(input_indices)
                elif not isinstance(inp, tuple):
                    flat_scopes.extend(scopes_per_node[inp])
                    size += len(scopes_per_node[inp])
                else:
                    flat_scopes.extend(scopes_per_node[inp[0]])
                    size += len(scopes_per_node[inp[0]])
            if isinstance(num_or_size_sums, int):
                num_or_size_sums = num_or_size_sums * [size // num_or_size_sums]

            new_scope = []
            offset = 0
            # For each sum generate the scope based on its size
            for i, s in enumerate(num_or_size_sums):
                scope = flat_scopes[offset]
                for j in range(1, s):
                    scope |= flat_scopes[j + offset]
                offset += s
                if ivs:
                    scope |= spn.Scope(node.ivs.node, i)
                new_scope.append(scope)
            scopes_per_node[node] = new_scope
Пример #2
0
 def test_get_scope(self):
     """Computing the scope of nodes of the SPN graph"""
     # Create graph
     v12 = spn.IVs(num_vars=2, num_vals=4, name="V12")
     v34 = spn.ContVars(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     p1 = spn.Product((v12, [0, 7]), name="P1")
     p2 = spn.Product((v12, [3, 4]), name="P2")
     p3 = spn.Product(v34, name="P3")
     n1 = spn.Concat(s1, s2, p3, name="N1")
     n2 = spn.Concat(p1, p2, name="N2")
     p4 = spn.Product((n1, [0]), (n1, [1]), name="P4")
     p5 = spn.Product((n2, [0]), (n1, [2]), name="P5")
     s3 = spn.Sum(p4, n2, name="S3")
     p6 = spn.Product(s3, (n1, [2]), name="P6")
     s4 = spn.Sum(p5, p6, name="S4")
     # Test
     self.assertListEqual(v12.get_scope(),
                          [spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 1), spn.Scope(v12, 1),
                           spn.Scope(v12, 1), spn.Scope(v12, 1)])
     self.assertListEqual(v34.get_scope(),
                          [spn.Scope(v34, 0), spn.Scope(v34, 1)])
     self.assertListEqual(s1.get_scope(),
                          [spn.Scope(v12, 0)])
     self.assertListEqual(s2.get_scope(),
                          [spn.Scope(v12, 1)])
     self.assertListEqual(p1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p3.get_scope(),
                          [spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n1.get_scope(),
                          [spn.Scope(v12, 0),
                           spn.Scope(v12, 1),
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p5.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p6.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
Пример #3
0
 def test_scope(self):
     """Scope creation and operations"""
     # Creation
     s1 = spn.Scope("a", 1)
     self.assertListEqual([i for i in s1],
                          [("a", 1)])
     s2 = spn.Scope("b", 1)
     s3 = spn.Scope("b", 2)
     # Merging
     s = spn.Scope.merge_scopes([s1, s2, s3])
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("b", 1), ("b", 2)])
     # Set operations
     s = s1 | s2 | s3
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("b", 1), ("b", 2)])
     s = s1.union(s2).union(s3)
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("b", 1), ("b", 2)])
     s = (s1 | s2 | s3) & spn.Scope("b", 1)
     self.assertListEqual(sorted([i for i in s]),
                          [("b", 1)])
     s = (s1 | s2 | s3).intersection(spn.Scope("b", 1))
     self.assertListEqual(sorted([i for i in s]),
                          [("b", 1)])
     s = (s1 | s2 | s3) - spn.Scope("b", 1)
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("b", 2)])
     s = (s1 | s2 | s3).difference(spn.Scope("b", 1))
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("b", 2)])
     s = (s1 | s2) ^ (spn.Scope("b", 1) | spn.Scope("c", 1))
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("c", 1)])
     s = (s1 | s2).symmetric_difference(
         (spn.Scope("b", 1) | spn.Scope("c", 1)))
     self.assertListEqual(sorted([i for i in s]),
                          [("a", 1), ("c", 1)])
     # Hash
     self.assertIsNotNone(hash(s))
     # Used in dicts
     d = {s1: 10, s: 12}
     self.assertEqual(d[spn.Scope("a", 1)], 10)
     self.assertEqual(d[spn.Scope("a", 1) | spn.Scope("c", 1)], 12)
     # Subsets
     self.assertTrue(s.issuperset(spn.Scope("c", 1)))
     self.assertTrue(spn.Scope("c", 1).issubset(s))
     self.assertFalse(s.issuperset(spn.Scope("d", 1)))
     self.assertFalse(spn.Scope("d", 1).issubset(s))
     self.assertTrue(s.isdisjoint(spn.Scope("d", 1)))
     self.assertFalse(s.isdisjoint(spn.Scope("a", 1)))
     # Test for empty scope
     self.assertFalse(spn.Scope("a", 1) & spn.Scope("b", 1))
     self.assertTrue(spn.Scope("a", 1) | spn.Scope("b", 1))
     self.assertEqual(len(spn.Scope("a", 1) & spn.Scope("b", 1)), 0)
     self.assertEqual(len(spn.Scope("a", 1) | spn.Scope("b", 1)), 2)
Пример #4
0
 def test_comput_scope(self):
     """Calculating scope of Product"""
     # Create a graph
     v12 = spn.IndicatorLeaf(num_vars=2, num_vals=4, name="V12")
     v34 = spn.RawLeaf(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s1.generate_latent_indicators()
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     p1 = spn.Product((v12, [0, 7]), name="P1")
     p2 = spn.Product((v12, [3, 4]), name="P1")
     p3 = spn.Product(v34, name="P3")
     n1 = spn.Concat(s1, s2, p3, name="N1")
     n2 = spn.Concat(p1, p2, name="N2")
     p4 = spn.Product((n1, [0]), (n1, [1]), name="P4")
     p5 = spn.Product((n2, [0]), (n1, [2]), name="P5")
     s3 = spn.Sum(p4, n2, name="S3")
     p6 = spn.Product(s3, (n1, [2]), name="P6")
     s4 = spn.Sum(p5, p6, name="S4")
     s4.generate_latent_indicators()
     # Test
     self.assertListEqual(v12.get_scope(),
                          [spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 1), spn.Scope(v12, 1),
                           spn.Scope(v12, 1), spn.Scope(v12, 1)])
     self.assertListEqual(v34.get_scope(),
                          [spn.Scope(v34, 0), spn.Scope(v34, 1)])
     self.assertListEqual(s1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(s2.get_scope(),
                          [spn.Scope(v12, 1)])
     self.assertListEqual(p1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p3.get_scope(),
                          [spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 1),
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(p5.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(p6.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1) |
                           spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(s4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1) |
                           spn.Scope(s1.latent_indicators.node, 0) |
                           spn.Scope(s4.latent_indicators.node, 0)])
Пример #5
0
    def test_compute_scope(self):
        """Calculating scope of Sums"""
        # Create a graph
        v12 = spn.IndicatorLeaf(num_vars=2, num_vals=4, name="V12")
        v34 = spn.RawLeaf(num_vars=3, name="V34")

        scopes_per_node = {
            v12: [
                spn.Scope(v12, 0),
                spn.Scope(v12, 0),
                spn.Scope(v12, 0),
                spn.Scope(v12, 0),
                spn.Scope(v12, 1),
                spn.Scope(v12, 1),
                spn.Scope(v12, 1),
                spn.Scope(v12, 1)
            ],
            v34: [spn.Scope(v34, 0),
                  spn.Scope(v34, 1),
                  spn.Scope(v34, 2)]
        }

        def generate_scopes_from_inputs(node,
                                        inputs,
                                        num_or_size_sums,
                                        latent_indicators=False):
            # Create a flat list of scopes, where the scope elements of a single input
            # node are subsequent in the list
            flat_scopes = []
            size = 0
            for inp in inputs:
                if isinstance(inp, tuple) and inp[1]:
                    input_indices = [inp[1]] if isinstance(inp[1],
                                                           int) else inp[1]
                    for i in input_indices:
                        flat_scopes.append(scopes_per_node[inp[0]][i])
                    size += len(input_indices)
                elif not isinstance(inp, tuple):
                    flat_scopes.extend(scopes_per_node[inp])
                    size += len(scopes_per_node[inp])
                else:
                    flat_scopes.extend(scopes_per_node[inp[0]])
                    size += len(scopes_per_node[inp[0]])
            if isinstance(num_or_size_sums, int):
                num_or_size_sums = num_or_size_sums * [
                    size // num_or_size_sums
                ]

            new_scope = []
            offset = 0
            # For each sum generate the scope based on its size
            for i, s in enumerate(num_or_size_sums):
                scope = flat_scopes[offset]
                for j in range(1, s):
                    scope |= flat_scopes[j + offset]
                offset += s
                if latent_indicators:
                    scope |= spn.Scope(node.latent_indicators.node, i)
                new_scope.append(scope)
            scopes_per_node[node] = new_scope

        def sums_layer_and_test(inputs,
                                num_or_size_sums,
                                name,
                                latent_indicators=False):
            """ Create a sums layer, generate its correct scope and test """
            sums_layer = spn.SumsLayer(*inputs,
                                       num_or_size_sums=num_or_size_sums,
                                       name=name)
            if latent_indicators:
                sums_layer.generate_latent_indicators()
            generate_scopes_from_inputs(sums_layer,
                                        inputs,
                                        num_or_size_sums,
                                        latent_indicators=latent_indicators)
            self.assertListEqual(sums_layer.get_scope(),
                                 scopes_per_node[sums_layer])
            return sums_layer

        def concat_layer_and_test(inputs, name):
            """ Create a concat node, generate its scopes and assert whether it is correct """
            scope = []
            for inp in inputs:
                if isinstance(inp, tuple):
                    indices = inp[1]
                    if isinstance(inp[1], int):
                        indices = [inp[1]]
                    for i in indices:
                        scope.append(scopes_per_node[inp[0]][i])
                else:
                    scope.extend(scopes_per_node[inp])
            concat = spn.Concat(*inputs, name=name)
            self.assertListEqual(concat.get_scope(), scope)
            scopes_per_node[concat] = scope
            return concat

        ss1 = sums_layer_and_test([(v12, [0, 1, 2, 3]), (v12, [1, 2, 5, 6]),
                                   (v12, [4, 5, 6, 7])],
                                  3,
                                  "Ss1",
                                  latent_indicators=True)

        ss2 = sums_layer_and_test([(v12, [6, 7]), (v34, 0)],
                                  num_or_size_sums=[1, 2],
                                  name="Ss2")
        ss3 = sums_layer_and_test([(v12, [3, 7]), (v34, 1),
                                   (v12, [4, 5, 6]), v34],
                                  num_or_size_sums=[1, 2, 2, 2, 2],
                                  name="Ss3")

        s1 = sums_layer_and_test([(v34, [1, 2])],
                                 num_or_size_sums=1,
                                 name="S1",
                                 latent_indicators=True)
        concat_layer_and_test([(ss1, [0, 2]), (ss2, 0)], name="N1")
        concat_layer_and_test([(ss1, 1), ss3, s1], name="N2")
        n = concat_layer_and_test([(ss1, 0), ss2, (ss3, [0, 1]), s1],
                                  name="N3")
        sums_layer_and_test([(ss1, [1, 2]), ss2],
                            num_or_size_sums=[2, 1, 1],
                            name="Ss4")
        sums_layer_and_test([(ss1, [0, 2]), (n, [0, 1]), (ss3, [4, 2])],
                            num_or_size_sums=[3, 2, 1],
                            name="Ss5")
Пример #6
0
 def test_comput_scope(self):
     """Calculating scope of PermuteProducts"""
     # Create graph
     v12 = spn.IndicatorLeaf(num_vars=2, num_vals=4, name="V12")
     v34 = spn.RawLeaf(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s1.generate_latent_indicators()
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     p1 = spn.Product((v12, [0, 7]), name="P1")
     p2 = spn.Product((v12, [3, 4]), name="P2")
     p3 = spn.Product(v34, name="P3")
     n1 = spn.Concat(s1, s2, p3, name="N1")
     n2 = spn.Concat(p1, p2, name="N2")
     pp1 = spn.PermuteProducts(n1, n2, name="PP1")  # num_prods = 6
     pp2 = spn.PermuteProducts((n1, [0, 1]), (n2, [0]), name="PP2")  # num_prods = 2
     pp3 = spn.PermuteProducts(n2, p3, name="PP3")  # num_prods = 2
     pp4 = spn.PermuteProducts(p2, p3, name="PP4")  # num_prods = 1
     pp5 = spn.PermuteProducts((n2, [0, 1]), name="PP5")  # num_prods = 1
     pp6 = spn.PermuteProducts(p3, name="PP6")  # num_prods = 1
     n3 = spn.Concat((pp1, [0, 2, 3]), pp2, pp4, name="N3")
     s3 = spn.Sum((pp1, [0, 2, 4]), (pp1, [1, 3, 5]), pp2, pp3, (pp4, 0),
                  pp5, pp6, name="S3")
     s3.generate_latent_indicators()
     n4 = spn.Concat((pp3, [0, 1]), pp5, (pp6, 0), name="N4")
     pp7 = spn.PermuteProducts(n3, s3, n4, name="PP7")  # num_prods = 24
     pp8 = spn.PermuteProducts(n3, name="PP8")  # num_prods = 1
     pp9 = spn.PermuteProducts((n4, [0, 1, 2, 3]), name="PP9")  # num_prods = 1
     # Test
     self.assertListEqual(v12.get_scope(),
                          [spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 0), spn.Scope(v12, 0),
                           spn.Scope(v12, 1), spn.Scope(v12, 1),
                           spn.Scope(v12, 1), spn.Scope(v12, 1)])
     self.assertListEqual(v34.get_scope(),
                          [spn.Scope(v34, 0), spn.Scope(v34, 1)])
     self.assertListEqual(s1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(s2.get_scope(),
                          [spn.Scope(v12, 1)])
     self.assertListEqual(p1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(p3.get_scope(),
                          [spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 1),
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(pp1.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(pp2.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(pp3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(pp4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(pp5.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1)])
     self.assertListEqual(pp6.get_scope(),
                          [spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(n3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(s3.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1) |
                           spn.Scope(s1.latent_indicators.node, 0) |
                           spn.Scope(s3.latent_indicators.node, 0)])
     self.assertListEqual(n4.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1),
                           spn.Scope(v12, 0) | spn.Scope(v12, 1),
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
     self.assertListEqual(pp7.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1) |
                           spn.Scope(s1.latent_indicators.node, 0) |
                           spn.Scope(s3.latent_indicators.node, 0)] * 24)
     self.assertListEqual(pp8.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(s1.latent_indicators.node, 0) | spn.Scope(v34, 0) |
                           spn.Scope(v34, 1)])
     self.assertListEqual(pp9.get_scope(),
                          [spn.Scope(v12, 0) | spn.Scope(v12, 1) |
                           spn.Scope(v34, 0) | spn.Scope(v34, 1)])
Пример #7
0
 def test_comput_scope(self):
     """Calculating scope of ProductsLayer"""
     # Create graph
     v12 = spn.IndicatorLeaf(num_vars=2, num_vals=4, name="V12")
     v34 = spn.RawLeaf(num_vars=2, name="V34")
     s1 = spn.Sum((v12, [0, 1, 2, 3]), name="S1")
     s1.generate_latent_indicators()
     s2 = spn.Sum((v12, [4, 5, 6, 7]), name="S2")
     pl1 = spn.ProductsLayer((v12, [0, 5, 6, 7]), (v12, [3, 4]),
                             v34,
                             num_or_size_prods=[4, 3, 1],
                             name="PL1")
     n1 = spn.Concat(s1, s2, (pl1, [2]), name="N1")
     n2 = spn.Concat((pl1, [0]), (pl1, [1]), name="N2")
     s3 = spn.Sum(pl1, name="S3")
     s3.generate_latent_indicators()
     pl2 = spn.ProductsLayer((n1, [0, 1]), (n1, 2), (n2, 0), (pl1, [1]),
                             n2,
                             s3, (n2, 1),
                             s3,
                             pl1,
                             num_or_size_prods=[2, 3, 3, 5],
                             name="PL2")
     s4 = spn.Sum((pl2, 0), n2, name="S4")
     s5 = spn.Sum(pl2, name="S5")
     s6 = spn.Sum((pl2, [1, 3]), name="S6")
     s6.generate_latent_indicators()
     pl3 = spn.ProductsLayer(s4, (n1, 2), num_or_size_prods=1, name="PL3")
     pl4 = spn.ProductsLayer(s4,
                             s5,
                             s6,
                             s4,
                             s5,
                             s6,
                             num_or_size_prods=2,
                             name="PL4")
     # Test
     self.assertListEqual(v12.get_scope(), [
         spn.Scope(v12, 0),
         spn.Scope(v12, 0),
         spn.Scope(v12, 0),
         spn.Scope(v12, 0),
         spn.Scope(v12, 1),
         spn.Scope(v12, 1),
         spn.Scope(v12, 1),
         spn.Scope(v12, 1)
     ])
     self.assertListEqual(
         v34.get_scope(),
         [spn.Scope(v34, 0), spn.Scope(v34, 1)])
     self.assertListEqual(
         s1.get_scope(),
         [spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0)])
     self.assertListEqual(s2.get_scope(), [spn.Scope(v12, 1)])
     self.assertListEqual(pl1.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v12, 1)
         | spn.Scope(v12, 1),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0),
         spn.Scope(v34, 1)
     ])
     self.assertListEqual(n1.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(s1.latent_indicators.node, 0),
         spn.Scope(v12, 1),
         spn.Scope(v34, 1)
     ])
     self.assertListEqual(n2.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v12, 1)
         | spn.Scope(v12, 1),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
     ])
     self.assertListEqual(s3.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s3.latent_indicators.node, 0)
     ])
     self.assertListEqual(pl2.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1)
         | spn.Scope(s1.latent_indicators.node, 0),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s3.latent_indicators.node, 0),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s3.latent_indicators.node, 0)
     ])
     self.assertListEqual(s4.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1)
         | spn.Scope(s1.latent_indicators.node, 0) | spn.Scope(v34, 0)
     ])
     self.assertListEqual(s5.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1)
         | spn.Scope(s1.latent_indicators.node, 0) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s3.latent_indicators.node, 0)
     ])
     self.assertListEqual(s6.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s3.latent_indicators.node, 0)
         | spn.Scope(s6.latent_indicators.node, 0)
     ])
     self.assertListEqual(pl3.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1)
         | spn.Scope(s1.latent_indicators.node, 0) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1)
     ])
     self.assertListEqual(pl4.get_scope(), [
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s1.latent_indicators.node, 0)
         | spn.Scope(s3.latent_indicators.node, 0)
         | spn.Scope(s6.latent_indicators.node, 0),
         spn.Scope(v12, 0) | spn.Scope(v12, 1) | spn.Scope(v34, 0)
         | spn.Scope(v34, 1) | spn.Scope(s1.latent_indicators.node, 0)
         | spn.Scope(s3.latent_indicators.node, 0)
         | spn.Scope(s6.latent_indicators.node, 0)
     ])