Пример #1
0
    def test_nontrivial_subproblem(self):
        """Check multi-variable multi-coupler subproblem creation.

        A 3by3 square lattice, with a 2x2 lattice subsolver, is the simplest 
        non-trivial test with edges in the decomposed problem.
        """
        problem_dims = (3, 3)
        #Vertical edges
        edgelist = [((i, j), (i + 1, j)) for i in range(problem_dims[0] - 1)
                    for j in range(problem_dims[1])]
        #Horizontal edges
        edgelist += [((i, j), (i, j + 1)) for i in range(problem_dims[0])
                     for j in range(problem_dims[1] - 1)]
        bqm = dimod.BinaryQuadraticModel.from_ising(
            {}, {edge: 1
                 for edge in edgelist})
        origin_embeddings = [{(i, j): None
                              for i in range(2) for j in range(2)}]
        state = State.from_sample(min_sample(bqm),
                                  bqm,
                                  origin_embeddings=origin_embeddings,
                                  problem_dims=problem_dims)

        # Creates one of 3x3 different subsubproblems, some of which are
        # disconnected, and some connected
        # Run multiple times to prevent coincidental agreement
        runnable = SublatticeDecomposer()
        for _ in range(10):
            state = runnable.next(state)
            self.assertEqual(len(state.subproblem.variables), 4)
            self.assertIn(next(iter(state.subproblem.variables)),
                          bqm.variables)
            self.assertEqual(len(state.embedding), 4)
            self.assertIn(next(iter(state.embedding.keys())), bqm.variables)
Пример #2
0
    def test_next_on_different_sized_constraints(self):
        bqm = dimod.BinaryQuadraticModel.empty(dimod.SPIN)

        variables = list('abcdefg')
        fixed_variables = list('abc')
        size = 3
        constraints = []

        # Set BQM and constraints of varying lengths
        for triplet in itertools.combinations(variables, size):
            for u, v in itertools.combinations(triplet, 2):
                bqm.add_interaction(u, v, -1)
            non_fixed_variables = set(triplet) - set(fixed_variables)
            constraints.append(non_fixed_variables)

        for fixed_variable in fixed_variables:
            bqm.fix_variable(fixed_variable, 1)

        # Get new state
        rcd = RandomConstraintDecomposer(size, constraints)
        state = State.from_sample(min_sample(bqm), bqm)
        newstate = rcd.run(state).result()

        self.assertIn('subproblem', newstate)
        self.assertTrue(len(newstate.subproblem) <= size)  # correct size
Пример #3
0
    def sample(self, bqm, initial_sample=None):
        """Sample from a binary quadratic model using composed runnable sampler.

        Args:
            bqm (:obj:`~dimod.BinaryQuadraticModel`):
                Binary quadratic model to be sampled from.

            initial_sample (dict, default=None):
                `bqm`-compatible sample used for initial state construction.
                Defaults to `hybrid.utils.min_sample(bqm)`.

        Returns:
            :obj:`~dimod.Response`: A `dimod` :obj:`.~dimod.Response` object.

        """
        if not isinstance(bqm, dimod.BinaryQuadraticModel):
            raise TypeError("'bqm' should be BinaryQuadraticModel")

        if initial_sample is None:
            initial_sample = min_sample(bqm)
        else:
            initial_sample = sample_as_dict(initial_sample)

        if len(initial_sample) != len(bqm):
            raise ValueError(
                "size of 'initial_sample' incompatible with 'bqm'")

        initial_state = State.from_sample(initial_sample, bqm)
        final_state = self._runnable_solver.run(initial_state)

        return dimod.Response.from_future(
            final_state, result_hook=lambda f: f.result().samples)
