Ejemplo n.º 1
0
    def test_linear_ranges_specified(self):
        graph = nx.barbell_graph(4, 16)
        decision_variables = (0, 4, 3)
        feasible_configurations = {(0, 0, 1): 0.}

        spec = pm.Specification(
            graph,
            decision_variables,
            feasible_configurations,
            ising_linear_ranges={v: [-v, 2]
                                 for v in graph},
            vartype=dimod.BINARY)

        # check default energy ranges
        for v in graph:
            self.assertEqual(spec.ising_linear_ranges[v], [-v, 2])

        spec = pm.Specification(
            graph,
            decision_variables,
            feasible_configurations,
            ising_linear_ranges={v: (-v, 2)
                                 for v in graph},
            vartype=dimod.BINARY)

        # check default energy ranges
        for v in graph:
            self.assertEqual(spec.ising_linear_ranges[v], [-v, 2])
Ejemplo n.º 2
0
    def test_relabel_inplace(self):
        graph = nx.circular_ladder_graph(12)
        decision_variables = (0, 2, 5)
        feasible_configurations = {(1, 1, 1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.SPIN)

        mapping = {
            i: v
            for i, v in enumerate('abcdefghijklmnopqrstuvwxyz') if i in graph
        }

        new_spec = spec.relabel_variables(mapping, copy=False)

        self.assertIs(new_spec, spec)  # should be the same object
        self.assertIs(new_spec.graph, spec.graph)

        # create a test spec
        graph = nx.relabel_nodes(graph, mapping)
        decision_variables = (mapping[v] for v in decision_variables)
        test_spec = pm.Specification(graph,
                                     decision_variables,
                                     feasible_configurations,
                                     vartype=dimod.SPIN)

        self.assertEqual(new_spec, test_spec)
        self.assertEqual(new_spec.ising_linear_ranges,
                         test_spec.ising_linear_ranges)
        self.assertEqual(new_spec.ising_quadratic_ranges,
                         test_spec.ising_quadratic_ranges)
Ejemplo n.º 3
0
    def test_relabel_copy(self):
        graph = nx.circular_ladder_graph(12)
        decision_variables = (0, 2, 5)
        feasible_configurations = {(1, 1, 1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.SPIN)

        mapping = dict(enumerate('abcdefghijklmnopqrstuvwxyz'))

        new_spec = spec.relabel_variables(mapping, copy=True)

        # create a test spec
        graph = nx.relabel_nodes(graph, mapping)
        decision_variables = (mapping[v] for v in decision_variables)
        test_spec = pm.Specification(graph,
                                     decision_variables,
                                     feasible_configurations,
                                     vartype=dimod.SPIN)

        self.assertEqual(new_spec, test_spec)
        self.assertEqual(new_spec.ising_linear_ranges,
                         test_spec.ising_linear_ranges)
        self.assertEqual(new_spec.ising_quadratic_ranges,
                         test_spec.ising_quadratic_ranges)
Ejemplo n.º 4
0
    def test_vartype_specified(self):
        graph = nx.complete_graph(12)
        decision_variables = (0, 2, 5)
        feasible_configurations = {(1, 1, 1): 0.}

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.SPIN)
        self.assertIs(spec.vartype, dimod.SPIN)

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.BINARY)
        self.assertIs(spec.vartype, dimod.BINARY)

        # now set up a spec that can only have one vartype
        graph = nx.complete_graph(12)
        decision_variables = (0, 2, 5)
        feasible_configurations = {(1, 1, -1): 0.}

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.SPIN)
        self.assertIs(spec.vartype, dimod.SPIN)

        # the feasible_configurations are spin
        with self.assertRaises(ValueError):
            spec = pm.Specification(graph,
                                    decision_variables,
                                    feasible_configurations,
                                    vartype=dimod.BINARY)
Ejemplo n.º 5
0
    def test_construction_from_edgelist(self):
        graph = nx.barbell_graph(10, 7)
        decision_variables = (0, 4, 3)
        feasible_configurations = {(-1, -1, -1): 0.}

        # specification from edges
        spec0 = pm.Specification(graph.edges, decision_variables, feasible_configurations, vartype=pm.SPIN)

        # specification from graph
        spec1 = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.SPIN)

        self.assertEqual(spec0, spec1)
