def output_dw(outfile, problem): "Output weights and strengths in dw format." if not problem.qubo: qprob = problem.convert_to_qubo() output_weights, output_strengths = qprob.weights, qprob.strengths else: output_weights = problem.weights output_strengths = problem.strengths try: L, M, N = qmasm.chimera_topology(qmasm.solver) except qmasm.NonChimera: qmasm.abend("dw output is supported only for Chimera-graph topologies") wdata = [] for q in range(len(output_weights)): if output_weights[q] != 0.0: wdata.append("Q%0d <== %.25g" % (q, output_weights[q])) wdata.sort() sdata = [] for sp, str in output_strengths.items(): if str != 0.0: try: coupler = coupler_number(M, N, L, sp[0], sp[1]) except IndexError: qmasm.abend("dw output is supported only for Chimera-graph topologies") sdata.append("C%04d <== %.25g" % (coupler, str)) sdata.sort() outfile.write("\n".join(wdata + sdata) + "\n")
def output_dw(outfile, problem): "Output weights and strengths in dw format." if not problem.qubo: qprob = problem.convert_to_qubo() output_weights, output_strengths = qprob.weights, qprob.strengths else: output_weights = problem.weights output_strengths = problem.strengths try: L, M, N = qmasm.chimera_topology(qmasm.solver) except KeyError: qmasm.abend("Failed to query the chimera topology") wdata = [] for q in range(len(output_weights)): if output_weights[q] != 0.0: wdata.append("Q%0d <== %.25g" % (q, output_weights[q])) wdata.sort() sdata = [] for sp, str in list(output_strengths.items()): if str != 0.0: coupler = coupler_number(M, N, L, sp[0], sp[1]) sdata.append("C%04d <== %.25g" % (coupler, str)) sdata.sort() outfile.write("\n".join(wdata + sdata) + "\n")
def output_bqpjson(outfile, as_qubo, problem): "Output weights and strengths in bqpjson format, either Ising or QUBO." # Prepare the "easy" fields. bqp = {} bqp["version"] = "1.0.0" bqp["id"] = random.randint(2**20, 2**60) bqp["scale"] = 1.0 bqp["offset"] = 0.0 if as_qubo: bqp["variable_domain"] = "boolean" else: bqp["variable_domain"] = "spin" # Prepare the list of all variables. var_ids = set(problem.weights.keys()) for q1, q2 in problem.strengths.keys(): var_ids.add(q1) var_ids.add(q2) bqp["variable_ids"] = sorted(var_ids) # Prepare the linear terms. lin_terms = [] for q, wt in sorted(problem.weights.items()): lin_terms.append({ "id": q, "coeff": wt}) bqp["linear_terms"] = lin_terms # Prepare the quadratic terms. quad_terms = [] strengths = qmasm.canonicalize_strengths(problem.strengths) for (q1, q2), wt in sorted(strengths.items()): quad_terms.append({ "id_tail": q1, "id_head": q2, "coeff": wt}) bqp["quadratic_terms"] = quad_terms # Prepare some metadata. metadata = {} if as_qubo: metadata["description"] = "QUBO problem compiled by QMASM (https://github.com/lanl/qmasm)" else: metadata["description"] = "Ising problem compiled by QMASM (https://github.com/lanl/qmasm)" metadata["command_line"] = qmasm.get_command_line() metadata["generated"] = datetime.datetime.utcnow().isoformat() if hasattr(problem, "embedding"): # Physical problem def attempt_assign(key, func): "Try assigning a key, but don't complain if we can't." try: metadata[key] = func() except KeyError: pass attempt_assign("dw_url", lambda: os.environ["DW_INTERNAL__HTTPLINK"]) attempt_assign("dw_solver_name", lambda: qmasm.solver_name) props = qmasm.solver.properties attempt_assign("dw_chip_id", lambda: props["chip_id"]) L, M, N = qmasm.chimera_topology(qmasm.solver) metadata["chimera_cell_size"] = L*2 metadata["chimera_degree"] = max(M, N) metadata["equivalent_ids"] = sorted(problem.chains) metadata["variable_names"] = {s: problem.embedding[n] for s, n in qmasm.sym_map.symbol_number_items()} else: metadata["variable_names"] = {s: [n] for s, n in qmasm.sym_map.symbol_number_items()} bqp["metadata"] = metadata # Output the problem in JSON format. outfile.write(json.dumps(bqp, indent=2, sort_keys=True) + "\n")
def find_dwave_embedding(logical, optimization, verbosity, hw_adj_file): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [ e for e in logical.strengths.keys() if logical.strengths[e] != 0.0 ] edges.sort() logical.edges = edges if hw_adj_file == None: try: hw_adj = get_hardware_adjacency(qmasm.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 is an all-to-all network that connects every node to # every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] else: hw_adj = read_hardware_adjacency(hw_adj_file, verbosity) # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. If we read # the topology from a file or otherwise can't prove that we have a Chimera # graph, we call this rectangle 0x0 and force the main embedding loop to # exit after a single iteration because we don't know the topology is even # rectangular. edgex = 0 edgey = 0 M = 0 N = 0 try: if hw_adj_file == None: L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2 * L ncells = (qmasm.next_sym_num + L2) // L2 # Round up the number of cells. if optimization >= 2: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M except qmasm.NonChimera: pass # 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: if edgex == M and edgey == N: alt_hw_adj = hw_adj else: # 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) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write( " No embedding cache directory was specified ($QMASMCACHE).\n" ) else: sys.stderr.write( " Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write( " Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write( " Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write( " No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if embedding != []: if verbosity >= 2: # SAPI's find_embedding is hard-wired to write to stdout. # Trick it into writing into a pipe instead. if edgex == 0 and edgey == 0: sys.stderr.write(" Trying to embed ... ") else: sys.stderr.write( " Trying a %dx%d unit-cell embedding ...\n\n" % (edgex, edgey)) sepLine = "=== EMBEDDING ===\n" r, w = os.pipe() pid = os.fork() if pid == 0: # Child -- perform the embedding. os.close(r) os.dup2(w, sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.write(w, sepLine) os.write(w, json.dumps(embedding) + "\n") os.close(w) os._exit(0) else: # Parent -- report the embedding's progress. os.close(w) pipe = os.fdopen(r, "r", 10000) while True: try: rstr = pipe.readline() if rstr == sepLine: break if rstr == "": qmasm.abend( "Embedder failed to terminate properly") sys.stderr.write(" %s" % rstr) except: pass # Receive the embedding from the child. embedding = json.loads(pipe.readline()) sys.stderr.write("\n") else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not (edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding
continue name_list = string.join(sorted(canon2syms[i])) sys.stderr.write(" q%-8d %s\n" % (i + 1, name_list)) sys.stderr.write("\n") # 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. qmasm.connect_to_dwave() # Output most or all solver properties. if cl_args.verbose >= 1: # Determine the width of the widest key. max_key_len = len("Parameter") ext_solver_properties = {} try: L, M, N = qmasm.chimera_topology(qmasm.solver) ext_solver_properties["chimera_toplogy_M_N_L"] = [M, N, L] except KeyError: pass ext_solver_properties.update(qmasm.solver.properties) solver_props = ext_solver_properties.keys() solver_props.sort() for k in solver_props: max_key_len = max(max_key_len, len(k)) # Output either "short" values (if verbose = 1) or all values (if # verbose > 1). short_value_len = 70 - max_key_len sys.stderr.write("Encountered the following solver properties:\n\n") sys.stderr.write(" %-*s Value\n" % (max_key_len, "Parameter")) sys.stderr.write(" %s -----\n" % ("-" * max_key_len))
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.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [e for e in list(logical.strengths.keys()) if logical.strengths[e] != 0.0] edges.sort() logical.edges = edges try: hw_adj = get_hardware_adjacency(qmasm.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 # is an all-to-all network that connects every node to every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2*L ncells = (qmasm.next_sym_num + L2) // L2 # Round up the number of cells. 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) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write(" No embedding cache directory was specified ($QMASMCACHE).\n") else: sys.stderr.write(" Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write(" Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write(" Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write(" No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if 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) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not(edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding
if len(discon_syms) > 0: qmasm.abend("Disconnected variables encountered: %s" % " ".join(sorted(discon_syms))) # Convert user-specified chains, anti-chains, and pins to assertions. logical_ising.append_assertions_from_statements() # 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. qmasm.connect_to_dwave() # Output either short or all solver properties. if cl_args.verbose >= 1: # Introduce a few extra solver properties. ext_solver_properties = {} try: L, M, N = qmasm.chimera_topology(qmasm.solver) ext_solver_properties["chimera_toplogy_M_N_L"] = [M, N, L] except KeyError: pass except qmasm.NonChimera: pass ext_solver_properties["solver_name"] = qmasm.solver_name try: ext_solver_properties["connection_name"] = os.environ["DW_INTERNAL__CONNECTION"] except KeyError: pass for what in ["couplers", "qubits"]: try: ext_solver_properties["num_active_" + what] = len(qmasm.solver.properties[what]) except KeyError: pass
def find_dwave_embedding(logical, optimization, verbosity, hw_adj_file): """Find an embedding of a logical problem in the D-Wave's physical topology. Store the embedding within the Problem object.""" # SAPI tends to choke when embed_problem is told to embed a problem # containing a zero-weight node whose adjacent couplers all have zero # strength. (Tested with SAPI 2.4.) To help out SAPI, we simply remove # all zero-strength couplers. edges = [e for e in logical.strengths.keys() if logical.strengths[e] != 0.0] edges.sort() logical.edges = edges if hw_adj_file == None: try: hw_adj = get_hardware_adjacency(qmasm.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 is an all-to-all network that connects every node to # every other node. endpoints = set([a for a, b in edges] + [b for a, b in edges]) hw_adj = [(a, b) for a in endpoints for b in endpoints if a != b] else: hw_adj = read_hardware_adjacency(hw_adj_file, verbosity) # Tell the user if we have any hope at all of embedding the problem. if verbosity >= 2: report_embeddability(edges, hw_adj) # Determine the edges of a rectangle of cells we want to use. If we read # the topology from a file or otherwise can't prove that we have a Chimera # graph, we call this rectangle 0x0 and force the main embedding loop to # exit after a single iteration because we don't know the topology is even # rectangular. edgex = 0 edgey = 0 M = 0 N = 0 num_vars = len(qmasm.sym_map.all_numbers()) try: if hw_adj_file == None: L, M, N = qmasm.chimera_topology(qmasm.solver) L2 = 2*L ncells = (num_vars + L2) // L2 # Round up the number of cells. if optimization >= 2: edgey = max(int(math.sqrt(ncells)), 1) edgex = max((ncells + edgey - 1) // edgey, 1) else: edgey = N edgex = M except qmasm.NonChimera: pass # 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: if edgex == M and edgey == N: alt_hw_adj = hw_adj else: # 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) logical.hw_adj = alt_hw_adj # See if we already have an embedding in the embedding cache. ec = EmbeddingCache(edges, alt_hw_adj) if verbosity >= 2: if ec.cachedir == None: sys.stderr.write(" No embedding cache directory was specified ($QMASMCACHE).\n") else: sys.stderr.write(" Using %s as the embedding cache directory ...\n" % ec.cachedir) embedding = ec.read() if embedding == []: # Cache hit, but embedding had failed if verbosity >= 2: sys.stderr.write(" Found failed embedding %s in the embedding cache.\n\n" % ec.hash) elif embedding != None: # Successful cache hit! if verbosity >= 2: sys.stderr.write(" Found successful embedding %s in the embedding cache.\n\n" % ec.hash) logical.embedding = embedding return if verbosity >= 2 and ec.cachedir != None: sys.stderr.write(" No existing embedding found in the embedding cache.\n") # Try to find an embedding, unless we previously determined that it had # failed. if embedding != []: if verbosity >= 2: # SAPI's find_embedding is hard-wired to write to stdout. # Trick it into writing into a pipe instead. if edgex == 0 and edgey == 0: sys.stderr.write(" Trying to embed ... ") else: sys.stderr.write(" Trying a %dx%d unit-cell embedding ...\n\n" % (edgex, edgey)) sepLine = "=== EMBEDDING ===\n" r, w = os.pipe() pid = os.fork() if pid == 0: # Child -- perform the embedding. os.close(r) os.dup2(w, sys.stdout.fileno()) embedding = find_embedding(edges, alt_hw_adj, verbose=1) sys.stdout.flush() os.write(w, sepLine) os.write(w, json.dumps(embedding) + "\n") os.close(w) os._exit(0) else: # Parent -- report the embedding's progress. os.close(w) pipe = os.fdopen(r, "r", 10000) while True: try: rstr = pipe.readline() if rstr == sepLine: break if rstr == "": qmasm.abend("Embedder failed to terminate properly") sys.stderr.write(" %s" % rstr) except: pass # Receive the embedding from the child. embedding = json.loads(pipe.readline()) sys.stderr.write("\n") else: embedding = find_embedding(edges, alt_hw_adj, verbose=0) ec.write(embedding) if len(embedding) > 0: # Success! break # Continued failure -- increase edgex or edgey and try again. if edgex < edgey: edgex += 1 else: edgey += 1 if not(edgex <= M and edgey <= N): qmasm.abend("Failed to embed the problem") logical.embedding = embedding