예제 #1
0
파일: dwave.py 프로젝트: dennishay/qmasm
def submit_dwave_problem(verbosity, physical, samples, anneal_time, spin_revs, postproc):
    "Submit a QMI to the D-Wave."
    # Map abbreviated to full names for postprocessing types.
    postproc = {"": "", "opt": "optimization", "sample": "sampling"}[postproc]

    # Submit a QMI to the D-Wave and get back a list of solution vectors.
    solver_params = dict(chains=physical.embedding,
                         num_reads=samples,
                         annealing_time=anneal_time,
                         num_spin_reversal_transforms=spin_revs,
                         postprocess=postproc)
    unused_params = dict()
    while True:
        # Repeatedly remove parameters the particular solver doesn't like until
        # it actually works -- or fails for a different reason.
        try:
            weight_list = qmasm.dict_to_list(physical.weights)
            answer = solve_ising(qmasm.solver, weight_list, physical.strengths, **solver_params)
            break
        except ValueError as e:
            # Is there a better way to extract the failing symbol than a regular
            # expression match?
            bad_name_match = re.match(r'"(.*?)"', str(e))
            if bad_name_match == None:
                raise e
            bad_name = bad_name_match.group(1)
            unused_params[bad_name] = solver_params[bad_name]
            del solver_params[bad_name]
        except RuntimeError as e:
            qmasm.abend(e)
    if verbosity >= 2:
        # Output parameters we kept and those we discarded
        sys.stderr.write("Parameters accepted by the %s solver:\n" % qmasm.solver_name)
        if len(solver_params) > 0:
            for k, v in solver_params.items():
                sys.stderr.write("    %s = %s\n" % (k, v))
        else:
            sys.stderr.write("    [none]\n")
        sys.stderr.write("\n")
        sys.stderr.write("Parameters rejected by the %s solver:\n" % qmasm.solver_name)
        if len(unused_params) > 0:
            for k, v in unused_params.items():
                sys.stderr.write("    %s = %s\n" % (k, v))
        else:
            sys.stderr.write("    [none]\n")
        sys.stderr.write("\n")

    # Tally the occurrences of each solution
    solutions = answer["solutions"]
    semifinal_answer = unembed_answer(solutions, physical.embedding, broken_chains="vote")
    try:
        num_occurrences = {tuple(k): v
                           for k, v in zip(semifinal_answer, answer["num_occurrences"])}
    except KeyError:
        num_occurrences = {tuple(a): 1 for a in semifinal_answer}

    # Discard solutions with broken pins or broken chains.
    valid_solns = [s for s in solutions if solution_is_intact(physical, s)]
    final_answer = unembed_answer(valid_solns, physical.embedding, broken_chains="discard")
    return answer, final_answer, num_occurrences
예제 #2
0
파일: solutions.py 프로젝트: losalamos/qasm
    def discard_broken_chains(self):
        "Discard solutions with broken chains.  Return the new solutions."
        # Tally the number of occurrences of each solution, because we lose the
        # association of solution to tally when we discard solutions.
        tallies = {tuple(s.soln_spins): s.tally for s in self.solutions}

        # Re-embed the raw solution, discarding broken chains.
        raw_solns = self.answer["solutions"]
        good_solns = unembed_answer(raw_solns, self.problem.embedding,
                                    broken_chains="discard",
                                    h=self.problem.weights,
                                    j=self.problem.strengths)

        # Convert from a list to a set for rapid lookup.
        good_soln_set = set()
        for s in good_solns:
            good_soln_set.add(tuple(s))

        # Filter the solution objects, retaining only those appearing in
        # good_solns.
        solutions = []
        for s in self.solutions:
            if tuple(s.soln_spins) in good_soln_set:
                solutions.append(s)
        return solutions