Ejemplo n.º 6
0
    def test_relabel_forwards_and_backwards(self):
        graph = nx.path_graph(4)
        graph.add_edge(0, 2)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)
        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        # make another one
        graph = nx.path_graph(4)
        graph.add_edge(0, 2)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)
        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        original_widget = pm.PenaltyModel.from_specification(
            spec, model, 2., -2)

        new_label_sets = [(10, 1), ('a', 'b'), (1, 'b'), ('1', '2', '3', '4'),
                          ('a', 'b', 'c', 'd')]
        new_label_sets.extend(itertools.permutations(graph))

        for new in new_label_sets:
            mapping = dict(enumerate(new))
            inv_mapping = {u: v for v, u in mapping.items()}

            # apply then invert with copy=False
            widget.relabel_variables(mapping, copy=False)
            widget.relabel_variables(inv_mapping, copy=False)
            self.assertEqual(widget, original_widget)

            # apply then invert with copy=True
            copy_widget = widget.relabel_variables(mapping, copy=True)
            inv_copy = copy_widget.relabel_variables(inv_mapping, copy=True)
            self.assertEqual(inv_copy, original_widget)
Ejemplo n.º 7
0
    def test_relabel_forwards_and_backwards(self):
        graph = nx.path_graph(4)
        graph.add_edge(0, 2)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=dimod.SPIN)

        # make another one
        graph = nx.path_graph(4)
        graph.add_edge(0, 2)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        original_spec = pm.Specification(graph,
                                         decision_variables,
                                         feasible_configurations,
                                         vartype=dimod.SPIN)

        identity = {v: v for v in graph}

        new_label_sets = [(10, 1), ('a', 'b'), (1, 'b'), ('1', '2', '3', '4'),
                          ('a', 'b', 'c', 'd')]
        new_label_sets.extend(itertools.permutations(graph))

        for new in new_label_sets:
            mapping = dict(enumerate(new))
            inv_mapping = {u: v for v, u in mapping.items()}

            # apply then invert with copy=True
            copy_spec = spec.relabel_variables(mapping, copy=True)
            inv_copy = copy_spec.relabel_variables(inv_mapping, copy=True)
            self.assertEqual(inv_copy, original_spec)
            self.assertEqual(inv_copy.ising_linear_ranges,
                             original_spec.ising_linear_ranges)
            self.assertEqual(inv_copy.ising_quadratic_ranges,
                             original_spec.ising_quadratic_ranges)

            # apply then invert with copy=False
            spec.relabel_variables(mapping, copy=False)
            if mapping == identity:
                self.assertEqual(spec, original_spec)
            else:
                self.assertNotEqual(spec, original_spec)
            spec.relabel_variables(inv_mapping, copy=False)
            self.assertEqual(spec, original_spec)
            self.assertEqual(spec.ising_linear_ranges,
                             original_spec.ising_linear_ranges)
            self.assertEqual(spec.ising_quadratic_ranges,
                             original_spec.ising_quadratic_ranges)
Ejemplo n.º 8
0
    def test_linear_ranges_bad(self):
        graph = nx.barbell_graph(4, 16)
        decision_variables = (0, 4, 3)
        feasible_configurations = {(0, 0, 1): 0.}

        with self.assertRaises(ValueError):
            pm.Specification(graph, decision_variables, feasible_configurations,
                             ising_linear_ranges={v: [-v, 'a'] for v in graph},
                             vartype=pm.BINARY)

        with self.assertRaises(TypeError):
            pm.Specification(graph, decision_variables, feasible_configurations,
                             ising_linear_ranges={v: [-v, 1, 1] for v in graph},
                             vartype=pm.BINARY)
