コード例 #1
0
def scale_weights_strengths(physical, verbosity):
    "Manually scale the weights and strengths so Qubist doesn't complain."
    h_range = physical.h_range
    j_range = physical.j_range
    weight_list = qmasm.dict_to_list(physical.weights)
    old_cap = max(
        [abs(w) for w in weight_list + list(physical.strengths.values())])
    new_cap = min(-h_range[0], h_range[1], -j_range[0], j_range[1])
    if old_cap == 0.0:
        # Handle the obscure case of a zero old_cap.
        old_cap = new_cap
    new_weights = qmasm.list_to_dict(
        [w * new_cap / old_cap for w in weight_list])
    new_strengths = {
        js: w * new_cap / old_cap
        for js, w in physical.strengths.items()
    }
    if verbosity >= 1 and old_cap != new_cap:
        sys.stderr.write(
            "Scaling weights and strengths from [%.10g, %.10g] to [%.10g, %.10g].\n\n"
            % (-old_cap, old_cap, -new_cap, new_cap))
    new_physical = copy.deepcopy(physical)
    new_physical.weights = new_weights
    new_physical.strengths = new_strengths
    return new_physical
コード例 #2
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
コード例 #3
0
ファイル: dwave.py プロジェクト: mikewlange/qmasm
def embed_problem_on_dwave(logical, optimize, verbosity):
    """Embed a logical problem in the D-Wave's physical topology.  Return a
    physical Problem object."""
    # Embed the problem.  Abort on failure.
    find_dwave_embedding(logical, optimize, verbosity)
    try:
        h_range = qmasm.solver.properties["h_range"]
        j_range = qmasm.solver.properties["j_range"]
    except KeyError:
        h_range = [-1.0, 1.0]
        j_range = [-1.0, 1.0]
    weight_list = qmasm.dict_to_list(logical.weights)
    smearable = any([s != 0.0 for s in list(logical.strengths.values())])
    try:
        [new_weights, new_strengths, new_chains, new_embedding] = embed_problem(
            weight_list, logical.strengths, logical.embedding, logical.hw_adj,
            True, smearable, h_range, j_range)
    except ValueError as e:
        qmasm.abend("Failed to embed the problem in the solver (%s)" % e)

    # Construct a physical Problem object.
    physical = copy.deepcopy(logical)
    physical.chains = new_chains
    physical.embedding = new_embedding
    physical.h_range = h_range
    physical.j_range = j_range
    physical.strengths = new_strengths
    physical.weights = defaultdict(lambda: 0.0,
                                   {q: new_weights[q]
                                    for q in range(len(new_weights))
                                    if new_weights[q] != 0.0})
    physical.pinned = []
    for l, v in logical.pinned:
        physical.pinned.extend([(p, v) for p in physical.embedding[l]])
    return physical
コード例 #4
0
ファイル: dwave.py プロジェクト: losalamos/qasm
def embed_problem_on_dwave(logical, optimization, verbosity, hw_adj_file):
    """Embed a logical problem in the D-Wave's physical topology.  Return a
    physical Problem object."""
    # Embed the problem.  Abort on failure.
    find_dwave_embedding(logical, optimization, verbosity, hw_adj_file)
    try:
        h_range = qmasm.solver.properties["h_range"]
        j_range = qmasm.solver.properties["j_range"]
    except KeyError:
        h_range = [-1.0, 1.0]
        j_range = [-1.0, 1.0]
    weight_list = qmasm.dict_to_list(logical.weights)
    smearable = any([s != 0.0 for s in logical.strengths.values()])
    try:
        [new_weights, new_strengths, new_chains, new_embedding] = embed_problem(
            weight_list, logical.strengths, logical.embedding, logical.hw_adj,
            True, smearable, h_range, j_range)
    except ValueError as e:
        qmasm.abend("Failed to embed the problem in the solver (%s)" % e)

    # Construct a physical Problem object.
    physical = copy.deepcopy(logical)
    physical.embedding = new_embedding
    physical.embedder_chains = set(new_chains)
    physical.h_range = h_range
    physical.j_range = j_range
    physical.strengths = new_strengths
    physical.weights = defaultdict(lambda: 0.0,
                                   {q: new_weights[q]
                                    for q in range(len(new_weights))
                                    if new_weights[q] != 0.0})
    physical.pinned = []
    for l, v in logical.pinned:
        physical.pinned.extend([(p, v) for p in physical.embedding[l]])
    return physical