예제 #3
0
    def discard_broken_chains(self):
        "Discard solutions with broken chains."
        # Tally the number of occurrences of each solution, because we lose the
        # association of solution to tally when we discard solutions.
        tallies = {tuple(s.soln_spins): s.tally for s in self.solutions}

        # Re-embed the raw solution, discarding broken chains.
        raw_solns = self.answer["solutions"]
        good_solns = unembed_answer(raw_solns, self.problem.embedding,
                                    broken_chains="discard",
                                    h=self.problem.weights,
                                    j=self.problem.strengths)

        # Convert from a list to a set for rapid lookup.
        good_soln_set = set()
        for s in good_solns:
            good_soln_set.add(tuple(s))

        # Filter the solution objects, retaining only those appearing in
        # good_solns.
        solutions = []
        for s in self.solutions:
            if tuple(s.soln_spins) in good_soln_set:
                solutions.append(s)
        self.solutions = solutions
예제 #4
0
파일: dwave.py 프로젝트: rizkg/qasm
def submit_dwave_problem(physical, samples, anneal_time):
    "Submit a QMI to the D-Wave."
    # Submit a QMI to the D-Wave and get back a list of solution vectors.
    solver_params = dict(chains=physical.embedding,
                         num_reads=samples,
                         annealing_time=anneal_time)
    while True:
        # Repeatedly remove parameters the particular solver doesn't like until
        # it actually works -- or fails for a different reason.
        try:
            answer = solve_ising(qasm.solver, physical.weights,
                                 physical.strengths, **solver_params)
            break
        except ValueError as e:
            # Is there a better way to extract the failing symbol than a regular
            # expression match?
            bad_name = re.match(r'"(.*?)"', str(e))
            if bad_name == None:
                raise e
            del solver_params[bad_name.group(1)]
        except RuntimeError as e:
            qasm.abend(e)

    # Discard solutions with broken pins or broken chains.
    solutions = answer["solutions"]
    valid_solns = [s for s in solutions if solution_is_intact(physical, s)]
    final_answer = unembed_answer(valid_solns,
                                  physical.embedding,
                                  broken_chains="discard")
    return answer, final_answer
def test_discard():
    embeddings = ({2, 5, 6}, [0], (1, 3))
    solutions = [[+1, +1, +1, +1, +3, +1, +1], [+1, +1, -1, +1, +1, -1, +1],
                 [+1, +1, -1, +1, +1, -1, -1], [+1, -1, -1, +1, +1, -1, -1],
                 [+1, -1, -1, -1, +1, -1, -1], [-1, -1, -1, -1, 33, -1, -1]]
    expected = [[+1, +1, +1], [-1, +1, +1], [-1, +1, -1], [-1, -1, -1]]
    assert unembed_answer(solutions, embeddings, 'discard') == expected
예제 #6
0
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 test_minimize_energy_easy():
    embeddings = ({0, 1}, [2], (4, 5, 6))
    h = [-1]
    j = {}
    solutions = [[-1, -1, +1, 3, -1, -1, -1], [-1, +1, -1, 3, +1, +1, +1]]
    expected = [[-1, +1, -1], [+1, -1, +1]]
    assert (unembed_answer(solutions, embeddings, 'minimize_energy', h,
                           j) == expected)
def test_discard_all():
    embeddings = [[0, 1]]
    solutions = [
        [-1, +1],
        [-1, +1],
        [+1, -1],
    ]
    assert unembed_answer(solutions, embeddings, 'discard') == []