Ejemplo n.º 9
0
    def test_binary_specification(self):
        graph = nx.Graph()
        for i in range(4):
            for j in range(4, 8):
                graph.add_edge(i, j)

        decision_variables = (0, 1)
        feasible_configurations = ((0, 0), (1, 1))  # equality

        spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.BINARY)
        widget = maxgap.get_penalty_model(spec)

        self.assertIs(widget.model.vartype, pm.BINARY)

        # test the correctness of the widget
        energies = {}
        for decision_config in itertools.product((0, 1), repeat=2):
            energies[decision_config] = float('inf')

            for aux_config in itertools.product((0, 1), repeat=6):
                sample = dict(enumerate(decision_config + aux_config))
                energy = widget.model.energy(sample)

                energies[decision_config] = min(energies[decision_config], energy)

        for decision_config, energy in energies.items():
            if decision_config in feasible_configurations:
                self.assertAlmostEqual(energy, widget.ground_energy)
            else:
                self.assertGreaterEqual(energy, widget.ground_energy + widget.classical_gap - 10**-6)
Ejemplo n.º 10
0
    def test_quadratic_ranges_partially_specified(self):
        graph = nx.barbell_graph(4, 16)
        decision_variables = (0, 4, 3)
        feasible_configurations = {(0, 0, 1): 0.}

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                ising_quadratic_ranges={
                                    0: {
                                        1: [0, 1],
                                        2: [-1, 0]
                                    },
                                    2: {
                                        0: [-1, 0]
                                    }
                                },
                                vartype=dimod.BINARY)

        ising_quadratic_ranges = spec.ising_quadratic_ranges
        for u in ising_quadratic_ranges:
            for v in ising_quadratic_ranges[u]:
                self.assertIs(ising_quadratic_ranges[u][v],
                              ising_quadratic_ranges[v][u])
        for u, v in graph.edges:
            self.assertIn(v, ising_quadratic_ranges[u])
            self.assertIn(u, ising_quadratic_ranges[v])

        self.assertEqual(ising_quadratic_ranges[0][1], [0, 1])
Ejemplo n.º 11
0
    def test_construction(self):

        # build a specification
        graph = nx.complete_graph(10)
        decision_variables = (0, 4, 5)
        feasible_configurations = {(-1, -1, -1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)

        # build a model
        model = pm.BinaryQuadraticModel({v: 0
                                         for v in graph},
                                        {edge: 0
                                         for edge in graph.edges},
                                        0.0,
                                        vartype=pm.Vartype.SPIN)

        # build a PenaltyModel explicitly
        pm0 = pm.PenaltyModel(graph, decision_variables,
                              feasible_configurations, pm.SPIN, model, .1, 0)

        # build from spec
        pm1 = pm.PenaltyModel.from_specification(spec, model, .1, 0)

        # should result in equality
        self.assertEqual(pm0, pm1)
Ejemplo n.º 12
0
    def test_bad_energy_range(self):
        graph = nx.path_graph(3)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)

        linear = {v: -3 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        with self.assertRaises(ValueError):
            widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        linear = {v: 0 for v in graph}
        quadratic = {edge: 5 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        with self.assertRaises(ValueError):
            widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)
Ejemplo n.º 13
0
    def test_retrieval(self):
        spec = pm.Specification(nx.path_graph(2), (0, 1), {(-1, -1), (1, 1)},
                                vartype=pm.SPIN)
        widget = pm.get_penalty_model(spec)

        self.assertEqual(widget.model.linear, {0: 0, 1: 0})
        self.assertEqual(widget.model.quadratic, {(0, 1): -1})
Ejemplo n.º 14
0
    def test_penalty_model_insert_retrieve(self):
        conn = self.clean_connection

        graph = nx.path_graph(3)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph, decision_variables,
                                feasible_configurations, pm.SPIN)

        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)

        widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        with conn as cur:
            pmc.insert_penalty_model(cur, widget)

        with conn as cur:
            pms = list(pmc.iter_penalty_model_from_specification(cur, spec))

            self.assertEqual(len(pms), 1)
            widget_, = pms
            self.assertEqual(widget_, widget)
Ejemplo n.º 15
0
    def test_construction_bad_graph(self):
        graph = 1
        decision_variables = (0, 4, 5)
        feasible_configurations = {(-1, -1, -1): 0.}

        with self.assertRaises(TypeError):
            pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.SPIN)
