def createConstraints(self):
     for i in range(len(self.shape_verts)):
         for vid in self.shape_verts[i]:
             self.m.addConstr(self.diff_x[vid] == self.px[vid] - self.vert_locs[vid][0])
             self.m.addConstr(self.diff_y[vid] == self.py[vid] - self.vert_locs[vid][1])
             self.m.addConstr(self.abs_diff_x[vid] == gp.abs_(self.diff_x[vid]))
             self.m.addConstr(self.abs_diff_y[vid] == gp.abs_(self.diff_y[vid]))
     for i in range(len(pair_rels)):
         p_rel = pair_rels[i]
         segs = [[p_rel[0], p_rel[1]], [p_rel[2], p_rel[3]]]
         for se in range(2):
             # (x, y) -> (x, y)
             if p_rel[4] == 0:
                 self.m.addConstr(self.px[segs[0][se]] - self.px[segs[1][se]] == self.ds_x[i])
                 self.m.addConstr(self.py[segs[0][se]] - self.py[segs[1][se]] == self.ds_y[i])
             # (x, y) -> (-y, x)
             elif p_rel[4] == 1:
                 self.m.addConstr(-self.py[segs[0][se]] - self.px[segs[1][se]] == self.ds_x[i])
                 self.m.addConstr(self.px[segs[0][se]] - self.py[segs[1][se]] == self.ds_y[i])
             # (x, y) -> (y, -x)
             elif p_rel[4] == 2:
                 self.m.addConstr(self.py[segs[0][se]] - self.px[segs[1][se]] == self.ds_x[i])
                 self.m.addConstr(-self.px[segs[0][se]] - self.py[segs[1][se]] == self.ds_y[i])
             # (x, y) -> (x, y)
             elif p_rel[4] == 3:
                 self.m.addConstr(-self.px[segs[0][se]] - self.px[segs[1][se]] == self.ds_x[i])
                 self.m.addConstr(-self.py[segs[0][se]] - self.py[segs[1][se]] == self.ds_y[i])
    def get_grb_vars(self, grb_model, x_batches, y_batches):
        domains = self.get_domains(x_batches, y_batches)[0]
        x_inp = domains.get_grb_vars(grb_model)
        grb_model.update()

        data_orig = x_batches[0]
        att_orig = data_orig[0, self.att_col_idx].item()
        att_adv = x_inp[self.att_col_idx]

        att_diff = grb_model.addVar(-GRB.INFINITY, GRB.INFINITY)
        grb_model.addConstr(att_diff == (att_orig - att_adv))
        abs_att_diff = grb_model.addVar(0, GRB.INFINITY)
        grb_model.addConstr(att_diff == abs_(abs_att_diff))

        f1 = grb_model.addVar(vtype=GRB.BINARY)
        f2 = grb_model.addVar(vtype=GRB.BINARY)
        if att_orig <= self.norm_threshold:
            grb_model.addConstr(f1 == and_([
                self.lt_ineq(att_adv, self.norm_threshold, grb_model),
                self.lt_ineq(abs_att_diff, self.below_epsilon, grb_model),
            ]))
        if att_orig > self.norm_threshold:
            grb_model.addConstr(f2 == and_([
                self.lt_ineq(att_adv, self.norm_threshold, grb_model),
                self.lt_ineq(abs_att_diff, self.above_epsilon, grb_model),
            ]))

        pre_condition = grb_model.addVar(vtype=GRB.BINARY)
        grb_model.addConstr(pre_condition == or_([f1, f2]))
        grb_model.addConstr(pre_condition == 1)

        return x_inp
Beispiel #3
0
 def addConstraints(self):
     cnt = 0
     for key in self.angle_diffs_dic:
         self.m.addConstr( self.diff[cnt] == self.a[key[0]] + self.k[cnt] * 360 - self.a[key[1]] - self.angle_diffs_dic[key])
         cnt += 1
     for i in range(len(self.angle_diffs_dic)):
         self.m.addConstr(self.abs_diff[i] == gp.abs_(self.diff[i]))
     for key in self.angle_diffs_constr_dic:
         self.m.addConstr( self.a[key[0]] + self.k[cnt] * 360 - self.a[key[1]], GRB.EQUAL, self.angle_diffs_constr_dic[key])
         cnt += 1
 def addConstraints(self):
     cnt = 0
     d_cnt = 0
     for key in self.angle_diffs_constr_dic:
         shape_id_0 = self.getShapeId(key[0])
         shape_id_1 = self.getShapeId(key[1])
         self.m.addConstr(self.diff[cnt] == self.a[shape_id_0] +
                          self.angles[key[0]] - self.a[shape_id_1] -
                          self.angles[key[1]] - self.d[d_cnt] * 90)
         self.m.addConstr(self.abs_diff[cnt] == gp.abs_(self.diff[cnt]))
         cnt += 1
         d_cnt += 1
def min_gamma(dist, c_nr):

    # Get the number of timesteps and clusters from distance vector
    k_nr = dist.shape[0]
    time_nr = dist.shape[1]

    # Set the model
    mod = grb.Model('MinGamma')

    # Create variables for the weights by their cluster and time
    weights = [(k, t) for k in range(k_nr) for t in range(time_nr)]
    gam = mod.addVars(weights, lb=0, ub=1, name="gam")

    # Create additional variables needed for the absolute value constraints
    additional = [(k, t) for k in range(k_nr) for t in range(time_nr - 1)]
    y1var = mod.addVars(additional, lb=-1, ub=1, name="y1var")
    y2var = mod.addVars(additional, lb=0, ub=1, name="y2var")

    # Set the objective function to minimize
    mod.setObjective( sum( dist[k,t]*gam[k,t] for k in range(k_nr) \
                        for t in range(time_nr) ), sense=grb.GRB.MINIMIZE )

    # Add the normalization and persistence constraints
    mod.addConstrs( (sum(gam[k,t] for k in range(k_nr)) == 1 for t in range(time_nr)), \
                    name = "normalization" )
    mod.addConstrs( ( y1var[k,t] == gam[k,t+1] - gam[k,t] \
                    for k in range(k_nr) for t in range(time_nr-1) ), \
                    name = "abs_y1" )
    mod.addConstrs( ( y2var[k,t] == grb.abs_(y1var[k,t]) \
                    for k in range(k_nr) for t in range(time_nr-1) ), \
                    name = "abs_y2" )
    mod.addConstr( (sum( y2var[k,t] for t in range(time_nr-1) \
                    for k in range(k_nr) ) <= c_nr ), name = "persistence")

    # Prevent output of optimization
    mod.setParam("TuneOutput", 0)

    # Compute optimal solution
    mod.optimize()

    # Get the solution for gamma
    if mod.status == grb.GRB.Status.OPTIMAL:
        solution = mod.getAttr('x', gam)
        gam_new = np.zeros((k_nr, time_nr))
        for k in range(k_nr):
            for t in range(time_nr):
                gam_new[k, t] = solution[(k, t)]
    else:
        print("Optimization failed")

    return gam_new
Beispiel #6
0
def sample_solutions(model, variables, num_samples=INF, norm=2, closest=True):
    from gurobipy import GRB, quicksum, abs_
    start_time = time.time()
    objective = model.getObjective()
    #sprint(objective, objective.getValue())
    # model = model.feasibility()
    # model.setObjective(0.0)
    if norm == 2:
        model.setParam(GRB.Param.NonConvex, 2)  # PSDTol
    objective_terms = []
    if closest:
        min_distance = model.addVar(lb=0., ub=GRB.INFINITY)
        objective_terms.append(min_distance)
    solutions = []  # TODO: sample initial solution from this set
    while len(solutions) < num_samples:
        terms = []
        for var in variables:
            for index, coord in enumerate(var):
                value = coord.X
                set_guess(coord, value, hard=True)
                delta = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY)
                model.addConstr(delta == coord - value)
                if norm == 1:
                    term = model.addVar(lb=0., ub=GRB.INFINITY)
                    model.addConstr(term == abs_(delta))
                elif norm == 2:
                    term = delta * delta
                else:
                    raise NotImplementedError(norm)
                terms.append(term)  # TODO: scale
        distance = quicksum(terms)
        if closest:
            model.addConstr(min_distance <= distance)
        else:
            objective_terms.append(distance)  # TODO: weight

        model.setObjective(quicksum(objective_terms),
                           sense=GRB.MAXIMIZE)  # MINIMIZE | MAXIMIZE
        model.optimize()
        print(
            '# {} | objective: {:.3f} | cost: {:.3f} | runtime: {:.3f}'.format(
                len(solutions), model.ObjVal, objective.getValue(),
                elapsed_time(start_time)))  # min_distance.X
        solution = [value_from_var(var) for var in variables]
        solutions.append(solution)
        yield solution
