Greedy descent as a post-processing

Greedy descent as a post-processing

Problem instance

import random
import dimod


N = 100
h = {}
J = {(i, j): random.gauss(0, 1) for i in range(N) for j in range(i + 1, N)}

bqm = dimod.BinaryQuadraticModel.from_ising(h, J)

Embed & Post to D-Wave solver

from dwave.system import DWaveSampler
from dwave.embedding import embed_bqm
from minorminer import find_embedding
from minorminer.busclique import find_clique_embedding

dw_sampler = DWaveSampler(profile='sigu-adv')
adj = {k: 1 for k in bqm.quadratic.keys()}
%time embedding = find_clique_embedding(g=dw_sampler.to_networkx_graph(), nodes=N, use_cache=True)
%time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)

# adj = {k: 1 for k in bqm.quadratic.keys()}
# %time embedding = find_embedding(adj, dw_sampler.edgelist, random_seed=1, threads=4)
# %time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)
CPU times: user 226 ms, sys: 16.2 ms, total: 243 ms
Wall time: 252 ms
CPU times: user 79 ms, sys: 632 µs, total: 79.6 ms
Wall time: 79.5 ms
%%time
raw_sampleset = dw_sampler.sample(bqm_embed, num_reads=1000)
CPU times: user 50.1 ms, sys: 860 µs, total: 50.9 ms
Wall time: 50.4 ms

Chain-break resolution

from dwave.embedding import unembed_sampleset
from dwave.embedding import majority_vote, weighted_random, discard, MinimizeEnergy

minimize_energy = MinimizeEnergy(bqm, embedding)
%time sampleset_mj = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=majority_vote)
%time sampleset_wr = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=weighted_random)
%time sampleset_dc = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=discard)
%time sampleset_me = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=minimize_energy)
CPU times: user 73 ms, sys: 23.3 ms, total: 96.3 ms
Wall time: 47.4 ms
CPU times: user 115 ms, sys: 24.4 ms, total: 139 ms
Wall time: 36.5 ms
CPU times: user 68.9 ms, sys: 11.8 ms, total: 80.7 ms
Wall time: 20.9 ms
CPU times: user 4.73 s, sys: 70.8 ms, total: 4.8 s
Wall time: 4.53 s

Greedy descent

from greedy import SteepestDescentSolver

greedy_sampler = SteepestDescentSolver()
sampleset_mj_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_mj.record.sample, seed=1)
sampleset_wr_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_wr.record.sample, seed=1)
sampleset_dc_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_dc.record.sample, seed=1)
sampleset_me_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_me.record.sample, seed=1)

sampleset_rand_init = greedy_sampler.sample(bqm, num_reads=1000, initial_states_generator='random', seed=1)

Results

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 18
plt.rcParams['axes.linewidth'] = 1.0
plt.rcParams['figure.facecolor'] = 'w'

plt.rcParams['font.size'] = 14
plt.rcParams['font.sans-serif'] = ['Arial']
plt.rcParams['mathtext.cal'] = 'serif'
plt.rcParams['mathtext.rm'] = 'serif'
plt.rcParams['mathtext.it'] = 'serif:italic'
plt.rcParams['mathtext.bf'] = 'serif:bold'
plt.rcParams['mathtext.fontset'] = 'cm'

plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['xtick.major.width'] = 1.0
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['ytick.major.width'] = 1.0

plt.rcParams['legend.loc'] = 'best'
plt.rcParams['legend.frameon'] = True
plt.rcParams['legend.framealpha'] = 1.0
plt.rcParams['legend.edgecolor'] = 'black'
plt.rcParams['legend.fancybox'] = False

plt.rcParams['grid.color'] = 'black'
plt.rcParams['grid.linewidth'] = 1.0
fig = plt.figure(figsize=(12, 8))
axes = fig.subplots(nrows=2, ncols=2)