Ejemplo n.º 16
0
    def test_insert_retrieve(self):
        dbfile = self.database

        linear = {'1': 0.0, '0': -0.5, '3': 1.0, '2': -0.5}
        quadratic = {
            ('0', '3'): -1.0,
            ('1', '2'): 1.0,
            ('0', '2'): 0.5,
            ('1', '3'): 1.0
        }
        offset = 0.0
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        offset,
                                        vartype=pm.SPIN)

        graph = nx.Graph()
        graph.add_edges_from(quadratic)
        decision_variables = ('0', '2', '3')
        feasible_configurations = ((-1, -1, -1), (-1, 1, -1), (1, -1, -1),
                                   (1, 1, 1))
        spec = pm.Specification(graph, decision_variables,
                                feasible_configurations, pm.SPIN)

        classical_gap = 2
        ground = -2.5

        pmodel = pm.PenaltyModel.from_specification(spec, model, classical_gap,
                                                    ground)

        pmc.cache_penalty_model(pmodel, database=dbfile)

        # print(spec.feasible_configurations)
        # print(spec.decision_variables)

        # get it back
        ret_pmodel = pmc.get_penalty_model(spec, database=dbfile)

        # now get back one with a different decision_variables
        spec2 = pm.Specification(graph, ('3', '0', '2'),
                                 feasible_configurations, pm.SPIN)
        try:
            ret_pmodel = pmc.get_penalty_model(spec2, database=dbfile)
            self.assertNotEqual(ret_pmodel, pmodel)
        except:
            pass
Ejemplo n.º 17
0
    def test_relabel_inplace_overlap(self):
        graph = nx.circular_ladder_graph(12)
        decision_variables = (0, 2, 5)
        feasible_configurations = {(1, 1, 1): 0.}
        spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.SPIN)

        mapping = {v: v + 5 for v in graph}

        new_spec = spec.relabel_variables(mapping, copy=False)
Ejemplo n.º 18
0
    def test_typical(self):
        graph = nx.complete_graph(3)
        spec = pm.Specification(graph, [0, 1], {(-1, -1): 0, (+1, +1): 0}, pm.SPIN)

        widget = maxgap.get_penalty_model(spec)

        # some quick test to see that the penalty model propogated in
        for v in graph:
            self.assertIn(v, widget.model.linear)
        for (u, v) in graph.edges:
            self.assertIn(u, widget.model.adj[v])
Ejemplo n.º 19
0
    def test_construction_typical(self):
        graph = nx.complete_graph(10)
        decision_variables = (0, 4, 5)
        feasible_configurations = {(-1, -1, -1): 0.}

        spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.SPIN)

        self.assertEqual(spec.graph, graph)  # literally the same object
        self.assertEqual(spec.decision_variables, decision_variables)
        self.assertEqual(spec.feasible_configurations, feasible_configurations)
        self.assertIs(spec.vartype, pm.SPIN)
Ejemplo n.º 20
0
    def test_relabel(self):
        graph = nx.path_graph(3)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)
        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        # now set up the same widget with 0 relabelled to 'a'
        graph = nx.path_graph(3)
        graph = nx.relabel_nodes(graph, {0: 'a'})
        decision_variables = ('a', 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.SPIN)
        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        test_widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        # without copy
        new_widget = widget.relabel_variables({0: 'a'}, copy=True)
        self.assertEqual(test_widget, new_widget)
        self.assertEqual(new_widget.decision_variables, ('a', 2))

        widget.relabel_variables({0: 'a'}, copy=False)
        self.assertEqual(widget, test_widget)
        self.assertEqual(widget.decision_variables, ('a', 2))
Ejemplo n.º 21
0
    def test_ranges_default(self):
        graph = nx.barbell_graph(4, 16)
        decision_variables = (0, 4, 3)
        feasible_configurations = {(0, 0, 0): 0.}

        spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.BINARY)

        for v in graph:
            self.assertEqual(spec.ising_linear_ranges[v], [-2, 2])

        for u, v in graph.edges:
            self.assertEqual(spec.ising_quadratic_ranges[u][v], [-1, 1])
            self.assertEqual(spec.ising_quadratic_ranges[v][u], [-1, 1])