Beispiel #7
0
    def to_gurobi(self, model):
        c_name = 'Abs_{n}_{layer}_{row}'.format(n=self.net,
                                                layer=self.layer,
                                                row=self.row)
        ret_constr = None

        if self.input.getLo() >= 0:
            # input is positive
            ret_constr = model.addConstr(
                self.output.to_gurobi(model) == self.input.to_gurobi(model),
                name=c_name)
        elif self.input.getHi() <= 0:
            # inputs is negative
            ret_constr = model.addConstr(
                self.output.to_gurobi(model) == -self.input.to_gurobi(model),
                name=c_name)
        elif fc.use_grb_native:
            ret_constr = model.addConstr(
                self.output.to_gurobi(model) == grb.abs_(
                    self.input.to_gurobi(model)),
                name=c_name)
        else:
            out_bound = max(abs(self.input.getLo()), abs(self.input.getHi()))
            bigM1 = out_bound + self.input.getHi()
            bigM2 = out_bound - self.input.getLo()
            model.addConstr(
                self.output.to_gurobi(model) >= -self.input.to_gurobi(model),
                name=c_name + '_a')
            model.addConstr(
                self.output.to_gurobi(model) >= self.input.to_gurobi(model),
                name=c_name + '_b')
            model.addConstr(
                self.output.to_gurobi(model) <= -self.input.to_gurobi(model) +
                self.delta.to_gurobi(model) * bigM1,
                name=c_name + '_c')
            ret_constr = model.addConstr(
                self.output.to_gurobi(model) <= self.input.to_gurobi(model) +
                (1 - self.delta.to_gurobi(model)) * bigM2,
                name=c_name + '_c')

        return ret_constr
Beispiel #8
0
def baseline2_gurobi(A, k, r):
    '''
    Not supported by Gurobi now

    max Tr(AP)
    s.t. P,I-P are PSD
        Tr(P) = r
        1^T|P|1 <= rk

    #input
    A: sample covariance matrix
    r: # of eigenvalues
    k: sparsity parameter

    #output
    Objective value
    '''
    d = A.shape[0]
    bl2 = gp.Model()

    # P
    P = []
    for i in range(d):
        P.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="P"))

    # Px = lambda x with lambda >= 0
    x = []
    Lambda = []
    for i in range(d):
        x.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="x"))
        Lambda.append(
            bl2.addVars(1,
                        lb=0,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="x"))
    for i in range(d):
        for j in range(i + 1, d):
            bl2.addConstr(Lambda[i] != Lambda[j])
    Ax = []
    for i in range(d):
        Ax.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="P"))
    for k in range(d):
        for i in range(d):
            bl2.addConstr(sum(x[k][j] * P[i][j] for j in range(d)) == Ax[k][i])
            bl2.addConstr(Lambda[k] * x[k][j] == Ax[k][i])

    # I-P
    I_P = []
    for i in range(d):
        I_P.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="I_P"))
    for i in range(d):
        for j in range(d):
            if i == j:
                bl2.addConstr(I_P[i][j] == 1 - P[i][j])
            else:
                bl2.addConstr(I_P[i][j] == -P[i][j])

    # (I-P)x = lambda x with lambda >= 0
    xI = []
    LambdaI = []
    for i in range(d):
        xI.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="x"))
        LambdaI.append(
            bl2.addVars(1,
                        lb=0,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="x"))
    for i in range(d):
        for j in range(i + 1, d):
            bl2.addConstr(LambdaI[i] != LambdaI[j])
    AxI = []
    for i in range(d):
        AxI.append(
            bl2.addVars(d,
                        lb=-GRB.INFINITY,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="P"))
    for k in range(d):
        for i in range(d):
            bl2.addConstr(
                sum(xI[k][j] * I_P[i][j] for j in range(d)) == AxI[k][i])
            bl2.addConstr(LambdaI[k] * xI[k][j] == AxI[k][i])

    # Tr(p) = r
    bl2.addConstr(sum(P[i][i] for i in range(d)) == r)

    # 1 |P| 1 <= rk
    absP = []
    for i in range(d):
        absP.append(
            bl2.addVars(d,
                        lb=0,
                        ub=GRB.INFINITY,
                        vtype=GRB.CONTINUOUS,
                        name="absP"))
    for j in range(d):
        for i in range(d):
            bl2.addConstr(absP[j][i] == gp.abs_(P[j][i]))
    bl2.addConstr(
        sum(sum(absP[j][i] for i in range(d)) for j in range(d)) <= r * k)

    # Tr(AP)
    obj = sum(sum(A[i][j] * P[j][i] for j in range(d)) for i in range(d))
    bl2.setObjective(obj, GRB.MAXIMIZE)
    bl2.params.NonConvex = 2
    bl2.optimize()
Beispiel #9
0
import gurobipy as grb

m = grb.Model()
x = m.addVar(lb=-10, name='x')
y = m.addVar(name='y')
m.addConstr(y == grb.abs_(x), name='C_abs')
m.addConstr(x >= -5, name='C_2')
m.addConstr(x <= 3, name='C3')
c = 2
m.setObjective(c * y)
m.optimize()
print("y=", y.X)
print('x=', x.X)
Beispiel #10
0
    def furthest_from_hull(self, qhull, var_limits, facet_eq,
                           write: bool = False, write_file: str = "pw.lp"):
        """
        The method should find the possible world satisfying the formulas furthest from the convex hull.
        Dtance from a point to the polytope is approximated as
        :param qhull:
        :param var_limits:
        :param write:
        :param write_file:
        :return:
        """
        # create ILP
        # returns satisfiability + point + objective
        mod = g.Model()
        # find all atoms in CNFs
        # create opt. variable for all possible assignments of constants to variables for each atom...
        opt_variable_mapping = {}  # key (predicate, [domain elements])
        greatest_distance = mod.addVar(lb=0.0, name="maxDist")
        tar_vars = []
        a_count = 0
        d_count = 0
        grand_d = []
        grand_a = []
        for i, wf in enumerate(self.formulas):  # Right now - every formula contains one clause
            cnf = wf.formula
            distinct_vars = cnf.get_distinct_vars()
            tar_var = mod.addVar(lb=0, ub=var_limits[i], vtype=g.GRB.INTEGER, name=f"Xf_{i}")
            tar_vars.append(tar_var)
            ds = []
            # print(cnf)
            assignment_generator = itt.permutations(self.domain, len(distinct_vars))
            if self.reflexive:
                assignment_generator = itt.product(self.domain, repeat=len(distinct_vars))
            for assignment in assignment_generator:
                assgnmt_dir = {a: b for a, b in zip(distinct_vars, assignment)}
                # D indicates that whole formula is satisfied in current assignment
                # D = {min A}  (see below)
                D = mod.addVar(lb=0.0, ub=1.0, name="D_{}".format(d_count))
                grand_d.append(D)
                d_count += 1
                ds.append(D)
                avars = []
                # print("Start")
                for clause in cnf.clauses:
                    # A indicates that a clause is satisfied in current assignment
                    # A = max{variables for each literal}
                    A = mod.addVar(lb=0.0, ub=1.0, name="A_{}".format(a_count))
                    avars.append(A)
                    grand_a.append(A)
                    a_count += 1
                    cl_literals = []
                    for literal in clause.literals:
                        pos_code = literal.atom.assignment_name(assgnmt_dir)
                        neg_code = f"~{pos_code}"
                        a_code = pos_code if literal.positive else neg_code
                        if a_code in opt_variable_mapping:
                            opt_var = opt_variable_mapping[a_code]
                            # print("Found")
                        else:
                            p_var = mod.addVar(vtype=g.GRB.BINARY, name=pos_code)
                            n_var = mod.addVar(vtype=g.GRB.BINARY, name=neg_code)
                            mod.addConstr(1 - p_var == n_var)
                            opt_variable_mapping[pos_code] = p_var
                            opt_variable_mapping[neg_code] = n_var
                            opt_var = p_var if literal.positive else n_var
                            # print("Not found")
                        cl_literals.append(opt_var)
                    mod.addGenConstrMax(A, cl_literals, 0.0)
                mod.addGenConstrMin(D, avars, 1.0)
            mod.addConstr(g.quicksum(ds) == tar_var)


        poly_lines, columns = qhull.equations.shape
        dist_vars = []
        indicators = []
        # Selected inequality must not hold
        #for ix in range(poly_lines):
        # Use inequality for chosen edge
        # qhull uses Ax + b < 0
        line = facet_eq[0:columns-1]
        b = facet_eq[columns-1]
        mod.addConstr(g.quicksum([w * v for w, v in zip(line, tar_vars)]) + b >= 0)  # TODO >= 1 but we need to rescale b  # inside polytope is <=
        # Find max L2 distance
        dst = mod.addVar(name="pd")
        mod.addConstr(g.quicksum([w * v for w, v in zip(line, tar_vars)]) + b == dst)
        mod.addConstr(greatest_distance == g.abs_(dst))
        mod.setObjective(greatest_distance, g.GRB.MAXIMIZE)
        if write:
            mod.write(write_file)
        mod.optimize()

        if mod.status == g.GRB.OPTIMAL:  # TODO not in INFEASIBLE, UNBOUNDED,
            print(mod.status)
            print("Found optimal solution")
            # if len(self.domain) < 7:
            #    for v in opt_variable_mapping.values():
            #        print(v.x, v.varname)
            # for v in grand_d:
            #     print(v.x, v.varname)
            # for v in grand_a:
            #     print(v.x, v.varname)
        else:
            print("Constraints are INFEASIBLE")
            print("inf or unb", g.GRB.INF_OR_UNBD == mod.status)
            print("unb", g.GRB.UNBOUNDED == mod.status)
            print("infis", g.GRB.INFEASIBLE == mod.status)

        out_list = [] if mod.status != g.GRB.OPTIMAL else [v.x for v in tar_vars]
        gdx = greatest_distance.x if mod.status == g.GRB.OPTIMAL else -1
        return mod.status == g.GRB.OPTIMAL, out_list, gdx
