def n_queens(n, sampler=None): """Returns a potential solution to the n-queens problem in a list of sets, each containing constraint IDs representing a queen's location. Args: n: Number of queens to place. sampler: A binary quadratic model sampler. Defaults to dwave-system's LeapHybridSampler. """ num_row_col_constraints = 2 * n row_col_constraint_ids = set(range(num_row_col_constraints)) num_diag_constraints = 4 * n - 6 # includes anti-diag constraints diag_constraint_ids = set( range(num_row_col_constraints, num_row_col_constraints + num_diag_constraints)) # Build subsets of constraint IDs. Each subset will become a variable in our BQM. subsets = build_subsets(n) # Build BQM with only row/col constraints bqm = exact_cover_bqm(row_col_constraint_ids, subsets) # Add diag/anti-diag constraints - duplicates are penalized. bqm = handle_diag_constraints(bqm, subsets, diag_constraint_ids) if sampler is None: sampler = LeapHybridSampler() sampleset = sampler.sample(bqm) sample = sampleset.first.sample return [subsets[i] for i in sample if sample[i]]
def optimize_leap(self): from pyqubo import Array,Constraint,Placeholder,UnaryEncInteger,Sum #LogEncInteger from dwave.system import LeapHybridSampler x = Array.create("x",shape=(self.num),vartype="BINARY") #y = LogEncInteger("y",lower=0,upper=5) y = UnaryEncInteger("y",lower=0,upper=5) #価値が最大になるように(符号を反転させる) H1 = -Sum(0,self.num,lambda i :x[i]*self.p[i].get_value() ) #H1 = -sum([x[i]*self.p[i].get_value() for i in range(self.num)]) #重さが目的の重量になるように H2 = Constraint((self.limit_weight -sum([x[i]*p_i.get_weight() for i,p_i in enumerate(self.p)]) - y*10)**2,"Const Weight") H = H1 + H2*Placeholder("balancer") model = H.compile() balance_dict = {"balancer":1.0} bqm = model.to_dimod_bqm(feed_dict=balance_dict) sampler = LeapHybridSampler() responses = sampler.sample(bqm,time_limit=3) solutions = model.decode_dimod_response(responses,feed_dict=balance_dict) if len(solutions[0][1]) == 0: print(f" y= { sum(2**i*y_i for i,y_i in enumerate(solutions[0][0]['y']))}") print("## LeapHybridSolver Optimized Result") self.print([int(solutions[0][0]['x'][i]) for i in range(self.num)]) else: print("## LeapHybridSolver Optimizing Failed")
def solve_knapsack(incidencias, controles, online, sampler=None, samplerSpin=None): timeBqmS = datetime.now() bqm, J = createBQM( incidencias, controles) #Se crea la matriz con las energías entre cada incidencia. timeBqmF = datetime.now() timeBQM = timeBqmF - timeBqmS print('Se han tardado ' + str(timeBQM) + ' segundos en crear el BQM.') timeSamplerS = datetime.now() if online: sampler = LeapHybridSampler( ) #Se inicializa el sampler. El LeapHybridSampler se utiliza para conectarse a else: #los ordenadores de D-Wave, y el ExactSolver para hacer una simulación en la sampler = ExactSolver() #computadora. #Probar SimulatedAnnealingSampler timeSamplerF = datetime.now() timeSampler = timeSamplerF - timeSamplerS print('Se han tardado ' + str(timeSampler) + ' segundos en crear el sampler.') timeSolverS = datetime.now() sampleset = sampler.sample( bqm ) #Se pasa el BQM que hemos creado anteriormente al sampler y busca las soluciones. timeSolverF = datetime.now() timeSolver = timeSolverF - timeSolverS print('Se han tardado ' + str(timeSolver) + ' segundos en resolver el problema.') sample = sampleset.first.sample #Se guarda qué incidencias han sido gestionadas y cuáles no. energy = sampleset.first.energy #Se guarda la energía que tiene la solución. #selected_item_ids = [] #for varname, value in sample.items(): # For each "x" variable, check whether its value is set, which # indicates that the corresponding item is included in the # knapsack # The index into the weight array is retrieved from the # variable name #if(sample[varname] == 1): #selected_item_ids.append(int(varname)) selected_item_ids = [] for varname, value in sample.items(): # For each "x" variable, check whether its value is set, which # indicates that the corresponding item is included in the # knapsack if value and varname.startswith('x'): # The index into the weight array is retrieved from the # variable name selected_item_ids.append(int(varname[1:])) return sorted(selected_item_ids), energy, timeSolver, sampleset, J
def QBSolve_quantum_solution(Q, times_list, token, annealing_time, print_energy=False): """This function use QC to get solution dictionary""" Qdict = Q_dict(Q) # print("QDICT: ", Qdict) # endpoint = 'https://cloud.dwavesys.com/sapi' # bqm = dimod.BinaryQuadraticModel.from_qubo(Qdict) # print("BQM: ", bqm) print("ACCESSING QUANTUM COMPUTER . . . . .") print("Anneal time: ", annealing_time) sampler = LeapHybridSampler(token=token) start = time.clock() # try: response = sampler.sample_qubo(Qdict, qpu_params={'annealing_time': annealing_time}) timing_dict = response.info # print("\n\n\n\nTIMING INFO: ", timing_dict) qc_time = timing_dict["qpu_access_time"] qc_time_list.append(qc_time) print("\n\n\n\n\nQC TIMES UHUHUHUHUHHUHU", qc_time_list) end = time.clock() # print("INFO: ", response.info) print("RESPONSE: ", response) # except ValueError: # print("\n\nEXCEPTION FOUND ...............\n") # # response = QBSolv.QBSolv().sample_qubo(Qdict, solver=sampler) # response = QBSolv.QBSolv().sample_qubo(Qdict) # print("RESPONSE: ", response) print("energies=" + str(list(response.data_vectors['energy']))) print("num_occurence=" + str(list(response.data_vectors['num_occurrences']))) if print_energy: print("energies=" + str(list(response.data_vectors['energy']))) time_taken = end - start times_list.append(time_taken) print("Time taken by QPU: ", time_taken) qb_solution = list(response.samples()) qb_solution_list = list(qb_solution[0].values()) return qb_solution_list
def _minimize_squared_loss_binary(H, y, lam): """Minimize squared loss using binary weight variables.""" bqm = _build_bqm(H, y, lam) sampler = LeapHybridSampler() results = sampler.sample(bqm, label='Example - QBoost') weights = np.array(list(results.first.sample.values())) energy = results.first.energy return weights, energy
def solve(self): if (self.useQPU): sampler = EmbeddingComposite(DWaveSampler(solver={'qpu': True})) sampleset = sampler.sample_qubo(self.Q, num_reads=self.n_reads, chain_strength=self.chain) elif (self.useNeal): bqm = BinaryQuadraticModel.from_qubo(self.Q, offset=self.offset) sampler = neal.SimulatedAnnealingSampler() sampleset = sampler.sample(bqm, num_reads=self.n_reads, chain_strength=self.chain) elif (self.useHyb): bqm = BinaryQuadraticModel.from_qubo(self.Q, offset=self.offset) sampler = LeapHybridSampler() sampleset = sampler.sample(bqm, num_reads=self.n_reads) else: bqm = BinaryQuadraticModel.from_qubo(self.Q, offset=self.offset) sampler = TabuSampler() sampleset = sampler.sample(bqm, num_reads=self.n_reads, chain_strength=self.chain) self.sampleset = sampleset
def get_sampler_from_config(self, profile=None, solver=None, sampler_type=None): """Return a dimod.Sampler object found in the user's configuration file, associated solver information, and any extra parameters needed.""" try: with Client.from_config(profile=profile, client=sampler_type) as client: if solver == None: solver = client.default_solver solver_name = solver["name__eq"] else: solver_name = solver solver = {"name": solver} if isinstance(client, hybrid.Client): sampler = LeapHybridSampler(profile=profile, solver=solver) elif isinstance(client, sw.Client): self.qmasm.abend("QMASM does not currently support remote software solvers") else: sampler = DWaveSampler(profile=profile, solver=solver) info = self._recursive_properties(sampler) info["solver_name"] = solver_name info["endpoint"] = client.endpoint if profile != None: info["profile"] = profile return sampler, info, {} except Exception as err: self.qmasm.abend("Failed to construct a sampler (%s)" % str(err))
def binary_clustering(feature_vecs, feature_index, **kwargs): h = {} J = {} cluster1 = [] #stores the indices for the first cluster cluster2 = [] #stores the indices for the second cluster #will recognize tabu or hybrid if 'sampler' in kwargs: sampler_type = kwargs['sampler'] else: sampler_type = "tabu" if 'time_limit' in kwargs: time_limit = kwargs['time_limit'] else: time_limit = 20 sampler = TabuSampler() sampler1 = LeapHybridSampler() for i in feature_index: for j in feature_index: if i < j: J[(i, j)] = np.linalg.norm(feature_vecs[i] - feature_vecs[j]) #Now use a sampler to solve it if sampler_type == "tabu": print("Choosing TABU sampler") sampler = TabuSampler() sampleset = sampler.sample_ising(h, J, num_reads=1, timeout=time_limit * 1000) bin_cluster = sampleset.first[0] else: print("Choosing the hybrid sampler") sampler1 = LeapHybridSampler() sampleset = sampler1.sample_ising(h, J, time_limit=time_limit) bin_cluster = sampleset.first[0] # Run the problem on the sampler and print the results for key in bin_cluster: #put in cluster 1 if -1, else 2 if bin_cluster[key] == -1: cluster1.append(key) elif bin_cluster[key] == 1: cluster2.append(key) return cluster1, cluster2
def generate_stars(N: int, nstars: int, annealer="neal", num_reads=100): """ Generate valid star positions on grid. Return a list of positions and an np.array. Annealer may be: 1. 'neal' (simulated); 2. 'leap' (real).""" g = 1 Q = constraint_two_dont_touch(N) regions = [*row_regions(N), *column_regions(N)] for region in regions: Q = Q + g * region_constraint(region, nstars) if annealer == 'neal': sampler = neal.SimulatedAnnealingSampler() sampleset = sampler.sample_qubo(Q, num_reads=num_reads) elif annealer == 'leap': # Go to DWave sampler = LeapHybridSampler() sampleset = sampler.sample_qubo(Q) else: raise Exception(f"Annealer {annealer} not recognized.") minimum_theo = -2 * N * nstars**2 * g valid_samples = [] sorted_records = sorted(sampleset.record, key=lambda r: r.energy) variables = sampleset.variables for record in sorted_records: sample = {x_ij: value for x_ij, value in zip(variables, record.sample)} energy = record.energy cond_1 = confirm_solution_stars(sample, regions, nstars) cond_2 = abs(energy - minimum_theo) < 1e-6 if not cond_1 | cond_2: break # Return a list of positions and an np.array. yield star_solutions(N, sample)
def sample_dwave(bqm: dimod.BinaryQuadraticModel, sample_label: str) -> dict[int, int]: """Ask the DWave sampler to return the best sample for the supplied binary quadratic model Args: bqm (dimod.BinaryQuadraticModel): Binary qudratic model representing the problem sample_label (str): Label to use for the sample - appears in the DWave dashboard Returns: A dictionary mapping the location of each element in the input "vector" to the corresponding 0/1 value returned by the sampler """ sampler = LeapHybridSampler() sample_set = sampler.sample(bqm, label=sample_label) return sample_set.first.sample
def test_small(self): demand, nfreq, reuse_distances = load_problem('small') bqm = frequency.construct_bqm(demand, nfreq, reuse_distances) sampler = LeapHybridSampler() results = sampler.sample(bqm) violation_dict = frequency.check_results(demand, nfreq, reuse_distances, results.first, verbose=False) self.assertEqual(violation_dict['demand-count'], 0) self.assertEqual(violation_dict['self-count'], 0) self.assertEqual(violation_dict['cross-count'], 0)
def quantum_tsp(self): sampler = LeapHybridSampler() # Get a QUBO representation of the problem Q = self.quantum_tsp_qubo() # use the sampler to find low energy states response = sampler.sample_qubo(Q) sample = response.first.sample route = [None] * len(self.G) for (city, time), val in sample.items(): if val: route[time] = city if self.start is not None and route[0] != self.start: # rotate to put the start in front idx = route.index(self.start) route = route[idx:] + route[:idx] return route
def __init__(self, hidlen, vislen, sampler="Test"): self.sep = 0 if sampler == "LeapHybridSampler": self.sampler = LeapHybridSampler() #accessing dwave self.sep = 1 if sampler == "DWaveSampler": self.sampler = AutoEmbeddingComposite(DWaveSampler()) if sampler == "Test": self.sampler = SimulatedAnnealingSampler() self.t_step = 1000 self.stepsize = 0.1 self.path = "" self.mute = True self.hidlen = hidlen #handling indexes self.vislen = vislen self.outlen = 10 self.hind = ['h' + str(i) for i in range(self.hidlen)] self.vind = ['v' + str(i) for i in range(self.vislen)] self.ind = self.hind + self.vind self.cmap = [] self.coef = np.zeros( (self.vislen + self.hidlen, self.vislen + self.hidlen), dtype=np.float_) #self.Q = {(i, j): self.coef[i][j] for i in self.ind for j in self.ind} self.bqm = dimod.BinaryQuadraticModel(self.coef, 'SPIN') self.response = 0 #response and data from it self.answerlen = 0 self.answer = [] self.index = [] for i in range(self.hidlen + self.vislen): self.index += [i] self.answer_occ = [] self.answern = 0 self.prob = [] self.top = [0] * 3 self.expected = 0 self.images = [] #images from dataset self.label = 0 self.labels = [] self.chosen_images = [] self.prob = [] self.chosen_prob = [] self.single_unfixed = [] self.double_unfixed = [] self.single_fixed = [] self.double_fixed = [] self.delta = [] self.mean_single = []
def solve_knapsack(costs, weights, weight_capacity, sampler=None): """Construct BQM and solve the knapsack problem Args: costs (array-like): Array of costs associated with the items weights (array-like): Array of weights associated with the items weight_capacity (int): Maximum allowable weight sampler (BQM sampler instance or None): A BQM sampler instance or None, in which case LeapHybridSampler is used by default Returns: Tuple: List of indices of selected items Solution energy """ bqm = build_knapsack_bqm(costs, weights, weight_capacity) if sampler is None: sampler = LeapHybridSampler() sampleset = sampler.sample(bqm) sample = sampleset.first.sample energy = sampleset.first.energy # Build solution from returned binary variables: selected_item_indices = [] for varname, value in sample.items(): # For each "x" variable, check whether its value is set, which # indicates that the corresponding item is included in the # knapsack if value and varname.startswith('x'): # The index into the weight array is retrieved from the # variable name selected_item_indices.append(int(varname[1:])) return sorted(selected_item_indices), energy
def solve_puzzle(N, nstars, grid, annealer="neal", num_reads=10): Q = constraint_two_dont_touch(N) regions = [ *region_lists(grid), *row_regions(N), *column_regions(N), ] g = 1 for region in regions: Q = Q + g * region_constraint(region, nstars) # Create Sampler if annealer == 'neal': sampler = neal.SimulatedAnnealingSampler() sampleset = sampler.sample_qubo(Q, num_reads=num_reads) elif annealer == 'leap': # Go to DWave sampler = LeapHybridSampler() sampleset = sampler.sample_qubo(Q) else: raise Exception(f"Annealer {annealer} not recognized.") minimum_energy = theoretical_minimum(N, nstars, g) sorted_records = sorted(sampleset.record, key=lambda r: r.energy) variables = sampleset.variables for record in sorted_records: sample = {x_ij: value for x_ij, value in zip(variables, record.sample)} energy = record.energy is_solution = confirm_solution_stars(sample, regions, nstars) if is_solution: _, solution = star_solutions(N, sample) return solution
def generate_regions(N: int, nstars: int, star_positions: list, star_grid: np.array, annealer="neal", num_reads=100): # Build Star Finder QUBO g1, g2, g3, g4 = 1, 1, 1, 1 color_size = np.array([N]*N) #Number of sites per color Q_reg_1 = g1 * constraint_sum_of_stars(N, nstars, star_positions) Q_reg_2 = g2 * constraint_unique_color(N) Q_reg_3 = g3 * constraint_contiguous(N) Q_reg_4 = g4 * constraint_sum_of_sites(N,color_size) Q_reg = Q_reg_1 + Q_reg_2 + Q_reg_3 + Q_reg_4 if annealer == 'neal': sampler = neal.SimulatedAnnealingSampler() sampleset = sampler.sample_qubo(Q_reg, num_reads=num_reads) elif annealer == 'leap': # Go to DWave sampler = LeapHybridSampler() sampleset = sampler.sample_qubo(Q_reg) else: raise Exception(f"Annealer {annealer} not recognized.") upper_bound = -g1*N*nstars**2 -g2*N**2 -g4*np.sum(color_size**2) lower_bound = upper_bound - g3*4*N**2 # Confirm Solution of Regions sample_star = {x(i, j): value for (i, j), value in np.ndenumerate(star_grid)} sorted_records = sorted(sampleset.record, key=lambda r: r.energy) variables = sampleset.variables for record in sorted_records: sample = {x_ij: value for x_ij, value in zip(variables, record.sample)} energy = record.energy grid = grid_solutions(N, sample) regions = [*region_lists(grid), *row_regions(N), *column_regions(N)] if confirm_solution_regions(sample_star, grid, nstars): yield grid
def main(sampler_type, region, show, inspect): if sampler_type is None: print("No solver selected, defaulting to hybrid") sampler_type = 'hybrid' # get the appropriate signed social network G = global_signed_social_network(region=region) # choose solver and any tuning parameters needed if sampler_type == 'cpu': params = dict(num_reads=100) sampler = SimulatedAnnealingSampler() elif sampler_type == 'hybrid': params = dict() sampler = LeapHybridSampler() elif sampler_type == 'qpu': params = dict( num_reads=100, chain_strength=2.0, ) sampler = dimod.TrackingComposite(EmbeddingComposite(DWaveSampler())) else: raise RuntimeError("unknown solver type") # use the chosen sampler (passing in the parameters) edges, colors = dnx.structural_imbalance( G, sampler, label='Example - Structural Imbalance', **params) if inspect and sampler_type == 'qpu': dwave.inspector.show(sampler.output) print("Found", len(edges), 'violations out of', len(G.edges), 'edges') draw_social_network(G, colors) if show: plt.show() else: filename = 'structural imbalance {} {}.png'.format( sampler_type, region) plt.savefig(filename, facecolor='white') plt.clf()
def __init__(self, B, K, C, gamma, xi, N, sampler_type) -> None: self.gamma = gamma self.B = B self.K = K self.C = C self.xi = xi self.N = N self.sampler_type = sampler_type if (sampler_type == 'HQPU'): self.sampler = LeapHybridSampler() if (sampler_type == 'SA'): self.sampler = neal.SimulatedAnnealingSampler() if (sampler_type == 'QPU'): self.sampler = EmbeddingComposite(DWaveSampler()) pass
def main(sampler_type, region, show): if sampler_type is None: print("No solver selected, defaulting to hybrid") sampler_type = 'hybrid' if region == 'global' and sampler_type == 'qpu': print("Given region is too large for the QPU, please choose another " "region or use hybrid.") # get the appropriate signed social network G = global_signed_social_network(region=region) # choose solver and any tuning parameters needed if sampler_type == 'cpu': params = dict(num_reads=100) sampler = SimulatedAnnealingSampler() elif sampler_type == 'hybrid': params = dict() sampler = LeapHybridSampler() elif sampler_type == 'qpu': params = dict( num_reads=100, chain_strength=2.0, ) sampler = EmbeddingComposite(DWaveSampler()) else: raise RuntimeError("unknown solver type") # use the chosen sampler (passing in the parameters) edges, colors = dnx.structural_imbalance(G, sampler, **params) print("Found", len(edges), 'violations out of', len(G.edges), 'edges') draw_social_network(G, colors) if show: plt.show() else: filename = 'stuctural imbalance {} {}.png'.format(sampler_type, region) plt.savefig(filename, facecolor='white', dpi=500) plt.clf()
def solve(self, useQPU=False, useNeal=False, useHyb=True, time_limit = 10, num_reads = 100, chain_strength = 10000): Q = self.Q BQM_offset = 0 # TODO: Use the accumulated quadratic constants from the constraints bqm = BinaryQuadraticModel.from_qubo(Q, offset=BQM_offset) self.sampleset = None # Call the requested solver if ( useQPU ): print("Solving using the DWaveSampler on the QPU...") sampler = EmbeddingComposite(DWaveSampler(solver={'qpu': True})) sampleset = sampler.sample_qubo(Q, num_reads=num_reads,chain_strength = chain_strength) elif ( useHyb ): print("Solving using the LeapHybridSolver...") sampler = LeapHybridSampler() sampleset = sampler.sample(bqm, time_limit = time_limit) elif ( useNeal ): print("Solving using the SimulatedAnnealing...") sampler = neal.SimulatedAnnealingSampler() sampleset = sampler.sample(bqm, num_reads = num_reads) else: print("Solving using the TabuSampler...") sampler = TabuSampler() sampleset = sampler.sample(bqm, num_reads = num_reads) self.sampleset = sampleset count = 0 for res in self.sampleset.data(): count += 1 return (count)
from cplexsolver import CplexNeosSolver from dwave.system import LeapHybridSampler, DWaveSampler, EmbeddingComposite from cliparser import parser if __name__ == "__main__": args = parser.parse_args() options = { 'no_time': args.no_time, 'verbosity': args.verbosity } if args.solver in ['hybrid', 'embed', 'sim_anneal', 'tabu']: solverClass = DwaveSolver if args.solver == 'hybrid': options['solver'] = LeapHybridSampler() elif args.solver == 'embed': options['solver'] = EmbeddingComposite(DWaveSampler()) elif args.solver == 'sim_anneal': options['solver'] = neal.SimulatedAnnealingSampler() elif args.solver == 'tabu': options['solver'] = 'tabu' options['visualize'] = args.visualize options['top_samples'] = args.sols_to_print elif args.solver == 'cplex': solverClass = CplexNeosSolver elif args.solver == 'qiskit': solverClass = QiskitSolver
# hybrid solver test with 10 edges, 4 vertices import dimod from dwave.system import LeapHybridSampler import numpy as np h = np.loadtxt('h.txt') J = np.loadtxt('J.txt') sampler = LeapHybridSampler() results = sampler.sample_ising(h, J, num_reads=100) out = open('Outputs.txt', 'w') for campione in results.record: for Nple in campione: out.write(str(Nple) + "\t") out.write("\n") out.close() print(results.first)
Q[ind, ind] += lagrange_soft_nurse * (preference ** 2 - (2 * min_duty_days * preference)) # Off-diagonal terms in soft nurse constraint # Include only the same nurse, across days for nurse in range(n_nurses): for day1 in range(n_days): for day2 in range(day1 + 1, n_days): ind1 = get_index(nurse, day1) ind2 = get_index(nurse, day2) Q[ind1, ind2] += 2 * lagrange_soft_nurse * preference ** 2 # Solve the problem, and use the offset to scale the energy e_offset = (lagrange_hard_shift * n_days * workforce ** 2) + (lagrange_soft_nurse * n_nurses * min_duty_days ** 2) bqm = BinaryQuadraticModel.from_qubo(Q, offset=e_offset) sampler = LeapHybridSampler() results = sampler.sample(bqm) # Get the results smpl = results.first.sample energy = results.first.energy print("Size ", size) print("Energy ", energy) # Check the results by doing the sums directly # J sum sum_j = 0 for i in range(size): for j in range(size): sum_j += J[i, j] * smpl[i] * smpl[j]
H_city = Constraint(normalize(sum((sum(q[i][t] for t in range(N-1))-1)**2 for i in range(N-1))), 'city') H_time = Constraint(normalize(sum((sum(q[i][t] for i in range(N-1))-1)**2 for t in range(N-1))), 'time') # Express objective function and compile it to model H = H_cost + Placeholder('lam') * (H_city + H_time) model = H.compile() # --- Solve QUBO --- # Get the QUBO matrix from the model feed_dict = {'lam':5.0} # the value of constraint qubo, offset = model.to_qubo(feed_dict=feed_dict) # Run QUBO on Leap's Hybrid Solver (hybrid_v1) sampler = LeapHybridSampler(token='') response = sampler.sample_qubo(qubo) sample = response.record['sample'][0] # decode the solution and check if constrains are satisfied sample_dict = {idx: sample[i] for i,idx in enumerate(response.variables)} decoded, broken, energy = model.decode_solution(sample_dict, 'BINARY', feed_dict=feed_dict) if broken == {}: print('The solution is valid') else: print('The solution is invalid') # --- Visualize the result --- # Create an array which shows traveling order from the solution
import dimod from dimod import BinaryQuadraticModel import numpy as np from dwave.system import LeapHybridSampler import sys N = int(sys.argv[1]) # Ising model x_i x_j h = {} J = {(i, j): 1 for i in range(N) for j in range(i + 1, N)} bqm = dimod.BinaryQuadraticModel.from_ising(h, J) sampler = LeapHybridSampler() sampleset = sampler.sample(bqm, time_limit=15) print(sampleset.info) print("Found solution at energy {}.".format(sampleset.first.energy)) print(len(sampleset.record[0][0]))
out_file = '18_H.png' # Graph data to be used : 0 .. idx_data = 2 G = read_bigraph(in_file, idx_data) Q = hamilton_qubo(G) bqm = dimod.BinaryQuadraticModel(Q, 'BINARY') # Choose one from below. The top two samplers are software algorithms, # while the bottoms are hardware / hybrid algorithms. #sampler = SimulatedAnnealingSampler() #sampler = TabuSampler() #sampler = EmbeddingComposite(DWaveSampler(solver={'qpu': True, 'postprocess': 'sampling'})) sampler = LeapHybridSampler() # Conduct optimization sampleset = sampler.sample(bqm) #print(sampleset.first) edges = list(G.edges) GS = nx.DiGraph() for (u, v), d in sampleset.first.sample.items(): if d == 1: if (u, v) in edges: GS.add_edge(u, v) else: print(u, v, ": not in G")
offset -= (2 * num_spots) * mill_constant # update quadratic for mill energy decrease for i in range(0, num_spots): if our[i] == 0: continue #idx = b.get_rowcol_idx(i) # This is the original idx = b.get_neighbor_idx(i) for j in idx: if i < j: quadratic[(i + 1, j + 1)] -= 2 * anti_mill_constant offset += (2 * num_spots) * anti_mill_constant vartype = dimod.SPIN bqm = dimod.BinaryQuadraticModel(linear, quadratic, offset, vartype) #sampler = dimod.SimulatedAnnealingSampler() sampler = LeapHybridSampler() #sampler=KerberosSampler() sample_set = sampler.sample(bqm, num_reads=10) #sampler = dimod.ExactSolver() #sample_set = sampler.sample(bqm) #print("sample_set:", sample_set) next_state = sample_set.samples()[0] # Maybe do sampling instead?? print("next_state:", next_state) for i in range(1, num_spots + 1): if next_state[i] == 1 and enemy[i - 1] != 1: # We added condition here enemy[i - 1] = 1 b.place_marker(pos=i - 1, player_num=2) play_counter += 1 print(enemy) print(b)
def main(token=None, n_nurses=3, n_days=11, nurses_per_day=1): """ Takes a number of nurses, a number of days, and a wanted capacity of nurses per day. Also takes in a Dwave Authentication Token. Returns its best try at assigning nurses properly to the schedule required. One can think of the output as being a grid of size row x col, with a desired number of Xs in any column, while avoiding neighbouring Xs in any row. This runs on the Dwave Hybrid Sampler. The solution will be fast and good, but relatively expensive on Dwave allowed minutes. This code includes an implementation of the algorithm described in Ikeda, K., Nakamura, Y. & Humble, T.S. Application of Quantum Annealing to Nurse Scheduling Problem. Sci Rep 9, 12837 (2019). `DOI: 10.1038/s41598-019-49172-3 <https://doi.org/10.1038/s41598-019-49172-3>`_, © The Author(s) 2019, use of which is licensed under a Creative Commons Attribution 4.0 International License :param n_nurses: The number of nurses as an integer (number of rows in solution) :param n_days: The number of days as an integer (number of columns in solution) :param nurses_per_day: The number of desired nurses per day, an integer (desired number of Xs in any given column) :param token: The Dwave token to be used. This should be a string, in the format used on the dwave leap website. :return: Returns a dictionary. Keys supported: * "Size" a string describing the problem size * "Energy" a string describing the energy of the solution * "HardNurseConstraint" a string describing the hard nurse constraint energy * "HardShiftConstraint" a string describing the hard shift constraint energy * "n_days" an integer - the number of days (columns) of the solution * "n_nurses" an integer - the number of nurses (rows) of the solution * "schedule" - A 2-dimensional array of integers. Lists the exact days each nurse works (The marked columns for each row). """ # Overall model variables: problem size # binary variable q_nd is the assignment of nurse n to day d n_nurses = n_nurses # count nurses n = 1 ... n_nurses n_days = n_days # count scheduling days as d = 1 ... n_days size = n_days * n_nurses print("solving with " + str(n_nurses) + " and " + str(n_days) + " nurses and days") # Parameters for hard nurse constraint # a is a positive correlation coefficient for implementing the hard nurse # constraint - value provided by Ikeda, Nakamura, Humble a = 3.5 # Parameters for hard shift constraint # Hard shift constraint: at least one nurse working every day # Lagrange parameter, for hard shift constraint, on workforce and effort lagrange_hard_shift = 1.3 # workforce = 1 # Workforce function W(d) - set to a constant for now workforce = nurses_per_day # Workforce function W(d) effort = 1 # Effort function E(n) - set to a constant for now # Parameters for soft nurse constraint # Soft nurse constraint: all nurses should have approximately even work # schedules # Lagrange parameter, for shift constraints, on work days is called gamma # in the paper # Minimum duty days 'min_duty_days' - the number of work days that each # nurse wants # to be scheduled. At present, each will do the minimum on average. # The parameter gamma's value suggested by Ikeda, Nakamura, Humble lagrange_soft_nurse = 0.3 # Lagrange parameter for soft nurse, gamma preference = 1 # preference function - constant for now # min_duty_days = int(n_days/n_nurses) min_duty_days = int(n_days * workforce / n_nurses) # Find composite index into 1D list for (nurse_index, day_index) def get_index(nurse_index, day_index): return nurse_index * n_days + day_index # Inverse of get_index - given a composite index in a 1D list, return the # nurse_index and day_index def get_nurse_and_day(index): nurse_index, day_index = divmod(index, n_days) return nurse_index, day_index # Hard nurse constraint: no nurse works two consecutive days # It does not have Lagrange parameter - instead, J matrix # symmetric, real-valued interaction matrix J, whereas all terms are # a or zero. # composite indices i(n, d) and j(n, d) as functions of n and d # J_i(n,d)j(n,d+1) = a and 0 otherwise. J = defaultdict(int) for nurse in range(n_nurses): for day in range(n_days - 1): nurse_day_1 = get_index(nurse, day) nurse_day_2 = get_index(nurse, day + 1) J[nurse_day_1, nurse_day_2] = a # Q matrix assign the cost term, the J matrix Q = deepcopy(J) # Hard shift constraint: at least one nurse working every day # The sum is over each day. # This constraint tries to make (effort * sum(q_i)) equal to workforce, # which is set to a constant in this implementation, so that one nurse # is working each day. # Overall hard shift constraint: # lagrange_hard_shift * sum_d ((sum_n(effort * q_i(n,d)) - workforce) ** 2) # # with constant effort and constant workforce: # = lagrange_hard_shift * sum_d ( effort * sum_n q_i(n,d) - workforce ) ** 2 # = lagrange_hard_shift * sum_d [ effort ** 2 * (sum_n q_i(n,d) ** 2) # - 2 effort * workforce * sum_n q_i(n,d) # + workforce ** 2 ] # The constant term is moved to the offset, below, right before we solve # the QUBO # # Expanding and merging the terms ( m is another sum over n ): # lagrange_hard_shift * (effort ** 2 - 2 effort * workforce) * # sum_d sum_n q_i(n,d) # + lagrange_hard_shift * effort ** 2 * sum_d sum_m sum_n q_i(n,d) q_j(m, d) # # Diagonal terms in hard shift constraint, without the workforce**2 term for nurse in range(n_nurses): for day in range(n_days): ind = get_index(nurse, day) Q[ind, ind] += lagrange_hard_shift * (effort**2 - (2 * workforce * effort)) # Off-diagonal terms in hard shift constraint # Include only the same day, across nurses for day in range(n_days): for nurse1 in range(n_nurses): for nurse2 in range(nurse1 + 1, n_nurses): ind1 = get_index(nurse1, day) ind2 = get_index(nurse2, day) Q[ind1, ind2] += 2 * lagrange_hard_shift * effort**2 # Soft nurse constraint: all nurses should have approximately even work # schedules # This constraint tries to make preference * sum(q_i) equal to min_duty_days, # so that the nurses have the same number of days. The sum of the q_i, # over the number of days, is each nurse's number of days worked in the # schedule. # Overall soft nurse constraint: # lagrange_soft_nurse * sum_n ((sum_d(preference * q_i(n,d)) - min_duty_days) ** 2) # with constant preference and constant min_duty_days: # = lagrange_soft_nurse * sum_n ( preference * sum_d q_i(n,d) - min_duty_days ) ** 2 # = lagrange_soft_nurse * sum_n [ preference ** 2 * (sum_d q_i(n,d) ** 2) # - 2 preference * min_duty_days * sum_d q_i(n,d) # + min_duty_days ** 2 ] # The constant term is moved to the offset, below, right before we solve # the QUBO # # The square of the the sum_d term becomes: # Expanding and merging the terms (d1 and d2 are sums over d): # = lagrange_soft_nurse * (preference ** 2 - 2 preference * min_duty_days) * sum_n sum_d q_i(n,d) # + lagrange_soft_nurse * preference ** 2 * sum_n sum_d1 sum_d2 q_i(n,d1) # * q_j(n, d2) # Diagonal terms in soft nurse constraint, without the min_duty_days**2 term for nurse in range(n_nurses): for day in range(n_days): ind = get_index(nurse, day) Q[ind, ind] += lagrange_soft_nurse * (preference**2 - (2 * min_duty_days * preference)) # Off-diagonal terms in soft nurse constraint # Include only the same nurse, across days for nurse in range(n_nurses): for day1 in range(n_days): for day2 in range(day1 + 1, n_days): ind1 = get_index(nurse, day1) ind2 = get_index(nurse, day2) Q[ind1, ind2] += 2 * lagrange_soft_nurse * preference**2 # Solve the problem, and use the offset to scale the energy e_offset = (lagrange_hard_shift * n_days * workforce**2) + ( lagrange_soft_nurse * n_nurses * min_duty_days**2) bqm = BinaryQuadraticModel.from_qubo(Q, offset=e_offset) endpoint = 'https://cloud.dwavesys.com/sapi/' client = 'qpu' #solver = 'DW_2000Q_5' # Use this to specify a solver, but leave commented out to let D-Wave's system autochoose a solver try: qpu_sampler = DWaveSampler(client=client, endpoint=endpoint, token=token) #solver=solver) except: return {'error': 'Token not accepted'} sampler = LeapHybridSampler(token=token) results = sampler.sample(bqm, qpu_sampler=qpu_sampler) # Get the results ret_value = dict() smpl = results.first.sample energy = results.first.energy print("Size ", size) print("Energy ", energy) ret_value["Size"] = "Size " + str(size) ret_value["Energy"] = "Energy " + str(energy) # Check the results by doing the sums directly # J sum # sum_j = 0 # for i in range(size): # for j in range(size): # sum_j += J[i, j] * smpl[i] * smpl[j] # print("Checking Hard nurse constraint ", sum_j) # Removed that method, as it created too many empty elements in J # This one only iterates over non-zero values in J sum_j = 0 for (i, j), val in J.items(): sum_j += val * smpl[i] * smpl[j] print("Checking Hard nurse constraint ", sum_j) ret_value["HardNurseConstraint"] = "Checking Hard nurse constraint " + str( sum_j) # workforce sum sum_w = 0 for d in range(n_days): sum_n = 0 for n in range(n_nurses): sum_n += effort * smpl[get_index(n, d)] sum_w += lagrange_hard_shift * (sum_n - workforce) * (sum_n - workforce) print("Checking Hard shift constraint ", sum_w) ret_value["HardShiftConstraint"] = "Checking Hard shift constraint " + str( sum_w) # min_duty_days sum sum_f = 0 for n in range(n_nurses): sum_d = 0 for d in range(n_days): sum_d += preference * smpl[get_index(n, d)] sum_f += lagrange_soft_nurse * (sum_d - min_duty_days) * ( sum_d - min_duty_days) print("Checking Soft nurse constraint ", sum_f) # Graphics sched = [get_nurse_and_day(j) for j in range(size) if smpl[j] == 1] str_header_for_output = " " * 11 str_header_for_output += " ".join(map(str, range(n_days))) print(str_header_for_output) schedule_mat = np.zeros((n_nurses, n_days)) for n in range(n_nurses): str_row = "" for d in range(n_days): if (n, d) in sched: outcome = "X" schedule_mat[n, d] = 1 else: outcome = " " if d > 9: outcome += " " str_row += " " + outcome print("Nurse ", n, str_row) ret_value["n_days"] = n_days ret_value["n_nurses"] = n_nurses ret_value["schedule"] = [ np.where(row == 1)[0].tolist() for row in schedule_mat ] # print(ret_value) return ret_value
for w in range(v+1,Total_Number_Houses): Q[(return_QUBO_Index(v,j), return_QUBO_Index(w,j))] += 2*A Q[(return_QUBO_Index(w,j), return_QUBO_Index(v,j))] += 2*A # Objective that minimizes distance for u in range(Total_Number_Houses): for v in range(Total_Number_Houses): if u!=v: for j in range(Total_Number_Houses): Q[(return_QUBO_Index(u,j), return_QUBO_Index(v,(j+1)%Total_Number_Houses))] += B*D[u][v] # Run the QUBO using qbsolv (classically solving) #resp = QBSolv().sample_qubo(Q) # Use LeapHybridSampler() for faster QPU access sampler = LeapHybridSampler() resp = sampler.sample_qubo(Q) # First solution is the lowest energy solution found sample = next(iter(resp)) # Display energy for best solution found print('Energy: ', next(iter(resp.data())).energy) # Print route for solution found route = [-1]*Total_Number_Houses for node in sample: if sample[node]>0: j = node%Total_Number_Houses v = (node-j)/Total_Number_Houses route[j] = int(v)
from dwave.system import LeapHybridSampler import dimod import sys # Graph partitioning on clique N = int(sys.argv[1]) gamma = 3 linear = (N - 1) * (1 - gamma) quad = (2 * gamma) - 2 bqm = dimod.AdjVectorBQM(dimod.Vartype.BINARY) bqm.offset = gamma * N**2 / 4 for i in range(N): bqm.set_linear(i, linear) for j in range(i + 1, N): bqm.quadratic[i, j] = quad sampler = LeapHybridSampler(profile='hss') response = sampler.sample(bqm) print(response.info) for sample, energy in response.data(['sample', 'energy']): print(sample, energy)