axes[0][0].hist(sampleset_mj.record.energy, density=True, alpha=0.3, label='none')
axes[0][0].hist(sampleset_mj_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[0][0].set_title('majority_vote')
axes[0][0].set_xlabel('energy')
axes[0][0].set_ylabel('density')
axes[0][0].legend(loc='upper right')

axes[0][1].hist(sampleset_wr.record.energy, density=True, alpha=0.3, label='none')
axes[0][1].hist(sampleset_wr_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[0][1].set_title('weighted_random')
axes[0][1].set_xlabel('energy')
axes[0][1].set_ylabel('density')
axes[0][1].legend(loc='upper right')

axes[1][0].hist(sampleset_dc.record.energy, density=True, alpha=0.3, label='none')
axes[1][0].hist(sampleset_dc_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[1][0].set_title('discard')
axes[1][0].set_xlabel('energy')
axes[1][0].set_ylabel('density')
axes[1][0].legend(loc='upper right')

axes[1][1].hist(sampleset_me.record.energy, density=True, alpha=0.3, label='none')
axes[1][1].hist(sampleset_me_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[1][1].set_title('minimize_energy')
axes[1][1].set_xlabel('energy')
axes[1][1].set_ylabel('density')
axes[1][1].legend(loc='upper right')

plt.tight_layout()
plt.show()
../../../_images/greedy_16_0.png
plt.hist(sampleset_rand_init.record.energy, density=True, alpha=0.3)
plt.title('discard')
plt.xlabel('energy')
plt.ylabel('density')
plt.tight_layout()
plt.show()
../../../_images/greedy_17_0.png
import pandas as pd


sampleset_list = [sampleset_mj, sampleset_wr, sampleset_dc, sampleset_me,
                  sampleset_mj_greedy, sampleset_wr_greedy, sampleset_dc_greedy, sampleset_me_greedy,
                  sampleset_rand_init]

aggregations = []
for samp in sampleset_list:
    energy = samp.record.energy
    aggregations.append([np.min(energy), np.mean(energy), np.max(energy), np.std(energy), np.sum(samp.record.num_occurrences)])

index = ['majority_vote', 'weighted_random', 'discard', 'minimize_energy',
         'majority_vote(greegy)', 'weighted_random(greegy)', 'discard(greegy)', 'minimize_energy(greegy)',
         'random init states(greedy)']
columns = ['energy(min)', 'energy(mean)', 'energy(max)', 'energy(std)', 'num_occurrences']
df_aggr = pd.DataFrame(aggregations, index=index, columns=columns)
df_aggr
energy(min) energy(mean) energy(max) energy(std) num_occurrences
majority_vote -642.618362 -509.955511 -324.870500 50.847352 1000
weighted_random -642.618362 -500.773185 -354.848499 51.451491 1000
discard -526.492295 -521.051695 -515.611096 5.440600 2
minimize_energy -664.536202 -531.262475 -403.476015 46.995649 1000
majority_vote(greegy) -718.968897 -663.864370 -519.651562 34.613129 1000
weighted_random(greegy) -718.968897 -663.951955 -540.121615 33.542041 1000
discard(greegy) -718.968897 -652.018753 -491.522041 36.380169 1000
minimize_energy(greegy) -718.968897 -662.864103 -527.712127 34.761184 1000
random init states(greedy) -718.968897 -652.001881 -491.522041 36.427022 1000

Supplement

from greedy import SteepestDescentSampler

SteepestDescentSampler == SteepestDescentSolver
True
from dwave.system import EmbeddingComposite
from greedy import SteepestDescentComposite

ec_sampler = EmbeddingComposite(dw_sampler, find_embedding=find_embedding,
                                embedding_parameters=dict(random_seed=1, threads=4))
greedy_sampler = SteepestDescentComposite(ec_sampler)

# sampleset = greedy_sampler.sample(bqm, num_reads=100)
from dwave.embedding.pegasus import find_clique_embedding, pegasus_graph

adj = {k: 1 for k in bqm.quadratic.keys()}
# %time embedding = find_clique_embedding(k=10, target_graph=dw_sampler.to_networkx_graph())
# %time embedding = find_clique_embedding(k=10, target_graph=pegasus.pegasus_graph(m=2))
%time embedding = find_clique_embedding(k=10, m=2)
%time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)
CPU times: user 29.1 ms, sys: 485 µs, total: 29.6 ms
Wall time: 29.6 ms
---------------------------------------------------------------------------
DisconnectedChainError                    Traceback (most recent call last)
<timed exec> in <module>

~/.anyenv/envs/pyenv/versions/3.8.2/lib/python3.8/site-packages/dwave/embedding/transforms.py in embed_bqm(source_bqm, embedding, target_adjacency, chain_strength, smear_vartype)
    374     else:
    375         target_edges = adjacency_to_edges(target_adjacency)
--> 376         embedding = EmbeddedStructure(target_edges, embedding)
    377 
    378     return embedding.embed_bqm(source_bqm, smear_vartype=smear_vartype,

~/.anyenv/envs/pyenv/versions/3.8.2/lib/python3.8/site-packages/dwave/embedding/transforms.py in __init__(self, target_edges, embedding)
     97         for u, emb_u in self.items():
     98             if len(emb_u) != disjoint_sets[u].size(0):
---> 99                 raise DisconnectedChainError(u)
    100 
    101     @property

DisconnectedChainError: chain for 0 is not connected
from dwave.system import DWaveCliqueSampler

dw_clique_sampler = DWaveCliqueSampler(profile='sigu-adv')
sampleset = dw_clique_sampler.sample(bqm, num_reads=1000)
print(dw_clique_sampler.parameters)
{'anneal_offsets': ['parameters'], 'anneal_schedule': ['parameters'], 'annealing_time': ['parameters'], 'answer_mode': ['parameters'], 'flux_biases': ['parameters'], 'flux_drift_compensation': ['parameters'], 'h_gain_schedule': ['parameters'], 'initial_state': ['parameters'], 'max_answers': ['parameters'], 'num_reads': ['parameters'], 'num_spin_reversal_transforms': ['parameters'], 'programming_thermalization': ['parameters'], 'readout_thermalization': ['parameters'], 'reduce_intersample_correlation': ['parameters'], 'reinitialize_state': ['parameters'], 'warnings': []}
dw_clique_sampler.largest_clique_size
120

Greedy descent as a post-processing

Problem instance

import random
import dimod


N = 100
h = {}
J = {(i, j): random.gauss(0, 1) for i in range(N) for j in range(i + 1, N)}

bqm = dimod.BinaryQuadraticModel.from_ising(h, J)

Embed & Post to D-Wave solver

from dwave.system import DWaveSampler
from dwave.embedding import embed_bqm
from minorminer import find_embedding
from minorminer.busclique import find_clique_embedding

dw_sampler = DWaveSampler(profile='sigu-adv')
adj = {k: 1 for k in bqm.quadratic.keys()}
%time embedding = find_clique_embedding(g=dw_sampler.to_networkx_graph(), nodes=N, use_cache=True)
%time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)

# adj = {k: 1 for k in bqm.quadratic.keys()}
# %time embedding = find_embedding(adj, dw_sampler.edgelist, random_seed=1, threads=4)
# %time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)
CPU times: user 226 ms, sys: 16.2 ms, total: 243 ms
Wall time: 252 ms
CPU times: user 79 ms, sys: 632 µs, total: 79.6 ms
Wall time: 79.5 ms
%%time
raw_sampleset = dw_sampler.sample(bqm_embed, num_reads=1000)
CPU times: user 50.1 ms, sys: 860 µs, total: 50.9 ms
Wall time: 50.4 ms

Chain-break resolution

from dwave.embedding import unembed_sampleset
from dwave.embedding import majority_vote, weighted_random, discard, MinimizeEnergy

minimize_energy = MinimizeEnergy(bqm, embedding)
%time sampleset_mj = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=majority_vote)
%time sampleset_wr = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=weighted_random)
%time sampleset_dc = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=discard)
%time sampleset_me = unembed_sampleset(raw_sampleset, embedding, bqm, chain_break_method=minimize_energy)
CPU times: user 73 ms, sys: 23.3 ms, total: 96.3 ms
Wall time: 47.4 ms
CPU times: user 115 ms, sys: 24.4 ms, total: 139 ms
Wall time: 36.5 ms
CPU times: user 68.9 ms, sys: 11.8 ms, total: 80.7 ms
Wall time: 20.9 ms
CPU times: user 4.73 s, sys: 70.8 ms, total: 4.8 s
Wall time: 4.53 s

