dimod.unembed_response

unembed_response(target_response, embedding, source_bqm, chain_break_method=None)[source]

Unembed the response.

Construct a response for the source binary quadratic model (BQM) by unembedding the given response from the target BQM.

Parameters:
  • target_response (Response) – Response from the target BQM.
  • embedding (dict) – Mapping from source graph to target graph as a dict of form {s: {t, …}, …}, where s is a source-model variable and t is a target-model variable.
  • source_bqm (BinaryQuadraticModel) – Source binary quadratic model.
  • chain_break_method (function, optional, default=:func:.majority_vote) – Method used to resolve chain breaks.
Returns:

Response for the source binary quadratic model.

Return type:

Response

Examples

This example embeds a Boolean AND gate, \(x_3 \Leftrightarrow x_1 \wedge x_2\), in a square-structured graph and samples with dimod reference structured sampler, StructureComposite, using the dimod reference ExactSolver sampler. The gate is represented as penalty model \(x_1 x_2 - 2(x_1+x_2)x_3 +3x_3\), which is submitted to the sampler as QUBO problem \(E(a_i, b_{i,j}; x_i) = 3x_3 + x_1x_2 - 2x_1x_3 - 2x_2x_3\). This QUBO represents a fully connected \(K_3\) graph. Samples are unembedded by unembed_response() and show that only valid states of the AND gate have zero energy (e.g., only input \(x_1 x_2=1,1\) results in \(z=1\)), while invalid states have higher energy.

>>> import dimod
>>> import networkx as nx
>>> # Binary quadratic model for the AND gate
>>> Q = {('x1', 'x2'): 1, ('x1', 'z'): -2, ('x2', 'z'): -2, ('z', 'z'): 3}
>>> bqm = dimod.BinaryQuadraticModel.from_qubo(Q)
>>> # Embed the BQM in a structured dimod sampler defined by a square graph
>>> target_graph = nx.cycle_graph(4)
>>> sampler = dimod.StructureComposite(dimod.ExactSolver(),
...                          list(target_graph.nodes), list(target_graph.edges))
>>> embedding = {'x1': {0}, 'x2': {1}, 'z': {2, 3}}
>>> target_Q = dimod.embed_qubo(Q, embedding, sampler.adjacency)
>>> # Sample on the target graph
>>> target_response = sampler.sample_qubo(target_Q)
>>> # Unembed samples back to the problem graph
>>> source_response = dimod.unembed_response(target_response, embedding, bqm)
>>> # Verify correct representation of the AND gate (first automatically then manually)
>>> for datum in source_response.data():
...     if (datum.sample['x1'] and datum.sample['x2']) == datum.sample['z']:
...         if datum.energy > 0:
...            print('Valid AND has high energy')
...
...     else:
...         if datum.energy == 0:
...             print('invalid AND has low energy')
...
>>> for datum in source_response.data():     
...     print(datum)
...
Sample(sample={'x2': 0, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 0, 'x1': 1, 'z': 0}, energy=0.0)
Sample(sample={'x2': 1, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 1, 'x1': 1, 'z': 1}, energy=0.0)
Sample(sample={'x2': 1, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 0, 'x1': 1, 'z': 0}, energy=0.0)
Sample(sample={'x2': 0, 'x1': 1, 'z': 0}, energy=0.0)
Sample(sample={'x2': 0, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 1, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 0, 'x1': 0, 'z': 0}, energy=0.0)
Sample(sample={'x2': 1, 'x1': 1, 'z': 0}, energy=1.0)
Sample(sample={'x2': 0, 'x1': 1, 'z': 1}, energy=1.0)
Sample(sample={'x2': 1, 'x1': 0, 'z': 1}, energy=1.0)
Sample(sample={'x2': 1, 'x1': 1, 'z': 0}, energy=1.0)
Sample(sample={'x2': 1, 'x1': 1, 'z': 0}, energy=1.0)
Sample(sample={'x2': 0, 'x1': 0, 'z': 1}, energy=3.0)