def build_dqm(W, C, n, p, a, verbose=True): """Builds discrete quadratic model representing the optimization problem. Args: - W: Numpy matrix. Represents passenger demand. Normalized with total demand equal to 1. - C: Numpy matrix. Represents airline leg cost. - n: Int. Number of cities in play. - p: Int. Number of hubs airports allowed. - a: Float in [0.0, 1.0]. Discount allowed for hub-hub legs. - verbose: Print to command-line for user. Returns: - dqm: DiscreteQuadraticModel representing the optimization problem. """ if verbose: print("\nBuilding DQM...\n") # Initialize DQM object. dqm = DiscreteQuadraticModel() for i in range(n): dqm.add_variable(n, label=i) # Objective: Minimize cost. for i in range(n): for j in range(n): for k in range(n): dqm.set_linear_case( i, k, dqm.get_linear_case(i, k) + C[i][k] * W[i][j]) dqm.set_linear_case( j, k, dqm.get_linear_case(j, k) + C[j][k] * W[i][j]) for m in range(n): if i != j: dqm.set_quadratic_case(i, k, j, m, a * C[k][m] * W[i][j]) # Constraint: Every leg must connect to a hub. gamma1 = 150 for i in range(n): for j in range(n): if i != j: dqm.set_linear_case(i, j, dqm.get_linear_case(i, j) + 1 * gamma1) dqm.set_quadratic_case( i, j, j, j, dqm.get_quadratic_case(i, j, j, j) - 1 * gamma1) # Constraint: Exactly p hubs required. gamma2 = 250 for i in range(n): dqm.set_linear_case(i, i, dqm.get_linear_case(i, i) + (1 - 2 * p) * gamma2) for j in range(i + 1, n): dqm.set_quadratic_case( i, i, j, j, dqm.get_quadratic_case(i, i, j, j) + 2 * gamma2) return dqm
def solve(adj_nodes, adj_edges, even_dist=False): dqm = DiscreteQuadraticModel() for i in adj_nodes: dqm.add_variable(NURSES, label=i) # classic graph coloring constraint that no two adjacent nodes have the same color for i0, i1 in adj_edges: dqm.set_quadratic(i0, i1, {(c, c): LAGRANGE for c in range(NURSES)}) shifts_per_nurse = DAYS * SHIFTS // NURSES if even_dist: # we should ensure that nurses get assigned a roughly equal amount of work for i in range(NURSES): for index, j in enumerate(adj_nodes): dqm.set_linear_case( j, i, dqm.get_linear_case(j, i) - LAGRANGE * (2 * shifts_per_nurse + 1)) for k_index in range(index + 1, len(adj_nodes)): k = adj_nodes[k_index] dqm.set_quadratic_case( j, i, k, i, LAGRANGE * (dqm.get_quadratic_case(j, i, k, i) + 2)) # some nurses may hate each other, so we should do out best to not put them in the same shift! for d in range(DAYS): for s in range(SHIFTS): for l1 in range(NURSES_PER_SHIFT): for l2 in range(l1 + 1, NURSES_PER_SHIFT): j = f"l{l1}_d{d}_s{s}" k = f"l{l2}_d{d}_s{s}" for conflict in CONFLICTS: for n1 in conflict: for n2 in conflict: if n1 == n2: continue dqm.set_quadratic_case( j, n1, k, n2, LAGRANGE2 * (dqm.get_quadratic_case(j, n1, k, n2) + 10)) sampler = LeapHybridDQMSampler(token=API_TOKEN) sampleset = sampler.sample_dqm(dqm, time_limit=10) sample = sampleset.first.sample energy = sampleset.first.energy return sample, energy
# Initialize the DQM object dqm = DiscreteQuadraticModel() # Build the DQM starting by adding variables for name in range(num_employees): dqm.add_variable(num_shifts, label=name) # Distribute employees equally across shifts according to preferences num_per_shift = int(num_employees/num_shifts) gamma = 1/(num_employees*num_shifts) for i in range(num_shifts): for j in range(num_employees): dqm.set_linear_case(j, i, dqm.get_linear_case(j, i) - gamma*(2*num_per_shift+1)) for k in range(j+1, num_employees): dqm.set_quadratic_case(j, i, k, i, gamma*(dqm.get_quadratic_case(j, i, k, i) + 2)) # Initialize the DQM solver sampler = LeapHybridDQMSampler() # Solve the problem using the DQM solver sampleset = sampler.sample_dqm(dqm, label='Example - Employee Scheduling') # Get the first solution, and print it # Mi da la soluzione migliore, quella in cui sono caduto più volte e me la salvo sample = sampleset.first.sample energy = sampleset.first.energy print("\nSchedule score:", energy) # Build schedule schedule = np.ones((num_employees, num_shifts))*num_shifts