Greedy descent

from greedy import SteepestDescentSolver

greedy_sampler = SteepestDescentSolver()
sampleset_mj_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_mj.record.sample, seed=1)
sampleset_wr_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_wr.record.sample, seed=1)
sampleset_dc_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_dc.record.sample, seed=1)
sampleset_me_greedy = greedy_sampler.sample(bqm, num_reads=1000, initial_states=sampleset_me.record.sample, seed=1)

sampleset_rand_init = greedy_sampler.sample(bqm, num_reads=1000, initial_states_generator='random', seed=1)

Results

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 18
plt.rcParams['axes.linewidth'] = 1.0
plt.rcParams['figure.facecolor'] = 'w'

plt.rcParams['font.size'] = 14
plt.rcParams['font.sans-serif'] = ['Arial']
plt.rcParams['mathtext.cal'] = 'serif'
plt.rcParams['mathtext.rm'] = 'serif'
plt.rcParams['mathtext.it'] = 'serif:italic'
plt.rcParams['mathtext.bf'] = 'serif:bold'
plt.rcParams['mathtext.fontset'] = 'cm'

plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['xtick.major.width'] = 1.0
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['ytick.major.width'] = 1.0

plt.rcParams['legend.loc'] = 'best'
plt.rcParams['legend.frameon'] = True
plt.rcParams['legend.framealpha'] = 1.0
plt.rcParams['legend.edgecolor'] = 'black'
plt.rcParams['legend.fancybox'] = False

