Exemple #1
0
def connect_to_dwave():
    """
    Establish a connection to the D-Wave, and use this to talk to a solver.
    We rely on the qOp infrastructure to set the environment variables properly.
    """
    try:
        url = os.environ["DW_INTERNAL__HTTPLINK"]
        token = os.environ["DW_INTERNAL__TOKEN"]
        proxy = os.environ["DW_INTERNAL__HTTPPROXY"]
        conn = RemoteConnection(url, token, proxy)
    except KeyError:
        url = "<local>"
        token = "<N/A>"
        conn = local_connection
    except IOError as e:
        qasm.abend("Failed to establish a remote connection (%s)" % e)
    try:
        qasm.solver_name = os.environ["DW_INTERNAL__SOLVER"]
    except:
        # Solver was not specified: Use the first available solver.
        qasm.solver_name = conn.solver_names()[0]
    try:
        qasm.solver = conn.get_solver(qasm.solver_name)
    except KeyError:
        qasm.abend("Failed to find solver %s on connection %s" %
                   (qasm.solver_name, url))
Exemple #2
0
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
Exemple #3
0
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 = qasm.solver.properties["h_range"]
        j_range = qasm.solver.properties["j_range"]
    except KeyError:
        h_range = [-1.0, 1.0]
        j_range = [-1.0, 1.0]
    weight_list = [logical.weights[q] for q in range(qasm.next_sym_num + 1)]
    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:
        qasm.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.weight_list = weight_list
    physical.weights = new_weights
    physical.pinned = []
    for l, v in logical.pinned:
        physical.pinned.extend([(p, v) for p in physical.embedding[l]])
    return physical
Exemple #4
0
 def error_in_line(self, msg):
     if self.lineno == None:
         qasm.abend(msg)
     else:
         sys.stderr.write('%s:%d: error: %s\n' %
                          (self.filename, self.lineno, msg))
     sys.exit(1)
Exemple #5
0
def parse_files(file_list):
    "Parse a list of file(s) into an internal representation."
    if file_list == []:
        # No files were specified: Read from standard input.
        parse_file("<stdin>", sys.stdin)
        if current_macro[0] != None:
            error_in_line("Unterminated definition of macro %s" %
                          current_macro[0])
    else:
        # Files were specified: Process each in turn.
        for infilename in file_list:
            try:
                infile = open(infilename)
            except IOError:
                qasm.abend('Failed to open %s for input' % infilename)
            parse_file(infilename, infile)
            if current_macro[0] != None:
                error_in_line("Unterminated definition of macro %s" %
                              current_macro[0])
            infile.close()
Exemple #6
0
def parse_pin(pin):
    "Parse a pin statement passed on the command line."
    for pstr in pin:
        lhs_rhs = pstr.split(":=")
        if len(lhs_rhs) != 2:
            qasm.abend('Failed to parse --pin="%s"' % pstr)
        lhs = lhs_rhs[0].strip().split()
        rhs = []
        for r in lhs_rhs[1].strip().upper().split():
            try:
                rhs.append(str2bool[r])
            except KeyError:
                for subr in r:
                    try:
                        rhs.append(str2bool[subr])
                    except KeyError:
                        qasm.abend('Failed to parse --pin="%s"' % pstr)
        if len(lhs) != len(rhs):
            qasm.abend(
                'Different number of left- and right-hand-side values in --pin="%s" (%d vs. %d)'
                % (pstr, len(lhs), len(rhs)))
        for l, r in zip(lhs, rhs):
            qasm.program.append(Pin("[command line]", 1, l, r))