def test_vote_ties():
    embeddings = [[0, 2], {1, 4}]
    solutions = [[+1, +1, -1, 3, -1], [-1, +1, +1, 3, -1], [+1, -1, -1, 3, +1],
                 [-1, -1, +1, 3, +1]]
    assert [
        x in (+1, -1) for s in unembed_answer(solutions, embeddings, 'vote')
        for x in s
    ]
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 ")"
예제 #11
0
파일: solutions.py 프로젝트: yinxx/qmasm
    def __init__(self, answer, problem, all_vars):
        # Store our arguments.
        self.answer = answer
        self.problem = problem
        self.all_vars = all_vars

        # Unembed the solutions.  Fix rather than discard invalid solutions.
        raw_solns = answer["solutions"]
        fixed_solns = unembed_answer(raw_solns,
                                     problem.embedding,
                                     broken_chains="minimize_energy",
                                     h=problem.weights,
                                     j=problem.strengths)

        # Define a mapping of physical to logical qubits.
        phys2log = {}
        for lq in range(len(self.problem.embedding)):
            for pq in self.problem.embedding[lq]:
                phys2log[pq] = lq

        # Establish mappings from qubit numbers to symbols.
        max_num = qmasm.sym_map.max_number()
        num2syms = [[] for _ in range(max_num + 1)]
        all_num2syms = [[] for _ in range(max_num + 1)]
        for s, n in qmasm.sym_map.symbol_number_items():
            all_num2syms[n].append(s)
            if all_vars or "$" not in s:
                num2syms[n].append(s)

        # Construct one solution object per solution.
        self.solutions = []
        try:
            tallies = answer["num_occurrences"]
        except KeyError:
            tallies = [1]
        energies = [
            (e + problem.simple_offset + problem.offset) / problem.range_scale
            for e in answer["energies"]
        ]
        for i in range(len(fixed_solns)):
            self.solutions.append(
                Solution(problem, num2syms, all_num2syms, phys2log, all_vars,
                         raw_solns[i], fixed_solns[i], tallies[i],
                         energies[i]))
예제 #12
0
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 test_weighted_random():
    # this test relies on random behaviour! yikes!
    # ensure runs and acceptance range are both suitably large
    runs = 10000
    embeddings = [(0, 3), [4, 2, 1, 5, 6, 7, 10]]
    solutions = [
        [+1, -1, -1, +1, -1, -1, -1, -1, 3, 3, -1],
        [-1, +1, +1, +1, -1, -1, -1, -1, 3, 3, -1],
    ]

    totals = [[0, 0], [0, 0]]
    for _ in xrange(runs):
        usols = unembed_answer(solutions, embeddings, 'weighted_random')
        for t, s in zip(totals, usols):
            t[0] += s[0]
            t[1] += s[1]

    assert totals[0][0] == runs
    assert totals[0][1] == -runs
    assert -400 < totals[1][0] < 400
    assert -4586 < totals[1][1] < -3986
예제 #14
0
파일: solutions.py 프로젝트: losalamos/qasm
    def __init__(self, answer, problem, all_vars):
        # Store our arguments.
        self.answer = answer
        self.problem = problem
        self.all_vars = all_vars

        # Unembed the solutions.  Fix rather than discard invalid solutions.
        raw_solns = answer["solutions"]
        fixed_solns = unembed_answer(raw_solns, problem.embedding,
                                     broken_chains="minimize_energy",
                                     h=problem.weights, j=problem.strengths)

        # Define a mapping of physical to logical qubits.
        phys2log = {}
        for lq in range(len(self.problem.embedding)):
            for pq in self.problem.embedding[lq]:
                phys2log[pq] = lq

        # Establish mappings from qubit numbers to symbols.
        max_num = qmasm.sym_map.max_number()
        num2syms = [[] for _ in range(max_num + 1)]
        all_num2syms = [[] for _ in range(max_num + 1)]
        for s, n in qmasm.sym_map.symbol_number_items():
            all_num2syms[n].append(s)
            if all_vars or "$" not in s:
                num2syms[n].append(s)

        # Construct one solution object per solution.
        self.solutions = []
        try:
            tallies = answer["num_occurrences"]
        except KeyError:
            tallies = [1]
        energies = [(e + problem.simple_offset + problem.offset)/problem.range_scale for e in answer["energies"]]
        for i in range(len(fixed_solns)):
            self.solutions.append(Solution(problem, num2syms, all_num2syms,
                                           phys2log, all_vars,
                                           raw_solns[i], fixed_solns[i],
                                           tallies[i], energies[i]))
