def test_linear(self): """Run a set of independent variables.""" size = 10 qubo = {} solution = {} for ii in range(size): qubo[(ii, ii)] = -1 solution[ii] = 1 results = dwave_qbsolv.QBSolv().sample_qubo(qubo) self.has_solution(results, solution, -size) results = dwave_qbsolv.QBSolv().sample_qubo(qubo, target=-size) self.has_solution(results, solution, -size)
def test_easy_loop(self): """Run a loop of variables without frustration.""" size = 10 qubo = {} solution = {} for ii in range(size): qubo[(ii, ii)] = -1 qubo[ii, (ii + 1) % size] = -1 solution[ii] = 1 results = dwave_qbsolv.QBSolv().sample_qubo(qubo) self.has_solution(results, solution, -2 * size) results = dwave_qbsolv.QBSolv().sample_qubo(qubo, target=-2 * size) self.has_solution(results, solution, -2 * size)
def test_qbsolv(self): import dwave_qbsolv as qbsolv h = {'a': -1, 'b': +1} J = {('a', 'b'): -1} resp = qbsolv.QBSolv().sample_ising(h, J)
def test_single_frustrated_loop(self): """Run a loop of variables with a frustrated link.""" size = 10 qubo = {} solution = {} for ii in range(size): qubo[(ii, ii)] = -1 qubo[ii, (ii + 1) % size] = -1 solution[ii] = 1 qubo[size - 1, 0] = 1 results = dwave_qbsolv.QBSolv().sample_qubo(qubo) self.has_solution(results, solution, -2 * size + 2) results = dwave_qbsolv.QBSolv().sample_qubo(qubo, target=-2 * size + 2) self.has_solution(results, solution, -2 * size + 2)
def QBSolve_classical_solution(Q, times_list, print_energy=False): """This function use classical QBSolve to get solution dictionary""" Qdict = Q_dict(Q) start = time.clock() response = QBSolv.QBSolv().sample_qubo(Qdict) # print("ENERGY: ", str(list(response.data_vectors['energy']))) # print("RESPONSE: ", response) qb_solution = list(response.samples()) if print_energy: print("energies=" + str(list(response.data_vectors['energy']))) end = time.clock() time_taken = end - start # print("Time taken by classical QBSolv: ", time_taken) times_list.append(time_taken) qb_solution_list = list(qb_solution[0].values()) return qb_solution_list
def test_callable_solver(self): """Run a set of beasely instances with 50 variables.""" qbsolv = dwave_qbsolv.QBSolv() tests_path = os.path.dirname(os.path.abspath(__file__)) import random callback_called = [False] def _callback(Q, best): callback_called[0] = True return [random.randint(0, 1) for _ in best] for index, expected_energy in enumerate(self.beasley50_energies): index += 1 qubo = load_qubo(self.beasley50_qubo_format.format(tests_path=tests_path, index=index)) # Python 3 feature # with self.subTest(index=index, energy=energy): # Give each problem three shots. One should be enough. # But this is a non-deterministic test. for _ in range(3): results = qbsolv.sample_qubo(qubo, find_max=True, solver=_callback) self.assertTrue(any(abs(energy - expected_energy) < ENERGY_ERROR for energy in results.energies())) break else: self.fail() # make sure at least one call invoked the callback self.assertTrue(callback_called[0])
def test_dimod_basic_qubo_alpha(self): n_variables = 50 # all 0s Q = {(alpha[v], alpha[v]): 1 for v in range(n_variables)} response = qbs.QBSolv().sample_qubo(Q, seed=5125) sample = next(iter(response)) for v in sample: self.assertEqual(sample[v], 0) # all 1s Q = {(alpha[u], alpha[v]): -1 for u, v in itertools.combinations(range(n_variables), 2)} response = qbs.QBSolv().sample_qubo(Q, seed=5342) sample = next(iter(response)) for v in sample: self.assertEqual(sample[v], 1)
def test_dimod_solver(self): """Run a set of beasely instances with 50 variables.""" qbsolv = dwave_qbsolv.QBSolv() tests_path = os.path.dirname(os.path.abspath(__file__)) for index, expected_energy in enumerate(self.beasley50_energies): index += 1 qubo = load_qubo( self.beasley50_qubo_format.format(tests_path=tests_path, index=index)) # Python 3 feature # with self.subTest(index=index, energy=energy): # Give each problem three shots. One should be enough. # But this is a non-deterministic test. for _ in range(3): results = qbsolv.sample_qubo(qubo, find_max=True, solver=dimod.RandomSampler()) self.assertTrue( any( abs(datum.energy - expected_energy) < ENERGY_ERROR for datum in results.data())) break else: self.fail()
def test_dimod_basic_ising(self): n_variables = 60 h = {v: -1 for v in range(n_variables)} J = {} response = qbs.QBSolv().sample_ising(h, J) sample = next(iter(response)) for v in sample: self.assertEqual(sample[v], 1)
def test_dimod_basic_qubo(self): n_variables = 50 # all 0s Q = {(v, v): 1 for v in range(n_variables)} response = qbs.QBSolv().sample_qubo(Q, seed=10) sample = next(iter(response)) for v in sample: self.assertEqual(sample[v], 0) # all 1s Q = {(u, v): -1 for u, v in itertools.combinations(range(n_variables), 2)} response = qbs.QBSolv().sample_qubo(Q, seed=167) sample = next(iter(response)) for v in sample: self.assertEqual(sample[v], 1) for sample, energy in response.data(['sample', 'energy']): self.assertEqual(dimod.qubo_energy(sample, Q), energy)
def test_energy_calculation(self): n_variables = 15 h = {alpha[v]: random.uniform(-2, 2) for v in range(n_variables)} J = {(alpha[u], alpha[v]): random.uniform(-1, 1) for u, v in itertools.combinations(range(n_variables), 2) if random.random() > .98} response = qbs.QBSolv().sample_ising(h, J) for sample, energy in response.data(['sample', 'energy']): self.assertLessEqual(abs(dimod.ising_energy(sample, h, J) - energy), 10**-5)
def solve_specialized_set_cover(input_sets, target_set): qubo = generate_qubo_specialized_set_cover(input_sets, target_set) actual_considered_input_sets = [] for s in input_sets: if s.issubset(target_set): actual_considered_input_sets.append(s) # N = len(actualConsideredInputSets) # n = len(targetSet) # print(N + N*n) # print(actualConsideredInputSets) # visualizeMatrix(qubo, N + N*n) qbsolv_params = dict(num_repeats=10, verbosity=-1) solutions = list(qbs.QBSolv().sample_qubo(qubo, **qbsolv_params).samples()) solution_list = [] for sol in solutions: temp = [] for i in range(max(sol.keys()) + 1): temp.append(sol[i]) solution_list.append(temp) # print(solution_list) potential_solutions = [] for sol in solution_list: temp = [] for i in range(len(actual_considered_input_sets)): if sol[i] == 1: temp.append(actual_considered_input_sets[i]) potential_solutions.append(temp) # print("potential_solutions", potential_solutions) potential_solutions.sort(key=lambda x: len(x)) for pot_sol in potential_solutions: total_set = set([]) for s in pot_sol: total_set = total_set.union(s) if target_set == total_set: return pot_sol # print("We could not find a Solution") return -1
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import networkx as nx import dwave_networkx as dnx import dwave_micro_client_dimod as micro import dwave_qbsolv urlc = 'https://cloud.dwavesys.com/sapi' tokenc = 'SE-bb7f104b4a99cf9a10eeb9637f0806761c9fcedc' solver_namec = 'DW_2000Q_1' structured_samplerc = micro.DWaveSampler(solver_namec, urlc, tokenc) samplerc = micro.EmbeddingComposite(structured_samplerc) samplerq = dwave_qbsolv.QBSolv() cloudsi = dnx.structural_imbalance(G, samplerc , num_reads=10000) qbsolvsi = dnx.structural_imbalance (G, samplerq , solver= samplerc) h = {v: node_values [v] for v in G.nodes } J = {(u, v): eval for u, v in G.edges } response = samplerc.sample_ising (h, J, num_reads=10000)
def test_single_bit(self): """Make sure the solver can tell which way to flip a single bit.""" qubo = {(0, 0): -1} results = dwave_qbsolv.QBSolv().sample_qubo(qubo) self.has_solution(results, {0: 1}, -1)
def forward_qa(self, penalties_and_rewards: dict, num_repeats: int) -> None: # language=rst """ Runs a single simulation step. Only works for batch_size = 1 and DiehlAndCook-Network. """ conn = self.connections inputs = {} # shape: number of layers * number of neurons qubo = {} # shape: (number of neurons * number of layers)^2 encoding = { } # to remember at which row_nr which layer starts, shape: number of layers nr_of_prev_nodes = 0 for l in self.layers: l_v = self.layers[l] inputs[l] = torch.zeros(1, l_v.n) # a tensor for each layer encoding[l] = nr_of_prev_nodes nr_of_prev_nodes += l_v.n # Decay voltages. if l == 'Ae': # layer of DiehlAndCookNodes l_v.v = l_v.decay * (l_v.v - l_v.rest) + l_v.rest # and adaptive thresholds l_v.theta *= l_v.theta_decay elif l == 'Ai': # layer of LIF-Nodes l_v.v = l_v.decay * (l_v.v - l_v.rest) + l_v.rest # else: l == 'X' -> layer of Input-Nodes -> does not have a voltage # prepare Quantum Annealing and get inputs # go through layers (and corresponding Input-connections) l_ae_v = self.layers['Ae'] l_ai_v = self.layers['Ai'] # Layer X of Input-Neurons: nothing to do # Layer Ae of excitatory DiehlAndCook-Nodes # needed later for Inputs from layers X and Ai (connections X->Ae and Ai->Ae) s_view_x = self.layers['X'].s.float().view(self.layers['X'].s.size(0), -1)[0].tolist() s_view_ai = self.layers['Ai'].s.float().view( self.layers['Ai'].s.size(0), -1)[0].tolist() for node_ae in range(l_ae_v.n): # Could spike -> needs constraints if l_ae_v.refrac_count[0, node_ae].item() == 0: nr_ae = node_ae + encoding['Ae'] # diagonal # = threshold + variable threshold theta - (voltage + connection-bias) # for c in conn: not needed in this case: always bias = 0 # if c[1] == 'Ae': # l_ae_v.v[0, node] += conn[c].b[node] qubo[(nr_ae, nr_ae)] = l_ae_v.thresh.item( ) + l_ae_v.theta[node_ae].item() - l_ae_v.v[0, node_ae].item() # + NUDGE? # off-diagonal, same layer # l_v.one_spike is always true in this example -> ensure just one node in this layer spikes for other_ae_node in range((node_ae + 1), l_ae_v.n): # node_column is not in refractory period either if l_ae_v.refrac_count[0, other_ae_node].item() == 0: other_nr = other_ae_node + encoding['Ae'] # penalty to make sure nodes do not spike at the same time qubo[(nr_ae, other_nr)] = penalties_and_rewards['Ae'] # off-diagonal, Inputs from layer X (connection X->Ae) # we work in the upper triangular matrix, connection goes from row to column for node_x in range(self.layers['X'].n): inp = s_view_x[node_x] * conn[ ('X', 'Ae')].w[node_x, node_ae].item() nr_x = node_x + encoding['X'] qubo[(nr_x, nr_ae)] = -1 * inp inputs['Ae'][0, node_ae] += inp # off-diagonal, Inputs from layer Ai (connection Ai->Ae) # we work in the upper triangular matrix, connection goes from column to row # actual connections (where weights ≠ 0) are only where node_ae ≠ node_ai for node_ai in range(self.layers['Ai'].n): if not node_ae == node_ai: inp = s_view_ai[node_ai] * conn[ ('Ai', 'Ae')].w[node_ai, node_ae].item() column_nr = node_ai + encoding['Ai'] qubo[(nr_ae, column_nr)] = -1 * inp inputs['Ae'][0, node_ae] += inp # else: reward can be omitted for excitatory neurons -> done here for performance reasons # Layer Ai of inhibitory LIF-Nodes # needed later for Inputs from layer Ae (connection Ae->Ai) s_view_ae = self.layers['Ae'].s.float().view( self.layers['Ae'].s.size(0), -1)[0].tolist() for node in range(l_ai_v.n): # Could spike -> needs constraints if l_ai_v.refrac_count[0, node].item() == 0: nr_ai = node + encoding['Ai'] # diagonal # = threshold - (voltage + connection-bias) # for c in conn: not needed in this case: always bias = 0 # if c[1] == 'Ai': # l_ai_v.v[0, node] += conn[c].b[node] qubo[(nr_ai, nr_ai)] = l_ai_v.thresh.item() - l_ai_v.v[ 0, node].item() # + NUDGE? # for off-diagonal, same layer: nothing to do # off-diagonal, Inputs from layer Ae (connection Ae->Ai) # we work in the upper triangular matrix, connection goes from row to column # actual connections (where weights ≠ 0) are only where node_ai = node_ae inp = s_view_ae[node] * conn[('Ae', 'Ai')].w[node, node].item() nr_ae = node + encoding['Ae'] qubo[(nr_ae, nr_ai)] = -1 * inp inputs['Ai'][0, node] += inp else: # might just have spiked -> needs reward to clamp qubit to 1 if s_view_ai[ node]: # reward would not harm if neuron did not spike, but embedding easier without nr_ai = node + encoding['Ai'] qubo[(nr_ai, nr_ai)] = penalties_and_rewards['Ai'] # Wegen Hin- und Rückconnection: Verfälscht "Rüberklappen" Inhalt, # da connection von Ae nach Ai ≠ connection von Ai nach Ae? # -> Nein, denn: Wenn connection Ae->Ai existiert, dann existiert nicht wirklich Ai->Ae und umgekehrt # Für Situationen, wo dies doch der Fall wäre (Recurrent NN), wäre folgende Argumentation möglich, # solange nicht geclamped wird (da bei clamping Ae-Neuron spikt, # obwohl nicht in refrac-Period (in aktueller Implementierung), hält dann 1. nicht): # 1. Wenn Input-spike auf connection Ae->Ai, dann Ae-neuron in refrac-Period # -> bekommt keine Input-spikes Ai->Ae, sondern leer # -> ok, weil insgesamt bei Klappen der Wert dann nur der von Ae->Ai ist # 2. Wenn Input-spike auf connection Ai->Ae, dann Ai-neuron in refrac-Period # -> bekommt keine Input-spikes Ae->Ai, sondern leer # -> ok, weil insgesamt bei Klappen der Wert dann nur der von Ai->Ae ist # 3. Beide gleichzeitig Input-Spike -> beide in refrac-Period -> auch kein Problem: Wert leer # 4. Beide gleichzeitig kein Input-Spike -> Wert auf beiden Connections = w * 0 = 0 # => "Rüberklappen" kein Problem, da keine Verfälschung # call Quantum Annealer or simulator (creates a triangular matrix out of qubo by itsself) # start = clock.time() # originally num_repeats=40, seems to work well with num_repeats=1, too (-> now default) solution = qbs.QBSolv().sample_qubo(qubo, num_repeats=num_repeats, verbosity=-1) # end = clock.time() # elapsed = end - start # print("\n Wall clock time qbsolv: %fs" % elapsed) print("\n Energy of qbsolv-solution: %f" % solution.first.energy) for l in self.layers: l_v = self.layers[l] # write spikes from (first) solution by filtering out 1s from neurons in refractory period if not l == 'X': # not layer of Input-Nodes spikes = torch.full((1, l_v.n), False, dtype=torch.bool) nr = encoding[l] for node in range(l_v.n): # is not in refractory period (has not just spiked) -> could spike if l_v.refrac_count[0, node].item() == 0: if solution.first.sample[nr + node] == 1: spikes[0][node] = True l_v.s = spikes # Integrate inputs into voltage # (bias not necessary, as always = 0 in this example, inputs are zero where in refrac-period # -> no need to check, Input-layer does not have voltage) l_v.v += inputs[l] # Decrement refractory counters. (Input-layer does not have refrac_count) l_v.refrac_count = (l_v.refrac_count > 0).float() * (l_v.refrac_count - l_v.dt) # Refractoriness, voltage reset, and adaptive thresholds. l_v.refrac_count.masked_fill_(l_v.s, l_v.refrac) l_v.v.masked_fill_(l_v.s, l_v.reset) if l == 'Ae': # layer of DiehlAndCookNodes l_v.theta += l_v.theta_plus * l_v.s.float().sum(0)
qubo = BinaryQuadraticModel.empty(dimod.BINARY) for n in range(N): qubo.add_offset(1) for k1 in range(K): for k2 in range(K): if k1 != k2: qubo.add_interaction(d2tod1(n, k1, K), d2tod1(n, k2, K), 1) for k in range(K): qubo.add_variable(d2tod1(n, k, K), -1) for (u, v) in neighbours: for k in range(K): qubo.add_interaction(d2tod1(u, k, K), d2tod1(v, k, K), 1) print(qubo) # Set up the solver sampler = dimod.SimulatedAnnealingSampler() solver = dwave_qbsolv.QBSolv() # Solve for the minimum energy configuration response = solver.sample(qubo, num_reads=300) sol = list(response.samples()) # Draw the final coloring configuration # Multiple possible minimum configurations are given as the output, here we take one of them to draw the graph s = sol[0] print(s) g = nx.Graph() g.add_nodes_from(nodes) g.add_edges_from(neighbours) pos = nx.spring_layout(g) nx.draw(g, pos=pos, with_labels=True, nodelist=nodes,
for var, value in fixed_variables.items(): bqm.fix_variable(var, value) # 'aux1' becomes disconnected, so needs to be fixed bqm.fix_variable('aux1', 1) # don't care value if _qpu: # find embedding and put on system print("Running using QPU\n") sampler = system.EmbeddingComposite(system.DWaveSampler()) response = sampler.sample_ising(bqm.linear, bqm.quadratic, num_reads=NUM_READS) else: # if no qpu access, use qbsolv's tabu print("Running using qbsolv's classical tabu search\n") sampler = qbsolv.QBSolv() response = sampler.sample_ising(bqm.linear, bqm.quadratic) #################################################################################################### # output results #################################################################################################### # responses are sorted in order of increasing energy, so the first energy is the minimum min_energy = next(response.energies()) best_samples = [ datum['sample'] for datum in response.data() if datum['energy'] == min_energy ] for sample in best_samples: for variable in list(sample.keys()):