def heuristicEmbed(solver_name, K): ''' Finds heuristic embedding for solver_name. Parameters: ---------- solver_name: str. Name of solver to connect to. Can be 'NASA','DW', or 'ISI'. K: the length of embedding. If K is an int, generates a complete graph embedding. Otherwise, assumes K is an iterable with couplings specified. ''' solver = connectSolver(solver_name) hardware_adj = get_hardware_adjacency(solver) # generate adjacency for complete graph if isinstance(K, int): J = np.triu(np.ones((K, K))) J_it = [ index for index, v in np.ndenumerate(J) if not np.isclose(v, 0) ] else: J_it = K embedding = find_embedding(J_int, hardware_adj) return embedding
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 sign_in(): global solver global adj print('Connecting to DWave') remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver(solver_name) adj = list(get_hardware_adjacency(solver)) print('Connected to DWave')
def get_native_embedding(solver): params = solver.properties.get('parameters', {}) #M = params.get('M', 12) #N = params.get('N', 12) M = params.get('M', 16) N = params.get('N', 16) L = params.get('L', 4) hardware_adj = get_hardware_adjacency(solver) embedder = processor(hardware_adj, M=M, N=N, L=L) embedding = embedder.largestNativeClique() return embedding
def __init__(self, solver_name, url, token, proxy_url=None): dimod.TemplateSampler.__init__(self) if proxy_url is None: self.connection = connection = RemoteConnection(url, token) else: self.connection = connection = RemoteConnection( url, token, proxy_url) self.solver = solver = connection.get_solver(solver_name) edges = get_hardware_adjacency(solver) self.structure = (set().union(*edges), edges)
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 balancedEmbed(solver_name, K): ''' Finds balanced embedding for solver_name. Parameters: ---------- solver_name: str. Name of solver to connect to. Can be 'NASA','DW', or 'ISI'. K: the length of embedding. Assumes a complete graph embedding ''' solver = connectSolver(solver_name) hardware_adj = get_hardware_adjacency(solver) if solver_name == 'ISI': M = 12 N = 12 else: M = 16 N = 16 embedder = processor(hardware_adj, M=M, N=N, L=4) embedding = embedder.tightestNativeClique(K) return embedding
def test(): solver = flexmock(properties={'couplers': [(0, 1), (3, 2), [10, 100]]}) assert get_hardware_adjacency(solver) == set([(0, 1), (1, 0), (2, 3), (3, 2), (10, 100), (100, 10)])
def runDW(h, J, embedding, stop_point=0.25, num_reads=1000, coupling_init=1.0, coupling_increment=0.1, min_solver_calls=1, max_solver_calls=1000, method='vote', last=True, num_gauges=1, solver_name='NASA', annealing_time=20): ''' Submits an instance to DW. Parameters ----- h : list, a list of fields J : a dictionary, where keys are a tuple corresponding to the coupling embedding : a list of lists. Can use DW sapi to generate stop_point :float, default: 0.25. Stop increasing coupling strength when returns at least this fraction of solutions are unbroken. num_reads: int, default: 1000. The number of reads. coupling_init: float, default: 1.0. The initial value of coupling, the value of the ferromagnetic coupling between physical qubits. If number of unbroken of solutions is not at least stop_point, then the magnitude of coupling is incremented by coupling_increment. Note however, that the though we specify coupling_init as positive, the coupling is negative. For example, Suppose coupling_init=1.0, coupling_increment (defined below) is 0.1, and stop_point = 0.25. The initial physical ferromagnetic coupling strength will be -1.0. If stop_point isn't reached, coupling is incremented by 0.1, or in other words, the new chain strength is -1.1. coupling is incremented by coupling_increment until stop_point is reached. coupling_increment: float, default: 0.1. Increment of coupling strength, min_solver_calls: int, default: 1. The minimum number of solver calls. max_solver_calls: int, default: 1000. The maximum number of solver calls. method: str, 'minimize_energy', 'vote', or 'discard', default: 'minimize_energy' How to deal with broken chains. 'minimize_energy' uses the energy minimization decoding. 'vote' uses majority vote decoding. 'discard' discard broken chains. last: bool, default: True If True, return the last num_reads solutions. If False, return the first num_reads solutions. num_gauges: int, default: 1 Number of gauge transformations. solver_name: str, 'NASA', 'ISI', or 'DW', default: 'NASA' Which solver to use. 'NASA' uses NASA's DW2000Q. 'ISI' uses ISI's DW2X. 'DW' uses DW's DW2000Q. Returns ------- A tuple of sols, c, ratio sols: numpy ndarray, shape = [num_reads, num_spins] Solutions where each row is a set of spins (num_spins dependent on solver) c: float The final value of the coupling strength used ratio: float The final fraction of unbroken solutions returned at coupling_strength c ''' meths = ['discard', 'vote', 'minimize_energy'] assert (method in meths) solver = connectSolver(solver_name) A = get_hardware_adjacency(solver) # embed problem (h0, j0, jc, new_emb) = embed_problem(h, J, embedding, A) # scale problem maxjh = max(max(np.abs(h0)), max(np.abs(j0.values()))) h0 = [el / maxjh for el in h0] j0 = {ij: v / maxjh for ij, v in zip(j0.keys(), j0.values())} ratio = 0 sols = [] ncalls = 0 l = coupling_init print coupling_init jc = dict.fromkeys(jc, -l) emb_j = j0.copy() emb_j.update(jc) kwargs = { 'num_reads': num_reads, 'num_spin_reversal_transforms': num_gauges, 'answer_mode': 'raw', 'annealing_time': annealing_time } # iteratively increase ferromagentic strength until returns a certain ratio # of solutions where there are no broken chains while ratio <= stop_point and ncalls < max_solver_calls: jc = dict.fromkeys(jc, -l) emb_j = j0.copy() emb_j.update(jc) if solver_name == 'ISI': _check_wait() problem = async_solve_ising(solver, h0, emb_j, **kwargs) await_completion([problem], 1, 50000) answer = problem.result() result = unembed_answer(answer['solutions'], new_emb, broken_chains='discard', h=h, j=J) sols += result nSols = len(result) l = l + coupling_increment ratio = nSols / float(len(answer['solutions'])) ncalls = ncalls + 1 print ratio # Don't remember why do this. Maybe for good measure if method == 'discard': nAdd = int(1 / ratio) + 1 else: nAdd = 1 l = l - coupling_increment for n in range(nAdd): if solver_name == 'ISI': _check_wait() problem = async_solve_ising(solver, h0, emb_j, **kwargs) await_completion([problem], 1, 50000) answer = problem.result() result = unembed_answer(answer['solutions'], new_emb, broken_chains=method, h=h, j=J) sols += result if len(sols) < num_reads: # try one more time problem = async_solve_ising(solver, h0, emb_j, **kwargs) await_completion([problem], 1, 50000) answer = problem.result() result = unembed_answer(answer['solutions'], new_emb, broken_chains=method, h=h, j=J) sols += result if last: if len(sols) >= num_reads: sols = sols[-num_reads:] else: print 'WARNING! DID NOT COLLECT ENOUGH READS...continuing' else: sols = sols[:num_reads] return (np.array(sols, dtype=np.int8), l, ratio)
def runDW_batch(h, J, embedding, stop_point=0.25, num_reads=1000, coupling_init=1.0, coupling_increment=0.1, min_solver_calls=1, max_solver_calls=1000, method='vote', last=True, num_gauges=1, solver_name='NASA', returnProblems=True): ''' Submits an instance to DW as a batch. Note that when used, sometimes the solutions are markedly different than when use runDW (no batch). Generally using run_DW() seems to be a better idea Parameters ----- h : list of lists, with each list is a list of fields J : a list of dictionary, where keys are a tuple corresponding to the coupling. Should be the same length as h. embedding : a list of lists. Can use DW sapi to generate stop_point :float, default: 0.25. Stop increasing coupling strength when returns at least this fraction of solutions are unbroken. num_reads: int, default: 1000. The number of reads. coupling_init: float, default: 1.0. The initial value of coupling, the value of the ferromagnetic coupling between physical qubits. If number of unbroken of solutions is not at least stop_point, then the magnitude of coupling is incremented by coupling_increment. Note however, that the though we specify coupling_init as positive, the coupling is negative. For example, Suppose coupling_init=1.0, coupling_increment (defined below) is 0.1, and stop_point = 0.25. The initial physical ferromagnetic coupling strength will be -1.0. If stop_point isn't reached, coupling is incremented by 0.1, or in other words, the new chain strength is -1.1. coupling is incremented by coupling_increment until stop_point is reached. coupling_increment: float, default: 0.1. Increment of coupling strength, min_solver_calls: int, default: 1. The minimum number of solver calls. max_solver_calls: int, default: 1000. The maximum number of solver calls. method: str, 'minimize_energy', 'vote', or 'discard', default: 'minimize_energy' How to deal with broken chains. 'minimize_energy' uses the energy minimization decoding. 'vote' uses majority vote decoding. 'discard' discard broken chains. last: bool, default: True If True, return the last num_reads solutions. If False, return the first num_reads solutions. num_gauges: int, default: 1 Number of gauge transformations. solver_name: str, 'NASA', 'ISI', or 'DW', default: 'NASA' Which solver to use. 'NASA' uses NASA's DW2000Q. 'ISI' uses ISI's DW2X. 'DW' uses DW's DW2000Q. returnProblems: bool Determines what it returns. If True, return problems, new_emb. If False return solutions only Returns ------- if returnProblems is True, returns problems, new_emb (to be used with get_async_sols) problems: list list of problems from async_solve_ising new_emb: list list of embeddings returned from embed_problem if returnProblems is False, returns solutions sols: np array Array of solutions ''' meths = ['discard', 'vote', 'minimize_energy'] assert (method in meths) if solver_name == 'NASA': url = 'https://qfe.nas.nasa.gov/sapi' token = 'NASA-870f7ee194d029923ad8f9cd063de357ba53b838' remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver('C16') elif solver_name == 'ISI': url = 'https://usci.qcc.isi.edu/sapi' token = 'QUCB-089028555cb44b4f3da34cd4c6dd4a73ec859bc8' remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver('DW2X') elif solver_name == 'DW': url = 'https://cloud.dwavesys.com/sapi' token = 'usc-171bafd63a1b07635fd696db283ad4c28b820d14' remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver('DW_2000Q_2_1') else: NameError('Unrecognized solver name') A = get_hardware_adjacency(solver) h0 = [] j0 = [] jc = [] new_emb = [] for n in range(len(h)): (h0t, j0t, jct, new_embt) = embed_problem(h[0], J[0], embedding, A) maxjh = max(max(np.abs(h0t)), max(np.abs(j0t.values()))) h0t = [el / maxjh for el in h0t] j0t = {ij: v / maxjh for ij, v in zip(j0t.keys(), j0t.values())} h0.append(h0t) j0.append(j0t) jc.append(jct) new_emb.append(new_embt) ncalls = 0 sols = np.empty(len(h0), dtype=object) if isinstance(coupling_init, list): l = coupling_init else: l = [coupling_init] * len(h) print np.unique(l) kwargs = { 'num_reads': num_reads, 'num_spin_reversal_transforms': num_gauges, 'answer_mode': 'raw' } problem = [] for n in range(len(h0)): jct = dict.fromkeys(jc[n], -l[n]) emb_j = j0[n].copy() emb_j.update(jct) if solver_name == 'ISI': _check_wait() problem.append(async_solve_ising(solver, h0[n], emb_j, **kwargs)) await_completion(problem, len(h), 50000) if returnProblems: return problem, new_emb for n in range(len(h0)): answer = problem[n].result() sols[n] = np.array(unembed_answer(answer['solutions'], new_emb[n], broken_chains=method, h=h[n], j=J[n]), dtype=np.int8) # return problem,new_emb return np.array(sols)
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])
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 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, 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
def dwave_embed(pot, overkill=True): #global solver #global adj #if solver == 0: sign_in() remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver(solver_name) adj = list(get_hardware_adjacency(solver)) #print('Connecting to DWave') #remote_connection = RemoteConnection('https://qfe.nas.nasa.gov/sapi', 'NASA-f73f6a756b922f9ebfcb6127740bec11bf986527') #solver = remote_connection.get_solver('C16') #adj = list(get_hardware_adjacency(solver)) const, h_, j, prob_adj = dwave_prepare(pot) embedding = [] if overkill: emb = {} beta = 2 max_length = 10e9 try: while emb == {} or max_length > 4: for i in range(3): emb_ = find_embedding(prob_adj, adj, max_beta=beta) # only take this embedding if it has a shorter max length if emb_ != {} and max([len(c) for c in emb_.values() ]) < max_length: emb = emb_.copy() max_length = max([len(c) for c in emb.values()]) if max_length < 4: break if beta > 64: emb_ = find_embedding(prob_adj, adj, tries=100) if emb_ != {} and max([len(c) for c in emb_.values() ]) < max_length: emb = emb_.copy() max_length = max([len(c) for c in emb.values()]) break beta = beta * 2 except RuntimeError as err: print(err) emb = find_embedding(prob_adj, adj) if emb == {}: print('Unable to find embedding for problem') return [False] * 4 else: print('Found an embedding') embedding = emb.values() else: while len(embedding) == 0: embedding = find_embedding(prob_adj, adj).values() remote_connection = 0 solver = 0 adj = 0 return embedding
def __init__(self): self.connection = RemoteConnection(config.DWAVE_SAPI_URL, config.DWAVE_TOKEN, config.DWAVE_PROXY) self.solver = self.connection.get_solver(config.DWAVE_SOLVER) self.adjacency_matrix = get_hardware_adjacency(self.solver)
def dwave(pot, states): if pot['num vars'] > 0: solved = False const = 0 h_ = [] J_ = {} state = [] free_state = [] embedding = [] while not solved: try: #global solver #global adj #if solver == 0: sign_in() #should try to make it so there is a pool of pool_size connections that the various threads can use remote_connection = RemoteConnection(url, token) solver = remote_connection.get_solver(solver_name) adj = list(get_hardware_adjacency(solver)) if 'embedding' in pot: const, h_, j, prob_adj = dwave_prepare(pot) embedding = pot['embedding'] else: # if we're doing a new embedding for each f -> v in state i message, then we'll have frozen a variable # so we need to remap the variables, since otherwise the h will have a 0 for this variable, but the embedding won't consider it map_vars(pot) const, h_, j, prob_adj = dwave_prepare(pot) while len(embedding) == 0: embedding = find_embedding(prob_adj, adj).values() [h, J, chains, embedding] = embed_problem(h_, j, embedding, adj) s = 0.50 h = [a * s for a in h] for k in J: J[k] = J[k] * s for k in chains: if k in J: J[k] += chains[k] else: J[k] = chains[k] # Submit problem #print('submitting problem') submitted_problems = [ async_solve_ising(solver, h, J, num_reads=10000, num_spin_reversal_transforms=5, answer_mode='histogram', auto_scale=True) ] await_completion(submitted_problems, len(submitted_problems), float('180')) res = unembed_answer( submitted_problems[0].result()['solutions'], embedding, 'discard') if len(res) > 0: state = array(res[0]) solved = True except Exception as err: print(err) solved = False #sleep(30) # wait 30 seconds and retry if len(h_) != len(state): print(h_, len(h_)) print(state, len(state)) print(pot) J_, _ = dict_2_mat(j, len(h_)) energy = h_.dot(state) + state.dot(J_.dot(state.transpose())) + const #for v in sorted(free_state): # energy += pot[v]*free_state[v] # state = append(state, free_state[v]) return energy, state else: if 'const' in pot: return pot['const'], states[0] else: return 0, states[0]
# from dwave_sapi2.core import remote # sapi_url = 'https://dw2x.dwavesys.com/sapi' # sapi_token = 'ENTER SAPI TOKEN' # solver_name = 'DW2X' # connection = remote.RemoteConnection(sapi_url, sapi_token) # solver = connection.get_solver(solver_name) #~ #~ Now that we're connected, let's pull down the adjacency information from #~ the solver. This is just a set of tuples ``(p, q)`` of qubit labels. Using #~ the ``c4-sw_optimize`` solver, this is simply a :math:`C_{4,4,4}` Chimera #~ graph. If you're using a hardware solver, this will be something more #~ interesting. #~ hardware_adj = get_hardware_adjacency(solver) #~ Reading the file in #~ ^^^^^^^^^^^^^^^^^^^ #~ #~ Here, we're going to read the embedding file. As explained in the previous #~ example, we've used the simplest file format possible; a text file where #~ every line corresponds to a chain of qubits, represented by a space- #~ delimited list of qubit labels. #~ embedding_file = open("embedded_clique_largest") embedding = [] for line in embedding_file: line = line.strip() # remove trailing newline if present
def __init__(self, solver_name): dimod.TemplateSampler.__init__(self) self.solver = solver = local_connection.get_solver(solver_name) edges = get_hardware_adjacency(solver) self.structure = (set().union(*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))]
# from dwave_sapi2.core import remote # sapi_url = 'https://cloud.dwavesys.com/sapi' # sapi_token = 'ENTER SAPI TOKEN' # solver_name = 'DW_2000Q_5' # connection = remote.RemoteConnection(sapi_url, sapi_token) # solver = connection.get_solver(solver_name) #~ #~ Now that we're connected, let's pull down the adjacency information from #~ the solver. This is just a set of tuples ``(p, q)`` of qubit labels. Using #~ the ``c4-sw_optimize`` solver, this is simply a :math:`C_{4,4,4}` Chimera #~ graph. If you're using a hardware solver, this will be something more #~ interesting. #~ hardware_adj = get_hardware_adjacency(solver) #~ Reading the file in #~ ^^^^^^^^^^^^^^^^^^^ #~ #~ Here, we're going to read the embedding file. As explained in the previous #~ example, we've used the simplest file format possible; a text file where #~ every line corresponds to a chain of qubits, represented by a space- #~ delimited list of qubit labels. The file also contains a single blank line #~ separating the two sides of the partition. #~ embedding_file = open("embedded_biclique_largest") found_blank = False embedding = [[], []] for line in embedding_file:
import dwave_sapi2.remote as remote import dwave_sapi2.local as local import dwave_sapi2.core as core import dwave_sapi2.util as util import dwave_sapi2.embedding as embedding import numpy as np #conn = remote.RemoteConnection('https://localhost:10443/sapi', 'TOKEN') #solver = conn.get_solver("DW2X") conn = local.local_connection solver = conn.get_solver("c4-sw_sample") A = util.get_hardware_adjacency(solver) #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