コード例 #5
0
ファイル: problem.py プロジェクト: losalamos/qasm
 def scale_weights_strengths(self, verbosity):
     "Manually scale the weights and strengths so Qubist doesn't complain."
     h_range = self.h_range
     j_range = self.j_range
     weight_list = qmasm.dict_to_list(self.weights)
     old_cap = max([abs(w) for w in weight_list + list(self.strengths.values())])
     new_cap = min(-h_range[0], h_range[1], -j_range[0], j_range[1])
     if old_cap == 0.0:
         # Handle the obscure case of a zero old_cap.
         old_cap = new_cap
     self.range_scale = new_cap/old_cap
     self.weights = qmasm.list_to_dict([w*self.range_scale for w in weight_list])
     self.strengths = {js: w*self.range_scale for js, w in self.strengths.items()}
     self.offset *= self.range_scale
     if verbosity >= 1 and old_cap != new_cap:
         sys.stderr.write("Scaling weights and strengths from [%.10g, %.10g] to [%.10g, %.10g].\n\n" % (-old_cap, old_cap, -new_cap, new_cap))
コード例 #6
0
ファイル: problem.py プロジェクト: mikewlange/qmasm
 def convert_to_qubo(self):
     """Transform an Ising problem into a QUBO problem.  Return the new
     QUBO problem."""
     if self.qubo:
         raise TypeError("Can convert only Ising problems to QUBO problems")
     new_obj = copy.deepcopy(self)
     qmatrix, _ = ising_to_qubo(qmasm.dict_to_list(self.weights), self.strengths)
     new_obj.weights = defaultdict(lambda: 0.0,
                                   {q1: wt
                                    for (q1, q2), wt in list(qmatrix.items())
                                    if q1 == q2})
     new_obj.strengths = defaultdict(lambda: 0.0,
                                     {(q1, q2): wt
                                      for (q1, q2), wt in list(qmatrix.items())
                                      if q1 != q2})
     new_obj.qubo = True
     return new_obj
コード例 #7
0
ファイル: problem.py プロジェクト: losalamos/qasm
 def convert_to_qubo(self):
     """Transform an Ising problem into a QUBO problem.  Return the new
     QUBO problem."""
     if self.qubo:
         raise TypeError("Can convert only Ising problems to QUBO problems")
     new_obj = copy.deepcopy(self)
     qmatrix, qoffset = ising_to_qubo(qmasm.dict_to_list(self.weights), self.strengths)
     new_obj.offset = qoffset
     new_obj.weights = defaultdict(lambda: 0.0,
                                   {q1: wt
                                    for (q1, q2), wt in qmatrix.items()
                                    if q1 == q2})
     new_obj.strengths = qmasm.canonicalize_strengths({(q1, q2): wt
                                                       for (q1, q2), wt in qmatrix.items()
                                                       if q1 != q2})
     new_obj.qubo = True
     return new_obj
コード例 #8
0
ファイル: dwave.py プロジェクト: stelleg/qmasm
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:
            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 = re.match(r'"(.*?)"', str(e))
            if bad_name == None:
                raise e
            del solver_params[bad_name.group(1)]
        except RuntimeError as e:
            qmasm.abend(e)

    # 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
コード例 #9
0
ファイル: problem.py プロジェクト: witty67/qmasm
 def scale_weights_strengths(self, verbosity):
     "Manually scale the weights and strengths so Qubist doesn't complain."
     h_range = self.h_range
     j_range = self.j_range
     weight_list = qmasm.dict_to_list(self.weights)
     old_cap = max(
         [abs(w) for w in weight_list + list(self.strengths.values())])
     new_cap = min(-h_range[0], h_range[1], -j_range[0], j_range[1])
     if old_cap == 0.0:
         # Handle the obscure case of a zero old_cap.
         old_cap = new_cap
     self.range_scale = new_cap / old_cap
     self.weights = qmasm.list_to_dict(
         [w * self.range_scale for w in weight_list])
     self.strengths = {
         js: w * self.range_scale
         for js, w in self.strengths.items()
     }
     if verbosity >= 1 and old_cap != new_cap:
         sys.stderr.write(
             "Scaling weights and strengths from [%.10g, %.10g] to [%.10g, %.10g].\n\n"
             % (-old_cap, old_cap, -new_cap, new_cap))
コード例 #10
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
コード例 #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="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
コード例 #12
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
コード例 #13
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
コード例 #14
0
ファイル: dwave.py プロジェクト: losalamos/qasm
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 = {"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]

    # Merge the result of seperate runs into a composite answer.
    answer = merge_answers(answers)

    # Return a Solutions object for further processing.
    return qmasm.Solutions(answer, physical, verbosity >= 2)
コード例 #15
0
ファイル: dwave.py プロジェクト: losalamos/qasm
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