Ejemplo n.º 22
0
    def test_retrieval(self):
        # put some stuff in the database

        spec = pm.Specification(nx.path_graph(2), (0, 1), {(-1, -1), (1, 1)}, vartype=pm.SPIN)
        model = pm.BinaryQuadraticModel({0: 0, 1: 0}, {(0, 1): -1}, 0.0, vartype=pm.SPIN)
        widget = pm.PenaltyModel.from_specification(spec, model, 2, -1)

        for cache in pm.iter_caches():
            cache(widget)

        # now try to get it back
        new_widget = pm.get_penalty_model(spec)

        self.assertEqual(widget, new_widget)
Ejemplo n.º 23
0
    def test_bad_relabel(self):
        graph = nx.path_graph(4)
        graph.add_edge(0, 2)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph, decision_variables, feasible_configurations, vartype=pm.SPIN)

        mapping = {0: 2, 1: 1}

        with self.assertRaises(ValueError):
            spec.relabel_variables(mapping, copy=True)

        with self.assertRaises(ValueError):
            spec.relabel_variables(mapping, copy=False)
Ejemplo n.º 24
0
    def test_arbitrary_labels_on_k44(self):
        dbfile = self.database

        graph = nx.Graph()
        for i in range(3):
            for j in range(3, 6):
                graph.add_edge(i, j)

        decision_variables = (0, 5)
        feasible_configurations = ((0, 0), (1, 1))  # equality

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.BINARY)

        linear = {v: 0 for v in graph}
        quadratic = {edge: 0 for edge in graph.edges}
        if decision_variables in quadratic:
            quadratic[decision_variables] = -1
        else:
            u, v = decision_variables
            assert (v, u) in quadratic
            quadratic[(v, u)] = -1
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        pmodel = pm.PenaltyModel.from_specification(spec, model, 2, -1)

        # now cache the pmodel to make sure there is something to find

        for thingy in itertools.permutations(range(6)):
            mapping = dict(enumerate(thingy))
            pmodel = pmodel.relabel_variables(mapping, copy=True)
            pmc.cache_penalty_model(pmodel, database=dbfile)

        # now relabel some variables
        mapping = {1: '1', 2: '2', 3: '3', 4: '4'}

        new_spec = spec.relabel_variables(mapping)

        # retrieve from the new_spec
        # now try to retrieve it
        retreived_pmodel = pmc.get_penalty_model(new_spec, database=dbfile)
Ejemplo n.º 25
0
    def test_and_on_k44(self):
        graph = nx.Graph()
        for i in range(4):
            for j in range(4, 8):
                graph.add_edge(i, j)

        decision_variables = (0, 2, 3)
        feasible_configurations = AND(2)

        mapping = {0: '0', 1: '1', 2: '2', 3: '3'}
        graph = nx.relabel_nodes(graph, mapping)
        decision_variables = tuple(mapping[x] for x in decision_variables)

        spin_configurations = tuple([tuple([2 * i - 1 for i in b]) for b in feasible_configurations])
        spec = pm.Specification(graph, decision_variables, spin_configurations, vartype=pm.SPIN)

        pm0 = maxgap.get_penalty_model(spec)
        self.check_generated_ising_model(pm0.feasible_configurations, pm0.decision_variables,
                                         pm0.model.linear, pm0.model.quadratic, pm0.ground_energy,
                                         pm0.classical_gap)
Ejemplo n.º 26
0
    def test_binary_specification(self):
        dbfile = self.database

        # set up a specification and a corresponding penaltymodel
        graph = nx.Graph()
        for i in 'abcd':
            for j in 'efgh':
                graph.add_edge(i, j)

        decision_variables = ('a', 'e')
        feasible_configurations = ((0, 0), (1, 1))  # equality

        spec = pm.Specification(graph,
                                decision_variables,
                                feasible_configurations,
                                vartype=pm.BINARY)

        linear = {v: 0 for v in graph}
        quadratic = {edge: 0 for edge in graph.edges}
        if decision_variables in quadratic:
            quadratic[decision_variables] = -1
        else:
            u, v = decision_variables
            assert (v, u) in quadratic
            quadratic[(v, u)] = -1
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        pmodel = pm.PenaltyModel.from_specification(spec, model, 2, -1)

        # now cache the pmodel to make sure there is something to find
        pmc.cache_penalty_model(pmodel, database=dbfile)

        # now try to retrieve it
        retreived_pmodel = pmc.get_penalty_model(spec, database=dbfile)

        self.assertIs(retreived_pmodel.model.vartype, pm.BINARY)

        # check that the specification is equal to the retreived_pmodel
        self.assertTrue(spec.__eq__(retreived_pmodel))