Пример #4
0
    def test_trivial_subproblem(self):
        """Check single-variable no-coupler subproblem creation.

        A 2by2 square lattice (a square), with a single variable subsolver,
        is the simplest non-trivial test.
        """

        problem_dims = (2, 2)
        # Vertical edges
        edgelist = [((i, j), (i + 1, j)) for i in range(problem_dims[0] - 1)
                    for j in range(problem_dims[1])]
        # Horizontal edges
        edgelist += [((i, j), (i, j + 1)) for i in range(problem_dims[0])
                     for j in range(problem_dims[1] - 1)]
        bqm = dimod.BinaryQuadraticModel.from_ising(
            {}, {edge: 1
                 for edge in edgelist})
        origin_embeddings = [{(0, 0): [0]}]
        state = State.from_sample(min_sample(bqm),
                                  bqm,
                                  origin_embeddings=origin_embeddings,
                                  problem_dims=problem_dims)

        # Creates subproblems located randomly at (0, 0), (0, 1), (1, 0) and
        # (1, 1).
        runnable = SublatticeDecomposer()
        for _ in range(10):
            state = runnable.next(state)
            self.assertEqual(len(state.subproblem.variables), 1)
            self.assertIn(next(iter(state.subproblem.variables)),
                          bqm.variables)
            self.assertEqual(len(state.embedding), 1)
            self.assertIn(next(iter(state.embedding.keys())), bqm.variables)
Пример #5
0
def run(problems, solver_factories):
    results = OrderedDict()

    # reuse the cloud client
    qpu = EmbeddingComposite(DWaveSampler())

    for problem in problems:
        results[problem] = OrderedDict()

        with open(problem) as fp:
            bqm = dimod.BinaryQuadraticModel.from_coo(fp)

        for name, factory in solver_factories:
            case = '{!r} with {!r}'.format(problem, name)

            try:
                solver = factory(qpu=qpu)
                init_state = State.from_sample(min_sample(bqm), bqm)

                with tictoc(case) as timer:
                    solution = solver.run(init_state).result()

            except Exception as exc:
                print("FAILED {case}: {exc!r}".format(**locals()))
                results[problem][name] = repr(exc)

            else:
                print("case={case!r}"
                      " energy={solution.samples.first.energy!r},"
                      " wallclock={timer.dt!r}".format(**locals()))
                results[problem][name] = dict(
                    energy=solution.samples.first.energy, wallclock=timer.dt)
Пример #6
0
    def test_basic(self):
        bqm = dimod.BinaryQuadraticModel({}, {'ab': 1, 'bc': -1, 'ca': 1}, 0, dimod.SPIN)
        state = State.from_sample(min_sample(bqm), bqm)
        antistate = State.from_sample(max_sample(bqm), bqm)

        result = GreedyPathMerge().run(States(state, antistate)).result()

        self.assertEqual(result.samples.first.energy, -3.0)
Пример #7
0
 def test_default_fold(self):
     bqm = dimod.BinaryQuadraticModel({'a': 1}, {}, 0, dimod.SPIN)
     states = States(
         State.from_sample(min_sample(bqm), bqm),  # energy: -1
         State.from_sample(max_sample(bqm), bqm),  # energy: +1
     )
     best = ArgMin().run(states).result()
     self.assertEqual(best.samples.first.energy, -1)
Пример #8
0
    def sample(self, bqm, initial_sample=None, return_state=False, **params):
        """Sample from a binary quadratic model using composed runnable sampler.

        Args:
            bqm (:obj:`~dimod.BinaryQuadraticModel`):
                Binary quadratic model to be sampled from.

            initial_sample (dict, default=None):
                `bqm`-compatible sample used for initial state construction.
                Defaults to `hybrid.utils.min_sample(bqm)`.

            return_state (bool, optional, default=False):
                If True, the final state is added to :attr:`dimod.SampleSet.info`
                of the returned sample set. Note that if a `state` key
                already exists in the sample set then it is overwritten.

            **params (dict):
                Sampling parameters passed down to the underlying workflow as
                run-time parameters.

        Note:
            Sampling via hybrid workflow is run asynchronously, and a sample set
            is returned as soon as workflow starts running. A blocking result
            resolve occurres on the first attribute access to the returned
            sample set.

        Returns:
            :class:`~dimod.SampleSet`:
                Possibly yet unresolved sample set.

        """
        if not isinstance(bqm, dimod.BinaryQuadraticModel):
            raise TypeError("'bqm' should be BinaryQuadraticModel")

        if initial_sample is None:
            initial_sample = min_sample(bqm)
        else:
            initial_sample = sample_as_dict(initial_sample)

        if len(initial_sample) != len(bqm):
            raise ValueError(
                "size of 'initial_sample' incompatible with 'bqm'")

        initial_state = State.from_sample(initial_sample, bqm)
        final_state = self._workflow.run(initial_state, **params)

        def result_hook(state):
            resolved = state.result()
            ss = resolved.samples
            if return_state:
                # note: this creates a cyclic reference to `samples` from the
                # sample set via `info['state']`, but that shouldn't be a
                # problem for GC
                ss.info.update(state=resolved)
            return ss

        return dimod.SampleSet.from_future(final_state,
                                           result_hook=result_hook)
