def __solveEdgeCost__(self, solver, fileName="network.dmx"): # Add objective objective = [] for v, edge in self.__edges.items(): objective.append(edge.getCost() * edge.getLPVar()) self.__prob__ += pulp.lpSum(objective) # Add Constraints for loop in self.loops: self.__prob__.addConstraint(loop.getLPFlowConstraint()) # Solve the objective function if solver == 'glpk': log.info('Using GLPK MIP solver') MIPsolver = lambda: self.__prob__.solve(pulp.GLPK(msg=0)) elif solver == 'pulp': log.info('Using PuLP MIP solver') MIPsolver = lambda: self.__prob__.solve() elif solver == 'gurobi': log.info('Using Gurobi MIP solver') MIPsolver = lambda: self.__prob__.solve(pulp.GUROBI_CMD()) log.info('Time Taken (in sec) to solve: %f', T.timeit(MIPsolver, number=1)) # Get solution for v, edge in self.__edges.items(): flow = pulp.value(edge.getLPVar()) edge.updateFlow(flow)
def solve(self,msg=0,**kwarg): # kind = 'CBC' if 'kind' in kwarg: kind = kwarg['kind'] time_limit = None if 'time_limit' in kwarg: time_limit = float(kwarg['time_limit']) random_seed = None if 'random_seed' in kwarg: random_seed = kwarg['random_seed'] ratio_gap = None if 'ratio_gap' in kwarg: ratio_gap = float(kwarg['ratio_gap']) start_time = time.time() # select solver for pl if kind == 'CPLEX': if time_limit is not None: # pulp does currently not support a timelimit in 1.5.9 self.mip.solve(pl.CPLEX_CMD(msg=msg, timelimit=time_limit)) else: self.mip.solve(pl.CPLEX_CMD(msg=msg)) elif kind == 'GLPK': self.mip.solve(pl.GLPK_CMD(msg=msg)) elif kind == 'SCIP': self.mip.solve(SCIP_CMD(msg=msg,time_limit=time_limit,ratio_gap=ratio_gap)) elif kind == 'CBC' or kind == 'COIN': options = [] if time_limit is not None: options.extend(['sec', str(time_limit)]) if random_seed is not None: options.extend(['randomSeed', str(random_seed)]) options.extend(['randomCbcSeed', str(random_seed)]) if ratio_gap is not None: options.extend(['ratio', str(ratio_gap)]) if kind == 'CBC': self.mip.solve(pl.PULP_CBC_CMD(msg=msg, options=options)) elif kind == 'COIN': self.mip.solve(pl.COIN(msg=msg, options=options)) elif kind == 'GUROBI': # GUROBI_CMD does not support a timelimit or epgap # GUROBI cannot dispatch parameters from options correctly options=[] if time_limit is not None: if ratio_gap is not None: self.mip.solve(pl.GUROBI(msg=msg,timeLimit=time_limit,epgap=ratio_gap)) elif time_limit is not None: self.mip.solve(pl.GUROBI(msg=msg, timeLimit=time_limit)) elif ratio_gap is not None: self.mip.solve(pl.GUROBI(msg=msg, epgap=ratio_gap)) else: self.mip.solve(pl.GUROBI_CMD(msg=msg)) else: raise Exception('ERROR: solver ' + kind + ' not known') if msg: print('INFO: execution time for solving mip (sec) = ' + str(time.time() - start_time)) if self.mip.status == 1 and msg: print('INFO: objective = ' + str(pl.value(self.mip.objective)))
def _solve(self, time_limit): if self.solver == "cbc": self.prob.solve(pulp.PULP_CBC_CMD(maxSeconds=time_limit)) elif self.solver == "cplex": self.prob.solve(pulp.CPLEX_CMD(msg=0, timelimit=time_limit)) elif self.solver == "gurobi": gurobi_options = [("TimeLimit", time_limit)] self.prob.solve(pulp.GUROBI_CMD(options=gurobi_options))
def solve(self): print('Solving Problem.') solver = self.params['pulp_solver'] if solver == 'GUROBI': solver = pulp.GUROBI_CMD() self.model.solve(solver) print("Status:", pulp.LpStatus[self.model.status]) else: self.model.solve(solver) print("Status:", pulp.LpStatus[self.model.status])
def solve(self): print('Solving Problem.') solver = self.params['pulp_solver'] if solver == 'GUROBI': solver = pulp.GUROBI_CMD() self.model.solve(solver) print("Status:", pulp.LpStatus[self.model.status]) else: self.model.solve(solver) print("Status:", pulp.LpStatus[self.model.status]) self.get_solution_as_excel(self.params['out_path'])
def solve(self, solver="cbc", timeout=None): """Solves this problem and returns the problem result. :param solver: The solver that should be used. Currently supported are "cbc", "gurobi", "glpk" and "cplex", defaults to "cbc" :type solver: str, optional :return: Result. :rtype: solver.SolverResult """ assert solver in [ "gurobi", "cbc", "glpk", "cplex" ], "solver must be in ['gurobi','cbc','glpk','cplex']" if timeout != None: assert isinstance( timeout, int), "timeout must be specified in seconds as integer value" if solver == "gurobi": gurobi_options = [ ("MIPGap",0), ("MIPGapAbs",0), ("FeasibilityTol",1e-9),\ ("IntFeasTol",1e-9),("NumericFocus",3)] if timeout != None: gurobi_options.append(("TimeLimit", str(timeout))) self.__pulpmodel.setSolver(pulp.GUROBI_CMD(options=gurobi_options)) elif solver == "cbc": cbc_options = ["--integerT", "0"] self.__pulpmodel.setSolver( pulp.PULP_CBC_CMD(gapRel=1e-9, timeLimit=timeout, options=cbc_options)) elif solver == "glpk": glpk_options = ["--tmlim", str(timeout)] if timeout != None else [] self.__pulpmodel.setSolver(pulp.GLPK_CMD(options=glpk_options)) elif solver == "cplex": self.__pulpmodel.setSolver(pulp.CPLEX_PY(timeLimit=timeout)) self.__pulpmodel.solve() status = { 1: "optimal", 0: "notsolved", -1: "infeasible", -2: "unbounded", -3: "undefined" }[self.__pulpmodel.status] result_vector = np.array([var.value() for var in self.__variables]) dual_result_vector = np.array( [constr.pi for constr in self.__constraints]) value = self.__pulpmodel.objective.value() return SolverResult(status, result_vector, dual_result_vector, value)
def check_lpsolver(c_vec, A_mat, b_vec): prob = pulp.LpProblem('prob', pulp.LpMinimize) m, n = A_mat.shape x = [pulp.LpVariable('x{}'.format(ix)) for ix in range(n)] prob += pulp.lpSum([ci * xi for ci, xi in zip(c_vec, x)]) for ix in range(m): prob += pulp.lpSum([ai * xi for ai, xi in zip(A_mat[ix], x) ]) >= b_vec[ix], 'con{}'.format(ix) prob.solve(pulp.GUROBI_CMD(msg=0)) # prob.solve(pulp.GLPK(msg=0)) if prob.status in [1, -2]: return True else: return False
def ParetoExtremeSet(F): """ Compute the set of extreme non-dominated tables in a given set-factor """ #try: if F.dimension == 1: # compute maximum value u = max([F.tables[i][0] for i in range(F.num_tables)]) H = SetFactor([]) H.addTable([u]) # find a maximum strategy for i in range(F.num_tables): if F.tables[i][0] == u: H.labels[0] = F.labels[i] break return H if F.num_tables <= 1: return F if F.num_tables <= 10: return ParetoSet(F) import pulp H = SetFactor(F.scope) N = F.num_tables #assert(N>1) D = F.dimension for t1 in range(N): x = (N - 1) * [None] for i in range(N - 1): x[i] = pulp.LpVariable("x" + str(i), 0.0, 1.0) prob = pulp.LpProblem("hull", pulp.LpMinimize) for i in range(D): c = [F.tables[t2][i] for t2 in range(N) if t2 != t1] prob += (F.tables[t1][i] - pulp.lpDot(c, x) <= 0.0) prob += (pulp.lpSum(x) == 1.0) prob += x[0] status = prob.solve(pulp.GUROBI_CMD(msg=0)) #print pulp.LpStatus[status] if pulp.LpStatus[status] == "Not Solved": # extreme point found H.addTable(F.tables[t1]) H.labels[H.num_tables - 1] = F.labels[t1] #assert( H.num_tables > 0) #print #print F.num_tables-H.num_tables, " dominated tables removed" return H
def solve_optimal_assignment(A, d, u, c, edge_list): s = time.time() prob = None print("\n----- Optimal Assignment Problem -----\n") print("\tCreating new problem instance...") prob = plp.LpProblem("Opt_assignment_problem", plp.LpMinimize) print("\tAdding super-graph variables...") flows = { i: plp.LpVariable(cat=plp.LpContinuous, lowBound=0, upBound=u[i], name=str(edge_list[:, 2][i])) for i in range(A.shape[1]) } print("\tAdding constraints...") percent_complete = 0 for j in range(A.shape[0]): # prob += plp.LpAffineExpression([(flows[i],A[j,i]) for i in range(A.shape[1])]) == d[j] prob += plp.lpSum(A[j, i] * flows[i] for i in range(A.shape[1])) == d[j] if (j / A.shape[0]) * 100 > percent_complete: print("\t\t{} % of constraints added".format(percent_complete)) percent_complete += 10 e1 = time.time() print("\tConstraints added. Total time took: ", int((e1 - s) / 60), "mins") objective = plp.lpSum([c[i] * flows[i] for i in range(A.shape[1])]) prob.setObjective(objective) prob.writeLP("Opt_assignment_problem.lp") print("\tSolving the optimal assignment problem...") prob.solve(solver=plp.GUROBI_CMD()) print("\tSolution status: ", plp.LpStatus[prob.status]) print("\tObjective function value: ", plp.value(prob.objective)) solution = pd.DataFrame(columns=['Variable', 'OptimalValue']) for i, v in enumerate(prob.variables()): solution.loc[i] = [v.name, v.varValue] solution.to_csv("./Optimal_solution.csv") print("\tSolutions saved.\n") e2 = time.time() print("\tTotal time took for solving the optimal assignment: ", int((e2 - s) / 60), "mins") return prob, flows, solution
def solve_problem(base_problem, opt_sense, k, objective_fn, F, constraint_lhs=None, constraint_rhs=None): problem_instance = modify_problem(base_problem, opt_sense, k, constraint_lhs, constraint_rhs) problem_instance.setObjective(objective_fn) problem_instance.sense = opt_sense problem_instance.writeLP( "Adv_problem_instance_{}.lp".format(0)) # ideally k problem_instance.solve(solver=plp.GUROBI_CMD()) if plp.LpStatus[problem_instance.status] != "Optimal": raise ("\tNo optimal solution found.\n Optimization ceased!") else: z = plp.value(problem_instance.objective) solution_df = pd.DataFrame(columns=['Variable', 'OptimalValue']) # for i,v in F.items(): # solution_df.loc[i] = [v.name, v.varValue] return z, solution_df
def solve(self, mdelta=None, outF=None): ''' Solves and extracts the output variables into xVal and yVal ''' # Modify the constraints with new delta self.__addObstConstraint(mdelta) # Solve the optimization problem with tempfile.NamedTemporaryFile() as fp: # using temporary file to write log self.prob.solve(pulp.GUROBI_CMD(msg=self.msg, options={})) ## Read log file to get number of nodes explored #fp.seek(0) #data = fp.read() ## Read the explored nodes #self.exploreNodes = re.findall("Explored (\d+) nodes", data)[0] self.exploreNodes = 0 #if self.gap == None: # # Do this only for the first time # self.gap = re.findall("gap (\d+.\d+)", data)[0] #self.prob.solve(pulp.GUROBI_CMD(msg=self.msg, options={})) self.msg = 0 # Populate the solution variable # print("Status: ", pulp.LpStatus[self.prob.status]) if 'Optimal' in pulp.LpStatus[self.prob.status]: self.feasible = True else: self.feasible = False # Get solution from waypoints if self.feasible: self.wayPoint = [] for i in range(self.__N + 1): self.wayPoint.append( [pulp.value(self.x[i][0]), pulp.value(self.x[i][1])]) self.__zVal = [] for i in range(self.__N): self.__zVal.append([[pulp.value(self.z[i][j][k]) for k in range(self.__dObst)] \ for j in range(self.__nObst)]) # Find the active points in the optimized way points (self.activePoints, self.activePtsIdx, self.activeObstIdx) = \ self.findActivePoints(mdelta) self._sol = {} for var in self.prob._variables: self._sol[str(var)] = pulp.value(var) if outF is not None: with open(outF + '.yaml', 'w') as outfile: Y.dump(self._sol, outfile, default_flow_style=False, explicit_start=True) return True else: return False
def generate_signal_milp_boolean(phi, start, rand_area, dimensions, U, epsilon): """ Function generating a signal satisfying an STL Formula. Takes as input: * phi: an STL Formula * start: a vector of the form [x0,y0,...] for the starting point coordinates * rand_area: the domain on which signals are generated. rand_area = [lb,ub] where lb is the lower bound and ub the upper bound of the domain. * dimensions: the dimensions on which the STLFormula is defined, e.g. dimensions=['x','y']. * U: a basic control policy standing for how much can move in 1 time stamp, i.e. \forall t \in [0,T], |s[t]-s[t+1]| < U \pm \epsilon * epsilon: basic control policy parameter The encoding details of the MILP optimization problem follows the boolean enconding of Raman et al., "Model predictive control with signaltemporal logic specifications" in 53rd IEEE Conference on Decision and Control. IEEE, 2014, pp. 81–87. """ dict_vars = {} #satisfaction of phi zvar1 = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(phi.horizon), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(phi.horizon)] = zvar1 opt_model = plp.LpProblem("MIP Model") #We want to optimize a signal. The lower and upperbounds are specified by the random area. s = plp.LpVariable.dicts("s", (range(phi.horizon + 1), range(len(dimensions))), rand_area[0], rand_area[1], plp.LpContinuous) #the start is specified for dim in range(len(dimensions)): opt_model += s[0][dim] == start[dim] #control policy for t in range(0, phi.horizon): opt_model += s[t + 1][0] - s[t][0] <= random.uniform( U - epsilon, U + epsilon) opt_model += -(s[t + 1][0] - s[t][0]) <= random.uniform( U - epsilon, U + epsilon) opt_model += s[t + 1][1] - s[t][1] <= random.uniform( U - epsilon, U + epsilon) opt_model += -(s[t + 1][1] - s[t][1]) <= random.uniform( U - epsilon, U + epsilon) #recursive function def model_phi1(phi, t, opt_model): if isinstance(phi, STLFormula.TrueF): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 elif isinstance(phi, STLFormula.FalseF): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 0 if isinstance(phi, STLFormula.Predicate): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar if phi.operator == operatorclass.gt or phi.operator == operatorclass.ge: opt_model += s[t][ phi.pi_index_signal] - phi.mu <= M_up * zvar - M_low opt_model += -(s[t][phi.pi_index_signal] - phi.mu) <= M_up * (1 - zvar) - M_low else: opt_model += -s[t][ phi.pi_index_signal] + phi.mu <= M_up * zvar - M_low opt_model += -(-s[t][phi.pi_index_signal] + phi.mu) <= M_up * (1 - zvar) - M_low elif isinstance(phi, STLFormula.Negation): model_phi1(phi.formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t)] = zvar1 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 - zvar1 elif isinstance(phi, STLFormula.Conjunction): model_phi1(phi.first_formula, t, opt_model) model_phi1(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z1_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar <= zvar1 opt_model += zvar <= zvar2 opt_model += zvar >= 1 - 2 + zvar1 + zvar2 elif isinstance(phi, STLFormula.Disjunction): model_phi1(phi.first_formula, t, opt_model) model_phi1(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z1_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar >= zvar1 opt_model += zvar >= zvar2 opt_model += zvar <= zvar1 + zvar2 elif isinstance(phi, STLFormula.Always): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi1(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] = pvar_i opt_model += zvar <= zvar_i opt_model += zvar >= 1 - (phi.t2 + 1 - phi.t1) + plp.lpSum([ dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) elif isinstance(phi, STLFormula.Eventually): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi1(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] = pvar_i opt_model += zvar >= zvar_i opt_model += zvar <= plp.lpSum([ dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) model_phi1(phi, phi.horizon, opt_model) opt_model += zvar1 == 1 opt_model.solve(plp.GUROBI_CMD(msg=False)) return [[s[j][i].varValue for i in range(len(dimensions))] for j in range(phi.horizon + 1)]
def generate_signal_milp_quantitative(phi, start, rand_area, dimensions, U, epsilon, OPTIMIZE_ROBUSTNESS): """ Function generating a signal satisfying an STL Formula. Takes as input: * phi: an STL Formula * start: a vector of the form [x0,y0,...] for the starting point coordinates * rand_area: the domain on which signals are generated. rand_area = [lb,ub] where lb is the lower bound and ub the upper bound of the domain. * dimensions: the dimensions on which the STLFormula is defined, e.g. dimensions=['x','y']. * U: a basic control policy standing for how much can move in 1 time stamp, i.e. \forall t \in [0,T], |s[t]-s[t+1]| < U \pm \epsilon * epsilon: basic control policy parameter * OPTIMIZE_ROBUSTNESS: a flag whether the robustness of the generated signal w.r.t. phi has to be maximized or not The encoding details of the MILP optimization problem follows the quantitative enconding of Raman et al., "Model predictive control with signaltemporal logic specifications" in 53rd IEEE Conference on Decision and Control. IEEE, 2014, pp. 81–87. """ dict_vars = {} #objective, maximize robustness rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(phi.horizon), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(phi.horizon)] = rvar #Initialize model if OPTIMIZE_ROBUSTNESS: opt_model = plp.LpProblem("MIP Model", plp.LpMaximize) opt_model += rvar else: opt_model = plp.LpProblem("MIP Model") #We want to optimize a signal. The lower and upperbounds are specified by the random area. s = plp.LpVariable.dicts("s", (range(phi.horizon + 1), range(len(dimensions))), rand_area[0], rand_area[1], plp.LpContinuous) #the start is specified for dim in range(len(dimensions)): opt_model += s[0][dim] == start[dim] #basic control policy, i.e. how much can move in 1 time stamp #\forall t \in [0,T], |s[t]-s[t+1]| < U \pm \epsilon for t in range(0, phi.horizon): opt_model += s[t + 1][0] - s[t][0] <= random.uniform( U - epsilon, U + epsilon) opt_model += -(s[t + 1][0] - s[t][0]) <= random.uniform( U - epsilon, U + epsilon) opt_model += s[t + 1][1] - s[t][1] <= random.uniform( U - epsilon, U + epsilon) opt_model += -(s[t + 1][1] - s[t][1]) <= random.uniform( U - epsilon, U + epsilon) #recursive function def model_phi(phi, t, opt_model): if isinstance(phi, STLFormula.Predicate): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar if phi.operator == operatorclass.gt or phi.operator == operatorclass.ge: opt_model += s[t][phi.pi_index_signal] - phi.mu == rvar else: opt_model += -s[t][phi.pi_index_signal] + phi.mu == rvar elif isinstance(phi, STLFormula.TrueF): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar opt_model += rvar >= M elif isinstance(phi, STLFormula.FalseF): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar opt_model += rvar <= -M elif isinstance(phi, STLFormula.Conjunction): model_phi(phi.first_formula, t, opt_model) model_phi(phi.second_formula, t, opt_model) try: pvar1 = dict_vars['p_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: pvar1 = plp.LpVariable('p_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['p_' + str(id(phi.first_formula)) + '_t_' + str(t)] = pvar1 try: pvar2 = dict_vars['p_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: pvar2 = plp.LpVariable('p_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['p_' + str(id(phi.second_formula)) + '_t_' + str(t)] = pvar2 try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar opt_model += pvar1 + pvar2 == 1 #(3) opt_model += rvar <= dict_vars['r_' + str(id(phi.first_formula)) + '_t_' + str(t)] #(4) opt_model += rvar <= dict_vars['r_' + str(id(phi.second_formula)) + '_t_' + str(t)] #(4) opt_model += dict_vars[ 'r_' + str(id(phi.first_formula)) + '_t_' + str(t)] - (1 - pvar1) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.first_formula)) + '_t_' + str(t)] + (1 - pvar1) * M #(5) opt_model += dict_vars[ 'r_' + str(id(phi.second_formula)) + '_t_' + str(t)] - (1 - pvar2) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.second_formula)) + '_t_' + str(t)] + (1 - pvar2) * M #(5) elif isinstance(phi, STLFormula.Disjunction): model_phi(phi.first_formula, t, opt_model) model_phi(phi.second_formula, t, opt_model) try: pvar1 = dict_vars['p_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: pvar1 = plp.LpVariable('p_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['p_' + str(id(phi.first_formula)) + '_t_' + str(t)] = pvar1 try: pvar2 = dict_vars['p_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: pvar2 = plp.LpVariable('p_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['p_' + str(id(phi.second_formula)) + '_t_' + str(t)] = pvar2 try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar opt_model += pvar1 + pvar2 == 1 #(3) opt_model += rvar >= dict_vars['r_' + str(id(phi.first_formula)) + '_t_' + str(t)] #(4) opt_model += rvar >= dict_vars['r_' + str(id(phi.second_formula)) + '_t_' + str(t)] #(4) opt_model += dict_vars[ 'r_' + str(id(phi.first_formula)) + '_t_' + str(t)] - (1 - pvar1) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.first_formula)) + '_t_' + str(t)] + (1 - pvar1) * M #(5) opt_model += dict_vars[ 'r_' + str(id(phi.second_formula)) + '_t_' + str(t)] - (1 - pvar2) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.second_formula)) + '_t_' + str(t)] + (1 - pvar2) * M #(5) elif isinstance(phi, STLFormula.Always): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar for t_i in range(phi.t1, phi.t2 + 1): model_phi(phi.formula, t_i, opt_model) try: pvar_i = dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: pvar_i = plp.LpVariable('p_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] = pvar_i opt_model += rvar <= dict_vars['r_' + str(id(phi.formula)) + '_t_' + str(t_i)] #(4) opt_model += dict_vars[ 'r_' + str(id(phi.formula)) + '_t_' + str(t_i)] - (1 - pvar_i) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.formula)) + '_t_' + str(t_i)] + (1 - pvar_i) * M #(5) opt_model += plp.lpSum([ dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) == 1 #(3) elif isinstance(phi, STLFormula.Eventually): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar for t_i in range(phi.t1, phi.t2 + 1): model_phi(phi.formula, t_i, opt_model) try: pvar_i = dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: pvar_i = plp.LpVariable('p_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] = pvar_i opt_model += rvar >= dict_vars['r_' + str(id(phi.formula)) + '_t_' + str(t_i)] #(4) opt_model += dict_vars[ 'r_' + str(id(phi.formula)) + '_t_' + str(t_i)] - (1 - pvar_i) * M <= rvar <= dict_vars[ 'r_' + str(id(phi.formula)) + '_t_' + str(t_i)] + (1 - pvar_i) * M #(5) opt_model += plp.lpSum([ dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) == 1 #(3) elif isinstance(phi, STLFormula.Negation): try: rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] except KeyError: rvar = plp.LpVariable('r_' + str(id(phi)) + '_t_' + str(t), cat='Continuous') dict_vars['r_' + str(id(phi)) + '_t_' + str(t)] = rvar model_phi(phi.formula, t, opt_model) try: rvar_i = dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t)] except KeyError: rvar_i = plp.LpVariable('p_' + str(id(phi.formula)) + '_t_' + str(t), cat='Binary') dict_vars['p_' + str(id(phi.formula)) + '_t_' + str(t)] = rvar_i opt_model += rvar == -rvar_i model_phi(phi, phi.horizon, opt_model) rvar = dict_vars['r_' + str(id(phi)) + '_t_' + str(phi.horizon)] opt_model += rvar >= 0 opt_model.solve(plp.GUROBI_CMD(msg=False)) if s[0][0].varValue == None: raise Exception("") return [[s[j][i].varValue for i in range(len(dimensions))] for j in range(phi.horizon + 1)]
def do_inference_ILP(ps, L, M, unary_params, pw_params, unary_features, pw_features, y_true=None, y_true_list=None, predicted_list=None, n_threads=4, USE_GUROBI=True): """ Inference using integer linear programming (ILP), could be: - Train/prediction inference for single-label SSVM (NOTE: NOT Hamming loss) - Prediction inference for multi-label SSVM """ assert (L > 1) assert (L <= M) assert (ps >= 0) assert (ps < M) if y_true is not None: assert (y_true_list is not None and type(y_true_list) == list) assert (len(y_true_list) == 1) assert (predicted_list is None) if predicted_list is not None: assert (y_true is None and y_true_list is None) # when the parameters are very small, GUROBI will suffer from precision problems # scaling parameters unary_params = 1e6 * unary_params pw_params = 1e6 * pw_params p0 = str(ps) pois = [str(p) for p in range(M)] # create a string list for each POI pb = pulp.LpProblem('Inference_ILP', pulp.LpMaximize) # create problem # visit_i_j = 1 means POI i and j are visited in sequence visit_vars = pulp.LpVariable.dicts('visit', (pois, pois), 0, 1, pulp.LpInteger) # isend_l = 1 means POI l is the END POI of trajectory isend_vars = pulp.LpVariable.dicts('isend', pois, 0, 1, pulp.LpInteger) # a dictionary contains all dummy variables dummy_vars = pulp.LpVariable.dicts('u', [x for x in pois if x != p0], 2, M, pulp.LpInteger) # add objective objlist = [] for pi in pois: # from for pj in pois: # to objlist.append( visit_vars[pi][pj] * (np.dot(unary_params[int(pj)], unary_features[int(pj)]) + np.dot(pw_params[int(pi), int(pj)], pw_features[int(pi), int(pj)]))) if y_true is not None: # Loss: normalised number of mispredicted POIs, Hamming loss is non-linear of 'visit' objlist.append(1) for j in range(M): pj = pois[j] for k in range(1, L): pk = str(y_true[k]) # objlist.append(-1.0 * visit_vars[pj][pk] / L) # loss term: normalised objlist.append(-1.0 * visit_vars[pj][pk]) pb += pulp.lpSum(objlist), 'Objective' # add constraints, each constraint should be in ONE line pb += pulp.lpSum([visit_vars[pi][pi] for pi in pois]) == 0, 'NoSelfLoops' pb += pulp.lpSum([visit_vars[p0][pj] for pj in pois]) == 1, 'StartAt_p0' pb += pulp.lpSum([visit_vars[pi][p0] for pi in pois]) == 0, 'NoIncoming_p0' pb += pulp.lpSum([visit_vars[pi][pj] for pi in pois for pj in pois]) == L - 1, 'Length' pb += pulp.lpSum([isend_vars[pi] for pi in pois]) == 1, 'OneEnd' pb += isend_vars[p0] == 0, 'StartNotEnd' for pk in [x for x in pois if x != p0]: pb += pulp.lpSum([visit_vars[pi][pk] for pi in pois]) == isend_vars[pk] + \ pulp.lpSum([visit_vars[pk][pj] for pj in pois if pj != p0]), 'ConnectedAt_' + pk pb += pulp.lpSum([visit_vars[pi][pk] for pi in pois]) <= 1, 'Enter_' + pk + '_AtMostOnce' pb += pulp.lpSum([visit_vars[pk][pj] for pj in pois if pj != p0]) + isend_vars[pk] <= 1, \ 'Leave_' + pk + '_AtMostOnce' for pi in [x for x in pois if x != p0]: for pj in [y for y in pois if y != p0]: pb += dummy_vars[pi] - dummy_vars[pj] + 1 <= (M - 1) * (1 - visit_vars[pi][pj]), \ 'SubTourElimination_' + pi + '_' + pj # additional constraints/cuts to filtering out specified sequences if predicted_list is not None: for j in range(len(predicted_list)): y = predicted_list[j] pb += pulp.lpSum([visit_vars[str(y[k])][str(y[k + 1])] for k in range(len(y) - 1)]) <= (len(y) - 2), \ 'exclude_%dth' % j pb.writeLP("traj_tmp.lp") # solve problem: solver should be available in PATH, default solver is CBC if USE_GUROBI is True: # gurobi_options = [('TimeLimit', '7200'), ('Threads', str(n_threads)), ('NodefileStart', '0.2'), ('Cuts', '2')] gurobi_options = [('TimeLimit', '10800'), ('Threads', str(n_threads)), ('NodefileStart', '0.5')] pb.solve(pulp.GUROBI_CMD(path='gurobi_cl', options=gurobi_options)) # GUROBI else: pb.solve( pulp.COIN_CMD(path='cbc', options=[ '-threads', str(n_threads), '-strategy', '1', '-maxIt', '2000000' ])) visit_mat = pd.DataFrame(data=np.zeros((len(pois), len(pois)), dtype=np.float), index=pois, columns=pois) isend_vec = pd.Series(data=np.zeros(len(pois), dtype=np.float), index=pois) for pi in pois: isend_vec.loc[pi] = isend_vars[pi].varValue for pj in pois: visit_mat.loc[pi, pj] = visit_vars[pi][pj].varValue # build the recommended trajectory recseq = [p0] while True: pi = recseq[-1] pj = visit_mat.loc[pi].idxmax() value = visit_mat.loc[pi, pj] assert (int(round(value)) == 1) recseq.append(pj) if len(recseq) == L: assert (int(round(isend_vec[pj])) == 1) return [np.asarray([int(x) for x in recseq])]
from __future__ import print_function import pulp solver_map = { 'gurobi': pulp.GUROBI_CMD(msg=False) } #FIXME when adding constraints, use a map to match to your own id class Math_prob: def __init__(self, var_ids): self.num_vars = 0 self.num_cons_linear = 0 self.num_cons_nonlinear = 0 self.vars = dict() self.vid_dict = dict() self.cons_linear = dict() self.objective = dict() self.solutions = dict() for vid in var_ids: self.vid_dict[self.add_var()] = vid def add_var(self, lower=0, upper=1): self.vars[self.num_vars] = (lower, upper) self.num_vars += 1 return self.num_vars - 1 def get_vars(self): variables = [(var_id, self.vars[var_id][0], self.vars[var_id][1]) for var_id in self.vars] return variables
# -*- coding: utf-8 -*- """ Created on Wed Oct 19 20:16:22 2016 @author: Chao """ import time import pulp from ReadData import getTableS1 from MIPSolver import AirportSolver if __name__ == "__main__": start = time.clock() tb1, tb2 = getTableS1() Solver = pulp.GUROBI_CMD().solve # Solver=pulp.CPLEX_CMD().solve # Solver=pulp.COIN_CMD(path="F:/Program Files (x86)/COIN-OR/1.7.4/win32-msvc10/bin/cbc.exe").solve # Solver=pulp.GLPK_CMD(path="F:/ToolBox/glpk-4.60/w64/glpsol.exe").solve AirportSolver(Solver, tb1, tb2, filename="../output/result.csv") end = time.clock() print("[Time: %.3f s]" % (end - start))
def solve(event): global n, trucks, solver, li, ax, warehouses, loc_x, loc_y, lines_x, lines_y, obj_value, exec_value global distances, distances2 print("solving...") ax.clear() ax.set_xlim(0,1000) ax.set_ylim(0,1000) plot_data(ax, loc_x, loc_y, warehouses) ax.text(400, 1075, "solving...", family="serif", horizontalalignment='left', verticalalignment='top') plt.draw() fig.canvas.draw() start_time = time.time() # Calculate constraint for Li total_l = 0 total_c = 0.0 paths = 0 slack = False while total_c < n or paths < trucks: c1 = min(c,n) total_c += c1 total_l += c1*(c1+1)/2 paths += 1 if total_c > n: slack = True if solver=="cbc" or solver=="glpk" or solver=="gurobi": # Objective function z = pulp.LpProblem('Test', pulp.LpMinimize) # Generate decision variables x = {} y = {} variables = [] l = {} s = {} for i in range(n+warehouses): for j in range(n+warehouses): if i==j: continue x[i,j] = pulp.LpVariable('x_' + str(i) + '_' + str(j), 0, 1, pulp.LpInteger) if i >= warehouses: l[i] = pulp.LpVariable('l_' + str(i), 1, min(n,c), pulp.LpInteger) # Objective function z += pulp.lpSum([distances[i][j] * x[i,j] for i in range(n+warehouses) for j in list(range(i)) + list(range(i+1,n+warehouses))]) # Constraints constraintSeq = [] constraintTrucks = [] for i in range(n+warehouses): if i>=warehouses: constraintSeq.append(l[i]) constraintFrom = [] constraintTo = [] for j in range(n+warehouses): if i==j: continue if i>=warehouses and j>=warehouses: z += pulp.lpSum([l[i], -1*l[j], n*x[i,j], -n+1]) <= 0 if i>=warehouses: constraintFrom.append(x[i,j]) constraintTo.append(x[j,i]) if i<warehouses: constraintTrucks.append(x[j,i]) if i>=warehouses: z += pulp.lpSum(constraintFrom) == 1 # paths from location z += pulp.lpSum(constraintTo) == 1 # paths to location if i==warehouses and (paths > 1 or warehouses>1): z += pulp.lpSum(constraintTrucks) == paths # paths to warehouse if not slack: z += pulp.lpSum(constraintSeq) == total_l else: z += pulp.lpSum(constraintSeq) <= total_l # Solve if solver=="cbc": status = z.solve() if solver=="glpk": status = z.solve(pulp.GLPK()) if solver=="gurobi": status = z.solve(pulp.GUROBI_CMD()) # should be 'Optimal' if pulp.LpStatus[status]!="Optimal": print("RESULT: ".pulp.LpStatus[status]) print("Objective function value: "+str(z.objective.value())) # Print variables & save path lines_x = [] lines_y = [] li = [0] * n for i in range(n+warehouses): if i>=warehouses: li[i-warehouses] = pulp.value(l[i]) for j in range(n+warehouses): if i==j: continue if pulp.value(x[i,j]) == 1: lines_x.append(loc_x[i]) lines_x.append(loc_x[j]) lines_y.append(loc_y[i]) lines_y.append(loc_y[j]) lines_x.append(np.nan) lines_y.append(np.nan) obj_value = "c=" + str(round(z.objective.value(),2)) elif solver=="cut plane": model = Model("tsp") model.hideOutput() x = {} l = {} for i in range(n+warehouses): for j in range(n+warehouses): if i != j: x[i,j] = model.addVar(ub=1, name="x(%s,%s)"%(i,j)) if (paths > 1 or warehouses > 1) and i >= warehouses: l[i] = model.addVar(ub=min(c,n),lb=1, name="l(%s)"%(i)) if paths == 1 and warehouses == 1: # SYMMETRIC DISTANCE MATRIX ONLY #for i in range(n+warehouses): #model.addCons(quicksum(x[j,i] for j in range(n+warehouses) if j != i) + \ # quicksum(x[i,j] for j in range(n+warehouses) if j != i) == 2,"Degree(%s)"%i) # ASYMMETRIC DISTANCE MATRIX for i in range(n+warehouses): model.addCons(quicksum(x[j,i] for j in range(n+warehouses) if j != i) == 1,"In(%s)"%i) model.addCons(quicksum(x[i,j] for j in range(n+warehouses) if j != i) == 1,"Out(%s)"%i) else: for i in range(warehouses, n+warehouses): model.addCons(quicksum(x[j,i] for j in range(n+warehouses) if j != i) == 1,"In(%s)"%i) model.addCons(quicksum(x[i,j] for j in range(n+warehouses) if j != i) == 1,"Out(%s)"%i) for i in range(warehouses, n+warehouses): for j in range(warehouses, n+warehouses): if i!=j: model.addCons(l[i] -l[j] +n*x[i,j] <= n-1, "Li(%s,%s)"%(i,j)) model.addCons(quicksum(x[j,i] for i in range(warehouses) for j in range(n+warehouses) if i!=j) == paths, "Paths(%s)"%paths) if not slack: model.addCons(quicksum(l[i] for i in range(warehouses,n+warehouses)) == total_l,"TotalL") else: model.addCons(quicksum(l[i] for i in range(warehouses,n+warehouses)) <= total_l, "TotalL") model.setObjective(quicksum(distances2[i,j]*x[i,j] for (i,j) in x), "minimize") EPS = 1.e-6 isMIP = False model.setPresolve(SCIP_PARAMSETTING.OFF) while True: model.optimize() #edges = [] lines_x = [] lines_y = [] edges = [] li = [0] * n for (i,j) in x: # i=j already skipped if model.getVal(x[i,j]) > EPS: #edges.append( (i,j) ) lines_x.append(loc_x[i]) lines_x.append(loc_x[j]) lines_y.append(loc_y[i]) lines_y.append(loc_y[j]) lines_x.append(np.nan) lines_y.append(np.nan) edges.append( (i,j) ) if paths>1 or warehouses>1: for i in range(warehouses, n+warehouses): li[i-warehouses] = int(model.getVal(l[i])) obj_value = "c=" + str(round(model.getObjVal(),2)) ax.clear() ax.set_xlim(0,1000) ax.set_ylim(0,1000) plot_data_lines(lines_x,lines_y) plot_data(ax, loc_x, loc_y, warehouses) ax.text(400, 1075, "solving...", family="serif", horizontalalignment='left', verticalalignment='top') fig.canvas.draw() if addcut(edges,model,x,warehouses) == False: if isMIP: # integer variables, components connected: solution found break model.freeTransform() for (i,j) in x: # all components connected, switch to integer model model.chgVarType(x[i,j], "B") if paths > 1 or warehouses > 1: for i in range(warehouses,n+warehouses): model.chgVarType(l[i], "I") isMIP = True sol_li = [0] * (n+warehouses) sol_xij = {} print('solved.') elif solver == 'held-karp': li = [0] * n opt, path = held_karp(distances) print(path) obj_value = "c=" + str(round(opt,2)) x = [[0 for x in range(n+warehouses)] for y in range(n+warehouses)] for idx, val in enumerate(path): if idx < (len(path)-1): x[val][path[idx+1]] = 1; elif idx == (len(path)-1): x[val][path[0]] = 1; for i in range(n+warehouses): for j in range(n+warehouses): if x[i][j] == 1: #edges.append( (i,j) ) lines_x.append(loc_x[i]) lines_x.append(loc_x[j]) lines_y.append(loc_y[i]) lines_y.append(loc_y[j]) lines_x.append(np.nan) lines_y.append(np.nan) #edges.append( (i,j) ) # Print computation time time2 = time.time() - start_time exec_value = time2 units = 'secs' if time2 > 60: time2 /= 60 units = 'mins' if time2 > 60: time2 /= 60 units = 'hours' time2 = round(time2,2) exec_value = "exec=" + str(time2) + " " + units print("--- " + str(time2) + " " + units + " ---") # Redraw points ax.clear() ax.set_xlim(0,1000) ax.set_ylim(0,1000) plot_data_lines(lines_x,lines_y) plot_data(ax, loc_x, loc_y, warehouses) ax.text(350, 1075, obj_value, family="serif", horizontalalignment='right', verticalalignment='top') ax.text(450, 1075, exec_value, family="serif", horizontalalignment='left', verticalalignment='top') fig.canvas.draw()
def MDVRP_optimise_fleet(nodesTab, vehicle_count, costMatrix, nbrVehicleInDepot): nbrDepots = nodesTab.nbrDepots nbrBubbles = nodesTab.nbrBubbles nbrNodes = nbrDepots + nbrBubbles for vehicle_count in range(1, vehicle_count + 1): problem = pulp.LpProblem("MDVRP", pulp.LpMinimize) x = [[[ pulp.LpVariable("x%s_%s,%s" % (i, j, k), cat="Binary") if i != j else None for k in range(vehicle_count) ] for j in range(nbrNodes)] for i in range(nbrNodes)] #objectif fonction to minimise problem += pulp.lpSum( (costMatrix.get_element(nodesTab.tab[i].id, nodesTab.tab[j].id) + constant.SERVICE_TIME) * x[i][j][k] if i != j else 0 for k in range(vehicle_count) for j in range(nbrNodes) for i in range(nbrNodes)) #constraint 1 & 2 for j in range(nbrBubbles): problem += pulp.lpSum(x[i][j][k] if i != j else 0 for i in range(nbrNodes) for k in range(vehicle_count)) == 1 for i in range(nbrBubbles): problem += pulp.lpSum(x[i][j][k] if i != j else 0 for j in range(nbrNodes) for k in range(vehicle_count)) == 1 #constraint 3 for k in range(vehicle_count): for j in range(nbrNodes): problem += pulp.lpSum(x[i][j][k] if i != j else 0 for i in range(nbrNodes)) - pulp.lpSum( x[j][i][k] for i in range(nbrNodes)) == 0 #constraint 4 & 5 for k in range(vehicle_count): problem += pulp.lpSum( nodesTab.tab[j].charge * x[i][j][k] if i != j else 0 for i in range(nbrNodes) for j in range(nbrBubbles)) <= constant.Q for k in range(vehicle_count): problem += pulp.lpSum( (costMatrix.get_element(nodesTab.tab[i].id, nodesTab.tab[j].id) + constant.SERVICE_TIME) * x[i][j][k] if i != j else 0 for i in range(nbrNodes) for j in range(nbrNodes)) <= constant.T #contraint 6 & 7 for k in range(vehicle_count): problem += pulp.lpSum(x[i][j][k] if i != j else 0 for i in range(nbrBubbles) for j in range(nbrBubbles, nbrNodes)) <= 1 for k in range(vehicle_count): problem += pulp.lpSum(x[i][j][k] if i != j else 0 for j in range(nbrBubbles) for i in range(nbrBubbles, nbrNodes)) <= 1 for i in range(nbrBubbles, nbrNodes): problem += pulp.lpSum( x[i][j][k] for k in range(vehicle_count) for j in range(nbrBubbles)) <= nbrVehicleInDepot[i - nbrBubbles] y = [] for i in range(nbrNodes): y.append(pulp.LpVariable('y_' + str(i), cat='Integer')) for k in range(vehicle_count): for i in range(nbrBubbles): for j in range(nbrBubbles): if (i != j): problem += pulp.lpSum(y[i] - y[j] + nbrNodes * x[i][j][k]) <= nbrNodes - 1 # print("subs") # subtours = [] # for i in range(1,nbrBubbles): # subtours += itertools.combinations(range(nbrBubbles), i) # print("subs2") # for s in subtours: # problem += pulp.lpSum(x[i][j][k] if i !=j else 0 for i, j in itertools.permutations(s,2) for k in range(vehicle_count)) <= len(s) - 1 print("solving for " + str(vehicle_count)) solver = pulp.GUROBI_CMD( options=[("MIPFocus", 1), ("TimeLimit", constant.GUROBI_TIME_LIMIT), ("ResultFile", "Gurobi_result_D" + str(nodesTab.nbrDepots) + "_B" + str(nodesTab.nbrBubbles) + ".json")]) solve = problem.solve(solver) if solve == 1: print(vehicle_count) print('Moving Time:', pulp.value(problem.objective) / 60) edge = [] for d in range(vehicle_count): for i in range(nbrNodes): for j in range(nbrNodes): if i != j and pulp.value(x[i][j][d]) == 1: edge.append((i, j)) for e in edge: print(e) routes = [] charges = [] times = [] for e in edge: if e[0] in range(nbrBubbles, nbrNodes): route = [] time = 0 ca = 0 j = e[1] route.append(nodesTab.tab[e[0]].id) ca = nodesTab.tab[e[1]].charge time += costMatrix.get_element( nodesTab.tab[e[0]].id, nodesTab.tab[e[1]].id) + constant.SERVICE_TIME while (j != e[0]): route.append(nodesTab.tab[j].id) for e2 in edge: if e2[0] == j: time += costMatrix.get_element( nodesTab.tab[j].id, nodesTab.tab[ e2[1]].id) + constant.SERVICE_TIME ca += nodesTab.tab[e2[1]].charge j = e2[1] break times.append(time) charges.append(ca) route.append(nodesTab.tab[e[0]].id) routes.append(route) for i in range(len(routes)): print(routes[i]) print("Total charge: ", charges[i], " Time : ", times[i] / 60, " minutes or ", times[i] / (60 * 60), " hours") print("----") G = nx.Graph() for node in range(nbrNodes): G.add_node(node, weight=nodesTab.tab[node].id) G.add_edges_from(edge) labels = {n: G.nodes[n]['weight'] for n in G.nodes} colors = [G.nodes[n]['weight'] for n in G.nodes] pos = nx.nx_agraph.graphviz_layout(G, prog="neato") nx.draw(G, pos=pos, with_labels=True, labels=labels, node_color=colors) #plt.show() # display plt.savefig("Graph_D" + str(nodesTab.nbrDepots) + "_B" + str(nodesTab.nbrBubbles)) G.clear() plt.clf() return routes, charges, times
def MDVRP_optimise(nodesTab, costMatrix, nbrVehicleInDepot, enhanced=False): nbrDepots = nodesTab.nbrDepots nbrBubbles = nodesTab.nbrBubbles nbrNodes = nbrBubbles + nbrDepots problem = pulp.LpProblem("MDVRP", pulp.LpMinimize) #Warning due to how pulp work d go from 0-nbrdepot max and not from their position in the bubbleTab x = [[[ pulp.LpVariable("x%s_%s,%s" % (i, j, d), cat="Binary") if i != j else None for d in range(nbrDepots) ] for j in range(nbrNodes)] for i in range(nbrNodes)] y = [[ pulp.LpVariable("y%s,%s" % (i, d), cat="Binary") for d in range(nbrDepots) ] for i in range(nbrNodes)] z = [[ pulp.LpVariable("z%s_%s" % (i, j), lowBound=0, cat="Integer") if i != j else None for j in range(nbrNodes) ] for i in range(nbrNodes)] #Minimising function problem += pulp.lpSum( (costMatrix.get_element(nodesTab.tab[i].id, nodesTab.tab[j].id) + constant.SERVICE_TIME) * x[i][j][d] if i != j else 0 for j in range(nbrNodes) for i in range(nbrNodes) for d in range(nbrDepots)) #constraint 2 for i in range(nbrBubbles): problem += pulp.lpSum(y[i][d] for d in range(nbrDepots)) == 1 #constraint 4 for i in range(nbrBubbles): for d in range(nbrDepots): problem += y[i][d] <= y[d + nbrBubbles][d] #constraint 27 for i in range(nbrBubbles): for d in range(nbrDepots): problem+= pulp.lpSum(x[i][j][d] if i != j else 0 for j in range(nbrNodes))+ \ pulp.lpSum(x[j][i][d] if i != j else 0 for j in range(nbrNodes)) == 2*y[i][d] #constraint 28 for j in range(nbrNodes): for d in range(nbrDepots): problem += pulp.lpSum(x[i][j][d] if i != j else 0 for i in range(nbrNodes)) == pulp.lpSum( x[j][i][d] if i != j else 0 for i in range(nbrNodes)) #constraint 29 for d in range(nbrDepots): problem += y[d + nbrBubbles][d] <= pulp.lpSum( x[i][j][d] if i != j else 0 for i in range(nbrNodes) for j in range(nbrNodes)) #constraint 30 for d in range(nbrDepots): problem+= 2*y[d+nbrBubbles][d] <= pulp.lpSum(x[j][d+nbrBubbles][d] for j in range(nbrBubbles) ) + \ pulp.lpSum(x[d+nbrBubbles][j][d] for j in range(nbrBubbles) ) #constraint 31 for j in range(nbrBubbles): problem+= pulp.lpSum(z[i][j] if i != j else 0 for i in range(nbrNodes) ) - pulp.lpSum(z[j][i] if i != j else 0 for i in range(nbrNodes) )\ == nodesTab.tab[j].charge #constraint 32 problem+= pulp.lpSum(z[d+nbrBubbles][j] for d in range(nbrDepots) for j in range(nbrBubbles))\ == pulp.lpSum(nodesTab.tab[j].charge for j in range(nbrBubbles)) #constraint 33 for i in range(nbrNodes): for j in range(nbrBubbles): if i != j: problem += z[i][j] <= pulp.lpSum( (constant.Q - nodesTab.tab[i].charge) * x[i][j][d] for d in range(nbrDepots)) for i in range(nbrBubbles): for d in range(nbrDepots): problem += pulp.lpSum(x[i][d + nbrBubbles][h] if h != d else 0 for h in range(nbrDepots)) == 0 for i in range(nbrBubbles): for d in range(nbrDepots): problem += pulp.lpSum(x[d + nbrBubbles][i][h] if h != d else 0 for h in range(nbrDepots)) == 0 if (enhanced == True): #constraint 37 for i in range(nbrBubbles): for j in range(nbrBubbles): if i != j: problem += z[i][j] >= pulp.lpSum( nodesTab.tab[j].charge * x[i][j][d] if i != j else 0 for d in range(nbrDepots)) #constraint 38 for j in range(nbrBubbles): problem += pulp.lpSum(x[i][j][d] if i != j else 0 for i in range(nbrNodes) for d in range(nbrDepots)) == 1 #constraint 39 for i in range(nbrBubbles): problem += pulp.lpSum(x[i][j][d] if i != j else 0 for j in range(nbrNodes) for d in range(nbrDepots)) == 1 #constraint 40 for i in range(nbrBubbles): for d in range(nbrDepots): problem += x[i][d + nbrBubbles][d] <= y[i][d] #constraint 41 for i in range(nbrBubbles): for d in range(nbrDepots): problem += x[d + nbrBubbles][i][d] <= y[i][d] #constraint 42 for i in range(nbrBubbles): for j in range(nbrBubbles): if i != j: for d in range(nbrDepots): problem += x[i][j][d] + y[i][d] + pulp.lpSum( y[j][h] if h != d else 0 for h in range(nbrDepots)) <= 2 #constraint 43 for i in range(nbrBubbles): for j in range(nbrBubbles): if i != j: for d in range(nbrDepots): problem += x[i][j][d] + x[j][i][d] <= 1 #constraint 44 problem += (pulp.lpSum( nodesTab.tab[i].charge for i in range(nbrBubbles))) / (constant.Q) <= pulp.lpSum( x[d + nbrBubbles][i][d] for i in range(nbrBubbles) for d in range(nbrDepots)) #constraint vehicle in depot for d in range(nbrDepots): problem += pulp.lpSum( x[d + nbrBubbles][i][d] for i in range(nbrBubbles)) <= nbrVehicleInDepot[d] #time light constraint problem += pulp.lpSum( (costMatrix.get_element(nodesTab.tab[i].id, nodesTab.tab[j].id) + constant.SERVICE_TIME) * x[i][j][d] if i != j else 0 for j in range(nbrNodes) for i in range(nbrNodes) for d in range(nbrDepots)) <= constant.T * pulp.lpSum( x[d + nbrBubbles][i][d] for i in range(nbrBubbles) for d in range(nbrDepots)) #solve = problem.solve(pulp.GUROBI_CMD()) #solve = problem.solve(pulp.GUROBI_CMD(options=[("MIPFocus", 1),("TimeLimit", constant.GUROBI_TIME_LIMIT)])) #solve=problem.solve(pulp.COIN_CMD(timeLimit=60)) #solve=problem.solve(pulp.GLPK_CMD(options=["--tmlim", "60",])) solver = pulp.GUROBI_CMD( options=[("MIPFocus", 1), ("TimeLimit", constant.GUROBI_TIME_LIMIT), ("ResultFile", "Gurobi_result_D" + str(nodesTab.nbrDepots) + "_B" + str(nodesTab.nbrBubbles) + ".json")]) solve = problem.solve(solver) if solve == 1: print('Moving Time:', pulp.value(problem.objective) / 60) edge = [] for d in range(nbrDepots): for i in range(nbrNodes): for j in range(nbrNodes): if i != j and pulp.value(x[i][j][d]) == 1: edge.append((i, j)) routes = [] charges = [] times = [] for e in edge: if e[0] in range(nbrBubbles, nbrNodes): route = [] time = 0 j = e[1] route.append(nodesTab.tab[e[0]].id) charges.append(pulp.value(z[e[0]][e[1]])) time += costMatrix.get_element( nodesTab.tab[e[0]].id, nodesTab.tab[e[1]].id) + constant.SERVICE_TIME while (j != e[0]): route.append(nodesTab.tab[j].id) for e2 in edge: if e2[0] == j: time += costMatrix.get_element( nodesTab.tab[j].id, nodesTab.tab[e2[1]].id) + constant.SERVICE_TIME j = e2[1] break times.append(time) route.append(nodesTab.tab[e[0]].id) routes.append(route) for i in range(len(routes)): print(routes[i]) print("Total charge: ", charges[i], " Time : ", times[i] / 60, " minutes or ", times[i] / (60 * 60), " hours") print("----") G = nx.Graph() for node in range(nbrNodes): G.add_node(node, weight=nodesTab.tab[node].id) G.add_edges_from(edge) labels = {n: G.nodes[n]['weight'] for n in G.nodes} colors = [G.nodes[n]['weight'] for n in G.nodes] pos = nx.nx_agraph.graphviz_layout(G, prog="neato") nx.draw(G, pos=pos, with_labels=True, labels=labels, node_color=colors) #plt.show() # display plt.savefig("Graph_D" + str(nodesTab.nbrDepots) + "_B" + str(nodesTab.nbrBubbles)) G.clear() plt.clf() return routes, charges, times return [], [], []
def directed_pompeiu_hausdorff_distance(phi1, phi2, rand_area): """ Function computing the directed pompeiu-hausdorff distance between 2 STL Formulae. Takes as input: * phi1: an STL Formula * phi2: an STL Formula * rand_area: the domain on which signals are generated. rand_area = [lb,ub] where lb is the lower bound and ub the upper bound of the domain. Follows the definition of Madsen et al., "Metrics for signal temporal logic formulae," in 2018 IEEE Conference on Decision andControl (CDC). pp. 1542–1547 The encoding details of the MILP optimization problem follow Raman et al., "Model predictive control with signaltemporal logic specifications,” in 53rd IEEE Conference on Decision and Control. IEEE, 2014, pp. 81–87. """ dict_vars = {} #objective, maximize epsilon epsilon = plp.LpVariable(name='epsilon', cat='Continuous', lowBound=0, upBound=rand_area[1] - rand_area[0]) #satisfaction of phi1 and phi2 zvar1 = plp.LpVariable('z1_' + str(id(phi1)) + '_t_' + str(phi1.horizon), cat='Binary') zvar2 = plp.LpVariable('z2_' + str(id(phi2)) + '_t_' + str(phi2.horizon), cat='Binary') dict_vars['z1_' + str(id(phi1)) + '_t_' + str(phi1.horizon)] = zvar1 dict_vars['z2_' + str(id(phi2)) + '_t_' + str(phi2.horizon)] = zvar2 opt_model = plp.LpProblem("MIP Model", plp.LpMaximize) opt_model += epsilon dict_vars['epsilon'] = epsilon #We want to optimize a signal. The lower and upperbounds are specified by the random area. s = plp.LpVariable.dicts( "s", (range(max(phi1.horizon, phi2.horizon) + 1), range(NB_DIMENSIONS)), rand_area[0], rand_area[1], plp.LpContinuous) #recursive function def model_phi1(phi, t, opt_model): if isinstance(phi, STLFormula.TrueF): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 elif isinstance(phi, STLFormula.FalseF): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 0 elif isinstance(phi, STLFormula.Negation): model_phi1(phi.formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t)] = zvar1 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 - zvar1 elif isinstance(phi, STLFormula.Predicate): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar if phi.operator == operatorclass.gt or phi.operator == operatorclass.ge: opt_model += s[t][ phi.pi_index_signal] - phi.mu <= M_up * zvar - M_low opt_model += -(s[t][phi.pi_index_signal] - phi.mu) <= M_up * (1 - zvar) - M_low else: opt_model += -s[t][ phi.pi_index_signal] + phi.mu <= M_up * zvar - M_low opt_model += -(-s[t][phi.pi_index_signal] + phi.mu) <= M_up * (1 - zvar) - M_low elif isinstance(phi, STLFormula.Conjunction): model_phi1(phi.first_formula, t, opt_model) model_phi1(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z1_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar <= zvar1 opt_model += zvar <= zvar2 opt_model += zvar >= 1 - 2 + zvar1 + zvar2 elif isinstance(phi, STLFormula.Disjunction): model_phi1(phi.first_formula, t, opt_model) model_phi1(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z1_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z1_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar >= zvar1 opt_model += zvar >= zvar2 opt_model += zvar <= zvar1 + zvar2 elif isinstance(phi, STLFormula.Always): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi1(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] = zvar_i opt_model += zvar <= zvar_i opt_model += zvar >= 1 - (phi.t2 + 1 - phi.t1) + plp.lpSum([ dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) elif isinstance(phi, STLFormula.Eventually): try: zvar = dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z1_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z1_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi1(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z1_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] = zvar_i opt_model += zvar >= zvar_i opt_model += zvar <= plp.lpSum([ dict_vars['z1_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) def model_phi2(phi, t, opt_model): if isinstance(phi, STLFormula.TrueF): try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 elif isinstance(phi, STLFormula.FalseF): try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 0 elif isinstance(phi, STLFormula.Negation): model_phi2(phi.formula, t, opt_model) try: zvar1 = dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z2_' + str(id(phi.formula)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t)] = zvar1 try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar == 1 - zvar1 elif isinstance(phi, STLFormula.Predicate): try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar if phi.operator == operatorclass.gt or phi.operator == operatorclass.ge: opt_model += s[t][ phi. pi_index_signal] - phi.mu + epsilon <= M_up * zvar - M_low opt_model += -(s[t][phi.pi_index_signal] - phi.mu) - epsilon <= M_up * (1 - zvar) - M_low else: opt_model += -s[t][ phi. pi_index_signal] + phi.mu + epsilon <= M_up * zvar - M_low opt_model += -(-s[t][phi.pi_index_signal] + phi.mu) - epsilon <= M_up * (1 - zvar) - M_low elif isinstance(phi, STLFormula.Conjunction): model_phi2(phi.first_formula, t, opt_model) model_phi2(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z2_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z2_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z2_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z2_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar <= zvar1 opt_model += zvar <= zvar2 opt_model += zvar >= 1 - 2 + zvar1 + zvar2 elif isinstance(phi, STLFormula.Disjunction): model_phi2(phi.first_formula, t, opt_model) model_phi2(phi.second_formula, t, opt_model) try: zvar1 = dict_vars['z2_' + str(id(phi.first_formula)) + '_t_' + str(t)] except KeyError: zvar1 = plp.LpVariable('z2_' + str(id(phi.first_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi.first_formula)) + '_t_' + str(t)] = zvar1 try: zvar2 = dict_vars['z2_' + str(id(phi.second_formula)) + '_t_' + str(t)] except KeyError: zvar2 = plp.LpVariable('z2_' + str(id(phi.second_formula)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi.second_formula)) + '_t_' + str(t)] = zvar2 try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar opt_model += zvar >= zvar1 opt_model += zvar >= zvar2 opt_model += zvar <= zvar1 + zvar2 elif isinstance(phi, STLFormula.Always): try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi2(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z2_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] = zvar_i opt_model += zvar <= zvar_i opt_model += zvar >= 1 - (phi.t2 + 1 - phi.t1) + plp.lpSum([ dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) elif isinstance(phi, STLFormula.Eventually): try: zvar = dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] except KeyError: zvar = plp.LpVariable('z2_' + str(id(phi)) + '_t_' + str(t), cat='Binary') dict_vars['z2_' + str(id(phi)) + '_t_' + str(t)] = zvar for t_i in range(phi.t1, phi.t2 + 1): model_phi2(phi.formula, t_i, opt_model) try: zvar_i = dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] except KeyError: zvar_i = plp.LpVariable('z2_' + str(id(phi.formula)) + '_t_' + str(t_i), cat='Binary') dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] = zvar_i opt_model += zvar >= zvar_i opt_model += zvar <= plp.lpSum([ dict_vars['z2_' + str(id(phi.formula)) + '_t_' + str(t_i)] for t_i in range(phi.t1, phi.t2 + 1) ]) model_phi1(phi1, phi1.horizon, opt_model) model_phi2(phi2, phi2.horizon, opt_model) zvar1 = dict_vars['z1_' + str(id(phi1)) + '_t_' + str(phi1.horizon)] zvar2 = dict_vars['z2_' + str(id(phi2)) + '_t_' + str(phi2.horizon)] opt_model += zvar1 == 1 opt_model += zvar2 == 0 opt_model.solve(plp.GUROBI_CMD(msg=False)) if epsilon.varValue == None: return 0.0 return epsilon.varValue