Exemple #7
0
def find_dwave_embedding(logical, optimize, verbosity):
    """Find an embedding of a logical problem in the D-Wave's physical topology.
    Store the embedding within the Problem object."""
    edges = logical.strengths.keys()
    edges.sort()
    try:
        hw_adj = get_hardware_adjacency(qasm.solver)
    except KeyError:
        # The Ising heuristic solver is an example of a solver that lacks a
        # fixed hardware representation.  We therefore assert that the hardware
        # exactly matches the problem'input graph.
        hw_adj = edges

    # Determine the edges of a rectangle of cells we want to use.
    L, M, N = qasm.chimera_topology(qasm.solver)
    L2 = 2 * L
    ncells = (qasm.next_sym_num + 1) // L2
    if optimize:
        edgey = max(int(math.sqrt(ncells)), 1)
        edgex = max((ncells + edgey - 1) // edgey, 1)
    else:
        edgey = N
        edgex = M

    # Announce what we're about to do.
    if verbosity >= 2:
        sys.stderr.write(
            "Embedding the logical adjacency within the physical topology.\n\n"
        )

    # Repeatedly expand edgex and edgey until the embedding works.
    while edgex <= M and edgey <= N:
        # Retain adjacencies only within the rectangle.
        alt_hw_adj = []
        for q1, q2 in hw_adj:
            c1 = q1 // L2
            if c1 % M >= edgex:
                continue
            if c1 // M >= edgey:
                continue
            c2 = q2 // L2
            if c2 % M >= edgex:
                continue
            if c2 // M >= edgey:
                continue
            alt_hw_adj.append((q1, q2))
        alt_hw_adj = set(alt_hw_adj)

        # Try to find an embedding.
        if verbosity >= 2:
            sys.stderr.write("  Trying a %dx%d unit-cell embedding ... " %
                             (edgex, edgey))
            status_file = tempfile.NamedTemporaryFile(mode="w", delete=False)
            stdout_fd = os.dup(sys.stdout.fileno())
            os.dup2(status_file.fileno(), sys.stdout.fileno())
            embedding = find_embedding(edges, alt_hw_adj, verbose=1)
            sys.stdout.flush()
            os.dup2(stdout_fd, sys.stdout.fileno())
            status_file.close()
            if len(embedding) > 0:
                sys.stderr.write("succeeded\n\n")
            else:
                sys.stderr.write("failed\n\n")
            with open(status_file.name, "r") as status:
                for line in status:
                    sys.stderr.write("    %s" % line)
            sys.stderr.write("\n")
            os.remove(status_file.name)
        else:
            embedding = find_embedding(edges, alt_hw_adj, verbose=0)
        if len(embedding) > 0:
            # Success!
            break

        # Failure -- increase edgex or edgey and try again.
        if edgex < edgey:
            edgex += 1
        else:
            edgey += 1
    if not (edgex <= M and edgey <= N):
        qasm.abend("Failed to embed the problem")

    # Store in the logical problem additional information about the embedding.
    logical.embedding = embedding
    logical.hw_adj = alt_hw_adj
    logical.edges = edges
Exemple #8
0
def parse_file(infilename, infile):
    global macros, current_macro, aliases, target, filename, lineno
    filename = infilename
    for line in infile:
        # Split the line into fields and apply text aliases.
        lineno += 1
        if line.strip() == "":
            continue
        fields = shlex.split(line, True)
        for i in range(len(fields)):
            try:
                fields[i] = aliases[fields[i]]
            except KeyError:
                pass

        # Process the line.
        if len(fields) == 0:
            # Ignore empty lines.
            continue
        elif len(fields) >= 2 and fields[0] == "!include":
            # "!include" "<filename>" -- process a named auxiliary file.
            incname = string.join(fields[1:], " ")
            if len(incname) >= 2 and incname[0] == "<" and incname[-1] == ">":
                # Search QASMPATH for the filename.
                incname = incname[1:-1]
                try:
                    qasmpath = string.split(os.environ["QASMPATH"], ":")
                    qasmpath.append(".")
                except KeyError:
                    qasmpath = ["."]
                found_incname = find_file_in_path(qasmpath, incname)
                if found_incname != None:
                    incname = found_incname
            elif len(incname) >= 2:
                # Search only the current directory for the filename.
                found_incname = find_file_in_path(["."], incname)
                if found_incname != None:
                    incname = found_incname
            try:
                incfile = open(incname)
            except IOError:
                qasm.abend('Failed to open %s for input' % incname)
            parse_file(incname, incfile)
            incfile.close()
        elif len(fields) == 2:
            if fields[0] == "!begin_macro":
                # "!begin_macro" <name> -- begin a macro definition.
                name = fields[1]
                if macros.has_key(name):
                    error_in_line("Macro %s is multiply defined" % name)
                if current_macro[0] != None:
                    error_in_line("Nested macros are not supported")
                current_macro = (name, [])
                target = current_macro[1]
            elif fields[0] == "!end_macro":
                # "!end_macro" <name> -- end a macro definition.
                name = fields[1]
                if current_macro[0] == None:
                    error_in_line(
                        "Ended macro %s with no corresponding begin" % name)
                if current_macro[0] != name:
                    error_in_line("Ended macro %s after beginning macro %s" %
                                  (name, current_macro[0]))
                macros[name] = current_macro[1]
                target = qasm.program
                current_macro = (None, [])
            else:
                # <symbol> <weight> -- increment a symbol's point weight.
                try:
                    val = float(fields[1])
                except ValueError:
                    error_in_line(
                        'Failed to parse "%s %s" as a symbol followed by a numerical weight'
                        % (fields[0], fields[1]))
                target.append(Weight(filename, lineno, fields[0], val))
        elif len(fields) == 3:
            if fields[1] == "=":
                # <symbol_1> = <symbol_2> -- create a chain between <symbol_1> and
                # <symbol_2>.
                target.append(Chain(filename, lineno, fields[0], fields[2]))
            elif fields[1] == ":=":
                # <symbol> := <value> -- force symbol <symbol> to have value
                # <value>.
                try:
                    goal = str2bool[fields[2].upper()]
                except KeyError:
                    error_in_line(
                        'Right-hand side ("%s") must be a Boolean value' %
                        fields[2])
                target.append(Pin(filename, lineno, fields[0], goal))
            elif fields[1] == "<->":
                # <symbol_1> <-> <symbol_2> -- make <symbol_1> an alias of
                # <symbol_2>.
                target.append(Alias(filename, lineno, fields[0], fields[2]))
            elif fields[0] == "!use_macro":
                # "!use_macro" <macro_name> <instance_name> -- instantiate
                # a macro using <instance_name> as each variable's prefix.
                name = fields[1]
                try:
                    target.append(
                        MacroUse(filename, lineno, name, macros[name],
                                 fields[2] + "."))
                except KeyError:
                    error_in_line("Unknown macro %s" % name)
            elif fields[0] == "!alias":
                # "!alias" <symbol> <text> -- replace a field of <symbol> with
                # <text>.
                aliases[fields[1]] = fields[2]
            elif is_float(fields[2]):
                # <symbol_1> <symbol_2> <strength> -- increment a coupler strength.
                try:
                    strength = float(fields[2])
                except ValueError:
                    error_in_line('Failed to parse "%s" as a number' %
                                  fields[2])
                target.append(
                    Strength(filename, lineno, fields[0], fields[1], strength))
            else:
                # Three fields but none of the above cases
                error_in_line('Cannot parse "%s"' % line)
        else:
            # Neither two nor three fields
            error_in_line('Cannot parse "%s"' % line)