def test_typical(): q = { (0, 0): 4, (0, 3): 5, (0, 5): 4, (1, 1): 5, (1, 6): 1, (1, 7): -2, (1, 9): -3, (3, 0): -2, (3, 1): 2, (4, 5): 4, (4, 8): 2, (4, 9): -1, (5, 1): 2, (5, 6): -5, (5, 8): -4, (6, 0): 1, (6, 5): 2, (6, 6): -4, (6, 7): -2, (7, 0): -2, (7, 5): -3, (7, 6): -5, (7, 7): -3, (7, 8): 1, (8, 0): 2, (8, 5): 1, (9, 7): -3 } h, j, offset = qubo_to_ising(q) assert h == [4, 2.5, 0, 1.25, 1.25, 0.25, -4, -5.5, 0.5, -1.75] norm_j = normalized_matrix(j) assert norm_j == { (0, 3): 0.75, (0, 5): 1, (0, 6): 0.25, (0, 7): -0.5, (0, 8): 0.5, (1, 3): 0.5, (1, 5): 0.5, (1, 6): 0.25, (1, 7): -0.5, (1, 9): -0.75, (4, 5): 1, (4, 8): 0.5, (4, 9): -0.25, (5, 6): -0.75, (5, 7): -0.75, (5, 8): -0.75, (6, 7): -1.75, (7, 8): 0.25, (7, 9): -0.75 } assert offset == -0.25
def convert_to_ising(self): """Transform a QUBO problem into an Ising problem. Return the new Ising problem.""" if not self.qubo: raise TypeError("Can convert only QUBO problems to Ising problems") new_obj = copy.deepcopy(self) qmatrix = {(q, q): w for q, w in list(new_obj.weights.items())} qmatrix.update(new_obj.strengths) hvals, new_obj.strengths, _ = qubo_to_ising(qmatrix) new_obj.strengths = defaultdict(lambda: 0.0, new_obj.strengths) new_obj.weights.update({i: hvals[i] for i in range(len(hvals))}) new_obj.qubo = False return new_obj
def convert_to_ising(self): """Transform a QUBO problem into an Ising problem. Return the new Ising problem.""" if not self.qubo: raise TypeError("Can convert only QUBO problems to Ising problems") new_obj = copy.deepcopy(self) qmatrix = {(q, q): w for q, w in new_obj.weights.items()} qmatrix.update(new_obj.strengths) hvals, new_obj.strengths, qoffset = qubo_to_ising(qmatrix) new_obj.strengths = qmasm.canonicalize_strengths(new_obj.strengths) new_obj.weights = {i: hvals[i] for i in range(len(hvals))} new_obj.offset = qoffset new_obj.qubo = False return new_obj
def convert_to_ising(self): """Transform a QUBO problem into an Ising problem. Return the new Ising problem.""" if not self.qubo: raise TypeError("Can convert only QUBO problems to Ising problems") new_obj = copy.deepcopy(self) qmatrix = {(q, q): w for q, w in new_obj.weights.items()} qmatrix.update(new_obj.strengths) hvals, new_obj.strengths, qoffset = qubo_to_ising(qmatrix) new_obj.strengths = qmasm.canonicalize_strengths(new_obj.strengths) new_obj.weights = {i: hvals[i] for i in range(len(hvals))} new_obj.offset = qoffset new_obj.qubo = False return new_obj
def hJ(x): a, b, c = x[0] one, two, three1, three2 = getweights(graph) Q = dict() for i in range(0, len(graph.y)): Q[(i, i)] = -1 * (-b * three1[i]) for j in range(i + 1, len(graph.y)): Q[(i, j)] = -0.5 * (a * one[i][j] - c * two[i][j] - b * three2[i][j]) Q[(j, i)] = Q[(i, j)] (h, J, x) = qubo_to_ising(Q) sampler = neal.SimulatedAnnealingSampler() hp = dict() for i in range(len(h)): hp[i] = h[i] response = sampler.sample_ising(hp, J, beta_range=(0.1, 10), num_reads=5) su = 0 for r in response: su += accuracy_score([(v + 1) / 2.0 for k, v in r.items()], graph.y) return su
def simplify_problem(logical, verbosity): """Try to find spins that can be removed from the problem because their value is known a priori.""" # SAPI's fix_variables function works only on QUBOs so we have to convert. # We directly use SAPI's ising_to_qubo function instead of our own # convert_to_qubo because the QUBO has to be in matrix form. hs = qmasm.dict_to_list(logical.weights) Js = logical.strengths Q, qubo_offset = ising_to_qubo(hs, Js) # Simplify the problem if possible. simple = fix_variables(Q, method="optimized") fixed_vars = simple["fixed_variables"] # At high verbosity levels, list all of the known symbols and their value. if verbosity >= 2: # Map each logical qubit to one or more symbols. num2syms = [[] for _ in range(len(qmasm.sym2num))] max_sym_name_len = 7 for q, n in qmasm.sym2num.items(): num2syms[n].append(q) max_sym_name_len = max(max_sym_name_len, len(repr(num2syms[n])) - 1) # Output a table of know values sys.stderr.write( "Elided qubits whose low-energy value can be determined a priori:\n\n" ) if len(fixed_vars) > 0: sys.stderr.write(" Logical %-*s Value\n" % (max_sym_name_len, "Name(s)")) sys.stderr.write(" ------- %s -----\n" % ("-" * max_sym_name_len)) truval = {0: "False", +1: "True"} for q, b in sorted(fixed_vars.items()): if num2syms[q] == []: continue name_list = " ".join(sorted(num2syms[q])) sys.stderr.write(" %7d %-*s %-s\n" % (q, max_sym_name_len, name_list, truval[b])) sys.stderr.write("\n") # Return the original problem if no qubits could be elided. if verbosity >= 2: sys.stderr.write(" %6d logical qubits before elision\n" % (qmasm.next_sym_num + 1)) if len(fixed_vars) == 0: if verbosity >= 2: sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.next_sym_num + 1)) return logical # Construct a simplified problem, renumbering so as to compact qubit # numbers. new_obj = copy.deepcopy(logical) new_obj.known_values = { s: 2 * fixed_vars[n] - 1 for s, n in qmasm.sym2num.items() if n in fixed_vars } new_obj.simple_offset = simple["offset"] hs, Js, ising_offset = qubo_to_ising(simple["new_Q"]) qubits_used = set([i for i in range(len(hs)) if hs[i] != 0.0]) for q1, q2 in Js.keys(): qubits_used.add(q1) qubits_used.add(q2) qmap = dict(zip(sorted(qubits_used), range(len(qubits_used)))) new_obj.chains = {(qmap[q1], qmap[q2]): None for q1, q2 in new_obj.chains.keys() if q1 in qmap and q2 in qmap} new_obj.weights = defaultdict( lambda: 0.0, {qmap[i]: hs[i] for i in range(len(hs)) if hs[i] != 0.0}) new_obj.strengths = qmasm.canonicalize_strengths({ (qmap[q1], qmap[q2]): wt for (q1, q2), wt in Js.items() }) new_obj.pinned = [(qmap[q], b) for q, b in new_obj.pinned if q in qmap] qmasm.sym2num = {s: qmap[q] for s, q in qmasm.sym2num.items() if q in qmap} try: qmasm.next_sym_num = max(qmasm.sym2num.values()) except ValueError: qmasm.next_sym_num = -1 if verbosity >= 2: sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.next_sym_num + 1)) return new_obj
def q_to_i(Q): # wrapper function for DW's qubo_to_ising # h,J,offset = q_to_i(Q) return qubo_to_ising(Q)
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 simplify_problem(logical, verbosity): """Try to find spins that can be removed from the problem because their value is known a priori.""" # SAPI's fix_variables function works only on QUBOs so we have to convert. # We directly use SAPI's ising_to_qubo function instead of our own # convert_to_qubo because the QUBO has to be in matrix form. hs = qmasm.dict_to_list(logical.weights) Js = logical.strengths Q, qubo_offset = ising_to_qubo(hs, Js) # Simplify the problem if possible. simple = fix_variables(Q, method="standard") fixed_vars = simple["fixed_variables"] if verbosity >= 2: # Also determine if we could get rid of more qubits if we care about # only *a* solution rather than *all* solutions. alt_simple = fix_variables(Q, method="optimized") all_gone = len(alt_simple["new_Q"]) == 0 # At high verbosity levels, list all of the known symbols and their value. if verbosity >= 2: # Map each logical qubit to one or more symbols. num2syms = [[] for _ in range(qmasm.sym_map.max_number() + 1)] max_sym_name_len = 7 for q, n in qmasm.sym_map.symbol_number_items(): num2syms[n].append(q) max_sym_name_len = max(max_sym_name_len, len(repr(num2syms[n])) - 1) # Output a table of know values sys.stderr.write("Elided qubits whose low-energy value can be determined a priori:\n\n") if len(fixed_vars) > 0: sys.stderr.write(" Logical %-*s Value\n" % (max_sym_name_len, "Name(s)")) sys.stderr.write(" ------- %s -----\n" % ("-" * max_sym_name_len)) truval = {0: "False", +1: "True"} for q, b in sorted(fixed_vars.items()): try: syms = qmasm.sym_map.to_symbols(q) except KeyError: continue name_list = " ".join(sorted(syms)) sys.stderr.write(" %7d %-*s %-s\n" % (q, max_sym_name_len, name_list, truval[b])) sys.stderr.write("\n") # Return the original problem if no qubits could be elided. if verbosity >= 2: sys.stderr.write(" %6d logical qubits before elision\n" % (qmasm.sym_map.max_number() + 1)) if len(fixed_vars) == 0: if verbosity >= 2: sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.sym_map.max_number() + 1)) if all_gone: sys.stderr.write(" Note: A complete solution can be found classically using roof duality and strongly connected components.\n\n") return logical # Construct a simplified problem, renumbering so as to compact qubit # numbers. new_obj = copy.deepcopy(logical) new_obj.known_values = {s: 2*fixed_vars[n] - 1 for s, n in qmasm.sym_map.symbol_number_items() if n in fixed_vars} new_obj.simple_offset = simple["offset"] hs, Js, ising_offset = qubo_to_ising(simple["new_Q"]) qubits_used = set([i for i in range(len(hs)) if hs[i] != 0.0]) for q1, q2 in Js.keys(): qubits_used.add(q1) qubits_used.add(q2) qmap = dict(zip(sorted(qubits_used), range(len(qubits_used)))) new_obj.chains = set([(qmap[q1], qmap[q2]) for q1, q2 in new_obj.chains if q1 in qmap and q2 in qmap]) new_obj.weights = defaultdict(lambda: 0.0, {qmap[i]: hs[i] for i in range(len(hs)) if hs[i] != 0.0}) new_obj.strengths = qmasm.canonicalize_strengths({(qmap[q1], qmap[q2]): wt for (q1, q2), wt in Js.items()}) new_obj.pinned = [(qmap[q], b) for q, b in new_obj.pinned if q in qmap] qmasm.sym_map.overwrite_with({s: qmap[q] for s, q in qmasm.sym_map.symbol_number_items() if q in qmap}) if verbosity >= 2: # Report the number of logical qubits that remain, but compute the # number that could be removed if only a single solution were required. sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.sym_map.max_number() + 1)) if all_gone: sys.stderr.write(" Note: A complete solution can be found classically using roof duality and strongly connected components.\n\n") return new_obj
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 simplify_problem(logical, verbosity): """Try to find spins that can be removed from the problem because their value is known a priori.""" # SAPI's fix_variables function works only on QUBOs so we have to convert. # We directly use SAPI's ising_to_qubo function instead of our own # convert_to_qubo because the QUBO has to be in matrix form. hs = qmasm.dict_to_list(logical.weights) Js = logical.strengths Q, qubo_offset = ising_to_qubo(hs, Js) # Simplify the problem if possible. simple = fix_variables(Q, method="standard") new_Q = simple["new_Q"] fixed_vars = simple["fixed_variables"] if verbosity >= 2: # Also determine if we could get rid of more qubits if we care about # only *a* solution rather than *all* solutions. alt_simple = fix_variables(Q, method="optimized") all_gone = len(alt_simple["new_Q"]) == 0 # Work around the rare case in which fix_variables drops a variable # entirely, leaving it neither in new_Q nor in fixed_variables. If this # happenes, we explicitly re-add the variable from Q to new_Q and # transitively everything it touches (removing from fixed_vars if a # variable appears there). old_vars = qubo_vars(Q) new_vars = qubo_vars(new_Q) new_vars.update(fixed_vars) missing_vars = sorted(old_vars.difference(new_vars)) while len(missing_vars) > 0: q = missing_vars.pop() for (q1, q2), val in Q.items(): if q1 == q or q2 == q: new_Q[(q1, q2)] = val fixed_vars.pop(q1, None) fixed_vars.pop(q2, None) if q1 == q and q2 > q: missing_vars.append(q2) elif q2 == q and q1 > q: missing_vars.append(q1) # At high verbosity levels, list all of the known symbols and their value. if verbosity >= 2: # Map each logical qubit to one or more symbols. num2syms = [[] for _ in range(qmasm.sym_map.max_number() + 1)] max_sym_name_len = 7 for q, n in qmasm.sym_map.symbol_number_items(): num2syms[n].append(q) max_sym_name_len = max(max_sym_name_len, len(repr(num2syms[n])) - 1) # Output a table of know values sys.stderr.write("Elided qubits whose low-energy value can be determined a priori:\n\n") if len(fixed_vars) > 0: sys.stderr.write(" Logical %-*s Value\n" % (max_sym_name_len, "Name(s)")) sys.stderr.write(" ------- %s -----\n" % ("-" * max_sym_name_len)) truval = {0: "False", +1: "True"} for q, b in sorted(fixed_vars.items()): try: syms = qmasm.sym_map.to_symbols(q) except KeyError: continue name_list = " ".join(sorted(syms)) sys.stderr.write(" %7d %-*s %-s\n" % (q, max_sym_name_len, name_list, truval[b])) sys.stderr.write("\n") # Return the original problem if no qubits could be elided. if verbosity >= 2: sys.stderr.write(" %6d logical qubits before elision\n" % (qmasm.sym_map.max_number() + 1)) if len(fixed_vars) == 0: if verbosity >= 2: sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.sym_map.max_number() + 1)) if all_gone: sys.stderr.write(" Note: A complete solution can be found classically using roof duality and strongly connected components.\n\n") return logical # Construct a simplified problem, renumbering so as to compact qubit # numbers. new_obj = copy.deepcopy(logical) new_obj.known_values = {s: 2*fixed_vars[n] - 1 for s, n in qmasm.sym_map.symbol_number_items() if n in fixed_vars} new_obj.simple_offset = simple["offset"] hs, Js, ising_offset = qubo_to_ising(new_Q) qubits_used = set([i for i in range(len(hs)) if hs[i] != 0.0]) for q1, q2 in Js.keys(): qubits_used.add(q1) qubits_used.add(q2) qmap = dict(zip(sorted(qubits_used), range(len(qubits_used)))) new_obj.chains = set([(qmap[q1], qmap[q2]) for q1, q2 in new_obj.chains if q1 in qmap and q2 in qmap]) new_obj.antichains = set([(qmap[q1], qmap[q2]) for q1, q2 in new_obj.antichains if q1 in qmap and q2 in qmap]) new_obj.weights = defaultdict(lambda: 0.0, {qmap[i]: hs[i] for i in range(len(hs)) if hs[i] != 0.0}) new_obj.strengths = qmasm.canonicalize_strengths({(qmap[q1], qmap[q2]): wt for (q1, q2), wt in Js.items()}) new_obj.pinned = [(qmap[q], b) for q, b in new_obj.pinned if q in qmap] qmasm.sym_map.overwrite_with({s: qmap[q] for s, q in qmasm.sym_map.symbol_number_items() if q in qmap}) if verbosity >= 2: # Report the number of logical qubits that remain, but compute the # number that could be removed if only a single solution were required. sys.stderr.write(" %6d logical qubits after elision\n\n" % (qmasm.sym_map.max_number() + 1)) if qmasm.sym_map.max_number() > -1 and all_gone: sys.stderr.write(" Note: A complete solution can be found classically using roof duality and strongly connected components.\n\n") return new_obj
def test_trivial(): h, j, offset = qubo_to_ising({}) assert h == [] assert j == {} assert offset == 0
def test_no_zeros(): h, j, offset = qubo_to_ising({(0, 0): 0, (4, 5): 0}) assert h == [] assert j == {} assert offset == 0
# 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 print "new_emb:", new_emb emb_j = j0.copy() emb_j.update(jc) print "emb_j:", emb_j