def test_minimize_energy():
    embeddings = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 10)]
    h = []
    j = {
        (0, 1): -1,
        (0, 2): 2,
        (0, 3): 2,
        (0, 4): -1,
        (2, 1): -1,
        (1, 3): 2,
        (3, 1): -1,
        (1, 4): -1,
        (2, 3): 1,
        (4, 2): -1,
        (2, 4): -1,
        (3, 4): 1
    }
    solutions = [[-1, -1, -1, -1, -1, -1, +1, +1, +1, 3, +1],
                 [+1, +1, +1, +1, +1, -1, +1, -1, -1, 3, -1],
                 [+1, +1, -1, +1, -1, -1, -1, -1, -1, 3, -1]]
    expected = [[-1, -1, +1, +1, -1], [+1, +1, +1, -1, +1],
                [-1, -1, -1, +1, -1]]
    assert (unembed_answer(solutions, embeddings, 'minimize_energy', h,
                           j) == expected)
예제 #16
0
def get_async_sols(problems, hs, Js, new_embs, method='vote'):
    """
    Returns solution for async problem.
    
    Parameters
    ----------
    problems: list
        list of problem handles returned by async_solve_ising

    hs: list of lists
        local fields

    Js: list of dicts
        problem couplings

    new_embs: list
        embeddings returned from embed_problem

    method: str
        decoding method. Can be 'minimize_energy','vote', or 'discard'

    Returns
    -------

    """
    sols = np.empty(len(hs), dtype=object)
    for n in range(len(hs)):
        answer = problems[n].result()
        sols[n] = np.array(unembed_answer(answer['solutions'],
                                          new_embs[n],
                                          broken_chains=method,
                                          h=hs[n],
                                          j=Js[n]),
                           dtype=np.int8)

    return sols
예제 #17
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])
예제 #18
0
#~
#~ Now, we've broken a few chains.  We modified the solution array in place,
#~ so as we execute the next section, it will use this broken soltuion.
#~
#~ Interpreting embedded solutions
#~ -------------------------------
#~
#~ Now, we'll take a look at the interpretation of solutions with broken
#~ chains.  This is still a matter of active research, but the sapi client
#~ provides a few strategies.
#~
#~ We'll use the ``minimize_energy`` strategy.  The description of the
#~ strategies provided by the sapi client, can be found in the documentation
#~ for :func:`unembed_answer`.  The ``minimize_energy`` strategy considers the
#~ chains one by one, and computes the hamiltonian energies associated with
#~ setting all spins up and all spins down, across the chain, and picks the
#~ spin value for that chain which attains the lower energy before moving on
#~ to the next chain.
#~

new_answer = unembed_answer(result['solutions'], new_emb, 'minimize_energy', h, J)
print "spin | chain spins"
for spin, chain in zip(new_answer[0], embedding):
    if spin == -1:
        spin = '-'
    else:
        spin = '+'
    spins = ['+' if res0[q] == 1 else '-' for q in chain]
    print "  %s  | %s"%(spin, "".join(spins))
def test_trivial():
    assert unembed_answer([], []) == []
    assert unembed_answer([], [], 'minimize_energy') == []
    assert unembed_answer([], [], 'vote') == []
    assert unembed_answer([], [], 'discard') == []
    assert unembed_answer([], [], 'weighted_random') == []
