dwave-system icon indicating copy to clipboard operation
dwave-system copied to clipboard

chain_break_fraction result seems strange

Open JoelPasvolsky opened this issue 5 years ago • 1 comments

Description I see chain_break_fraction defined as vectors['chain_break_fraction'] = broken_chains(target_sampleset, chains).mean(axis=1)[idxs] where broken_chains is an array of T/F, so my expectation is that if a sample has n chains that chain_break_fraction can have values of [i/n for i in range(n+1)].

In the example below I have 5 chains, so I'd understand values [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] , but where does 0.09090909 come from?

SampleSet(rec.array([([1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], -2., 420, 0.09090909),
           ([0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], -2., 475, 0.09090909),
           ([1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], -2.,   2, 0.        ),
           ([1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1], -2.,   6, 0.        ),
           ([1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], -2.,   1, 0.        ),
           ([1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0], -2.,  12, 0.        ),
           ([0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0], -2.,  16, 0.        ),
           ([1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], -2.,   4, 0.        ),
           ([1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0], -2.,  14, 0.        ),
           ([0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], -2.,   7, 0.        ),
           ([0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0], -2.,  19, 0.        ),
           ([1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0], -2.,   2, 0.        ),
           ([0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0], -2.,   1, 0.        ),
           ([0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0], -2.,   8, 0.        ),
           ([0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0], -2.,   4, 0.        ),
           ([0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1], -2.,   8, 0.        ),
           ([1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0], -2.,   1, 0.09090909)],
          dtype=[('sample', 'i1', (11,)), ('energy', '<f8'), ('num_occurrences', '<i4'), ('chain_break_fraction', '<f8')]), ['a', 'and3', 'and5', 'b', 'c', 'd', 'not1', 'not6', 'or2', 'or4', 'z'], {'timing': {'qpu_sampling_time': 163960, 'qpu_anneal_time_per_sample': 20, 'qpu_readout_time_per_sample': 123, 'qpu_access_time': 171518, 'qpu_access_overhead_time': 1427, 'qpu_programming_time': 7558, 'qpu_delay_time_per_sample': 21, 'total_post_processing_time': 421, 'post_processing_overhead_time': 421, 'total_real_time': 171518, 'run_time_chip': 163960, 'anneal_time_per_run': 20, 'readout_time_per_run': 123}, 'embedding': {'b': [1851], 'not1': [1723], 'c': [1852], 'or2': [1854, 1849], 'a': [1726], 'and3': [1721, 1724], 'd': [1853], 'or4': [1720, 1848, 1725], 'and5': [1594, 1722], 'not6': [1592, 1598], 'z': [1599]}}, 'BINARY')

To Reproduce

import dwavebinarycsp
import dwavebinarycsp.factories.constraint.gates as gates
import operator

csp = dwavebinarycsp.ConstraintSatisfactionProblem(dwavebinarycsp.BINARY)
csp.add_constraint(operator.ne, ['b', 'not1'])  # add NOT 1 gate
csp.add_constraint(gates.or_gate(['b', 'c', 'or2']))  # add OR 2 gate
csp.add_constraint(gates.and_gate(['a', 'not1', 'and3']))  # add AND 3 gate
csp.add_constraint(gates.or_gate(['d', 'or2', 'or4']))  # add OR 4 gate
csp.add_constraint(gates.and_gate(['and3', 'or4', 'and5']))  # add AND 5 gate
csp.add_constraint(operator.ne, ['or4', 'not6'])  # add NOT 6 gate
csp.add_constraint(gates.or_gate(['and5', 'not6', 'z']))  # add OR 7 gate

bqm = dwavebinarycsp.stitch(csp)

from dwave.system.composites import EmbeddingComposite

# Set up a D-Wave system as the sampler
sampler = EmbeddingComposite(DWaveSampler())

response = sampler.sample(bqm, num_reads=1000, return_embedding=True)

Expected behavior values [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] or a clearer explanation of chain_break_fraction.

Environment:

  • OS: Windows
  • Python version: 3.6

Additional context Add any other context about the problem here.

JoelPasvolsky avatar Nov 21 '19 17:11 JoelPasvolsky

Cycling home I realized that 0.09090909 comes from the broken_chains() treating single qubits as chains, so the calculation should have been [i/num_vars for i in range(num_vars+1)], and in this case 1/11. I'm not sure this is the best approach. If I have 8 single-qubit variables and two chains, one broken, my response to 0.1 will be different in terms of say pumping up chain_strength amplitude versus 0.5.

JoelPasvolsky avatar Nov 22 '19 01:11 JoelPasvolsky