Beispiel #1
0
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
Beispiel #2
0
 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
Beispiel #3
0
 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
Beispiel #4
0
 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
Beispiel #5
0
Datei: energy.py Projekt: bishk/q
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
Beispiel #6
0
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)
Beispiel #8
0
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])
Beispiel #9
0
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))]
Beispiel #11
0
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
Beispiel #12
0
def test_trivial():
    h, j, offset = qubo_to_ising({})
    assert h == []
    assert j == {}
    assert offset == 0
Beispiel #13
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