예제 #20
0
파일: solvers.py 프로젝트: pearsona/bp
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]
예제 #21
0
파일: dwave.py 프로젝트: mikewlange/qmasm
def submit_dwave_problem(verbosity, physical, samples, anneal_time, spin_revs, postproc, discard):
    "Submit a QMI to the D-Wave."
    # Map abbreviated to full names for postprocessing types.
    postproc = {"": "", "opt": "optimization", "sample": "sampling"}[postproc]

    # Determine the annealing time to use.
    if anneal_time == None:
        try:
            # Use the default value.
            anneal_time = qmasm.solver.properties["default_annealing_time"]
        except KeyError:
            try:
                # If the default value is undefined, use the minimum allowed
                # value.
                anneal_time = qmasm.solver.properties["annealing_time_range"][0]
            except KeyError:
                # If all else fails, use 20 as a reasonable default.
                annealing_time = 20

    # Submit a QMI to the D-Wave and get back a list of solution vectors.
    solver_params = dict(chains=physical.embedding,
                         num_reads=samples,
                         annealing_time=anneal_time,
                         num_spin_reversal_transforms=spin_revs,
                         postprocess=postproc)
    unused_params = dict()
    while True:
        # Repeatedly remove parameters the particular solver doesn't like until
        # it actually works -- or fails for a different reason.
        try:
            weight_list = qmasm.dict_to_list(physical.weights)
            answer = solve_ising(qmasm.solver, weight_list, physical.strengths, **solver_params)
            break
        except ValueError as e:
            # Is there a better way to extract the failing symbol than a regular
            # expression match?
            bad_name_match = re.match(r'"(.*?)"', str(e))
            if bad_name_match == None:
                raise e
            bad_name = bad_name_match.group(1)
            unused_params[bad_name] = solver_params[bad_name]
            del solver_params[bad_name]
        except RuntimeError as e:
            qmasm.abend(e)
    if verbosity >= 2:
        # Output parameters we kept and those we discarded
        sys.stderr.write("Parameters accepted by the %s solver:\n" % qmasm.solver_name)
        if len(solver_params) > 0:
            for k, v in list(solver_params.items()):
                sys.stderr.write("    %s = %s\n" % (k, v))
        else:
            sys.stderr.write("    [none]\n")
        sys.stderr.write("\n")
        sys.stderr.write("Parameters rejected by the %s solver:\n" % qmasm.solver_name)
        if len(unused_params) > 0:
            for k, v in list(unused_params.items()):
                sys.stderr.write("    %s = %s\n" % (k, v))
        else:
            sys.stderr.write("    [none]\n")
        sys.stderr.write("\n")

    # Tally the occurrences of each solution
    solutions = answer["solutions"]
    semifinal_answer = unembed_answer(solutions, physical.embedding,
                                      broken_chains="minimize_energy",
                                      h=physical.weights, j=physical.strengths)
    try:
        num_occurrences = {tuple(k): v
                           for k, v in zip(semifinal_answer, answer["num_occurrences"])}
    except KeyError:
        num_occurrences = {tuple(a): 1 for a in semifinal_answer}

    # Discard solutions with broken pins or broken chains unless instructed not to.
    valid_solns = [s for s in solutions if solution_is_intact(physical, s)]
    num_not_broken = len(valid_solns)
    if discard in ["yes", "maybe"]:
        final_answer = unembed_answer(valid_solns, physical.embedding,
                                      broken_chains="discard",
                                      h=physical.weights, j=physical.strengths)
    if discard == "no" or (discard == "maybe" and len(final_answer) == 0):
        final_answer = semifinal_answer
    return answer, final_answer, num_occurrences, num_not_broken