Пример #9
0
 def test_custom_fold(self):
     bqm = dimod.BinaryQuadraticModel({'a': 1}, {}, 0, dimod.SPIN)
     states = States(
         State.from_sample(min_sample(bqm), bqm),  # energy: -1
         State.from_sample(max_sample(bqm), bqm),  # energy: +1
     )
     fold = ArgMin(key=lambda s: -s.samples.first.energy)
     best = fold.run(states).result()
     self.assertEqual(best.samples.first.energy, 1)
Пример #10
0
class TestHybridRunnable(unittest.TestCase):
    bqm = dimod.BinaryQuadraticModel({}, {
        'ab': 1,
        'bc': 1,
        'ca': -1
    }, 0, dimod.SPIN)
    init_state = State.from_sample(min_sample(bqm), bqm)

    def test_generic(self):
        runnable = HybridRunnable(TabuSampler(), fields=('problem', 'samples'))
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_validation(self):
        with self.assertRaises(TypeError):
            HybridRunnable(1, 'ab')

        with self.assertRaises(ValueError):
            HybridRunnable(TabuSampler(), None)

        with self.assertRaises(ValueError):
            HybridRunnable(TabuSampler(), ('a'))

        self.assertIsInstance(HybridRunnable(TabuSampler(), 'ab'),
                              HybridRunnable)
        self.assertIsInstance(HybridRunnable(TabuSampler(), ('a', 'b')),
                              HybridRunnable)
        self.assertIsInstance(HybridRunnable(TabuSampler(), ['a', 'b']),
                              HybridRunnable)

    def test_problem_sampler_runnable(self):
        runnable = HybridProblemRunnable(TabuSampler())
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_subproblem_sampler_runnable(self):
        runnable = HybridSubproblemRunnable(TabuSampler())
        state = self.init_state.updated(subproblem=self.bqm)
        response = runnable.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().subsamples.record[0].energy, -3.0)

    def test_runnable_composition(self):
        runnable = IdentityDecomposer() | HybridSubproblemRunnable(
            TabuSampler()) | IdentityComposer()
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)
Пример #11
0
    def test_racing_workflow_with_oracle_subsolver(self):
        workflow = hybrid.LoopUntilNoImprovement(hybrid.RacingBranches(
            hybrid.InterruptableTabuSampler(),
            hybrid.EnergyImpactDecomposer(size=1)
            | HybridSubproblemRunnable(dimod.ExactSolver())
            | hybrid.SplatComposer()) | hybrid.ArgMin(),
                                                 convergence=3)
        state = State.from_sample(min_sample(self.bqm), self.bqm)
        response = workflow.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)
Пример #12
0
    def test_custom_key(self):
        """Custom key function works, here best state has the highest energy."""

        bqm = dimod.BinaryQuadraticModel({'a': 1}, {}, 0, dimod.SPIN)
        states = States(
            State.from_sample(min_sample(bqm), bqm),  # energy: -1
            State.from_sample(max_sample(bqm), bqm),  # energy: +1
        )

        tracker = TrackMin(key=lambda s: -s.samples.first.energy)
        for state in states:
            tracker.run(state).result()
        self.assertEqual(tracker.best.samples.first.energy, +1)
Пример #13
0
    def test_default_tracking(self):
        """Best seen state is kept (default: state with sampleset with the lowest energy)"""

        bqm = dimod.BinaryQuadraticModel({'a': 1}, {}, 0, dimod.SPIN)
        min_state = State.from_sample(min_sample(bqm), bqm)  # energy: -1
        max_state = State.from_sample(max_sample(bqm), bqm)  # energy: +1

        tracker = TrackMin()
        _ = tracker.run(max_state).result()
        self.assertEqual(tracker.best.samples.first.energy, +1)
        _ = tracker.run(min_state).result()
        self.assertEqual(tracker.best.samples.first.energy, -1)
        _ = tracker.run(max_state).result()
        self.assertEqual(tracker.best.samples.first.energy, -1)