def fault_model(gate_type):
    labels, configurations = GATES[gate_type]
    configurations = fault_gate(configurations, FAULT_GAP)
    size = len(next(iter(configurations)))
    while True:
        G = nx.complete_graph(size)
        nx.relabel_nodes(G, dict(enumerate(labels)), copy=False)
        spec = pm.Specification(G, labels, configurations, pm.SPIN)
        try:
            pmodel = pm.get_penalty_model(spec)
            if not pmodel:
                raise LookupError("failed to get penalty model from factory")
            # print("penalty model fits on K{}".format(size))
            break
        except pm.ImpossiblePenaltyModel:
            # print("penalty model does not fit on K{}".format(size))
            size += 1

    # print('h: {}'.format(pmodel.model.linear))
    # print('J: {}\n'.format(pmodel.model.quadratic))
    return pmodel
Ejemplo n.º 28
0
    def test_typical(self):
        dbfile = self.database

        # insert a penalty model
        graph = nx.path_graph(3)
        decision_variables = (0, 2)
        feasible_configurations = {(-1, -1): 0., (+1, +1): 0.}
        spec = pm.Specification(graph, decision_variables,
                                feasible_configurations, pm.SPIN)
        linear = {v: 0 for v in graph}
        quadratic = {edge: -1 for edge in graph.edges}
        model = pm.BinaryQuadraticModel(linear,
                                        quadratic,
                                        0.0,
                                        vartype=pm.SPIN)
        widget = pm.PenaltyModel.from_specification(spec, model, 2., -2)

        # cache the penaltymodel
        pmc.cache_penalty_model(widget, database=dbfile)

        # retrieve it
        widget_ = pmc.get_penalty_model(spec, database=dbfile)

        self.assertEqual(widget_, widget)