def create_ilp_formulation_for_ddp(config, ilp_type='improved'):
    try:
        start_time = datetime.datetime.now()
        model = gurobipy.Model(config.name_model)
        logger.info("Creating completion variables.")

        logger.info("Defining R completion.")
        hat_rs = define_matching_vars(model=model,
                                      edge_set=general_allowable_set(config.ind_cbg_compl_R),
                                      edge_conditions=general_conditional_set(config.ind_cbg_compl_R),
                                      vertex_set=[],
                                      vertex_conditions={x: False for x in config.ind_cbg_compl_R})

        logger.info("Defining genome X.")
        xes, indexing_set = define_guided_matching_using_graph(model=model,
                                                               edge_conditions={**{edge: False for edge in
                                                                                   config.ind_cbg_R_edges},
                                                                                **{pair: True for pair in
                                                                                   general_allowable_set(
                                                                                       config.ind_cbg_compl_R)}},
                                                               equiv_map=config.equiv_map,
                                                               edge_variables=hat_rs)

        logger.info("Creating connectivity variables and constraints.")
        aes, tilde_as = create_connectivity_variables(model=model, vertex_set=config.bg_vertex2ind.values())

        add_certain_connectivity_constraints(model=model,
                                             edges=config.ind_bg_A_edges,
                                             connect_vars=aes)

        if ilp_type == 'basic':
            logger.info("Defining A completion.")
            hat_as = define_matching_vars(model=model,
                                          edge_set=general_allowable_set(config.ind_compl_A),
                                          edge_conditions=general_conditional_set(config.ind_compl_A),
                                          vertex_set=[],
                                          vertex_conditions={x: False for x in config.ind_compl_A})

            add_uncertain_connectivity_constraints(model=model,
                                                   edge_set=indexing_set,
                                                   edge_vars=xes,
                                                   connect_vars=aes,
                                                   biggest_const=config.biggest_const)

            add_uncertain_connectivity_constraints(model=model,
                                                   edge_set=general_allowable_set(config.ind_compl_A),
                                                   edge_vars=hat_as,
                                                   connect_vars=aes,
                                                   biggest_const=config.biggest_const)
            logger.info("Creating telomeric variables and constraints.")
            dot_as = create_vars_count_odd_paths(model=model,
                                                 telomeric_vertices=config.ind_bg_A_telomers,
                                                 connect_vars=aes,
                                                 biggest_const=config.biggest_const)

            logger.info("CREATING OBJECTIVE FUNCTION.")
            model.setObjective(tilde_as.sum('*') - dot_as.sum('*'), gurobipy.GRB.MAXIMIZE)

        elif ilp_type == 'improved':
            set_pairs_for_paths = general_allowable_set(config.ind_forth_type_telomers) | \
                                  product_set(config.ind_second_type_telomers,
                                              config.ind_third_type_telomers) | \
                                  product_set(config.ind_second_type_telomers,
                                              config.ind_forth_type_telomers)

            logger.info("Creating variables for counting paths.")
            hat_cs = create_path_variables(model=model,
                                           pairs_set=set_pairs_for_paths)

            add_uncertain_connectivity_constraints_a(model=model,
                                                     edge_set=indexing_set,
                                                     edge_vars=xes,
                                                     connect_vars=aes,
                                                     biggest_const=config.biggest_const)
            add_uncertain_connectivity_constraints_c(model=model,
                                                     edge_set=set_pairs_for_paths,
                                                     edge_vars=hat_cs,
                                                     connect_vars=aes,
                                                     biggest_const=config.biggest_const)

            p44 = create_helping_path_variables(model=model,
                                                connect_vars=hat_cs,
                                                pair_set=general_allowable_set(config.ind_forth_type_telomers),
                                                biggest_const=config.biggest_const)
            p23 = create_helping_path_variables(model=model,
                                                connect_vars=hat_cs,
                                                pair_set=product_set(config.ind_second_type_telomers,
                                                                     config.ind_third_type_telomers),
                                                biggest_const=config.biggest_const)
            p24 = create_helping_path_variables(model=model,
                                                connect_vars=hat_cs,
                                                pair_set=product_set(config.ind_second_type_telomers,
                                                                     config.ind_forth_type_telomers),
                                                biggest_const=config.biggest_const)
            c1 = len(config.ind_first_type_telomers)

            # create_objective
            logger.info("CREATING OBJECTIVE FUNCTION.")
            tmp = model.addVar(lb=-config.biggest_const, ub=config.biggest_const, vtype=gurobipy.GRB.INTEGER, name="tmp")
            model.addConstr(tmp == p24 - c1 - p23)
            abs_var = model.addVar(ub=config.biggest_const, vtype=gurobipy.GRB.INTEGER, name="abs_tmp")
            model.addConstr(abs_var == gurobipy.abs_(tmp))
            model.setObjective(tilde_as.sum('*') - p44 - 1 / 4 * (c1 + p23 + 3 * p24 + abs_var), gurobipy.GRB.MAXIMIZE)

        else:
            logger.error('Error: Unknown type. Use "basic" or "improved"')
            return None

        logger.info("FINISH CREATE MODEL.")
        model.params.logFile = config.log_file
        model.params.MIPFocus = 2
        model.params.timeLimit = config.time_limit
        model.optimize()

        logger.info("The number of cycles and paths is " + str(int(model.objVal)))
        print("The number of cycles and paths is " + str(int(model.objVal)))
        answer = get_param_of_solution_for_double_distance(model=model,
                                                           multiplicity=config.multiplicity,
                                                           number_of_genes=len(config.s_all_genes),
                                                           number_of_R_telomers=len(config.ind_cbg_R_telomers),
                                                           working_time=datetime.datetime.now() - start_time)

        return answer

    except gurobipy.GurobiError as e:
        logger.error(
            "Some error has been raised. Please, report to github bug tracker. \n Text exception: {0}".format(e))
        return None