예제 #22
0
def submit_dwave_problem(verbosity, physical, samples, anneal_time, spin_revs,
                         postproc, discard):
    "Submit a QMI to the D-Wave."
    # Map abbreviated to full names for postprocessing types.
    postproc = {
        "none": "",
        "opt": "optimization",
        "sample": "sampling"
    }[postproc]

    # Determine the annealing time to use.
    if anneal_time == None:
        anneal_time = get_default_annealing_time()

    # Compute a list of the number of samples to take each iteration
    # and the number of spin reversals to perform.
    samples_list = compute_sample_counts(samples, anneal_time)
    spin_rev_list = compute_spin_rev_counts(spin_revs, samples_list)
    nqmis = len(samples_list)  # Number of (non-unique) QMIs to submit

    # Submit one or more QMIs to the D-Wave.
    problems = []
    for i in range(nqmis):
        solver_params = dict(chains=physical.embedding,
                             num_reads=samples_list[i],
                             annealing_time=anneal_time,
                             num_spin_reversal_transforms=spin_rev_list[i],
                             postprocess=postproc)
        unused_params = dict()
        while True:
            # Repeatedly remove parameters the particular solver doesn't like
            # until it actually works -- or fails for a different reason.
            try:
                weight_list = qmasm.dict_to_list(physical.weights)
                p = async_solve_ising(qmasm.solver, weight_list,
                                      physical.strengths, **solver_params)
                problems.append(p)
                break
            except ValueError as e:
                # Is there a better way to extract the failing symbol than a
                # regular expression match?
                bad_name_match = re.match(r'"(.*?)"', str(e))
                if bad_name_match == None:
                    raise e
                bad_name = bad_name_match.group(1)
                unused_params[bad_name] = solver_params[bad_name]
                del solver_params[bad_name]
            except RuntimeError as e:
                qmasm.abend(e)
    if verbosity >= 2:
        report_parameters_used(solver_params, unused_params)

    # Output problem IDs as soon as they become available.
    if verbosity >= 1:
        try:
            while any([
                    problems[i].status()["problem_id"] == ""
                    for i in range(nqmis)
            ]):
                await_completion(problems, nqmis, 1)
            report_subproblems_submitted(nqmis, problems, samples_list,
                                         spin_rev_list)
        except KeyError:
            pass  # Not all solvers support "problem_id".

    # Wait for the solver to complete.
    if verbosity >= 2:
        sys.stderr.write("Number of subproblems completed:\n\n")
        cdigits = len(str(nqmis))  # Digits in the number of completed QMIs
        tdigits = len(str(nqmis * 5))  # Estimate 5 seconds per QMI submission
        start_time = time.time()
    done = False
    while not done:
        done = await_completion(problems, nqmis, 10)
        if verbosity >= 2:
            ncomplete = sum([
                problems[i].status()["state"] == "DONE" for i in range(nqmis)
            ])
            sys.stderr.write(
                "    %*d of %d (%3.0f%%) after %*.0f seconds\n" %
                (cdigits, ncomplete, nqmis, 100.0 * float(ncomplete) /
                 float(nqmis), tdigits, time.time() - start_time))
    if verbosity >= 2:
        sys.stderr.write("\n")
    answers = [p.result() for p in problems]

    # Tally the occurrences of each solution
    answer = merge_answers(answers)
    solutions = answer["solutions"]
    semifinal_answer = unembed_answer(solutions,
                                      physical.embedding,
                                      broken_chains="minimize_energy",
                                      h=physical.weights,
                                      j=physical.strengths)
    try:
        num_occurrences = {
            tuple(k): v
            for k, v in zip(semifinal_answer, answer["num_occurrences"])
        }
    except KeyError:
        num_occurrences = {tuple(a): 1 for a in semifinal_answer}

    # Discard solutions with broken pins or broken chains unless instructed
    # not to.
    valid_solns = [s for s in solutions if solution_is_intact(physical, s)]
    num_not_broken = len(valid_solns)
    if discard in ["yes", "maybe"]:
        final_answer = unembed_answer(valid_solns,
                                      physical.embedding,
                                      broken_chains="discard",
                                      h=physical.weights,
                                      j=physical.strengths)
    if discard == "no" or (discard == "maybe" and len(final_answer) == 0):
        final_answer = semifinal_answer
    return answer, final_answer, num_occurrences, num_not_broken
예제 #23
0
# We are now ready to embed our problem onto the graph:

[h, j0, jc, embeddings] = embed_problem(h, J, embedding, adjacency)

# j0 contains the original couplings that we defined and jc contains the couplings that enforce the integrity of the chains (they correlate the qubits within the chains). Thus, we need to combine them again into one big J dictionary:

J = j0.copy()
J.update(jc)

# Now, we're ready to solve the embedded problem:

params = {"answer_mode": 'histogram', "num_reads": 10000}
raw_results = solve_ising(solver, h, J, **params)

print 'Lowest energy found: {}'.format(raw_results['energies'])
print 'Number of occurences: {}'.format(raw_results['num_occurrences'])

unembedded_results = unembed_answer(raw_results['solutions'], embedding, broken_chains='vote')

print 'Solution string: {}'.format(unembedded_results)

'''
you should get the correct result in all readouts:

Lowest energy found: [-5.0]
Number of occurences: [10000]
Solution string: [[1, -1, -1, 1]]
'''