Ejemplo n.º 29
0
def stitch(csp, min_classical_gap=2.0, max_graph_size=8):
    """Build a binary quadratic model with minimal energy levels at solutions to the specified constraint satisfaction
    problem.

    Args:
        csp (:obj:`.ConstraintSatisfactionProblem`):
            Constraint satisfaction problem.

        min_classical_gap (float, optional, default=2.0):
            Minimum energy gap from ground. Each constraint violated by the solution increases
            the energy level of the binary quadratic model by at least this much relative
            to ground energy.

        max_graph_size (int, optional, default=8):
            Maximum number of variables in the binary quadratic model that can be used to
            represent a single constraint.

    Returns:
        :class:`~dimod.BinaryQuadraticModel`

    Notes:
        For a `min_classical_gap` > 2 or constraints with more than two variables, requires
        access to factories from the penaltymodel_ ecosystem to construct the binary quadratic
        model.

    .. _penaltymodel: https://github.com/dwavesystems/penaltymodel

    Examples:
        This example creates a binary-valued constraint satisfaction problem
        with two constraints, :math:`a = b` and :math:`b \\ne c`, and builds
        a binary quadratic model with a minimum energy level of -2 such that
        each constraint violation by a solution adds the default minimum energy gap.

        >>> import dwavebinarycsp
        >>> import operator
        >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY)
        >>> csp.add_constraint(operator.eq, ['a', 'b'])  # a == b
        >>> csp.add_constraint(operator.ne, ['b', 'c'])  # b != c
        >>> bqm = dwavebinarycsp.stitch(csp)
        >>> bqm.energy({'a': 0, 'b': 0, 'c': 1})  # satisfies csp
        -2.0
        >>> bqm.energy({'a': 0, 'b': 0, 'c': 0})  # violates one constraint
        0.0
        >>> bqm.energy({'a': 1, 'b': 0, 'c': 0}) # violates two constraints
        2.0

        This example creates a binary-valued constraint satisfaction problem
        with two constraints, :math:`a = b` and :math:`b \\ne c`, and builds
        a binary quadratic model with a minimum energy gap of 4.
        Note that in this case the conversion to binary quadratic model adds two
        ancillary variables that must be minimized over when solving.

        >>> import dwavebinarycsp
        >>> import operator
        >>> import itertools
        >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY)
        >>> csp.add_constraint(operator.eq, ['a', 'b'])  # a == b
        >>> csp.add_constraint(operator.ne, ['b', 'c'])  # b != c
        >>> bqm = dwavebinarycsp.stitch(csp, min_classical_gap=4.0)
        >>> list(bqm)   # # doctest: +SKIP
        ['a', 'aux1', 'aux0', 'b', 'c']
        >>> min([bqm.energy({'a': 0, 'b': 0, 'c': 1, 'aux0': aux0, 'aux1': aux1}) for
        ... aux0, aux1 in list(itertools.product([0, 1], repeat=2))])  # satisfies csp
        -6.0
        >>> min([bqm.energy({'a': 0, 'b': 0, 'c': 0, 'aux0': aux0, 'aux1': aux1}) for
        ... aux0, aux1 in list(itertools.product([0, 1], repeat=2))])  # violates one constraint
        -2.0
        >>> min([bqm.energy({'a': 1, 'b': 0, 'c': 0, 'aux0': aux0, 'aux1': aux1}) for
        ... aux0, aux1 in list(itertools.product([0, 1], repeat=2))])  # violates two constraints
        2.0

        This example finds for the previous example the minimum graph size.

        >>> import dwavebinarycsp
        >>> import operator
        >>> csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY)
        >>> csp.add_constraint(operator.eq, ['a', 'b'])  # a == b
        >>> csp.add_constraint(operator.ne, ['b', 'c'])  # b != c
        >>> for n in range(8, 1, -1):
        ...     try:
        ...         bqm = dwavebinarycsp.stitch(csp, min_classical_gap=4.0, max_graph_size=n)
        ...     except dwavebinarycsp.exceptions.ImpossibleBQM:
        ...         print(n+1)
        ...
        3

    """
    def aux_factory():
        for i in count():
            yield 'aux{}'.format(i)

    aux = aux_factory()

    bqm = dimod.BinaryQuadraticModel.empty(csp.vartype)

    # developer note: we could cache them and relabel, for now though let's do the simple thing
    # penalty_models = {}
    for const in csp.constraints:
        configurations = const.configurations

        if len(const.variables) > max_graph_size:
            msg = (
                "The given csp contains a constraint {const} with {num_var} variables. "
                "This cannot be mapped to a graph with {max_graph_size} nodes. "
                "Consider checking whether your constraint is irreducible."
                "").format(const=const,
                           num_var=len(const.variables),
                           max_graph_size=max_graph_size)
            raise ImpossibleBQM(msg)

        pmodel = None

        if len(const) == 0:
            # empty constraint
            continue

        if min_classical_gap <= 2.0:
            if len(const) == 1 and max_graph_size >= 1:
                bqm.update(_bqm_from_1sat(const))
                continue
            elif len(const) == 2 and max_graph_size >= 2:
                bqm.update(_bqm_from_2sat(const))
                continue

        # developer note: we could cache them and relabel, for now though let's do the simple thing
        # if configurations in penalty_models:
        #     raise NotImplementedError

        for G in iter_complete_graphs(const.variables, max_graph_size + 1,
                                      aux):

            # construct a specification
            spec = pm.Specification(graph=G,
                                    decision_variables=const.variables,
                                    feasible_configurations=configurations,
                                    vartype=csp.vartype)

            # try to use the penaltymodel ecosystem
            try:
                pmodel = pm.get_penalty_model(spec)
            except pm.ImpossiblePenaltyModel:
                # hopefully adding more variables will make it possible
                continue

            if pmodel.classical_gap >= min_classical_gap:
                break

        # developer note: we could cache them and relabel, for now though let's do the simple thing
        # penalty_models[configurations] = pmodel

        if pmodel is None:
            msg = ("No penalty model can be build for constraint {}".format(
                const))
            raise ImpossibleBQM(msg)

        bqm.update(pmodel.model)

    return bqm
Ejemplo n.º 30
0
 def test_construction_empty(self):
     spec = pm.Specification(nx.Graph(), [], {}, pm.SPIN)
     self.assertEqual(len(spec), 0)