Beispiel #12
0
def get_layer_bound_LP(Ws,bs,UBs,LBs,x0,eps,p,neuron_states,nlayer,pred_label,target_label,compute_full_bounds=False,untargeted=False):
    import gurobipy as grb
    # storing upper and lower bounds for last layer
    UB = np.empty_like(bs[-1])
    LB = np.empty_like(bs[-1])
    # neuron_state is an array: neurons never activated set to -1, neurons always activated set to +1, indefinite set to 0    
    # indices
    alphas = []
    # for n layer network, we have n-1 layers of relu
    for i in range(nlayer-1):
        idx_unsure = (neuron_states[i] == 0).nonzero()[0]
        # neuron_state is an integer array for efficiency reasons. We should convert it to float
        alpha = neuron_states[i].astype(np.float32)
        alpha[idx_unsure] = UBs[i+1][idx_unsure]/(UBs[i+1][idx_unsure]-LBs[i+1][idx_unsure])
        alphas.append(alpha)
    
    start = time.time()
    m = grb.Model("LP")
    m.setParam("outputflag",0)
    # disable parallel Gurobi solver, using 1 thread only
    m.setParam("Method",1) # dual simplex
    m.setParam("Threads", 1) # only 1 thread
    # z and zh are list of lists, each list for one layer of variables
    # z starts from 1, matching Zico's notation
    z = []
    z.append(None)
    # z hat starts from 2
    zh = []
    zh.append(None)
    zh.append(None)
    
    if p == "2" or p == "1":
        # ztrans (transformation of z1 only for lp norm), starts from 1 matching z
        ztrans = []
        ztrans.append(None)
    
    ## LP codes: 
    
    # we start our label from 1 to nlayer+1 (the last one is the final objective layer)
    # valid range for z: 1 to nlayer (z_1 is just input, z_{nlayer} is the last relu layer output)
    # valid range for z_hat: 2 to nlayer+1 (there is no z_hat_1 as it is the input, z_{nlayer+1} is final output)
    for i in range(1,nlayer+2):
        if i == 1: # first layer
            # first layer, only z exists, no z hat
            zzs = []
            zzts = []
            # UBs[0] is for input x. Create a variable for each input
            # and set its lower and upper bounds
            for j in range(1,len(UBs[0])+1):
                zij = m.addVar(vtype=grb.GRB.CONTINUOUS, lb=LBs[0][j-1], ub=UBs[0][j-1], name="z_"+str(i)+"_"+str(j))
                zzs.append(zij)
                if p == "2" or p == "1":                
                    # transformation variable at z1 only
                    if p == "2":
                        ztij = m.addVar(vtype=grb.GRB.CONTINUOUS, name="zt_"+str(i)+"_"+str(j))
                    elif p == "1":
                        ztij = m.addVar(vtype=grb.GRB.CONTINUOUS, lb=0, name="zt_"+str(i)+"_"+str(j))
                    zzts.append(ztij)  
            z.append(zzs)
            if p == "2" or p == "1":
                ztrans.append(zzts)
        elif i< nlayer+1:
            # middle layer, has both z and z hat
            zzs = []
            zzhs = []
            for j in range(1,len(UBs[i-1])+1):
                zij = m.addVar(vtype=grb.GRB.CONTINUOUS, name="z_"+str(i)+"_"+str(j))
                zzs.append(zij)
                
                zhij = m.addVar(vtype=grb.GRB.CONTINUOUS,lb=-np.inf,name="zh_"+str(i)+"_"+str(j))
                zzhs.append(zhij)
            z.append(zzs)
            zh.append(zzhs)
        else: # last layer, i == nlayer + 1
            # only has z hat, length is the same as the output
            # there is no relu, so no z
            zzhs = []
            for j in range(1,len(bs[-1])+1):
                zhij = m.addVar(vtype=grb.GRB.CONTINUOUS,lb=-np.inf,name="zh_"+str(i)+"_"+str(j))
                zzhs.append(zhij)
            zh.append(zzhs)
    
    m.update()

    # Adding weights constraints for all layers
    for i in range(1,nlayer+1):
        W = Ws[i-1] # weights of layer i
        for j in range(W.shape[0]):
            """
            sum_term = bs[i-1][j]
            for s in range(W.shape[1]):
                # z start from 1
                sum_term += z[i][s]*W[j,s]
            """
            sum_term = grb.LinExpr(W[j], z[i]) + bs[i-1][j]
            # this is the output of layer i, and let z_hat_{i+1} equal to it
            # z_hat_{nlayer+1} is the final output (logits)
            m.addConstr(sum_term == zh[i+1][j], "weights==_"+str(i)+"_"+str(j))
            # m.addConstr(sum_term <= zh[i+1][j], "weights<=_"+str(i)+"_"+str(j))
            # m.addConstr(sum_term >= zh[i+1][j], "weights>=_"+str(i)+"_"+str(j))
    
    # nlayer network only has nlayer - 1 activations
    for i in range(1, nlayer):
        # UBs[0] is the bounds for input x, so start from 1
        for j in range(len(UBs[i])):
            # neuron_states starts from 0
            if neuron_states[i-1][j] == 1:
                m.addConstr(z[i+1][j] == zh[i+1][j], "LPposr==_"+str(j))
                # m.addConstr(z[i+1][j] <= zh[i+1][j], "LPpos<=_"+str(j))
                # m.addConstr(z[i+1][j] >= zh[i+1][j], "LPpos>=_"+str(j))
            elif neuron_states[i-1][j] == -1:
                m.addConstr(z[i+1][j] == 0, "LPneg==_"+str(j))
                # m.addConstr(z[i+1][j] <= 0, "LPneg<=_"+str(j))
                # m.addConstr(z[i+1][j] >= 0, "LPneg>=_"+str(j))
            elif neuron_states[i-1][j] == 0:
                # m.addConstr(z[i+1][j] >= 0, "LPunsure>=0_"+str(j))
                m.addConstr(z[i+1][j] >= zh[i+1][j], "LPunsure>=_"+str(j))
                m.addConstr(z[i+1][j] <= alphas[i-1][j]*(zh[i+1][j]-LBs[i][j]), "LPunsure<=_"+str(j))
            else:
                raise(RuntimeError("unknown neuron_state: "+neuron_states[i])) 

    
#    #finally, add constraints for z[1], the input -> For p == "i", this is already added in the input variable range zij
#    for i in range(len(UBs[0])):
#         m.addConstr(z[1][i] <= UBs[0][i], "inputs+_"+str(i))
#         m.addConstr(z[1][i] >= LBs[0][i], "inputs-_"+str(i))         

    if p == "2": 
        #finally, add constraints for z[1] and ztrans[1], the input
        for i in range(len(UBs[0])):
            m.addConstr(ztrans[1][i] == z[1][i] - x0[i], "INPUTtrans_"+str(i))
        # quadratic constraints
        m.addConstr(grb.quicksum(ztrans[1][i]*ztrans[1][i] for i in range(len(UBs[0]))) <= eps*eps, "INPUT L2 norm QCP")
    elif p == "1":
         #finally, add constraints for z[1] and ztrans[1], the input
        temp = []
        for i in range(len(UBs[0])):
            tempi = m.addVar(vtype=grb.GRB.CONTINUOUS)
            temp.append(tempi)
                    
        for i in range(len(UBs[0])):
            # absolute constraints: seem that option1 and 2a, 2c are the right answer (compared to p = 2 result) 
            # option 1
            #m.addConstr(ztrans[1][i] >= z[1][i] - x0[i], "INPUTtransPOS_"+str(i))
            #m.addConstr(ztrans[1][i] >= -z[1][i] + x0[i], "INPUTtransNEG_"+str(i))
            
            # option 2a: same answer as option 1
            # note if we write , the result is different
            #zzz = m.addVar(vtype=grb.GRB.CONTINUOUS)
            #m.addConstr(zzz == z[1][i]-x0[i])
            #m.addConstr(ztrans[1][i] == grb.abs_(zzz), "INPUTtransABS_"+str(i))
            
            # option 2b: gives different sol as 2a and 2c, guess it's because abs_() has to take a variable,
            # and that's why 2a and 2c use additional variable zzz or temp
            # but now it gives Attribute error on "gurobipy.LinExpr", so can't use this anymore
            #m.addConstr(ztrans[1][i] == grb.abs_(z[1][i]-x0[i]), "INPUTtransABS_"+str(i))
            
            # option 2c: same answer as 2a
            m.addConstr(temp[i] == z[1][i]-x0[i])
            m.addConstr(ztrans[1][i] == grb.abs_(temp[i]), "INPUTtransABS_"+str(i))    
            
            # option 3: same answer as 2b
            #m.addConstr(ztrans[1][i] <= z[1][i] - x0[i], "INPUTtransPOS_"+str(i))
            #m.addConstr(ztrans[1][i] >= -z[1][i] + x0[i], "INPUTtransNEG_"+str(i))


        # L1 constraints
        m.addConstr(grb.quicksum(ztrans[1][i] for i in range(len(UBs[0]))) <= eps, "INPUT L1 norm")
            
    

    # another way to write quadratic constraints
    ###expr = grb.QuadExpr()
    ###expr.addTerms(np.ones(len(UBs[0])), z[1], z[1])
    ###m.addConstr(expr <= eps*eps)

    m.update()

    print("[L2][LP solver initialized] time_lp_init = {:.4f}".format(time.time() - start))
    # for middle layers, need to compute full bounds
    if compute_full_bounds:
        # compute upper bounds        
        # z_hat_{nlayer+1} is the logits (final output, or inputs for layer nlayer+1)
        ##for j in [pred_label,target_label]:
        for j in range(Ws[nlayer-1].shape[0]):
            m.setObjective(zh[nlayer+1][j], grb.GRB.MAXIMIZE)    
            # m.write('grbtest_LP_2layer_'+str(j)+'.lp')    
            start = time.time()
            m.optimize()
            UB[j] = m.objVal
            m.reset()
            print("[L2][upper bound solved] j = {}, time_lp_solve = {:.4f}".format(j, time.time() - start))
            
        # compute lower bounds        
        ##for j in [pred_label,target_label]:
        for j in range(Ws[nlayer-1].shape[0]):
            m.setObjective(zh[nlayer+1][j], grb.GRB.MINIMIZE)    
            # m.write('grbtest_LP_2layer_'+str(j)+'.lp')    
            start = time.time()
            m.optimize()
            LB[j] = m.objVal
            m.reset()
            print("[L2][lower bound solved] j = {}, time_lp_solve = {:.4f}".format(j, time.time() - start))
            
        bnd_gx0 = LB[target_label]-UB[pred_label]
    else: # use the g_x0 tricks if it's last layer call:
        if untargeted:
            bnd_gx0 = []
            start = time.time()
            for j in range(Ws[nlayer-1].shape[0]):
                if j != pred_label:
                    m.setObjective(zh[nlayer+1][pred_label]-zh[nlayer+1][j], grb.GRB.MINIMIZE)
                    m.optimize()
                    bnd_gx0.append(m.objVal)
                    # print("[L2][Solved untargeted] j = {}, value = {:.4f}".format(j, m.objVal))
                    m.reset()
        else:
            m.setObjective(zh[nlayer+1][pred_label]-zh[nlayer+1][target_label], grb.GRB.MINIMIZE)
            start = time.time()
            m.optimize()
            bnd_gx0 = m.objVal
            m.reset()
        print("[L2][g(x) bound solved] time_lp_solve = {:.4f}".format(time.time() - start))
   
    return UB, LB, bnd_gx0