plt.rcParams['grid.color'] = 'black'
plt.rcParams['grid.linewidth'] = 1.0
fig = plt.figure(figsize=(12, 8))
axes = fig.subplots(nrows=2, ncols=2)

axes[0][0].hist(sampleset_mj.record.energy, density=True, alpha=0.3, label='none')
axes[0][0].hist(sampleset_mj_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[0][0].set_title('majority_vote')
axes[0][0].set_xlabel('energy')
axes[0][0].set_ylabel('density')
axes[0][0].legend(loc='upper right')

axes[0][1].hist(sampleset_wr.record.energy, density=True, alpha=0.3, label='none')
axes[0][1].hist(sampleset_wr_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[0][1].set_title('weighted_random')
axes[0][1].set_xlabel('energy')
axes[0][1].set_ylabel('density')
axes[0][1].legend(loc='upper right')

axes[1][0].hist(sampleset_dc.record.energy, density=True, alpha=0.3, label='none')
axes[1][0].hist(sampleset_dc_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[1][0].set_title('discard')
axes[1][0].set_xlabel('energy')
axes[1][0].set_ylabel('density')
axes[1][0].legend(loc='upper right')

axes[1][1].hist(sampleset_me.record.energy, density=True, alpha=0.3, label='none')
axes[1][1].hist(sampleset_me_greedy.record.energy, density=True, alpha=0.3, label='greedy')
axes[1][1].set_title('minimize_energy')
axes[1][1].set_xlabel('energy')
axes[1][1].set_ylabel('density')
axes[1][1].legend(loc='upper right')

plt.tight_layout()
plt.show()
../../../_images/greedy_16_0.png
plt.hist(sampleset_rand_init.record.energy, density=True, alpha=0.3)
plt.title('discard')
plt.xlabel('energy')
plt.ylabel('density')
plt.tight_layout()
plt.show()
../../../_images/greedy_17_0.png
import pandas as pd


sampleset_list = [sampleset_mj, sampleset_wr, sampleset_dc, sampleset_me,
                  sampleset_mj_greedy, sampleset_wr_greedy, sampleset_dc_greedy, sampleset_me_greedy,
                  sampleset_rand_init]

aggregations = []
for samp in sampleset_list:
    energy = samp.record.energy
    aggregations.append([np.min(energy), np.mean(energy), np.max(energy), np.std(energy), np.sum(samp.record.num_occurrences)])

index = ['majority_vote', 'weighted_random', 'discard', 'minimize_energy',
         'majority_vote(greegy)', 'weighted_random(greegy)', 'discard(greegy)', 'minimize_energy(greegy)',
         'random init states(greedy)']
columns = ['energy(min)', 'energy(mean)', 'energy(max)', 'energy(std)', 'num_occurrences']
df_aggr = pd.DataFrame(aggregations, index=index, columns=columns)
df_aggr
energy(min) energy(mean) energy(max) energy(std) num_occurrences
majority_vote -642.618362 -509.955511 -324.870500 50.847352 1000
weighted_random -642.618362 -500.773185 -354.848499 51.451491 1000
discard -526.492295 -521.051695 -515.611096 5.440600 2
minimize_energy -664.536202 -531.262475 -403.476015 46.995649 1000
majority_vote(greegy) -718.968897 -663.864370 -519.651562 34.613129 1000
weighted_random(greegy) -718.968897 -663.951955 -540.121615 33.542041 1000
discard(greegy) -718.968897 -652.018753 -491.522041 36.380169 1000
minimize_energy(greegy) -718.968897 -662.864103 -527.712127 34.761184 1000
random init states(greedy) -718.968897 -652.001881 -491.522041 36.427022 1000

Supplement

from greedy import SteepestDescentSampler

SteepestDescentSampler == SteepestDescentSolver
True
from dwave.system import EmbeddingComposite
from greedy import SteepestDescentComposite

ec_sampler = EmbeddingComposite(dw_sampler, find_embedding=find_embedding,
                                embedding_parameters=dict(random_seed=1, threads=4))
greedy_sampler = SteepestDescentComposite(ec_sampler)

# sampleset = greedy_sampler.sample(bqm, num_reads=100)
from dwave.embedding.pegasus import find_clique_embedding, pegasus_graph

adj = {k: 1 for k in bqm.quadratic.keys()}
# %time embedding = find_clique_embedding(k=10, target_graph=dw_sampler.to_networkx_graph())
# %time embedding = find_clique_embedding(k=10, target_graph=pegasus.pegasus_graph(m=2))
%time embedding = find_clique_embedding(k=10, m=2)
%time bqm_embed = embed_bqm(bqm, embedding, dw_sampler.adjacency)
CPU times: user 29.1 ms, sys: 485 µs, total: 29.6 ms
Wall time: 29.6 ms
---------------------------------------------------------------------------
DisconnectedChainError                    Traceback (most recent call last)
<timed exec> in <module>

~/.anyenv/envs/pyenv/versions/3.8.2/lib/python3.8/site-packages/dwave/embedding/transforms.py in embed_bqm(source_bqm, embedding, target_adjacency, chain_strength, smear_vartype)
    374     else:
    375         target_edges = adjacency_to_edges(target_adjacency)
--> 376         embedding = EmbeddedStructure(target_edges, embedding)
    377 
    378     return embedding.embed_bqm(source_bqm, smear_vartype=smear_vartype,

~/.anyenv/envs/pyenv/versions/3.8.2/lib/python3.8/site-packages/dwave/embedding/transforms.py in __init__(self, target_edges, embedding)
     97         for u, emb_u in self.items():
     98             if len(emb_u) != disjoint_sets[u].size(0):
---> 99                 raise DisconnectedChainError(u)
    100 
    101     @property

DisconnectedChainError: chain for 0 is not connected
from dwave.system import DWaveCliqueSampler

dw_clique_sampler = DWaveCliqueSampler(profile='sigu-adv')
sampleset = dw_clique_sampler.sample(bqm, num_reads=1000)
print(dw_clique_sampler.parameters)
{'anneal_offsets': ['parameters'], 'anneal_schedule': ['parameters'], 'annealing_time': ['parameters'], 'answer_mode': ['parameters'], 'flux_biases': ['parameters'], 'flux_drift_compensation': ['parameters'], 'h_gain_schedule': ['parameters'], 'initial_state': ['parameters'], 'max_answers': ['parameters'], 'num_reads': ['parameters'], 'num_spin_reversal_transforms': ['parameters'], 'programming_thermalization': ['parameters'], 'readout_thermalization': ['parameters'], 'reduce_intersample_correlation': ['parameters'], 'reinitialize_state': ['parameters'], 'warnings': []}
dw_clique_sampler.largest_clique_size
120