def main(args): if args.input_file == None: data = json.load(sys.stdin) else: with open(args.input_file) as file: data = json.load(file) bqpjson.validate(data) if data['variable_domain'] != 'spin': print('only spin domains are supported. Given %s' % data['variable_domain']) quit() if not os.path.exists(HFS_DIR): os.makedirs(HFS_DIR) data = bqpjson.spin_to_bool(data) hfs_data = StringIO() hfs_scale, hfs_offset = bqpjson.bqpjson_to_hfs(data, hfs_data, precision=args.precision) hfs_data = hfs_data.getvalue() if args.show_input: print('INFO: hfs solver input', file=sys.stderr) print(hfs_data, file=sys.stderr) first_line = hfs_data.split('\n', 1)[0] chimera_degree_effective = int(first_line.split()[0]) print('INFO: found effective chimera degree {}'.format( chimera_degree_effective), file=sys.stderr) tmp_hfs_file = create_tmp_file(prefix='hfs_') tmp_sol_file = create_tmp_file(prefix='sol_') #print('INFO: hfs temp input file {}'.format(tmp_hfs_file)) print('INFO: hfs temp solution file {}'.format(tmp_sol_file)) print('INFO: writing data to {}'.format(tmp_hfs_file), file=sys.stderr) with open(tmp_hfs_file, 'w') as hfs_file: hfs_file.write(hfs_data) # print(err.getvalue()) if args.docker_run: # assume that the hfs_alg container is available volume_map = '{}:/{}'.format(os.path.abspath(HFS_DIR), HFS_DIR) cmd = ['docker', 'run', '-v', volume_map, 'hfs_alg'] else: # assume that the qubo executable is natively accessible cmd = ['qubo'] # s - seed # m0 - mode of operation, try to find minimum value by heuristic search # N - size of Chimera graph cmd.extend( ['-s', str(args.seed), '-m0', '-N', str(chimera_degree_effective)]) if args.runtime_limit != None: # t - min run time for some modes # T - max run time for some modes cmd.extend([ '-t', str(args.runtime_limit), '-T', str(args.runtime_limit + 10) ]) cmd.extend(['-O', tmp_sol_file]) cmd.append(tmp_hfs_file) print('INFO: running command {}'.format(cmd), file=sys.stderr) proc = Popen(cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = proc.communicate() stdout = stdout.decode('utf-8') stderr = stderr.decode('utf-8') print('INFO: qubo stderr', file=sys.stderr) print(stderr, file=sys.stderr) print('INFO: qubo stdout', file=sys.stderr) print(stdout, file=sys.stderr) results = [] reading_results = False for line in stdout.split('\n'): if not reading_results: if 'Nodes' in line and 'bv' in line and 'nsol' in line: reading_results = True else: parts = line.split() if len(parts) == 3: parts = (int(parts[0]), int(parts[1]), float(parts[2])) results.append(Result(*parts)) else: reading_results = False print('INFO: found {} result lines'.format(len(results)), file=sys.stderr) assert (len(results) > 0) if args.show_hfs_solution: print('INFO: qubo solution', file=sys.stderr) with open(tmp_sol_file) as f: print(f.read(), file=sys.stderr) nodes = len(data['variable_ids']) edges = len(data['quadratic_terms']) lt_lb = -sum(abs(lt['coeff']) for lt in data['linear_terms']) qt_lb = -sum(abs(qt['coeff']) for qt in data['quadratic_terms']) lower_bound = lt_lb + qt_lb scaled_lower_bound = data['scale'] * (lower_bound + data['offset']) best_nodes = results[-1].nodes best_runtime = results[-1].runtime best_hfs_objective = results[-1].objective scaled_hfs_objective = hfs_scale * (best_hfs_objective + hfs_offset) verify_hfs_solution(tmp_hfs_file, tmp_sol_file, best_hfs_objective) result = evaluate_solution_in_bqpjson(data, tmp_sol_file) if result is None: print("INFO: using objective evaluated in HFS data", file=sys.stderr) best_objective, scaled_objective = best_hfs_objective, scaled_hfs_objective else: print("INFO: using objective evaluated in bqpjson data", file=sys.stderr) best_objective, scaled_objective = result print() print("INFO: scaled HFS objective = {}".format(scaled_hfs_objective), file=sys.stderr) print("INFO: scaled bqpjson objective = {}".format(scaled_objective), file=sys.stderr) print("INFO: HFS error = {}".format(scaled_hfs_objective - scaled_objective), file=sys.stderr) print() print() if args.show_solution: hfs_solution = read_solution(tmp_sol_file) chimera_degree = data['metadata']['chimera_degree'] chimera_cell_size = data['metadata']['chimera_cell_size'] bqp_solution = ', '.join([ "-1" if hfs_solution[hfs_site_idx( vid, chimera_degree, chimera_cell_size)] <= 0.5 else "1" for vid in data['variable_ids'] ]) print('BQP_SOLUTION, %d, %d, %f, %f, %s' % (nodes, edges, scaled_objective, best_runtime, bqp_solution)) print('BQP_DATA, %d, %d, %f, %f, %f, %f, %f, %d, %d' % (nodes, edges, scaled_objective, scaled_lower_bound, best_objective, lower_bound, best_runtime, 0, best_nodes)) remove_tmp_file(tmp_hfs_file) remove_tmp_file(tmp_sol_file)
def main(args): if args.input_file == None: data = json.load(sys.stdin) else: with open(args.input_file) as file: data = json.load(file) bqpjson.validate(data) if data['variable_domain'] != 'spin': print('only spin domains are supported. Given %s' % data['variable_domain']) quit() dw_config = dc.config.load_config(os.getenv("HOME") + "/dwave.conf", profile=args.profile) dw_chip_id = None if 'dw_endpoint' in data['metadata'] and not args.ignore_solver_metadata: dw_config['endpoint'] = data['metadata']['dw_endpoint'] print('using d-wave endpoint provided in data file: %s' % dw_config['endpoint']) if 'dw_solver_name' in data['metadata'] and not args.ignore_solver_metadata: dw_config['solver'] = data['metadata']['dw_solver_name'] print('using d-wave solver name provided in data file: %s' % dw_config['solver']) if 'dw_chip_id' in data['metadata'] and not args.ignore_solver_metadata: dw_chip_id = data['metadata']['dw_chip_id'] print('found d-wave chip id in data file: %s' % dw_chip_id) client = dc.Client.from_config(**dw_config) solver = client.get_solver() if not dw_chip_id is None: if solver.properties['chip_id'] != dw_chip_id: print( 'WARNING: qpu chip ids do not match. data: %s hardware: %s' % (dw_chip_id, solver.properties['chip_id'])) couplers = solver.properties['couplers'] sites = solver.properties['qubits'] site_range = tuple(solver.properties['h_range']) coupler_range = tuple(solver.properties['j_range']) h = {} #obj = data['offset'] for lt in data['linear_terms']: i = lt['id'] assert (not i in h) h[i] = lt['coeff'] J = {} for qt in data['quadratic_terms']: i = qt['id_tail'] j = qt['id_head'] assert (not (i, j) in J) J[(i, j)] = qt['coeff'] params = { 'auto_scale': False, 'num_reads': args.num_reads, 'num_spin_reversal_transforms': int(math.ceil(args.num_reads / args.spin_reversal_transform_rate)) - 1, 'annealing_time': args.annealing_time } print('d-wave parameters:') for k, v in params.items(): print(' {} - {}'.format(k, v)) t0 = time.time() answers = solver.sample_ising(h, J, **params) solve_time = time.time() - t0 client.close() for i in range(len(answers['energies'])): print('%f - %d' % (answers['energies'][i], answers['num_occurrences'][i])) if i > 50: print('showed 50 of %d' % len(answers['energies'])) break if args.compute_hamming_distance: min_energy = min(e for e in answers['energies']) min_energy_states = [] for i in range(len(answers['energies'])): if math.isclose(answers['energies'][i], min_energy): sol = answers['solutions'][i] min_energy_states.append( [sol[vid] for vid in data['variable_ids']]) for i in range(len(answers['energies'])): sol = answers['solutions'][i] state = [sol[vid] for vid in data['variable_ids']] min_dist = len(data['variable_ids']) for min_state in min_energy_states: dist = sum(min_state[i] != state[i] for i in range(len(data['variable_ids']))) if dist < min_dist: min_dist = dist print('BQP_ENERGY, %d, %d, %f, %f, %d, %d' % (len(data['variable_ids']), len(data['quadratic_terms']), min_energy, answers['energies'][i], answers['num_occurrences'][i], min_dist)) #print(answers['solutions'][0]) qa_solution = answers['solutions'][0] nodes = len(data['variable_ids']) edges = len(data['quadratic_terms']) lt_lb = -sum(abs(lt['coeff']) for lt in data['linear_terms']) qt_lb = -sum(abs(qt['coeff']) for qt in data['quadratic_terms']) lower_bound = lt_lb + qt_lb #best_objective = answers['energies'][0] #best_nodes = args.num_reads qpu_runtime = answers['timing']['total_real_time'] / 1000000.0 #scaled_objective = data['scale']*(best_objective+data['offset']) #scaled_lower_bound = data['scale']*(lower_bound+data['offset']) #return data = bqpjson.spin_to_bool(data) variable_ids = set(data['variable_ids']) variable_product_ids = set([(qt['id_tail'], qt['id_head']) for qt in data['quadratic_terms']]) m = Model() if args.runtime_limit != None: m.setParam('TimeLimit', args.runtime_limit - qpu_runtime) m.setParam('Threads', args.thread_limit) if args.cuts != None: m.setParam('Cuts', args.cuts) #m.setParam('Presolve', 2) #m.setParam('MIPFocus', 1) #m.setParam('MIPFocus', 2) variable_lookup = {} for vid in variable_ids: variable_lookup[vid] = m.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='site_%04d' % vid) variable_lookup[vid].start = (0 if qa_solution[vid] <= 0 else 1) m.update() spin_data = bqpjson.core.swap_variable_domain(data) if len(spin_data['linear_terms']) <= 0 or all( lt['coeff'] == 0.0 for lt in spin_data['linear_terms']): print('detected spin symmetry, adding symmetry breaking constraint') v1 = data['variable_ids'][0] m.addConstr(variable_lookup[(v1, v1)] == 0) obj = 0.0 for lt in data['linear_terms']: i = lt['id'] obj += lt['coeff'] * variable_lookup[i] for qt in data['quadratic_terms']: i = qt['id_tail'] j = qt['id_head'] obj += qt['coeff'] * variable_lookup[i] * variable_lookup[j] m.setObjective(obj, GRB.MINIMIZE) m.update() m._cut_count = 0 m.optimize(cut_counter) # if args.show_solution: # print('') # for k,v in variable_lookup.items(): # print('{:<18}: {}'.format(v.VarName, v.X)) lower_bound = m.MIPGap * m.ObjVal + m.ObjVal scaled_objective = data['scale'] * (m.ObjVal + data['offset']) scaled_lower_bound = data['scale'] * (lower_bound + data['offset']) best_solution = ', '.join([ "-1" if variable_lookup[vid].X <= 0.5 else "1" for vid in data['variable_ids'] ]) print('') if args.show_solution: print('BQP_SOLUTION, %d, %d, %f, %f, %s' % (len(variable_ids), len(variable_product_ids), scaled_objective, m.Runtime, best_solution)) print('BQP_DATA, %d, %d, %f, %f, %f, %f, %f, %d, %d' % (len(variable_ids), len(variable_product_ids), scaled_objective, scaled_lower_bound, m.ObjVal, lower_bound, m.Runtime + qpu_runtime, m._cut_count, m.NodeCount))
def main(args): if args.input_file == None: data = json.load(sys.stdin) else: with open(args.input_file) as file: data = json.load(file) bqpjson.validate(data) if data['variable_domain'] != 'spin': print('only spin domains are supported. Given %s' % data['variable_domain']) quit() data = bqpjson.spin_to_bool(data) variable_ids = set(data['variable_ids']) variable_product_ids = set([(qt['id_tail'], qt['id_head']) for qt in data['quadratic_terms']]) m = Model() if args.runtime_limit != None: m.setParam('TimeLimit', args.runtime_limit) m.setParam('Threads', args.thread_limit) if args.cuts != None: m.setParam('Cuts', args.cuts) #m.setParam('Presolve', 2) #m.setParam('MIPFocus', 1) #m.setParam('MIPFocus', 2) variable_lookup = {} for vid in variable_ids: variable_lookup[vid] = m.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='site_%04d' % vid) m.update() spin_data = bqpjson.core.swap_variable_domain(data) if len(spin_data['linear_terms']) <= 0 or all( lt['coeff'] == 0.0 for lt in spin_data['linear_terms']): print('detected spin symmetry, adding symmetry breaking constraint') v1 = data['variable_ids'][0] m.addConstr(variable_lookup[v1] == 0) obj = 0.0 for lt in data['linear_terms']: i = lt['id'] obj += lt['coeff'] * variable_lookup[i] for qt in data['quadratic_terms']: i = qt['id_tail'] j = qt['id_head'] obj += qt['coeff'] * variable_lookup[i] * variable_lookup[j] m.setObjective(obj, GRB.MINIMIZE) m.update() m._cut_count = 0 m.optimize(cut_counter) # if args.show_solution: # print('') # for k,v in variable_lookup.items(): # print('{:<18}: {}'.format(v.VarName, v.X)) lower_bound = m.MIPGap * m.ObjVal + m.ObjVal scaled_objective = data['scale'] * (m.ObjVal + data['offset']) scaled_lower_bound = data['scale'] * (lower_bound + data['offset']) best_solution = ', '.join([ "-1" if variable_lookup[vid].X <= 0.5 else "1" for vid in data['variable_ids'] ]) print() if args.show_solution: print('BQP_SOLUTION, %d, %d, %f, %f, %s' % (len(variable_ids), len(variable_product_ids), scaled_objective, m.Runtime, best_solution)) print('BQP_DATA, %d, %d, %f, %f, %f, %f, %f, %d, %d' % (len(variable_ids), len(variable_product_ids), scaled_objective, scaled_lower_bound, m.ObjVal, lower_bound, m.Runtime, m._cut_count, m.NodeCount))