dwavesystems / minorminer

minorminer is a heuristic tool for minor embedding: given a minor and target graph, it tries to find a mapping that embeds the minor into the target.
https://docs.ocean.dwavesys.com/en/stable/docs_minorminer/source/sdk_index.html
Apache License 2.0
48 stars 40 forks source link

FixedEmbeddingComposite crashes #171

Closed DevelopDaily closed 4 years ago

DevelopDaily commented 4 years ago

Here is a simple test case to crash the function FixedEmbeddingComposite. The QUBO info is in this file q96.zip, which is used to construct a 96x96 QUBO numpymatrix.

// Q comes from the attached file
model = dimod.BinaryQuadraticModel.from_numpy_matrix(Q)
sampler = DWaveSampler(solver={'qpu': True})  
found = find_embedding(model.quadratic, sampler.edgelist, verbose=1)

//The following line crashes.
sampler_fixed_embedding = FixedEmbeddingComposite(sampler, found)

The strange thing is that the find_embeddingactually succeeds, but the FixedEmbeddingCompositecrashes with this error:

ValueError: no embedding found

joelgdwave commented 4 years ago

Hello @DevelopDaily, I am not finding an embedding for this Q matrix, using find_embedding. Could you please capture the embedding that you found, as a JSON object, and attach it here? find_embedding, for me, is returning an empty set, indicating that it didn't find an embedding.

arcondello commented 4 years ago

find_embedding returns an empty dictionary when it cannot find an embedding. FixedEmbeddingComposite then raises an exception to indicate that to the user.

When you say that "find_embedding actually succeeds" do you mean that it returns an embedding or an empty dict?

DevelopDaily commented 4 years ago

The find_embedding returns an empty dictionary. I expect the find_embeddingwould also throw an exception if it cannot find an embedding as the FixedEmbeddingCompositedoes. Anyway, that is my wrong assumption.

Now that I understand the empty dictionary return actually means "failed to find an embedding", what should I do to make it find one?

Mind you, my QUBO matrix is quite simple. It is populated with random numbers between -10 and 10.

arcondello commented 4 years ago

First you should make sure that you're targeting an advantage system rather than a QPU.

sampler = DWaveSampler(solver=dict(topology__type='pegasus'))

If your QUBO is dense, you should try to use DWaveCliqueSampler with an advantage system. I believe 96 variables should fit.

sampler = DWaveCliqueSampler(solver=dict(topology__type='pegasus'))

An alternative would be to tune the running of minorminer, to see if a longer run will result in it finding an embedding.

boothby commented 4 years ago

An intermediate solution is to use the clique embedder (this is done under the hood with DWaveCliqueSampler)

from minorminer.busclique import find_clique_embedding
sampler_graph = sampler.to_networkx_graph()
found = find_clique_embedding(96, sampler_graph)
randomir commented 4 years ago

Good suggestion, @arcondello. Just a minor typo, it should say topology__type='pegasus'.

arcondello commented 4 years ago

Thank's @randomir, fixed above.

DevelopDaily commented 4 years ago

@arcondello Thanks. Your advice works perfectly.

@boothby Your code does not work for me. Could you please elaborate more on your code? When running it, I got these arcane errors:

File "minorminer/busclique.pyx", line 85, in minorminer.busclique.find_clique_embedding

AttributeError: 'int' object has no attribute 'graph'
File "minorminer/busclique.pyx", line 90, in minorminer.busclique.find_clique_embedding

ValueError: g must be either a dwave_networkx.chimera_graph or a dwave_networkx.pegasus_graph
boothby commented 4 years ago

Ah, my apologies, I swapped the arguments to find_clique_embedding. I've edited my comment.

DevelopDaily commented 4 years ago

@boothby Thanks. It works beautifully now.