Пример #14
0
class TestRandomSubproblemDecomposer(unittest.TestCase):
    bqm = dimod.BinaryQuadraticModel({}, {'ab': 1, 'bc': 1}, 0, dimod.SPIN)
    state = State.from_sample(min_sample(bqm), bqm)

    def test_simple(self):
        runnable = RandomSubproblemDecomposer(size=1)
        state = self.state
        for _ in range(10):
            state = runnable.next(state)
            self.assertEqual(len(state.subproblem.variables), 1)
            self.assertIn(next(iter(state.subproblem.variables)),
                          self.bqm.variables)

    def test_look_and_feel(self):
        self.assertEqual(repr(RandomSubproblemDecomposer(7)),
                         'RandomSubproblemDecomposer(size=7)')
Пример #15
0
    def test_typical_construction(self):
        bqm = dimod.BinaryQuadraticModel.empty(dimod.SPIN)

        variables = list('abcdefg')
        constraints = []
        for triplet in itertools.combinations(variables, 3):
            for u, v in itertools.combinations(triplet, 2):
                bqm.add_interaction(u, v, -1)
            constraints.append(triplet)

        rcd = RandomConstraintDecomposer(3, constraints)
        rcd.init(state=State.from_sample(min_sample(bqm), bqm))

        # check that the graph is complete
        G = rcd.constraint_graph
        for i in range(len(constraints)):
            self.assertIn(i, G.nodes)
Пример #16
0
    def test_next(self):
        bqm = dimod.BinaryQuadraticModel.empty(dimod.SPIN)

        variables = list('abcdefg')
        constraints = []
        for triplet in itertools.combinations(variables, 3):
            for u, v in itertools.combinations(triplet, 2):
                bqm.add_interaction(u, v, -1)
            constraints.append(triplet)

        rcd = RandomConstraintDecomposer(3, constraints)

        state = State.from_sample(min_sample(bqm), bqm)

        newstate = rcd.run(state).result()

        self.assertIn('subproblem', newstate)
        self.assertTrue(len(newstate.subproblem) <= 3)  # correct size
Пример #17
0
    def test_sampling_parameters_filtering(self):
        class Sampler(dimod.ExactSolver):
            """Exact solver that fails if a sampling parameter is provided."""
            parameters = {}

            def sample(self, bqm):
                return super().sample(bqm)

        workflow = hybrid.LoopUntilNoImprovement(hybrid.RacingBranches(
            hybrid.InterruptableTabuSampler(),
            hybrid.EnergyImpactDecomposer(size=1)
            | HybridSubproblemRunnable(Sampler())
            | hybrid.SplatComposer()) | hybrid.ArgMin(),
                                                 convergence=3)
        state = State.from_sample(min_sample(self.bqm), self.bqm)
        response = workflow.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)
Пример #18
0
    def test_exclude_dimensions(self):
        """Check exclude_dims parameter at origin_embedding_index=0.

        If all dimensions are excluded, ``embedding`` field should match the 
        ``origin_embedding``.
        """
        problem_dims = (3, 3)
        # Vertical edges
        edgelist = [((i, j), (i + 1, j)) for i in range(problem_dims[0] - 1)
                    for j in range(problem_dims[1])]
        # Horizontal edges
        edgelist += [((i, j), (i, j + 1)) for i in range(problem_dims[0])
                     for j in range(problem_dims[1] - 1)]
        bqm = dimod.BinaryQuadraticModel.from_ising(
            {}, {edge: 1
                 for edge in edgelist})
        origin_embeddings = [{(i, j): None
                              for i in range(2) for j in range(2)}]
        exclude_dims = list(range(len(problem_dims)))
        oei = 0
        state = State.from_sample(min_sample(bqm),
                                  bqm,
                                  origin_embeddings=origin_embeddings,
                                  problem_dims=problem_dims,
                                  exclude_dims=exclude_dims,
                                  origin_embedding_index=oei)

        # Creates a 2x2 subproblem at the origin for 0th embedding
        # Run multiple times to prevent coincidental agreement
        runnable = SublatticeDecomposer()
        for _ in range(10):
            state = runnable.next(state)
            self.assertEqual(len(state.subproblem.variables), 4)
            self.assertIn(next(iter(state.subproblem.variables)),
                          bqm.variables)
            self.assertEqual(len(state.embedding), 4)
            self.assertIn(next(iter(state.embedding.keys())), bqm.variables)
            self.assertIn(next(iter(state.embedding)),
                          state.origin_embeddings[oei])
