Skip to content

Commit

Permalink
Merge pull request #190 from randomir/remove-int-ident
Browse files Browse the repository at this point in the history
Remove interruptable identity
  • Loading branch information
randomir committed Aug 23, 2019
2 parents c733a46 + ee84c2d commit 1687c4a
Show file tree
Hide file tree
Showing 11 changed files with 32 additions and 28 deletions.
1 change: 0 additions & 1 deletion README.rst
Expand Up @@ -80,7 +80,6 @@ Example
# Define the workflow
iteration = hybrid.RacingBranches(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
hybrid.EnergyImpactDecomposer(size=2)
| hybrid.QPUSubproblemAutoEmbeddingSampler()
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/flow.rst
Expand Up @@ -17,7 +17,7 @@ Classes
.. autoclass:: Const
.. autoclass:: Dup
.. autoclass:: Identity
.. autofunction:: InterruptableIdentity
.. autoclass:: BlockingIdentity
.. autoclass:: Lambda
.. autoclass:: Loop
.. autoclass:: LoopUntilNoImprovement
Expand Down
1 change: 0 additions & 1 deletion examples/hybrid-sampler.py
Expand Up @@ -31,7 +31,6 @@
# define the workflow
workflow = hybrid.Loop(
hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
hybrid.EnergyImpactDecomposer(size=50, rolling=True, traversal='bfs')
| hybrid.QPUSubproblemAutoEmbeddingSampler()
Expand Down
1 change: 0 additions & 1 deletion examples/nested-branches.py
Expand Up @@ -31,7 +31,6 @@

# construct a workflow that races Simulated Annealing against SA/Tabu on a subproblem
iteration = hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.SimulatedAnnealingProblemSampler(),
hybrid.EnergyImpactDecomposer(size=50)
| hybrid.RacingBranches(
Expand Down
3 changes: 1 addition & 2 deletions examples/qbsolv-like-alt.py
Expand Up @@ -52,10 +52,9 @@ def merge_substates(_, substates):
subsampler = hybrid.Parallel(qpu, random) | hybrid.ArgMin()

iteration = hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
subproblems | subsampler
) | hybrid.ArgMin()
) | hybrid.ArgMin() | hybrid.TrackMin(output=True)

main = hybrid.Loop(iteration, max_iter=10, convergence=3)

Expand Down
3 changes: 1 addition & 2 deletions examples/qbsolv-like.py
Expand Up @@ -30,12 +30,11 @@

# define the workflow
iteration = hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
hybrid.EnergyImpactDecomposer(size=50, rolling=True, rolling_history=0.15)
| hybrid.QPUSubproblemAutoEmbeddingSampler()
| hybrid.SplatComposer()
) | hybrid.ArgMin()
) | hybrid.ArgMin() | hybrid.TrackMin(output=True)

main = hybrid.Loop(iteration, max_iter=10, convergence=3)

Expand Down
1 change: 0 additions & 1 deletion examples/tabu-postprocessing.py
Expand Up @@ -30,7 +30,6 @@

# run Tabu in parallel with QPU, but post-process QPU samples with very short Tabu
iteration = hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
hybrid.EnergyImpactDecomposer(size=50)
| hybrid.QPUSubproblemAutoEmbeddingSampler(num_reads=100)
Expand Down
29 changes: 20 additions & 9 deletions hybrid/flow.py
Expand Up @@ -31,7 +31,7 @@
'Branch', 'Branches', 'RacingBranches', 'Race', 'ParallelBranches', 'Parallel',
'Map', 'Reduce', 'Lambda', 'ArgMin', 'Unwind', 'TrackMin',
'Loop', 'LoopUntilNoImprovement', 'LoopWhileNoImprovement',
'Identity', 'InterruptableIdentity', 'Dup', 'Const', 'Wait'
'Identity', 'BlockingIdentity', 'Dup', 'Const', 'Wait'
]

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -649,14 +649,18 @@ class TrackMin(traits.NotValidated, Runnable):
If `output=True`, then this defines the variable/key name in the
input state that shall be included in the output state.
output_key (str, optional, default='best_samples')
output_key (str, optional, default='samples')
If `output=True`, then the key under which the `input_key` from the
best state seen so far is stored in the output state.
Note:
If `output` option is turned on, and `output_key` is not changed, the
output will by default change the state's `samples` on output.
"""

def __init__(self, key=None, output=False, input_key='samples',
output_key='best_samples', **runopts):
output_key='samples', **runopts):
super(TrackMin, self).__init__(**runopts)
if key is None:
key = 'samples.first.energy'
Expand Down Expand Up @@ -1018,13 +1022,20 @@ def next(self, state, **runopts):
return state.updated()


def InterruptableIdentity(**runopts):
"""Trivial interruptable identity runnable. The output is a direct copy of
the input, with a distinction from :class:`.Identity` that it will halt
until explicitly stopped (useful for example in :class:`.RacingBranches`
to prevent short-circuiting of racing branches with the identity branch).
class BlockingIdentity(Wait):
"""Trivial identity runnable that blocks indefinitely before producing
output, but is interruptable. The output is a direct copy of
the input, but to receive the output, the block has to be explicitly stopped
(useful for example in :class:`.RacingBranches` to prevent short-circuiting
of racing branches with the identity branch).
::
BlockingIdentity := Identity | Wait
Due to nature of :class:`.Identity`, :class:`.BlockingIdentity` is
functionally equivalent to :class:`.Wait`.
"""
return Identity(**runopts) | Wait(**runopts)


