Пример #1
0
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)
Пример #2
0
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))
Пример #3
0
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))