Пример #19
0
import dimod

from hybrid.samplers import (QPUSubproblemAutoEmbeddingSampler,
                             InterruptableTabuSampler)
from hybrid.decomposers import EnergyImpactDecomposer
from hybrid.composers import SplatComposer
from hybrid.core import State
from hybrid.flow import RacingBranches, ArgMin, Loop
from hybrid.utils import min_sample

# load a problem
problem = sys.argv[1]
with open(problem) as fp:
    bqm = dimod.BinaryQuadraticModel.from_coo(fp)

# define the solver
iteration = RacingBranches(
    InterruptableTabuSampler(),
    EnergyImpactDecomposer(max_size=50, rolling=True, rolling_history=0.15)
    | QPUSubproblemAutoEmbeddingSampler()
    | SplatComposer()) | ArgMin()
main = Loop(iteration, max_iter=10, convergence=3)

# run solver
init_state = State.from_sample(min_sample(bqm), bqm)
solution = main.run(init_state).result()

# show results
print("Solution: sample={s.samples.first}".format(s=solution))
Пример #20
0
class TestHybridRunnable(unittest.TestCase):
    bqm = dimod.BinaryQuadraticModel({}, {
        'ab': 1,
        'bc': 1,
        'ca': -1
    }, 0, dimod.SPIN)
    init_state = State.from_sample(min_sample(bqm), bqm)

    def test_generic(self):
        runnable = HybridRunnable(TabuSampler(), fields=('problem', 'samples'))
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_validation(self):
        with self.assertRaises(TypeError):
            HybridRunnable(1, 'ab')

        with self.assertRaises(ValueError):
            HybridRunnable(TabuSampler(), None)

        with self.assertRaises(ValueError):
            HybridRunnable(TabuSampler(), ('a'))

        self.assertIsInstance(HybridRunnable(TabuSampler(), 'ab'),
                              HybridRunnable)
        self.assertIsInstance(HybridRunnable(TabuSampler(), ('a', 'b')),
                              HybridRunnable)
        self.assertIsInstance(HybridRunnable(TabuSampler(), ['a', 'b']),
                              HybridRunnable)

    def test_problem_sampler_runnable(self):
        runnable = HybridProblemRunnable(TabuSampler())
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_subproblem_sampler_runnable(self):
        runnable = HybridSubproblemRunnable(TabuSampler())
        state = self.init_state.updated(subproblem=self.bqm)
        response = runnable.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().subsamples.record[0].energy, -3.0)

    def test_runnable_composition(self):
        runnable = IdentityDecomposer() | HybridSubproblemRunnable(
            TabuSampler()) | IdentityComposer()
        response = runnable.run(self.init_state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_racing_workflow_with_oracle_subsolver(self):
        workflow = hybrid.LoopUntilNoImprovement(hybrid.RacingBranches(
            hybrid.InterruptableTabuSampler(),
            hybrid.EnergyImpactDecomposer(size=1)
            | HybridSubproblemRunnable(dimod.ExactSolver())
            | hybrid.SplatComposer()) | hybrid.ArgMin(),
                                                 convergence=3)
        state = State.from_sample(min_sample(self.bqm), self.bqm)
        response = workflow.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)

    def test_sampling_parameters_filtering(self):
        class Sampler(dimod.ExactSolver):
            """Exact solver that fails if a sampling parameter is provided."""
            parameters = {}

            def sample(self, bqm):
                return super().sample(bqm)

        workflow = hybrid.LoopUntilNoImprovement(hybrid.RacingBranches(
            hybrid.InterruptableTabuSampler(),
            hybrid.EnergyImpactDecomposer(size=1)
            | HybridSubproblemRunnable(Sampler())
            | hybrid.SplatComposer()) | hybrid.ArgMin(),
                                                 convergence=3)
        state = State.from_sample(min_sample(self.bqm), self.bqm)
        response = workflow.run(state)

        self.assertIsInstance(response, concurrent.futures.Future)
        self.assertEqual(response.result().samples.record[0].energy, -3.0)