Exemple #1
0
    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)
Exemple #2
0
	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)))
Exemple #3
0
 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])
Exemple #5
0
 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'])
Exemple #6
0
    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)
Exemple #7
0
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
Exemple #8
0
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
Exemple #11
0
    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)]
Exemple #14
0
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])]
Exemple #15
0
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
     
Exemple #16
0
# -*- 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()
Exemple #18
0
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
Exemple #19
0
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 [], [], []
Exemple #20
0
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