Beispiel #13
0
    vy[i] = m.addVar(name="vy_" + str(i))
    abs_vx[i] = m.addVar(name="abs_vx_" + str(i))
    abs_vy[i] = m.addVar(name="abs_vy_" + str(i))

# define vs
m.addConstr(vx[0] == px[1] - px[0])
m.addConstr(vy[0] == py[1] - py[0])
m.addConstr(vx[1] == px[3] - px[2])
m.addConstr(vy[1] == py[3] - py[2])

# v0 v1 orthogonal
m.addConstr(vx[0] * vx[1] + vy[0] * vy[1] == 0)

# define abs x y
for i in range(2):
    m.addConstr(abs_vx[i] == gp.abs_(vx[i]))
    m.addConstr(abs_vy[i] == gp.abs_(vy[i]))

# v length
m.addConstr(abs_vx[0] + abs_vy[0] == 1)
m.addConstr(abs_vx[1] + abs_vy[1] == 1)

# # Set objective: maximize x
# m.setObjective(objective, GRB.MINIMIZE)

# First optimize() call will fail - need to set NonConvex to 2
try:
    m.params.NonConvex = 2
    m.optimize()
except gp.GurobiError:
    print("Optimize failed due to non-convexity")
Beispiel #14
0
def optimize_planning(
    timeline: List[str],
    workcenters: List[str],
    needs,
    wc_cost_reg: Dict[str, int],
    wc_cost_ot: Dict[str, int],
    wc_cost_we: Dict[str, int],
    inventory_carrying_cost: int,
    customer_orders: List[str],
    cycle_times,
    delay_cost: int,
) -> pd.DataFrame:
    # Split weekdays/weekends
    weekdays = []
    weekend = []
    for date in timeline:
        day = datetime.datetime.strptime(date, "%Y/%m/%d")
        if day.weekday() < 5:
            weekdays.append(date)
        else:
            weekend.append(date)

    # Initiate optimization model
    model = gurobipy.Model("Optimize production planning")

    # DEFINE VARIABLES
    # Quantity variable
    x_qty = model.addVars(
        timeline,
        customer_orders,
        workcenters,
        lb=0,
        vtype=gurobipy.GRB.INTEGER,
        name="plannedQty",
    )

    # Time variable
    x_time = model.addVars(
        timeline,
        customer_orders,
        workcenters,
        lb=0,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="plannedTime",
    )

    # Set the value of x_time
    model.addConstrs(
        ((x_time[(date, mo, wc)]
          == x_qty[(date, mo, wc)] * cycle_times[(mo, wc)] for date in timeline
          for mo in customer_orders for wc in workcenters)),
        name="x_time_constr",
    )

    # Qty to display
    quantity = model.addVars(timeline,
                             workcenters,
                             lb=0,
                             vtype=gurobipy.GRB.INTEGER,
                             name="qty")

    # Set the value of qty
    model.addConstrs(
        ((quantity[(date, wc)] == gurobipy.quicksum(x_qty[(date, mo, wc)]
                                                    for mo in customer_orders)
          for date in timeline for wc in workcenters)),
        name="wty_time_constr",
    )

    # Variable status of the line ( 0 = closed, 1 = opened)
    line_opening = model.addVars(timeline,
                                 workcenters,
                                 vtype=gurobipy.GRB.BINARY,
                                 name="Open status")

    # Load variables (hours) - regular and overtime
    reg_hours = model.addVars(
        timeline,
        workcenters,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="Regular hours",
    )

    ot_hours = model.addVars(
        timeline,
        workcenters,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="Overtime hours",
    )

    reg_hours_bis = model.addVars(
        timeline,
        workcenters,
        lb=7,
        ub=8,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="regHours",
    )
    ot_hours_bis = model.addVars(timeline,
                                 workcenters,
                                 lb=0,
                                 ub=4,
                                 vtype=gurobipy.GRB.CONTINUOUS,
                                 name="OTHours")

    # Set the value of reg and OT hours)
    model.addConstrs(
        (reg_hours[(date, wc)]
         == reg_hours_bis[(date, wc)] * line_opening[(date, wc)]
         for date in timeline for wc in workcenters),
        name="total_hours_constr",
    )

    model.addConstrs(
        (ot_hours[(date, wc)]
         == ot_hours_bis[(date, wc)] * line_opening[(date, wc)]
         for date in timeline for wc in workcenters),
        name="total_hours_constr",
    )

    # Variable total load (hours)
    total_hours = model.addVars(
        timeline,
        workcenters,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="Total hours",
    )

    # Set the value of total load (regular + overtime)
    model.addConstrs(
        (total_hours[(date, wc)]
         == (reg_hours[(date, wc)] + ot_hours[(date, wc)]) for date in timeline
         for wc in workcenters),
        name="Link total hours - reg/ot hours",
    )

    # Set total hours of production in link with the time variable
    model.addConstrs(
        ((total_hours[(date, wc)] == gurobipy.quicksum(
            x_time[(date, mo, wc)] for mo in customer_orders)
          for date in timeline for wc in workcenters)),
        name="total_hours_constr",
    )

    # Variable cost
    labor_cost = model.addVars(timeline,
                               workcenters,
                               lb=0,
                               vtype=gurobipy.GRB.CONTINUOUS,
                               name="Labor cost")

    # Set the value of cost (hours * hourly cost)
    model.addConstrs(
        (labor_cost[(date, wc)] == reg_hours[(date, wc)] * wc_cost_reg[wc] +
         ot_hours[(date, wc)] * wc_cost_ot[wc] for date in weekdays
         for wc in workcenters),
        name="Link labor cost - working hours - wd",
    )

    model.addConstrs(
        (labor_cost[(date, wc)] == total_hours[(date, wc)] * wc_cost_we[wc]
         for date in weekend for wc in workcenters),
        name="Link labor cost - working hours - we",
    )

    # Variable gap early/late production
    gap_prod = model.addVars(
        timeline,
        customer_orders,
        lb=-10000,
        ub=10000,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="gapProd",
    )
    abs_gap_prod = model.addVars(
        timeline,
        customer_orders,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="absGapProd",
    )
    # Set the value of gap for early production
    for l in range(len(timeline)):
        model.addConstrs(
            (gap_prod[(timeline[l], mo)]
             == gurobipy.quicksum(x_qty[(date, mo, wc)]
                                  for date in timeline[:l + 1]
                                  for wc in workcenters) -
             (gurobipy.quicksum(needs[(date, mo)]
                                for date in timeline[:l + 1]))
             for mo in customer_orders),
            name="gap_prod",
        )

    # Set the value of ABS(gap for early production)
    model.addConstrs(
        ((abs_gap_prod[(date, mo)] == gurobipy.abs_(gap_prod[(date, mo)]))
         for date in timeline for mo in customer_orders),
        name="abs gap prod",
    )

    # Create variable "early production" and "inventory costs"
    early_prod = model.addVars(
        timeline,
        customer_orders,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="early prod",
    )
    inventory_costs = model.addVars(
        timeline,
        customer_orders,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="inventory costs",
    )

    # Set the value of early production
    model.addConstrs(
        (early_prod[(date, m)]
         == (gap_prod[(date, m)] + abs_gap_prod[(date, m)]) / 2
         for date in timeline for m in customer_orders),
        name="early prod",
    )

    # Set the value of inventory costs
    model.addConstrs(
        ((inventory_costs[(date, m)]
          == early_prod[(date, m)] * inventory_carrying_cost)
         for date in timeline for m in customer_orders),
        name="inventory costs",
    )

    # Create variable "late production" and "delay costs"
    late_prod = model.addVars(
        timeline,
        customer_orders,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="late prod",
    )
    delay_costs = model.addVars(
        timeline,
        customer_orders,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="inventory costs",
    )

    # Set the value of late production
    model.addConstrs(
        (late_prod[(date, m)]
         == (abs_gap_prod[(date, m)] - gap_prod[(date, m)]) / 2
         for date in timeline for m in customer_orders),
        name="late prod",
    )

    # Set the value of delay costs
    model.addConstrs(
        ((delay_costs[(date, m)] == late_prod[(date, m)] * delay_cost)
         for date in timeline for m in customer_orders),
        name="delay costs",
    )

    # CONSTRAINT
    # Constraint: Total hours of production = required production time
    model.addConstr(
        (gurobipy.quicksum(x_qty[(date, mo, wc)] for date in timeline
                           for mo in customer_orders for wc in workcenters)
         == (gurobipy.quicksum(needs[(date, mo)] for date in timeline
                               for mo in customer_orders))),
        name="total_req",
    )

    # DEFINE MODEL
    # Objective : minimize a function
    model.ModelSense = gurobipy.GRB.MINIMIZE

    # Function to minimize
    objective = 0
    objective += gurobipy.quicksum(labor_cost[(date, wc)] for date in timeline
                                   for wc in workcenters)
    objective += gurobipy.quicksum(inventory_costs[(date, mo)]
                                   for date in timeline
                                   for mo in customer_orders)
    objective += gurobipy.quicksum(delay_costs[(date, mo)] for date in timeline
                                   for mo in customer_orders)

    # SOLVE MODEL
    model.setObjective(objective)
    model.optimize()

    sol = pd.DataFrame(data={"Solution": model.X}, index=model.VarName)

    print("Total cost = $" + str(model.ObjVal))

    # model.write("Planning_optimization.lp")
    # file = open("Planning_optimization.lp", 'r')
    # print(file.read())
    # file.close()

    return sol