예제 #24
0
    def query_dwave(self, h, J, embedding, samples, temperature, batch_size):
        """
        Queries D-Wave multiple times for solution of the given Ising model,
        aggregating the unembedded results.
        """

        results = {
            'energies': [],
            'solutions': [],
            'num_occurrences': [],
            'timing': []
        }

        num_batches = samples // batch_size

        for i in range(num_batches):
            batch_solved = False
            while not batch_solved:
                try:
                    self.info("Sampling batch {i}".format(i=i))
                    batch = solve_ising(self.solver,
                                        h,
                                        J,
                                        answer_mode='histogram',
                                        auto_scale=True,
                                        num_reads=batch_size,
                                        num_spin_reversal_transforms=5,
                                        beta=1.0 / float(temperature),
                                        postprocess='sampling',
                                        chains=embedding)
                    batch_solved = True
                    self.info("Done")
                except Exception as e:
                    self.verbose(str(e))
                    self.info("Exception occured, retrying...")

            # Collect the batch results
            batch_solutions = unembed_answer(batch['solutions'],
                                             embedding,
                                             broken_chains='vote')

            results['solutions'].extend(batch_solutions)
            results['num_occurrences'].extend(batch['num_occurrences'])

        # Aggregate the same unembedded answers
        aggregated = defaultdict(dict)
        data = zip(results['solutions'], results['num_occurrences'])

        for result, count in data:
            key = tuple(result)
            result_data = aggregated.get(key, {})

            # Recompute the average solution energy
            prior_count = result_data.get('count', 0)
            result_data['count'] = prior_count + count

            aggregated[key] = result_data

        # Return as a sorted list
        aggregated_list = [(key, value['count'])
                           for key, value in aggregated.items()]
        return list(sorted(aggregated_list, key=lambda x: x[1]))
예제 #25
0
    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))]
예제 #26
0
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 test_vote_noties():
    embeddings = [(1, 2), [3, 5, 4]]
    solutions = [(3, +1, +1, -1, -1, -1), (3, -1, -1, -1, +1, +1),
                 (3, -1, -1, +1, +1, -1), (3, +1, +1, -1, +1, -1)]
    expected = [[+1, -1], [-1, +1], [-1, +1], [+1, -1]]
    assert unembed_answer(solutions, embeddings, 'vote') == expected
