def sapi_refine_modularity( graph, solver, hardware_size, # max size subproblem ptn_variables, # ptn_variables[node] = 0,1,'free' num_reads, annealing_time, embeddings=False, # if false, get fast embedding ): sub_B_matrix, bias, constant = get_sub_mod_matrix(graph, ptn_variables) n = sub_B_matrix.shape[0] if n > hardware_size: print n, hardware_size raise ValueError('Number free variables exceeds hardware size') coupler = {} # we add negative because we maximize modularity bias = [-i for i in bias] for i in range(n - 1): for j in range(i + 1, n): coupler[(i, j)] = -sub_B_matrix.item((i, j)) coupler[(j, i)] = -sub_B_matrix.item((j, i)) A = get_hardware_adjacency(solver) #print "embedding..." if not embeddings: print 'finding embedding ....' embeddings = find_embedding(coupler, A, verbose=0, fast_embedding=True) (h0, j0, jc, new_emb) = embed_problem(bias, coupler, embeddings, A, clean=True, smear=True) emb_j = j0.copy() emb_j.update(jc) #print "On DWave..." result = solve_ising(solver, h0, emb_j, num_reads=num_reads, annealing_time=annealing_time) #print result #print "On DWave...COMPLETE" energies = result['energies'] #print energies #print result['solutions'] #print min(energies), max(energies) new_answer = unembed_answer(result['solutions'], new_emb, 'minimize_energy', bias, coupler) min_energy = 10**10 best_soln = [] for i, ans in enumerate(new_answer): soln = ans[0:n] assert 3 not in soln en = energies[i] if en < min_energy: #print 'energy', en min_energy = en best_soln = copy.deepcopy(soln) return get_new_partition(best_soln, ptn_variables)
def __init__(self, solver, network, verbose=0): self._verbose = verbose # have D-Wave find an embedding of our network into the Chimera self._A = dw_util.get_hardware_adjacency(solver) self._emb = dw_embedding.find_embedding(network.j(), self._A, \ verbose=verbose, timeout=settings.EMBEDDING_TIMEOUT) if verbose: print 'embedding:', self._emb
def run_heur_embedding(self, full_adj=True): '''Setup and run the Heuristic algorithm''' # update embedding type in case direct call self.embed_method = 'heur' active_cells, qca_adj = self.get_reduced_qca_adj() S_size = len(qca_adj) A_size = len(self.chimera_adj) # construct S, the problem adjacency edge list S = set() smap = {c: i for i, c in enumerate(active_cells)} for c1, adj in qca_adj.items(): for c2 in adj: if c1 < c2: S.add((smap[c1], smap[c2])) # construct A, the chimera adjacency edge list A = set() for qb1 in self.chimera_adj: for qb2 in self.chimera_adj[qb1]: l1 = tuple_to_linear(qb1, self.M, self.N, L=self.L, index0=True) l2 = tuple_to_linear(qb2, self.M, self.N, L=self.L, index0=True) A.add((l1, l2)) try: print 'Running heuristic embedding' #models = find_embedding(S, S_size, A, A_size) models = find_embedding(S, A) except Exception as e: print(e.message()) print 'Embedding finished' self.good = len(models) == S_size # map models to standard format mapper = lambda ind: linear_to_tuple( ind, self.M, self.N, L=self.L, index0=True) self.models = { active_cells[i]: [mapper(c) for c in model] for i, model in enumerate(models) }
def embedding_example(): # formulate k_6 structured graph h = [1, 1, 1, 1, 1, 1] J = {(i, j): 1 for i in range(6) for j in range(i)} solver = local_connection.get_solver("c4-sw_optimize") A = get_hardware_adjacency(solver) # find and print embeddings for problem graph embeddings = find_embedding(J, A, verbose=1) print "embeddings are: ", embeddings # embed the problem into solver graph (h0, j0, jc, new_emb) = embed_problem(h, J, embeddings, A) print "embedded problem result:\nj0: ", j0 print "jc: ", jc # find unembedded results for chain strengths -0.5, -1.0, -2.0 for chain_strength in (-0.5, -1.0, -2.0): # set chain strength values jc = dict.fromkeys(jc, chain_strength) # create new J array concatenating j0 with jc emb_j = j0.copy() emb_j.update(jc) # solve embedded problem answer = solve_ising(solver, h0, emb_j, num_reads=10) # unembed and print result of the form: # solution [solution #] # var [var #] : [var value] ([qubit index] : [original qubit value] ...) result = unembed_answer(answer['solutions'], new_emb, broken_chains="minimize_energy", h=h, j=J) print "result for chain strength = ", chain_strength for i, (embsol, sol) in enumerate(zip(answer['solutions'], result)): print "solution", i for j, emb in enumerate(embeddings): print "var %d: %d (" % (j, sol[j]), for k in emb: print "%d:%d" % (k, embsol[k]), print ")"
def find_dwave_embedding(logical, optimization, verbosity, hw_adj_file): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [ e for e in logical.strengths.keys() if logical.strengths[e] != 0.0 ] edges.sort() logical.edges = edges if hw_adj_file == None: try: hw_adj = get_hardware_adjacency(qmasm.solver) except KeyError: # The Ising heuristic solver is an example of a solver that lacks a # fixed hardware representation. We therefore assert that the # hardware is an all-to-all network that connects every node to # every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] else: hw_adj = read_hardware_adjacency(hw_adj_file, verbosity) # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. If we read # the topology from a file or otherwise can't prove that we have a Chimera # graph, we call this rectangle 0x0 and force the main embedding loop to # exit after a single iteration because we don't know the topology is even # rectangular. edgex = 0 edgey = 0 M = 0 N = 0 try: if hw_adj_file == None: L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2 * L ncells = (qmasm.next_sym_num + L2) // L2 # Round up the number of cells. if optimization >= 2: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M except qmasm.NonChimera: pass # Announce what we're about to do. if verbosity >= 2: sys.stderr.write( "Embedding the logical adjacency within the physical topology.\n\n" ) # Repeatedly expand edgex and edgey until the embedding works. while edgex <= M and edgey <= N: if edgex == M and edgey == N: alt_hw_adj = hw_adj else: # Retain adjacencies only within the rectangle. alt_hw_adj = [] for q1, q2 in hw_adj: c1 = q1 // L2 if c1 % M >= edgex: continue if c1 // M >= edgey: continue c2 = q2 // L2 if c2 % M >= edgex: continue if c2 // M >= edgey: continue alt_hw_adj.append((q1, q2)) alt_hw_adj = set(alt_hw_adj) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write( " No embedding cache directory was specified ($QMASMCACHE).\n" ) else: sys.stderr.write( " Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write( " Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write( " Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write( " No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if embedding != []: if verbosity >= 2: # SAPI's find_embedding is hard-wired to write to stdout. # Trick it into writing into a pipe instead. if edgex == 0 and edgey == 0: sys.stderr.write(" Trying to embed ... ") else: sys.stderr.write( " Trying a %dx%d unit-cell embedding ...\n\n" % (edgex, edgey)) sepLine = "=== EMBEDDING ===\n" r, w = os.pipe() pid = os.fork() if pid == 0: # Child -- perform the embedding. os.close(r) os.dup2(w, sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.write(w, sepLine) os.write(w, json.dumps(embedding) + "\n") os.close(w) os._exit(0) else: # Parent -- report the embedding's progress. os.close(w) pipe = os.fdopen(r, "r", 10000) while True: try: rstr = pipe.readline() if rstr == sepLine: break if rstr == "": qmasm.abend( "Embedder failed to terminate properly") sys.stderr.write(" %s" % rstr) except: pass # Receive the embedding from the child. embedding = json.loads(pipe.readline()) sys.stderr.write("\n") else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not (edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding
def find_dwave_embedding(logical, optimize, verbosity): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [e for e in list(logical.strengths.keys()) if logical.strengths[e] != 0.0] edges.sort() logical.edges = edges try: hw_adj = get_hardware_adjacency(qmasm.solver) except KeyError: # The Ising heuristic solver is an example of a solver that lacks a # fixed hardware representation. We therefore assert that the hardware # is an all-to-all network that connects every node to every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2*L ncells = (qmasm.next_sym_num + L2) // L2 # Round up the number of cells. if optimize: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M # Announce what we're about to do. if verbosity >= 2: sys.stderr.write("Embedding the logical adjacency within the physical topology.\n\n") # Repeatedly expand edgex and edgey until the embedding works. while edgex <= M and edgey <= N: # Retain adjacencies only within the rectangle. alt_hw_adj = [] for q1, q2 in hw_adj: c1 = q1//L2 if c1 % M >= edgex: continue if c1 // M >= edgey: continue c2 = q2//L2 if c2 % M >= edgex: continue if c2 // M >= edgey: continue alt_hw_adj.append((q1, q2)) alt_hw_adj = set(alt_hw_adj) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write(" No embedding cache directory was specified ($QMASMCACHE).\n") else: sys.stderr.write(" Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write(" Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write(" Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write(" No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if embedding != []: if verbosity >= 2: sys.stderr.write(" Trying a %dx%d unit-cell embedding ... " % (edgex, edgey)) status_file = tempfile.NamedTemporaryFile(mode="w", delete=False) stdout_fd = os.dup(sys.stdout.fileno()) os.dup2(status_file.fileno(), sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.dup2(stdout_fd, sys.stdout.fileno()) status_file.close() if len(embedding) > 0: sys.stderr.write("succeeded\n\n") else: sys.stderr.write("failed\n\n") with open(status_file.name, "r") as status: for line in status: sys.stderr.write(" %s" % line) sys.stderr.write("\n") os.remove(status_file.name) else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not(edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding
def anneal(C_i, C_ij, mu, sigma, l, strength_scale, energy_fraction, ngauges, max_excited_states): url = "https://usci.qcc.isi.edu/sapi" token = "your-token" h = np.zeros(len(C_i)) J = {} for i in range(len(C_i)): h_i = -2 * sigma[i] * C_i[i] for j in range(len(C_ij[0])): if j > i: J[(i, j)] = 2 * C_ij[i][j] * sigma[i] * sigma[j] h_i += 2 * (sigma[i] * C_ij[i][j] * mu[j]) h[i] = h_i vals = np.array(J.values()) cutoff = np.percentile(vals, AUGMENT_CUTOFF_PERCENTILE) to_delete = [] for k, v in J.items(): if v < cutoff: to_delete.append(k) for k in to_delete: del J[k] isingpartial = [] if FIXING_VARIABLES: Q, _ = ising_to_qubo(h, J) simple = fix_variables(Q, method='standard') new_Q = simple['new_Q'] print('new length', len(new_Q)) isingpartial = simple['fixed_variables'] if (not FIXING_VARIABLES) or len(new_Q) > 0: cant_connect = True while cant_connect: try: print('about to call remote') conn = dwave_sapi2.remote.RemoteConnection(url, token) solver = conn.get_solver("DW2X") print('called remote', conn) cant_connect = False except IOError: print('Network error, trying again', datetime.datetime.now()) time.sleep(10) cant_connect = True A = get_hardware_adjacency(solver) mapping = [] offset = 0 for i in range(len(C_i)): if i in isingpartial: mapping.append(None) offset += 1 else: mapping.append(i - offset) if FIXING_VARIABLES: new_Q_mapped = {} for (first, second), val in new_Q.items(): new_Q_mapped[(mapping[first], mapping[second])] = val h, J, _ = qubo_to_ising(new_Q_mapped) # run gauges nreads = 200 qaresults = np.zeros((ngauges * nreads, len(h))) for g in range(ngauges): embedded = False for attempt in range(5): a = np.sign(np.random.rand(len(h)) - 0.5) h_gauge = h * a J_gauge = {} for i in range(len(h)): for j in range(len(h)): if (i, j) in J: J_gauge[(i, j)] = J[(i, j)] * a[i] * a[j] embeddings = find_embedding(J.keys(), A) try: (h0, j0, jc, new_emb) = embed_problem(h_gauge, J_gauge, embeddings, A, True, True) embedded = True break except ValueError: # no embedding found print('no embedding found') embedded = False continue if not embedded: continue # adjust chain strength rescale_couplers = strength_scale * max( np.amax(np.abs(np.array(h0))), np.amax(np.abs(np.array(list(j0.values()))))) # print('scaling by', rescale_couplers) for k, v in j0.items(): j0[k] /= strength_scale for i in range(len(h0)): h0[i] /= strength_scale emb_j = j0.copy() emb_j.update(jc) print("Quantum annealing") try_again = True while try_again: try: qaresult = solve_ising(solver, h0, emb_j, num_reads=nreads, annealing_time=a_time, answer_mode='raw') try_again = False except: print('runtime or ioerror, trying again') time.sleep(10) try_again = True print("Quantum done") qaresult = np.array( unembed_answer(qaresult["solutions"], new_emb, 'vote', h_gauge, J_gauge)) qaresult = qaresult * a qaresults[g * nreads:(g + 1) * nreads] = qaresult if FIXING_VARIABLES: j = 0 for i in range(len(C_i)): if i in isingpartial: full_strings[:, i] = 2 * isingpartial[i] - 1 else: full_strings[:, i] = qaresults[:, j] j += 1 else: full_strings = qaresults s = full_strings energies = np.zeros(len(qaresults)) s[np.where(s > 1)] = 1.0 s[np.where(s < -1)] = -1.0 bits = len(s[0]) for i in range(bits): energies += 2 * s[:, i] * (-sigma[i] * C_i[i]) for j in range(bits): if j > i: energies += 2 * s[:, i] * s[:, j] * sigma[i] * sigma[ j] * C_ij[i][j] energies += 2 * s[:, i] * sigma[i] * C_ij[i][j] * mu[j] unique_energies, unique_indices = np.unique(energies, return_index=True) ground_energy = np.amin(unique_energies) # print('ground energy', ground_energy) if ground_energy < 0: threshold_energy = (1 - energy_fraction) * ground_energy else: threshold_energy = (1 + energy_fraction) * ground_energy lowest = np.where(unique_energies < threshold_energy) unique_indices = unique_indices[lowest] if len(unique_indices) > max_excited_states: sorted_indices = np.argsort( energies[unique_indices])[-max_excited_states:] unique_indices = unique_indices[sorted_indices] final_answers = full_strings[unique_indices] print('number of selected excited states', len(final_answers)) return final_answers else: final_answer = [] for i in range(len(C_i)): if i in isingpartial: final_answer.append(2 * isingpartial[i] - 1) final_answer = np.array(final_answer) return np.array([final_answer])
# Heuristic embedding # suppose we can't manually embed our 2D checkerboard example. J and h then remain unchanged from our initial definitions: J = {(0,1): 1, (0,2): 1, (1,3): 1, (2,3): 1} h = [-1,0,0,0] connection = RemoteConnection(DWAVE_SAPI_URL, DWAVE_TOKEN) solver = connection.get_solver(DWAVE_SOLVER) # first get the adjacency matrix of the current hardware graph: adjacency = get_hardware_adjacency(solver) # Now let's try to find an embedding of our problem: embedding = find_embedding(J.keys(), adjacency) # We are now ready to embed our problem onto the graph: [h, j0, jc, embeddings] = embed_problem(h, J, embedding, adjacency) # j0 contains the original couplings that we defined and jc contains the couplings that enforce the integrity of the chains (they correlate the qubits within the chains). Thus, we need to combine them again into one big J dictionary: J = j0.copy() J.update(jc) # Now, we're ready to solve the embedded problem: params = {"answer_mode": 'histogram', "num_reads": 10000} raw_results = solve_ising(solver, h, J, **params)
def sample_ising(self, h, J, embedding_tag=None, **sapi_kwargs): """Embeds the given problem using sapi's find_embedding then invokes the given sampler to solve it. Args: h (dict/list): The linear terms in the Ising problem. If a dict, should be of the form {v: bias, ...} where v is a variable in the Ising problem, and bias is the linear bias associated with v. If a list, should be of the form [bias, ...] where the indices of the biases are the variables in the Ising problem. J (dict): A dictionary of the quadratic terms in the Ising problem. Should be of the form {(u, v): bias} where u, v are variables in the Ising problem and bias is the quadratic bias associated with u, v. embedding_tag: Allows the user to specify a tag for the generated embedding. Useful for when the user wishes to submit multiple problems with the same logical structure. Additional keyword parameters are the same as for SAPI's solve_ising function, see QUBIST documentation. Returns: :class:`dimod.SpinResponse`: The unembedded samples. Examples: >>> sampler = sapi.EmbeddingComposite(sapi.SAPILocalSampler('c4-sw_optimize')) >>> response = sampler.sample_ising({}, {(0, 1): 1, (0, 2): 1, (1, 2): 1}) Using the embedding_tag, the embedding is generated only once. >>> h = {0: .1, 1: 1.3, 2: -1.} >>> J = {(0, 1): 1, (1, 2): 1, (0, 2): 1} >>> sampler = sapi.EmbeddingComposite(sapi.SAPILocalSampler('c4-sw_optimize')) >>> response0 = sampler.sample_ising(h, J, embedding_tag='K3') >>> response1 = sampler.sample_ising(h, J, embedding_tag='K3') """ # get the sampler that is used by the composite sampler = self._child # the ising_index_labels decorator converted the keys of h to be indices 0, n-1 # sapi wants h to be a list, so let's make that conversion, using the keys as # the indices. h_list = [h[v] for v in range(len(h))] # get the structure of the child sampler. The first value are the nodes which # we don't need, the second is the set of edges available. (__, edgeset) = sampler.structure if embedding_tag is None or embedding_tag not in self.cached_embeddings: # we have not previously cached an embedding so we need to determine it # get the adjacency structure of our problem S = set(J) S.update({(v, v) for v in h}) # embed our adjacency structure, S, into the edgeset of the sampler. embeddings = find_embedding(S, edgeset) # sometimes it fails, often because the problem is too large if J and not embeddings: raise Exception('No embedding found') # now it is possible that h_list might include nodes not in embedding, so let's # handle that case here if len(h_list) > len(embeddings): emb_qubits = set().union(*embeddings) while len(h_list) > len(embeddings): for v in sampler.solver.properties['qubits']: if v not in emb_qubits: embeddings.append([v]) emb_qubits.add(v) break if embedding_tag is not None: # save the embedding for posterity self.cached_embeddings[embedding_tag] = embeddings else: # the user has asserted that we can reuse a previously created embedding embeddings = self.cached_embeddings[embedding_tag] # embed the problem h0, j0, jc, new_emb = embed_problem(h_list, J, embeddings, edgeset) # combine jc and j0 emb_j = j0.copy() emb_j.update(jc) # pass the chains we made into the sampler if it wants them if 'chains' in sampler.solver.properties['parameters'] and 'chains' not in sapi_kwargs: sapi_kwargs['chains'] = new_emb # invoke the child sampler emb_response = sampler.sample_ising(h0, emb_j, **sapi_kwargs) # we need the samples back into lists for the unembed_answer function answers = [[sample[i] for i in range(len(sample))] for sample in emb_response] # unemnbed solutions = unembed_answer(answers, new_emb, 'minimize_energy', h_list, J) # and back once again into dicts for dimod... samples = ({v: sample[v] for v in h} for sample in solutions) sample_data = (data for __, data in emb_response.samples(data=True)) response = dimod.SpinResponse() response.add_samples_from(samples, sample_data=sample_data, h=h, J=J) return response
def find_dwave_embedding(logical, optimize, verbosity): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" edges = logical.strengths.keys() edges.sort() try: hw_adj = get_hardware_adjacency(qasm.solver) except KeyError: # The Ising heuristic solver is an example of a solver that lacks a # fixed hardware representation. We therefore assert that the hardware # exactly matches the problem'input graph. hw_adj = edges # Determine the edges of a rectangle of cells we want to use. L, M, N = qasm.chimera_topology(qasm.solver) L2 = 2 * L ncells = (qasm.next_sym_num + 1) // L2 if optimize: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M # Announce what we're about to do. if verbosity >= 2: sys.stderr.write( "Embedding the logical adjacency within the physical topology.\n\n" ) # Repeatedly expand edgex and edgey until the embedding works. while edgex <= M and edgey <= N: # Retain adjacencies only within the rectangle. alt_hw_adj = [] for q1, q2 in hw_adj: c1 = q1 // L2 if c1 % M >= edgex: continue if c1 // M >= edgey: continue c2 = q2 // L2 if c2 % M >= edgex: continue if c2 // M >= edgey: continue alt_hw_adj.append((q1, q2)) alt_hw_adj = set(alt_hw_adj) # Try to find an embedding. if verbosity >= 2: sys.stderr.write(" Trying a %dx%d unit-cell embedding ... " % (edgex, edgey)) status_file = tempfile.NamedTemporaryFile(mode="w", delete=False) stdout_fd = os.dup(sys.stdout.fileno()) os.dup2(status_file.fileno(), sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.dup2(stdout_fd, sys.stdout.fileno()) status_file.close() if len(embedding) > 0: sys.stderr.write("succeeded\n\n") else: sys.stderr.write("failed\n\n") with open(status_file.name, "r") as status: for line in status: sys.stderr.write(" %s" % line) sys.stderr.write("\n") os.remove(status_file.name) else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) if len(embedding) > 0: # Success! break # Failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not (edgex <= M and edgey <= N): qasm.abend("Failed to embed the problem") # Store in the logical problem additional information about the embedding. logical.embedding = embedding logical.hw_adj = alt_hw_adj logical.edges = edges
def solvequbo(self): # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # EMBEDDING: # gets the hardware adjacency for the solver in use. self.Adjacency = get_hardware_adjacency(self.solver) # gets the embedding for the D-Wave hardware self.Embedding = find_embedding(self.qubo_dict, self.Adjacency) # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # CONVERSIONS AND RESCALING: # convert qubo to ising (self.h, self.J, self.ising_offset) = qubo_to_ising(self.qubo_dict) # Even though auto_scale = TRUE, we are rescaling values # Normalize h and J to be between +/-1 self.h_max = max(map(abs, self.h)) if len(self.J.values()) > 0: j_max = max([abs(x) for x in self.J.values()]) else: j_max = 1 # In [0,1], this scales down J values to be less than jc j_scale = 0.8 # Use the largest large value if self.h_max > j_max: j_max = self.h_max # This is the actual scaling rescale = j_scale / j_max self.h1 = map(lambda x: rescale * x, self.h) if len(self.J.values()) > 0: self.J1 = {key: rescale * val for key, val in self.J.items()} else: self.J1 = self.J # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # EMBEDDING: # gets the hardware adjacency for the solver in use. self.Adjacency = get_hardware_adjacency(self.solver) # gets the embedding for the D-Wave hardware self.Embedding = find_embedding(self.qubo_dict, self.Adjacency) # Embed the rescale values into the hardware graph [self.h0, self.j0, self.jc, self.Embedding ] = embed_problem(self.h1, self.J1, self.Embedding, self.Adjacency, self.clean, self.smear, self.h_range, self.J_range) # embed_problem returns two J's, one for the biases from your problem, one for the chains. self.j0.update(self.jc) # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # SOLVE PROBLEM ON D-WAVE: # generate the embedded solution to the ising problem. self.dwave_return = solve_ising(self.solver, self.h0, self.j0, **self.params) #print("dwave_return") #print(self.dwave_return['solutions']) # the unembedded answer to the ising problem. unembed = np.array( unembed_answer(self.dwave_return['solutions'], self.Embedding, broken_chains="minimize_energy", h=self.h, j=self.J)) #[0] # convert ising string to qubo string ising_ans = [ list(filter(lambda a: a != 3, unembed[i])) for i in range(len(unembed)) ] #print(ising_ans) #print("ISING ANS") # Because the problem is unembedded, the energy will be different for the embedded, and unembedded problem. # ising_energies = dwave_return['energies'] self.h_energy = [ sum(self.h1[v] * val for v, val in enumerate(unembed[i])) for i in range(len(unembed)) ] self.J_energy = [ sum(self.J1[(u, v)] * unembed[i, u] * unembed[i, v] for u, v in self.J1) for i in range(len(unembed)) ] self.ising_energies = np.array(self.h_energy) + np.array(self.J_energy) #print(self.h_energy) #print(self.J_energy) #print(self.ising_energies) #print("ENERGIES") # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # CONVERT ANSWER WITH ENERGY TO QUBO FORM: # Rescale and add back in the ising_offset and another constant self.dwave_energies = self.ising_energies / rescale + self.ising_offset #[map(lambda x: (x / rescale + self.ising_offset), self.ising_energies[i]) for i in range(len(self.ising_energies))] # QUBO RESULTS: self.qubo_ans = ( np.array(ising_ans) + 1 ) / 2 #[map(lambda x: (x + 1) / 2, ising_ans[i]) for i in range(len(ising_ans))]
def find_dwave_embedding(logical, optimization, verbosity, hw_adj_file): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [e for e in logical.strengths.keys() if logical.strengths[e] != 0.0] edges.sort() logical.edges = edges if hw_adj_file == None: try: hw_adj = get_hardware_adjacency(qmasm.solver) except KeyError: # The Ising heuristic solver is an example of a solver that lacks a # fixed hardware representation. We therefore assert that the # hardware is an all-to-all network that connects every node to # every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] else: hw_adj = read_hardware_adjacency(hw_adj_file, verbosity) # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. If we read # the topology from a file or otherwise can't prove that we have a Chimera # graph, we call this rectangle 0x0 and force the main embedding loop to # exit after a single iteration because we don't know the topology is even # rectangular. edgex = 0 edgey = 0 M = 0 N = 0 num_vars = len(qmasm.sym_map.all_numbers()) try: if hw_adj_file == None: L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2*L ncells = (num_vars + L2) // L2 # Round up the number of cells. if optimization >= 2: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M except qmasm.NonChimera: pass # Announce what we're about to do. if verbosity >= 2: sys.stderr.write("Embedding the logical adjacency within the physical topology.\n\n") # Repeatedly expand edgex and edgey until the embedding works. while edgex <= M and edgey <= N: if edgex == M and edgey == N: alt_hw_adj = hw_adj else: # Retain adjacencies only within the rectangle. alt_hw_adj = [] for q1, q2 in hw_adj: c1 = q1//L2 if c1 % M >= edgex: continue if c1 // M >= edgey: continue c2 = q2//L2 if c2 % M >= edgex: continue if c2 // M >= edgey: continue alt_hw_adj.append((q1, q2)) alt_hw_adj = set(alt_hw_adj) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write(" No embedding cache directory was specified ($QMASMCACHE).\n") else: sys.stderr.write(" Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write(" Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write(" Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write(" No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if embedding != []: if verbosity >= 2: # SAPI's find_embedding is hard-wired to write to stdout. # Trick it into writing into a pipe instead. if edgex == 0 and edgey == 0: sys.stderr.write(" Trying to embed ... ") else: sys.stderr.write(" Trying a %dx%d unit-cell embedding ...\n\n" % (edgex, edgey)) sepLine = "=== EMBEDDING ===\n" r, w = os.pipe() pid = os.fork() if pid == 0: # Child -- perform the embedding. os.close(r) os.dup2(w, sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.write(w, sepLine) os.write(w, json.dumps(embedding) + "\n") os.close(w) os._exit(0) else: # Parent -- report the embedding's progress. os.close(w) pipe = os.fdopen(r, "r", 10000) while True: try: rstr = pipe.readline() if rstr == sepLine: break if rstr == "": qmasm.abend("Embedder failed to terminate properly") sys.stderr.write(" %s" % rstr) except: pass # Receive the embedding from the child. embedding = json.loads(pipe.readline()) sys.stderr.write("\n") else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not(edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding
#A = util.get_chimera_adjacency(1,1,4) S_size = 3 #S = {} # A list should work as well as a dictionary. # Only required to be an iterable specifying pairs of nodes. S = [] for i in range(S_size): for j in range(S_size): # S[(i,j)] = 1 S.append((i, j)) print S emb = embedding.find_embedding(S, A, verbose=1) print emb Q = {(0, 0): 1, (1, 1): 1, (2, 2): 1, (0, 1): 1, (0, 2): -2, (1, 2): -2} (h, j, ising_offset) = util.qubo_to_ising(Q) print "h:", h print "j:", j print "ising_offset:", ising_offset (h0, j0, jc, new_emb) = embedding.embed_problem(h, j, emb, A) print "h0:", h0 print "j0:", j0 print "jc:", jc