m.addConstr(bias17 == z117 - 0.5, "bias17")
m.addConstr(bias18 == z118 - 0.5, "bias18")
m.addConstr(bias19 == z119 - 0.5, "bias19")
m.addConstr(bias20 == z120 - 0.5, "bias20")
m.addConstr(bias21 == z121 - 0.5, "bias21")
m.addConstr(bias22 == z122 - 0.5, "bias22")
m.addConstr(bias23 == z123 - 0.5, "bias23")
m.addConstr(bias24 == z124 - 0.5, "bias24")
m.addConstr(bias25 == z125 - 0.5, "bias25")
m.addConstr(bias26 == z126 - 0.5, "bias26")
m.addConstr(bias27 == z127 - 0.5, "bias27")
m.addConstr(bias28 == z128 - 0.5, "bias28")
m.addConstr(bias29 == z129 - 0.5, "bias29")
m.addConstr(bias30 == z130 - 0.5, "bias30")
m.addConstr(bias31 == z131 - 0.5, "bias31")
m.addConstr(bias_abs0 == abs_(bias0), "bias_abs0")
m.addConstr(bias_abs1 == abs_(bias1), "bias_abs1")
m.addConstr(bias_abs2 == abs_(bias2), "bias_abs2")
m.addConstr(bias_abs3 == abs_(bias3), "bias_abs3")
m.addConstr(bias_abs4 == abs_(bias4), "bias_abs4")
m.addConstr(bias_abs5 == abs_(bias5), "bias_abs5")
m.addConstr(bias_abs6 == abs_(bias6), "bias_abs6")
m.addConstr(bias_abs7 == abs_(bias7), "bias_abs7")
m.addConstr(bias_abs8 == abs_(bias8), "bias_abs8")
m.addConstr(bias_abs9 == abs_(bias9), "bias_abs9")
m.addConstr(bias_abs10 == abs_(bias10), "bias_abs10")
m.addConstr(bias_abs11 == abs_(bias11), "bias_abs11")
m.addConstr(bias_abs12 == abs_(bias12), "bias_abs12")
m.addConstr(bias_abs13 == abs_(bias13), "bias_abs13")
m.addConstr(bias_abs14 == abs_(bias14), "bias_abs14")
m.addConstr(bias_abs15 == abs_(bias15), "bias_abs15")
Beispiel #16
0
    a[i] = m.addVar(name="a_" + str(i), ub=360)
    k[i] = m.addVar(name="k_" + str(i), vtype=GRB.BINARY)
    diff[i] = m.addVar(name="diff_" + str(i), lb=-360, ub=360)
    abs_diff[i] = m.addVar(name="abs_diff_" + str(i), ub=360)
kp = m.addVar(name="kp", vtype=GRB.BINARY)

m.addConstr(a[5] + kp * 360 - a[3], GRB.EQUAL, 180)

for face_id in range(2):
    offset = face_id * 4
    for i in range(4):
        m.addConstr(diff[i + offset] == a[(i + 1) % 4 + offset] +
                    k[i + offset] * 360 - a[i + offset] - 90)

for i in range(8):
    m.addConstr(abs_diff[i] == gp.abs_(diff[i]))

objective = gp.LinExpr()
for i in range(8):
    objective += abs_diff[i]

# Set objective: maximize x
m.setObjective(objective, GRB.MINIMIZE)

# First optimize() call will fail - need to set NonConvex to 2
try:
    m.write("m.lp")
    # m.feasRelaxS(0, True, False, True)
    # m.write("feasopt1.lp")
    m.optimize()
except gp.GurobiError:
def optimize_planning(
    timeline: List[str],
    workcenters: List[str],
    needs: Dict[str, int],
    wc_cost_reg: Dict[str, int],
    wc_cost_ot: Dict[str, int],
    wc_cost_we: Dict[str, int],
    inventory_cost: int,
    delay_cost: int,
) -> pd.DataFrame:

    # Weekdays / Weekends
    weekdays = []
    weekend = []
    for i in timeline:
        date = datetime.datetime.strptime(i, "%Y/%m/%d")
        if date.weekday() < 5:
            weekdays.append(i)
        else:
            weekend.append(i)

    # Initiate optimization model
    model = gurobipy.Model("Optimize production planning")

    # DEFINE VARIABLES
    # Load variables (hours) - regular and overtime
    reg_hours = model.addVars(
        timeline,
        workcenters,
        lb=7,
        ub=8,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="Regular hours",
    )
    ot_hours = model.addVars(
        timeline,
        workcenters,
        lb=0,
        ub=4,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="OT hours",
    )
    # Status of the line ( 0 = closed, 1 = opened)
    line_opening = model.addVars(timeline,
                                 workcenters,
                                 vtype=gurobipy.GRB.BINARY,
                                 name="Open")
    # Variable total load (hours)
    total_hours = model.addVars(
        timeline,
        workcenters,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="Total hours",
    )
    # Variable cost
    cost = model.addVars(timeline,
                         workcenters,
                         vtype=gurobipy.GRB.CONTINUOUS,
                         name="Cost")

    # Set the value of cost (hours * hourly cost)
    model.addConstrs(
        (cost[(date, wc)]
         == reg_hours[(date, wc)] * wc_cost_reg[wc] * line_opening[(date, wc)]
         + ot_hours[(date, wc)] * wc_cost_ot[wc] * line_opening[(date, wc)]
         for date in weekdays for wc in workcenters),
        name="Cost weekdays",
    )
    model.addConstrs(
        (cost[(date, wc)] == (reg_hours[(date, wc)] + ot_hours[(date, wc)]) *
         wc_cost_we[wc] * line_opening[(date, wc)] for date in weekend
         for wc in workcenters),
        name="Cost weekend",
    )

    # Set the value of total load (regular + overtime)
    model.addConstrs(
        (total_hours[(date, wc)]
         == (reg_hours[(date, wc)] + ot_hours[(date, wc)]) *
         line_opening[(date, wc)] for date in timeline for wc in workcenters),
        name="Total hours = reg + OT",
    )

    # Constraint: Total hours of production = required production time
    model.addConstr(
        (gurobipy.quicksum(total_hours[(date, wc)] for date in timeline
                           for wc in workcenters) == gurobipy.quicksum(
                               needs[date] for date in timeline)),
        name="Total hours = need",
    )

    # Create variable "early production", "late production" and "inventory costs"
    # Gap early/late production
    gap_prod = model.addVars(
        timeline,
        lb=-10000,
        ub=10000,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="gapProd",
    )
    abs_gap_prod = model.addVars(
        timeline,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="absGapProd",
    )

    # Set the value of gap production vs need
    model.addConstrs(
        ((gap_prod[timeline[k]]
          == gurobipy.quicksum(total_hours[(date, wc)]
                               for date in timeline[:k + 1]
                               for wc in workcenters) -
          (gurobipy.quicksum(needs[date] for date in timeline[:k + 1])))
         for k in range(len(timeline))),
        name="gap prod",
    )

    model.addConstrs(
        ((abs_gap_prod[date] == gurobipy.abs_(gap_prod[date]))
         for date in timeline),
        name="abs gap prod",
    )

    # Create variable "early production" and "inventory costs"
    early_prod = model.addVars(
        timeline,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="early prod",
    )
    inventory_costs = model.addVars(
        timeline,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="inventory costs",
    )

    # Set the value of early production
    model.addConstrs(
        ((early_prod[date] == (gap_prod[date] + abs_gap_prod[date]) / 2)
         for date in timeline),
        name="early prod",
    )

    # Set the value of inventory costs
    model.addConstrs(
        ((inventory_costs[date] == early_prod[date] * inventory_cost)
         for date in timeline),
        name="inventory costs",
    )

    # Create variable "late production" and "delay costs"
    late_prod = model.addVars(
        timeline,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="early prod",
    )
    delay_costs = model.addVars(
        timeline,
        vtype=gurobipy.GRB.CONTINUOUS,
        name="inventory costs",
    )

    # Set the value of late production
    model.addConstrs(
        ((late_prod[date] == (abs_gap_prod[date] - gap_prod[date]) / 2)
         for date in timeline),
        name="late prod",
    )

    # Set the value of delay costs
    model.addConstrs(
        ((delay_costs[date] == late_prod[date] * delay_cost)
         for date in timeline),
        name="delay costs",
    )

    # DEFINE MODEL
    # Objective : minimize a function
    model.ModelSense = gurobipy.GRB.MINIMIZE
    # Function to minimize
    optimization_var = (gurobipy.quicksum(cost[(date, wc)] for date in timeline
                                          for wc in workcenters) +
                        gurobipy.quicksum(inventory_costs[date]
                                          for date in timeline) +
                        gurobipy.quicksum(delay_costs[date]
                                          for date in timeline))

    objective = 0
    objective += optimization_var

    # SOLVE MODEL
    model.setObjective(objective)
    model.optimize()

    sol = pd.DataFrame(data={"Solution": model.X}, index=model.VarName)
    sol = sol.filter(like="Total hours", axis=0)

    print("Total cost = $" + str(model.ObjVal))

    # FORMAT THE RESULT
    planning = sol
    planning["Date"] = list(planning.index.values)
    planning[["Date", "Line"]] = planning["Date"].str.split(",", expand=True)
    planning["Date"] = planning["Date"].str.split("[").str[1]
    planning["Line"] = planning["Line"].str.split("]").str[0]
    planning = planning.pivot(index="Line", columns="Date", values="Solution")

    return planning