class Const(traits.NotValidated, Runnable):
Expand Down
2 changes: 1 addition & 1 deletion hybrid/reference/kerberos.py
Expand Up @@ -89,7 +89,7 @@ def Kerberos(max_iter=100, max_time=None, convergence=3, energy_threshold=None,
energy_reached = lambda en: en <= energy_threshold

iteration = hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.BlockingIdentity(),
hybrid.InterruptableTabuSampler(
timeout=tabu_timeout),
hybrid.InterruptableSimulatedAnnealingProblemSampler(
Expand Down
3 changes: 1 addition & 2 deletions hybrid/reference/qbsolv.py
Expand Up @@ -34,13 +34,12 @@ def SimplifiedQbsolv(max_iter=10, max_time=None, convergence=3,

workflow = hybrid.Loop(
hybrid.Race(
hybrid.InterruptableIdentity(),
hybrid.InterruptableTabuSampler(),
hybrid.EnergyImpactDecomposer(
size=max_subproblem_size, rolling=True, rolling_history=0.15)
| hybrid.QPUSubproblemAutoEmbeddingSampler()
| hybrid.SplatComposer()
) | hybrid.ArgMin(),
) | hybrid.ArgMin() | hybrid.TrackMin(output=True),
max_iter=max_iter, max_time=max_time,
convergence=convergence, terminate=energy_reached)

Expand Down
14 changes: 7 additions & 7 deletions tests/test_flow.py
Expand Up @@ -27,7 +27,7 @@
Branch, Branches, RacingBranches, ParallelBranches,
ArgMin, Map, Reduce, Lambda, Unwind, TrackMin,
LoopUntilNoImprovement, LoopWhileNoImprovement, SimpleIterator, Loop,
Identity, InterruptableIdentity, Dup, Const, Wait
Identity, BlockingIdentity, Dup, Const, Wait
)
from hybrid.core import State, States, Runnable, Present
from hybrid.utils import min_sample, max_sample
Expand Down Expand Up @@ -272,7 +272,7 @@ def halt(self):
self.assertEqual([s.x for s in res], [2, 1, 2])

# "endomorphic case"
rb = RacingBranches(InterruptableIdentity(), Slow(), Fast(), Slow())
rb = RacingBranches(BlockingIdentity(), Slow(), Fast(), Slow())
res = rb.run(State(x=0)).result()
self.assertEqual([s.x for s in res], [0, 2, 1, 2])

Expand Down Expand Up @@ -872,10 +872,10 @@ def test_input_type_invariant(self):
self.assertEqual(Identity().run(inp2).result(), inp2)


class TestInterruptableIdentity(unittest.TestCase):
class TestBlockingIdentity(unittest.TestCase):

def test_basic(self):
ident = InterruptableIdentity()
ident = BlockingIdentity()
state = State(x=1, y='a', z=[1,2,3])

inp = copy.deepcopy(state)
Expand All @@ -887,7 +887,7 @@ def test_basic(self):
self.assertFalse(out is inp)

def test_interruptable(self):
ident = InterruptableIdentity()
ident = BlockingIdentity()
state = State(x=1)
out = ident.run(state)

Expand All @@ -907,14 +907,14 @@ def test_interruptable(self):

def test_input_type_invariant(self):
inp = State(x=1)
ii = InterruptableIdentity()
ii = BlockingIdentity()
fut = ii.run(inp)
ii.stop()
out = fut.result()
self.assertEqual(out, inp)

inp = States(State(x=1), State(x=2))
ii = InterruptableIdentity()
ii = BlockingIdentity()
fut = ii.run(inp)
ii.stop()
out = fut.result()
Expand Down

0 comments on commit 1687c4a

Please sign in to comment.