예제 #28
0
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)
예제 #29
0
    def sample_ising(self, h, J, embedding_tag=None, **sapi_kwargs):
        """Embeds the given problem using sapi's find_embedding then invokes
        the given sampler to solve it.

        Args:
            h (dict/list): The linear terms in the Ising problem. If a
                dict, should be of the form {v: bias, ...} where v is
                a variable in the Ising problem, and bias is the linear
                bias associated with v. If a list, should be of the form
                [bias, ...] where the indices of the biases are the
                variables in the Ising problem.
            J (dict): A dictionary of the quadratic terms in the Ising
                problem. Should be of the form {(u, v): bias} where u,
                v are variables in the Ising problem and bias is the
                quadratic bias associated with u, v.
            embedding_tag: Allows the user to specify a tag for the generated
                embedding. Useful for when the user wishes to submit multiple
                problems with the same logical structure.
            Additional keyword parameters are the same as for
            SAPI's solve_ising function, see QUBIST documentation.

        Returns:
            :class:`dimod.SpinResponse`: The unembedded samples.

        Examples:
            >>> sampler = sapi.EmbeddingComposite(sapi.SAPILocalSampler('c4-sw_optimize'))
            >>> response = sampler.sample_ising({}, {(0, 1): 1, (0, 2): 1, (1, 2): 1})

            Using the embedding_tag, the embedding is generated only once.
            >>> h = {0: .1, 1: 1.3, 2: -1.}
            >>> J = {(0, 1): 1, (1, 2): 1, (0, 2): 1}
            >>> sampler = sapi.EmbeddingComposite(sapi.SAPILocalSampler('c4-sw_optimize'))
            >>> response0 = sampler.sample_ising(h, J, embedding_tag='K3')
            >>> response1 = sampler.sample_ising(h, J, embedding_tag='K3')

        """
        # get the sampler that is used by the composite
        sampler = self._child

        # the ising_index_labels decorator converted the keys of h to be indices 0, n-1
        # sapi wants h to be a list, so let's make that conversion, using the keys as
        # the indices.
        h_list = [h[v] for v in range(len(h))]

        # get the structure of the child sampler. The first value are the nodes which
        # we don't need, the second is the set of edges available.
        (__, edgeset) = sampler.structure

        if embedding_tag is None or embedding_tag not in self.cached_embeddings:
            # we have not previously cached an embedding so we need to determine it

            # get the adjacency structure of our problem
            S = set(J)
            S.update({(v, v) for v in h})

            # embed our adjacency structure, S, into the edgeset of the sampler.
            embeddings = find_embedding(S, edgeset)

            # sometimes it fails, often because the problem is too large
            if J and not embeddings:
                raise Exception('No embedding found')

            # now it is possible that h_list might include nodes not in embedding, so let's
            # handle that case here
            if len(h_list) > len(embeddings):
                emb_qubits = set().union(*embeddings)
                while len(h_list) > len(embeddings):
                    for v in sampler.solver.properties['qubits']:
                        if v not in emb_qubits:
                            embeddings.append([v])
                            emb_qubits.add(v)
                            break

            if embedding_tag is not None:
                # save the embedding for posterity
                self.cached_embeddings[embedding_tag] = embeddings
        else:
            # the user has asserted that we can reuse a previously created embedding
            embeddings = self.cached_embeddings[embedding_tag]

        # embed the problem
        h0, j0, jc, new_emb = embed_problem(h_list, J, embeddings, edgeset)

        # combine jc and j0
        emb_j = j0.copy()
        emb_j.update(jc)

        # pass the chains we made into the sampler if it wants them
        if 'chains' in sampler.solver.properties['parameters'] and 'chains' not in sapi_kwargs:
            sapi_kwargs['chains'] = new_emb

        # invoke the child sampler
        emb_response = sampler.sample_ising(h0, emb_j, **sapi_kwargs)

        # we need the samples back into lists for the unembed_answer function
        answers = [[sample[i] for i in range(len(sample))] for sample in emb_response]

        # unemnbed
        solutions = unembed_answer(answers, new_emb, 'minimize_energy', h_list, J)

        # and back once again into dicts for dimod...
        samples = ({v: sample[v] for v in h} for sample in solutions)
        sample_data = (data for __, data in emb_response.samples(data=True))
        response = dimod.SpinResponse()
        response.add_samples_from(samples, sample_data=sample_data, h=h, J=J)

        return response
예제 #30
0
#~
#~ Now, we've broken a few chains.  We modified the solution array in place,
#~ so as we execute the next section, it will use this broken soltuion.
#~
#~ Interpreting embedded solutions
#~ -------------------------------
#~
#~ Now, we'll take a look at the interpretation of solutions with broken
#~ chains.  This is still a matter of active research, but the sapi client
#~ provides a few strategies.
#~
#~ We'll use the ``minimize_energy`` strategy.  The description of the
#~ strategies provided by the sapi client, can be found in the documentation
#~ for :func:`unembed_answer`.  The ``minimize_energy`` strategy considers the
#~ chains one by one, and computes the hamiltonian energies associated with
#~ setting all spins up and all spins down, across the chain, and picks the
#~ spin value for that chain which attains the lower energy before moving on
#~ to the next chain.
#~

new_answer = unembed_answer(result['solutions'], new_emb, 'minimize_energy', h,
                            J)
print "spin | chain spins"
for spin, chain in zip(new_answer[0], flat_embedding):
    if spin == -1:
        spin = '-'
    else:
        spin = '+'
    spins = ['+' if res0[q] == 1 else '-' for q in chain]
    print "  %s  | %s" % (spin, "".join(spins))
예제 #31
0
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

ans = core.solve_ising(solver, h0, emb_j, num_reads=1000)
print ans
# for x in ans['solutions']:
#     for y in new_emb:
#         print (x[y[0]]+1)/2
#     print '----'
res = embedding.unembed_answer(ans['solutions'], new_emb, 'discard', h, j)
print(np.array(res) + 1) / 2