Beispiel #18
0
    def createConstraints(self):
        for i in range(len(self.vert_locs)):
            self.m.addConstr(self.diff_x[i] == self.px[i] -
                             self.vert_locs[i][0])
            self.m.addConstr(self.diff_y[i] == self.py[i] -
                             self.vert_locs[i][1])
        for i in range(len(self.shape_verts)):
            for vid in self.shape_verts[i]:
                # self.m.addConstr(self.diff_x[vid] - self.diff_x.sum(vid_1, '*') / len(self.shape_verts[i]) == self.std_diff_x[vid] for vid_1 in self.shape_verts[i])
                self.m.addConstr(
                    self.diff_x.sum(vid_1, '*') == 0
                    for vid_1 in self.shape_verts[i])
                self.m.addConstr(
                    self.abs_std_diff_x[vid] == gp.abs_(self.std_diff_x[vid]))
                self.m.addConstr(
                    self.diff_y[vid] - self.diff_y.sum(vid_1, '*') /
                    len(self.shape_verts[i]) == self.std_diff_y[vid]
                    for vid_1 in self.shape_verts[i])
                self.m.addConstr(
                    self.abs_std_diff_y[vid] == gp.abs_(self.std_diff_y[vid]))
        for i in range(len(pair_rels)):
            p_rel = pair_rels[i]
            segs = [[p_rel[0], p_rel[1]], [p_rel[2], p_rel[3]]]
            for se in range(2):
                # (x, y) -> (x, y)
                if p_rel[4] == 0:
                    self.m.addConstr(self.px[segs[0][se]] -
                                     self.px[segs[1][se]] == self.ds_x[i])
                    self.m.addConstr(self.py[segs[0][se]] -
                                     self.py[segs[1][se]] == self.ds_y[i])
                # (x, y) -> (-y, x)
                elif p_rel[4] == 1:
                    self.m.addConstr(-self.py[segs[0][se]] -
                                     self.px[segs[1][se]] == self.ds_x[i])
                    self.m.addConstr(self.px[segs[0][se]] -
                                     self.py[segs[1][se]] == self.ds_y[i])
                # (x, y) -> (y, -x)
                elif p_rel[4] == 2:
                    self.m.addConstr(self.py[segs[0][se]] -
                                     self.px[segs[1][se]] == self.ds_x[i])
                    self.m.addConstr(-self.px[segs[0][se]] -
                                     self.py[segs[1][se]] == self.ds_y[i])
                # (x, y) -> (x, y)
                elif p_rel[4] == 3:
                    self.m.addConstr(-self.px[segs[0][se]] -
                                     self.px[segs[1][se]] == self.ds_x[i])
                    self.m.addConstr(-self.py[segs[0][se]] -
                                     self.py[segs[1][se]] == self.ds_y[i])

        def addObjective(self):
            self.objective = gp.LinExpr()
            for i in range(self.vert_locs):
                self.objective += self.abs_std_diff_x[i]
                self.objective += self.abs_std_diff_y[i]

            self.m.setObjective(self.objective, GRB.MINIMIZE)

        def solve(self):
            try:
                # m.params.NonConvex = 2
                m.write("opt_verts.lp")
                m.feasRelaxS(0, True, False, True)
                m.write("opt_verts_relaxed.lp")
                m.optimize()
            except gp.GurobiError:
                print("Optimize failed")

            #
            f = open("opt_pts.txt", "w")
            for i in range(8):
                print("x_", i, ": ", px[i].x)
                print("y_", i, ": ", py[i].x)
                f.write(str(px[i].x) + " " + str(py[i].x) + "\n")
            f.close()

            for v in m.getVars():
                print('%s %g' % (v.varName, v.x))
Beispiel #19
0
如果目标函数带系数可以创建矩阵变量x = addMVars(4) 对系数列表 a = [1, 2, 3, 4]作矩阵计算 a@x
但比较坑的是gurobi中系数列表必须为numpy.array, 并且约束条件a[0] == x[0]是没办法写进addConstr()的,
不支持矩阵决策变量。
'''

# 创建模型
m = gp.Model("ex1.2")

# 创建变量
x = m.addVars(4, lb=-GRB.INFINITY, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS)
a = m.addVars(4, lb=0, ub=GRB.INFINITY, vtype=GRB.CONTINUOUS)

# 设置目标函数
m.setObjective(a[0] + 2 * a[1] + 3 * a[2] + 4 * a[3], GRB.MINIMIZE)

# 设置约束
m.addConstr(x[0] - x[1] - x[2] + x[3] == 0, 'c0')
m.addConstr(x[0] - x[1] + x[2] - 3 * x[3] == 1, 'c1')
m.addConstr(x[0] - x[1] - 2 * x[2] + 3 * x[3] == -0.5, 'c2')

# 绝对值约束
m.addConstrs(((a[i] == gp.abs_(x[i])) for i in range(4)))

# 模型求解
m.optimize()

# 输出结果
print('Obj: %g' % m.objVal)
for v in m.getVars():
    print('%s %g' % (v.varName, v.x))
Beispiel #20
0
    def calculate_trajectory(self, x0, t_elapsed):
        """
        Uses Gurobi to calculate optimal trajectory points (self.xstar) and 
        control inputs (self.ustar)

        """

        # Options
        Nin = 6  # number of sides in inner-ellipse polygon approx
        Nout = 15  # number of sides in outer-ellipse polygon approx

        initial_state = x0.reshape(6)
        goal_state = np.zeros(6)
        n = self.mean_motion
        mc = self.mass_chaser

        # Shorten the number of initial time steps (self.tau0) based on the amount of time elapsed
        tau = int(max(10, np.round(self.tau0 - t_elapsed / self.dt_plan)))
        print("time elapsed = ", t_elapsed)

        # Set Ranges
        smax = 15000  # arbitrary (included bounds to speed up solver)
        vmax = 10  # [m/s] max velocity
        Fmax = 2  # [N] max force

        # Initialize states
        sx = []
        sy = []
        sz = []
        vx = []
        vy = []
        vz = []
        Fx = []
        Fy = []
        Fz = []
        snorm = []
        sxabs = []
        syabs = []
        vnorm = []
        vxabs = []
        vyabs = []
        zeta = []

        m = gp.Model("QPTraj")

        # Define variables at each of the tau timesteps
        for t in range(tau):
            sx.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-smax,
                         ub=smax,
                         name="sx" + str(t)))
            vx.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-vmax,
                         ub=vmax,
                         name="vx" + str(t)))
            Fx.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-Fmax,
                         ub=Fmax,
                         name="Fx" + str(t)))
            sy.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-smax,
                         ub=smax,
                         name="sy" + str(t)))
            vy.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-vmax,
                         ub=vmax,
                         name="vy" + str(t)))
            Fy.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-Fmax,
                         ub=Fmax,
                         name="Fy" + str(t)))
            sz.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-smax,
                         ub=smax,
                         name="sz" + str(t)))
            vz.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-vmax,
                         ub=vmax,
                         name="vz" + str(t)))
            Fz.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=-Fmax,
                         ub=Fmax,
                         name="Fz" + str(t)))
            snorm.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=smax,
                         name="snorm" + str(t)))
            sxabs.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=smax,
                         name="sxabs" + str(t)))
            syabs.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=smax,
                         name="syabs" + str(t)))
            vnorm.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=vmax,
                         name="vnorm" + str(t)))
            vxabs.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=vmax,
                         name="vxabs" + str(t)))
            vyabs.append(
                m.addVar(vtype=GRB.CONTINUOUS,
                         lb=0,
                         ub=vmax,
                         name="vyabs" + str(t)))

        for p in range(Nin):
            zeta.append(m.addVar(vtype=GRB.BINARY, name="zeta" + str(p)))

        m.update()

        # Set Initial Conditions
        m.addConstr(sx[0] == initial_state[0], "sx0")
        m.addConstr(sy[0] == initial_state[1], "sy0")
        m.addConstr(sz[0] == initial_state[2], "sz0")
        m.addConstr(vx[0] == initial_state[3], "vx0")
        m.addConstr(vy[0] == initial_state[4], "vy0")
        m.addConstr(vz[0] == initial_state[5], "vz0")

        # Specify Terminal Set
        if self.f_goal_set == 0:  # origin
            m.addConstr(sx[-1] == goal_state[0], "sxf")
            m.addConstr(sy[-1] == goal_state[1], "syf")
            m.addConstr(sz[-1] == goal_state[2], "szf")
            m.addConstr(vx[-1] == goal_state[3], "vxf")
            m.addConstr(vy[-1] == goal_state[4], "vyf")
            m.addConstr(vz[-1] == goal_state[5], "vzf")
        elif self.f_goal_set == 1:  # stationary point or periodic line
            m.addConstr(sx[-1] == goal_state[0], "sxf")
            m.addConstr(vx[-1] == goal_state[3], "vxf")
            m.addConstr(vy[-1] == goal_state[4], "vyf")
        elif self.f_goal_set == 2:  # ellipse
            m.addConstr(vy[-1] + 2 * n * sx[-1] == 0, "ellipse1")
            m.addConstr(sy[-1] - (2 / n) * vx[-1] == 0, "ellipse2")

        # Set dynamic speed limit
        for t in range(tau):
            # Define the norms:
            m.addConstr(sxabs[t] == gp.abs_(sx[t]))
            m.addConstr(syabs[t] == gp.abs_(sy[t]))
            m.addConstr(snorm[t] == gp.max_(sxabs[t], syabs[t]),
                        "snorm" + str(t))
            m.addConstr(vxabs[t] == gp.abs_(vx[t]))
            m.addConstr(vyabs[t] == gp.abs_(vy[t]))
            m.addConstr(vnorm[t] == gp.max_(vxabs[t], vyabs[t]),
                        "vnorm" + str(t))

            # Speed limit constraint:
            m.addConstr(vnorm[t] <= self.kappa_speed * snorm[t])

        # Collision Avoidance Constraint
        if self.f_collision_avoidance:
            for t in range(tau):
                m.addConstr(snorm[t] >= self.collision_dist)
            if initial_state[0] < self.collision_dist or initial_state[
                    1] < self.collision_dist:
                print(
                    "\nERROR: Initial position is too close! Collision constraint violated!\n"
                )

        # # Final point within [1km-5km] of target
        # m.addConstr( snorm[-1] <= 2000 )
        # m.addConstr( snorm[-1] >= 1000 )

        # Terminal constraint: inner polygonal approx on outer ellipse bound
        Nout = Nout + 1
        aout = self.semiminor_out
        bout = self.semiminor_out * 2
        theta = np.linspace(0, 2 * np.pi, Nout)
        for j in range(0, Nout - 1):
            x0 = aout * np.cos(theta[j])
            y0 = bout * np.sin(theta[j])
            x1 = aout * np.cos(theta[j + 1])
            y1 = bout * np.sin(theta[j + 1])
            alphax = y0 - y1
            alphay = x1 - x0
            gamma = alphay * y1 + alphax * x1
            m.addConstr(alphax * sx[-1] + alphay * sy[-1] >= gamma,
                        "OPA" + str(j))

        # Terminal constraint: outer polygonal approx on inner ellipse bound
        if self.f_collision_avoidance:
            a_in = self.semiminor_in
            b_in = self.semiminor_in * 2
            theta = np.linspace(0, 2 * np.pi, Nin + 1)
            big_M = 100000
            for j in range(0, Nin):
                x0 = a_in * np.cos(theta[j])
                y0 = b_in * np.sin(theta[j])
                c1 = (2 * x0 / (a_in**2))
                c2 = (2 * y0 / (b_in**2))
                cmag = np.sqrt(c1**2 + c2**2)
                c1 = c1 / cmag
                c2 = c2 / cmag
                m.addConstr(
                    c1 * sx[-1] + c2 * sy[-1] - c1 * x0 - c2 * y0 -
                    big_M * zeta[j] >= -big_M, "IPA" + str(j))
            m.addConstr(sum(zeta[p] for p in range(Nin)) >= 0.5)

        # Set Dynamics
        for t in range(tau - 1):
            # Dynamics
            m.addConstr(sx[t + 1] == sx[t] + vx[t] * self.dt_plan,
                        "Dsx_" + str(t))
            m.addConstr(sy[t + 1] == sy[t] + vy[t] * self.dt_plan,
                        "Dsy_" + str(t))
            m.addConstr(sz[t + 1] == sz[t] + vz[t] * self.dt_plan,
                        "Dsz_" + str(t))
            m.addConstr(
                vx[t + 1] == vx[t] + sx[t] * 3 * n**2 * self.dt_plan +
                vy[t] * 2 * n * self.dt_plan + Fx[t] * (1 / mc) * self.dt_plan,
                "Dvx_" + str(t))
            m.addConstr(
                vy[t + 1] == vy[t] - vx[t] * 2 * n * self.dt_plan + Fy[t] *
                (1 / mc) * self.dt_plan, "Dvy_" + str(t))
            m.addConstr(
                vz[t + 1] == vz[t] + (-n**2) * sz[t] * self.dt_plan + Fz[t] *
                (1 / mc) * self.dt_plan, "Dvz_" + str(t))

        # Set Objective ( minimize: sum(Fx^2 + Fy^2) )
        obj = Fx[0] * Fx[0] + Fy[0] * Fy[0] + Fz[0] * Fz[0]
        for t in range(0, tau):
            obj = obj + Fx[t] * Fx[t] + Fy[t] * Fy[t] + Fz[t] * Fz[t]

        m.setObjective(obj, GRB.MINIMIZE)
        m.setParam('OutputFlag', False)

        # Optimize and report on results
        m.optimize()

        # Save desired trajectory
        self.xstar = np.zeros([6, tau])
        self.ustar = np.zeros([3, tau])
        self.snorm = np.zeros([tau])
        self.vnorm = np.zeros([tau])

        for t in range(tau):  # TODO: find quicker way to do this
            self.xstar[0, t] = m.getVarByName("sx" + str(t)).x
            self.xstar[1, t] = m.getVarByName("sy" + str(t)).x
            self.xstar[3, t] = m.getVarByName("vx" + str(t)).x
            self.xstar[4, t] = m.getVarByName("vy" + str(t)).x
            self.ustar[0, t] = m.getVarByName("Fx" + str(t)).x
            self.ustar[1, t] = m.getVarByName("Fy" + str(t)).x
            self.ustar[2, t] = m.getVarByName("Fz" + str(t)).x
            self.snorm[t] = m.getVarByName("snorm" + str(t)).x
            self.vnorm[t] = m.getVarByName("vnorm" + str(t)).x