class Backup(object):
    """ Class object for normal-based backup network model.

    Parameters
    ----------
    nodes: set of nodes
    links: set of links
    capacity: capacities per link based based on random failures 
    mean: mean for failure random variable
    std: standard deviation for failure random variable
    invstd: inverse of Phi-normal distribution for (1-epsilon)

    
    Returns
    -------
    solution: set of capacity assigned per backup link. 
    
    """
    # Private model object
    __model = []
    
    # Private model variables
    __BackupCapacity = {}
    __bBackupLink = {}
    __ValidLink = {}
        
    # Private model parameters
    __links = []
    __nodes = []
    __capacity = []
    __mean = []
    __std = []
    __invstd = 1
    
    def __init__(self,nodes,links,capacity,mean,std,invstd):
        '''
        Constructor
        '''
        self.__links = links
        self.__nodes = nodes
        self.__capacity = capacity
        self.__mean = mean
        self.__std = std
        self.__invstd = invstd
        
        self.__loadModel()
                
    def __loadModel(self):
                
        # Create optimization model
        self.__model = Model('Backup')
    
        # Auxiliary variables for SOCP reformulation
        U = {}
        R = {}
      
        # Create variables
        for i,j in self.__links:
            self.__BackupCapacity[i,j] = self.__model.addVar(lb=0, obj=1, name='Backup_Capacity[%s,%s]' % (i, j))
        self.__model.update()
         
        for i,j in self.__links:
            for s,d in self.__links:
                self.__bBackupLink[i,j,s,d] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Link[%s,%s,%s,%s]' % (i, j, s, d))
        self.__model.update()
        
        for i,j in self.__links:
            U[i,j] = self.__model.addVar(obj=1,name='U[%s,%s]' % (i, j))
        self.__model.update()
        
        for i,j in self.__links:
            for s,d in self.__links:
                R[i,j,s,d] = self.__model.addVar(obj=1,name='R[%s,%s,%s,%s]' % (i,j,s,d))
        self.__model.update()
        
        self.__model.modelSense = GRB.MINIMIZE
        #m.setObjective(quicksum([fixedCosts[p]*open[p] for p in plants]))
        self.__model.setObjective(quicksum(self.__BackupCapacity[i,j] for i,j in self.__links))
        self.__model.update()
        
           
        #------------------------------------------------------------------------#
        #                    Constraints definition                              #
        #                                                                        #
        #                                                                        #
        #------------------------------------------------------------------------#
         
        # Link capacity constraints
        for i,j in self.__links:
            self.__model.addConstr(self.__BackupCapacity[i,j] >= quicksum(self.__mean[s,d]*self.__bBackupLink[i,j,s,d] for (s,d) in self.__links) + U[i,j]*self.__invstd,'[CONST]Link_Cap_%s_%s' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints
        for i,j in self.__links:
            self.__model.addConstr(quicksum(R[i,j,s,d]*R[i,j,s,d] for (s,d) in self.__links) <= U[i,j]*U[i,j],'[CONST]SCOP1[%s][%s]' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints    
        for i,j in self.__links:
            for s,d in self.__links:
                self.__model.addConstr(self.__std[s,d]*self.__bBackupLink[i,j,s,d] == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i, j,s,d))
        self.__model.update()
        
        for i in self.__nodes:
            for s,d in self.__links:
                # Flow conservation constraints
                if i == s:
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 1,'Flow1[%s,%s,%s,%s]' % (i,j,s, d))
                # Flow conservation constraints
                elif i == d:
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == -1,'Flow2[%s,%s,%s,%s]' % (i,j,s, d))
                # Flow conservation constraints
                else:    
                    self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - 
                                           quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 0,'Flow3[%s,%s,%s,%s]' % (i,j,s, d))
        self.__model.update()
                
        
    def optimize(self,MipGap, TimeLimit):
        
        self.__model.write('backup.lp')
        
        if MipGap != None:
            self.__model.params.timeLimit = TimeLimit
        if TimeLimit != None:
            self.__model.params.MIPGap = MipGap
         
        # Compute optimal solution
        self.__model.optimize()
        
        # Print solution
        if self.__model.status == GRB.Status.OPTIMAL:
            solution = self.__model.getAttr('x', self.__BackupCapacity)
            for i,j in self.__links:
                if solution[i,j] > 0:
                    print('%s -> %s: %g' % (i, j, solution[i,j]))
            
        else:
            print('Optimal value not found!\n')
            solution = []
            
        return solution;    
    
    def reset(self):
        '''
        Reset model solution
        '''
        self.__model.reset()
예제 #2
1
def get_mapping(PG, VG):
    vnodes, vhosts = multidict({n: len(VG.node[n]['host_ports']) for n in VG.nodes()})
    pnodes, phosts = multidict({n: len(PG.node[n]['host_ports']) for n in PG.nodes()})
    parcs, pcapacity = multidict({(m, n): PG.edge[m][n]['weight'] for (m, n) in PG.edges()})
    parcs = tuplelist(parcs)

    varcs, vcapacity = multidict({(m, n): VG.edge[m][n]['weight'] for (m, n) in VG.edges()})
    varcs = tuplelist(varcs)

    m = Model('mapping')

    # Create variables
    node_mapping = {}
    for i in vnodes:
        for j in pnodes:
            node_mapping[i, j] = m.addVar(vtype=GRB.BINARY, name="x_%s_%s" % (i, j))


    edge_mapping = {}
    for i in vnodes:
        for p in VG.neighbors(i):
            for (j, q) in parcs:
                edge_mapping[i, p, j, q] = m.addVar(vtype=GRB.BINARY, name="y_%s_%s_%s_%s" % (i, p, j, q))

    m.update()

    # Arc capacity constraints
    for i in vnodes:
        m.addConstr(quicksum(node_mapping[i, j] for j in pnodes) == 1, 'node_%s' % i)

    for i in vnodes:
        for p in VG.neighbors(i):
            for (j, q) in parcs:
                m.addConstr(edge_mapping[i, p, j, q] <= ( node_mapping[i, j] + node_mapping[p, q] )/2, 'edge_%s_%s_%s_%s' % (i, p, j, q))

    for (j, q) in parcs:
        m.addConstr(quicksum(edge_mapping[i, p, j, q] + edge_mapping[p, i, j, q]for (i, p) in varcs) <= pcapacity[j, q], 'pcap_%s_%s' % (j, q))

    for (i, p) in varcs:
        m.addConstr(quicksum(edge_mapping[i, p, j, q] + edge_mapping[p, i, j, q] for (j, q) in parcs) >= vcapacity[i, p], 'vcap_%s_%s' % (i, p))

    for j in pnodes:
        m.addConstr(quicksum(node_mapping[i, j] * vhosts[i] for i in vnodes) <= phosts[j], 'phosts_%s' % j)
    for i in vnodes:
        m.addConstr(quicksum(node_mapping[i, j] * phosts[j] for j in pnodes) >= vhosts[i], 'vhosts_%s' % i)
    # Compute optimal solution
    m.optimize()

    # Print solution
    if m.status == GRB.status.OPTIMAL:
        mapping = {}
        mapping2 = {}
        portlist = {}

        for n in PG:
            if 'host_ports' in PG.node[n]:
                portlist[n] = PG.node[n]['host_ports']

        solution = m.getAttr('x', edge_mapping)
        for h in solution:
            if solution[h] == 1.0:
                vid1, vid2, pid1, pid2 = h
                vport1, vport2 = list(VG.node[vid1]['links'][vid2])[0]

                if (vid1, pid1) not in mapping:
                    mapping[(vid1, pid1)] =[vid1, pid1]
                if (pid1, vid1) not in mapping2:
                    mapping2[(pid1, vid1)] =[pid1, vid1]
                (pport1, pport2) = PG.node[pid1]['links'][pid2].pop()
                # print vid1, vid2, pid1, pid2, pport1, pport2
                if pid1 != pid2:
                    PG.node[pid2]['links'][pid1].remove((pport2, pport1))
                mapping[(vid1, pid1)].append(vport1)
                mapping[(vid1, pid1)].append(pport1)
                mapping2[(pid1, vid1)].append(pport1)
                mapping2[(pid1, vid1)].append(vport1)

                if (vid2, pid2) not in mapping:
                    mapping[(vid2, pid2)] =[vid2, pid2]
                if (pid2, vid2) not in mapping2:
                    mapping2[(pid2, vid2)] =[pid2, vid2]
                mapping[(vid2, pid2)].append(vport2)
                mapping[(vid2, pid2)].append(pport2)
                mapping2[(pid2, vid2)].append(pport2)
                mapping2[(pid2, vid2)].append(vport2)

        solution2 = m.getAttr('x', node_mapping)
        print [h for h in solution2 if solution2[h] == 1.0]
        for h in solution2:
            if solution2[h] == 1.0:
                vid, pid = h
                if len(VG.node[vid]['host_ports']) == 0:
                    continue

                for vport in VG.node[vid]['host_ports']:
                    pport = portlist[pid].pop()
                    mapping[(vid, pid)].append(vport)
                    mapping[(vid, pid)].append(pport)
                    mapping2[(pid, vid)].append(pport)
                    mapping2[(pid, vid)].append(vport)

    return mapping, mapping2


def main():
    args = parse_args()

    VG = gen_graph(args.target_topology)
    if not networkx.is_connected(VG):
        print 'Target topology is not connected'
        sys.exit(1)

    PG = gen_graph(args.host_topology, int_idx=True)

    mapping, mapping2 = get_mapping(PG, VG)

    f = open(args.output, "w")
    print >>f, "P2Vmap"
    for id in mapping2:
        for id2 in mapping2[id]:
            print >>f, id2,
        print>>f, "65535 65535"
    print >>f, "V2Pmap"
    for id in mapping:
        for id2 in mapping[id]:
            print >>f, id2,
        print>>f, "65535 65535"


if __name__ == "__main__":
    main()
예제 #3
0
    def retrieve_values(lp_problem: LpProblem, lp_variables: List[LpVariable],
                        model: gurobipy.Model) -> None:
        """ Extract the value of variables from the gurobi model and set them into the Flipy objects

        Parameters
        ----------
        lp_problem:
            The Flipy object into which the variable values will be set
        lp_variables:
            A list of LpVariables of the problem
        model:
            The gurobi model to grab the variable values from
        """
        try:
            var_name_to_values = dict(
                zip(model.getAttr(gurobipy.GRB.Attr.VarName, model.getVars()),
                    model.getAttr(gurobipy.GRB.Attr.X, model.getVars())))
            for var in lp_variables:
                var.set_value(var_name_to_values[var.name])
            for constraint in lp_problem.lp_constraints.values():
                if constraint.slack:
                    constraint.slack_variable.set_value(
                        var_name_to_values[constraint.slack_variable.name])
        except (gurobipy.GurobiError, AttributeError):
            pass
예제 #4
0
def parse_results(model: gp.Model) -> None:
    objVal = model.getObjective().getValue()
    print("Get optimal Obj: {}".format(objVal))
    print("Solution:")
    for name, val in zip(model.getAttr("varName"), model.getAttr("x")):
        print("Var {}: {}".format(name, val))

    for con, val in zip(model.getAttr("constrName"), model.getAttr("Pi")):
        print("Dual var of {}: {}".format(con, val))
예제 #5
0
def VRPSol(n, K, C, Ps, Ds, d, F, TimeLimit):
    m = Model()
    m.setParam(GRB.Param.TimeLimit, TimeLimit)
    # Create variables
    x = {}
    for i in Ps:
        for j in Ps:
            if i != j :
                x[i,j] = m.addVar(obj=F(Ps[i], Ps[j]), vtype=GRB.BINARY,
                                  name='x'+str(i)+'_'+str(j))
    # Create Miller variables (subtour elimination)
    u = {}
    for i in Ds:
        if i != d:
            u[i] = m.addVar(obj=0.0, vtype=GRB.CONTINUOUS,
                            lb=Ds[i], ub=C, name='u'+str(i))
            
    m.update()
    # Add outdegree constraint
    for j in Ps:
        if j != d:
            Ls = list(filter(lambda z: z!=j, Ps))
            m.addConstr(quicksum(x[i,j] for i in Ls) == 1)
    # Add indegree constraint
    for i in Ps:
        if i != d:
            Ls = filter(lambda z: z!=i, Ps)
            m.addConstr(quicksum(x[i,j] for j in Ls) == 1)
    # Number of vehicles
    Ls = list(filter(lambda z: z!=d, Ps))                   
    m.addConstr(quicksum(x[i,d] for i in Ls) == K)
    m.addConstr(quicksum(x[d,j] for j in Ls) == K)
    # Subtour elimination constraints
    for i in Ls:
        for j in Ls:
            if i != j:
                m.addConstr( u[i] - u[j] +C*x[i,j] <= C - Ds[j] )

    m.update()

    # Solve the model
    m.optimize()
    solution = m.getAttr('x', x)
    selected = [(i,j) for (i,j) in solution if solution[i,j] > 0.5]

    # Xs = [p for p in Ps.values()]
    # Ws = [w for w in Ds.values()]
    
    # for i,j in selected:
    #     DisegnaSegmento(Ps[i], Ps[j])
    # plt.scatter([i for i,j in Xs[1:]], [j for i,j in Xs[1:]], 
    #             s=Ws[1:], alpha=0.3, cmap='viridis')
    # plt.plot([Xs[0][0]], [Xs[0][1]], marker='s', color='red', alpha=0.5)
    # plt.axis('square')
    # plt.axis('off')
    
    return m.objVal, selected
예제 #6
0
def ilp_node_reachability(reachability_dic, max_delay=180, log_path=None):

    # List of nodes ids
    node_ids = sorted(list(reachability_dic.keys()))
    #node_ids = node_ids[:100]

    try:

        # Create a new model
        m = Model("region_centers")

        if log_path:
            m.Params.LogFile = '{}/region_centers_{}.log'.format(
                log_path, max_delay)

        # xi = 1, if vertex Vi is used as a region center and 0 otherwise
        x = m.addVars(node_ids, vtype=GRB.BINARY, name="x")

        # Ensures that every node in the road network graph is reachable
        # within 'max_delay' travel time by at least one region center
        # selected from the nodes in the graph.
        # To extract the region centers, we select from V all vertices
        # V[i] such that x[i] = 1.
        for d in node_ids:
            m.addConstr(
                quicksum(x[o] * is_reachable(reachability_dic, o, d, max_delay)
                         for o in node_ids) >= 1)

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

        # Solve
        m.optimize()

        region_centers = list()

        if m.status == GRB.Status.OPTIMAL:

            var_x = m.getAttr('x', x)
            for n in node_ids:
                if var_x[n] > 0.0001:
                    region_centers.append(n)

            return region_centers

        else:
            print('No solution')
            return None

    except GurobiError as e:
        print('Error code ' + str(e.errno) + ": " + str(e))

    except AttributeError as e:
        print('Encountered an attribute error:' + str(e))
예제 #7
0
def solve_model(model: gurobipy.Model):
    model.optimize()
    if model.getAttr("STATUS") != gurobipy.GRB.OPTIMAL:
        raise ValueError
    sol = model.getVars()
    out = ""
    value = 0
    for v in sol:
        out += f"{v.VarName} {v.X}\n"
        value += 1 if v.X >= 0.5 else 0

    return out, value
예제 #8
0
def BarycenterBipartite(images, G):
    """ Compute the Kantorovich Wasserstein Barycenter of any order using bipartite subgraphs"""
    K = len(images)
    n = len(images[0])

    # Build model
    m = Model()
    m.setParam(GRB.Param.Method, 2)
    m.setParam(GRB.Param.NumericFocus, 1)
    m.setParam(GRB.Param.OutputFlag, 0)
    m.setParam(GRB.Param.Crossover, 0)
    m.setAttr(GRB.Attr.ModelSense, 1)

    # Create variables
    Y = {}
    for v in range(n):
        Y[v] = m.addVar(obj=0)

    X = {}
    for e in G.edges():
        i, j = e
        for k in range(K):
            X[i, j, k] = m.addVar(obj=G.edges[i, j]['weight'])

    m.update()

    # In and out flow variable on the bipartite graph
    for v in range(n):
        Fs = [w for w in G.out_edges(v)]
        for k in range(K):
            m.addConstr(quicksum(X[i, j, k] for i, j in Fs) == images[k][v])

    for v in range(n):
        Bs = [w for w in G.in_edges(n + v)]
        for k in range(K):
            m.addConstr(quicksum(X[i, j, k] for i, j in Bs) == Y[v])

    m.addConstr(quicksum(Y[v] for v in Y) == 1.0)

    # Solve the model
    m.optimize()

    return m.getAttr(GRB.Attr.ObjVal), [Y[i].X for i in Y]
예제 #9
0
def gurobi_tsp(distance_matrix):
    """
    Solves tsp problem.
    :param distance_matrix: symmetric matrix of distances, where the i,j element is the distance between object i and j
    :return: matrix containing {0, 1}, 1 for each transition that is included in the tsp solution
    """
    n = len(distance_matrix)
    m = Model()
    m.setParam("OutputFlag", False)
    m.setParam("Threads", 1)

    # Create variables
    vars = {}
    for i in range(n):
        for j in range(i + 1):
            vars[i, j] = m.addVar(obj=0.0 if i == j else distance_matrix[i][j],
                                  vtype=GRB.BINARY,
                                  name="e" + str(i) + "_" + str(j))
            vars[j, i] = vars[i, j]
        m.update()

    # Add degree-2 constraint, and forbid loops
    for i in range(n):
        m.addConstr(quicksum(vars[i, j] for j in range(n)) == 2)
        vars[i, i].ub = 0
    m.update()

    # Optimize model
    m._vars = vars
    m.params.LazyConstraints = 1

    def subtour_fn(model, where):
        return subtourelim(n, model, where)

    m.optimize(subtour_fn)
    solution = m.getAttr("x", vars)
    selected = [(i, j) for i in range(n) for j in range(n)
                if solution[i, j] > 0.5]
    result = np.zeros_like(distance_matrix)
    for (i, j) in selected:
        result[i][j] = 1

    return result
예제 #10
0
def BarycenterL2(images, G):
    """ Compute the Kantorovich Wasserstein Barycenter of order 1 with L2 as ground distance """
    K = len(images)

    # Build model
    m = Model()
    m.setParam(GRB.Param.Method, 2)
    m.setParam(GRB.Param.NumericFocus, 1)
    m.setParam(GRB.Param.OutputFlag, 0)
    m.setParam(GRB.Param.Crossover, 0)
    m.setAttr(GRB.Attr.ModelSense, 1)

    # Create variables
    Y = {}
    for v in G.nodes():
        Y[v] = m.addVar(obj=0)

    X = {}
    for e in G.edges():
        i, j = e
        for k in range(K):
            X[i, j, k] = m.addVar(obj=G.edges[i, j]['weight'])

    m.update()

    # Flow variables
    for v in G.nodes():
        Fs = [w for w in G.out_edges(v)]
        Bs = [w for w in G.in_edges(v)]
        for k in range(K):
            m.addConstr(
                quicksum(X[i, j, k] for i, j in Fs) -
                quicksum(X[i, j, k] for i, j in Bs) == images[k][v] - Y[v])

    m.addConstr(quicksum(Y[v] for v in G.nodes()) == 1.0)

    m.update()

    # Solve the model
    m.optimize()

    return m.getAttr(GRB.Attr.ObjVal), [Y[i].X for i in Y]
예제 #11
0
def WassersteinDualSimplex(h1, h2, M):
    """ Find the Wasserstein distance using the dual simplex """
    n = len(h1)

    # Build model
    m = Model()
    m.setParam(GRB.Param.NumericFocus, 3)
    #m.setParam(GRB.Param.TimeLimit, 300)
    #m.setParam(GRB.Param.Presolve,    0)
    #m.setParam(GRB.Param.Threads,     1)
    #  Options are:
    #      -1=automatic, 0=primal simplex, 1=dual simplex, 2=barrier,
    #                    3=concurrent, 4=deterministic concurrent.
    #m.setParam(GRB.Param.Method, 0)
    print('1. Start building model')
    # Create variables
    x = {}
    P = set()
    D = []
    for i in range(n):
        if h1[i] > 0:
            x[i] = {}
            for j in range(n):
                if h2[j] > 0:
                    x[i][j] = m.addVar(ub=min(h1[i], h2[j]), obj=M[i][j])
                    D.append((i, j))
                    P.add(j)
    D = tuplelist(D)
    m.update()
    print('2. Add initial constraint sets')
    for i in x:
        m.addConstr(quicksum(x[i][j] for j in x[i]) <= h1[i])

    for j in P:
        m.addConstr(quicksum(x[i][j] for i, j in D.select('*', j)) >= h2[j])
    print('3. Start solution phase')
    # Solve the model
    m.optimize()

    return m.getAttr(GRB.Attr.ObjVal)
예제 #12
0
파일: rnd_matrix.py 프로젝트: stegua/dotlib
def SolveCuttingPlane(h1, h2, M):
    m = Model()
    m.setParam(GRB.Param.TimeLimit, 300)
    m.setParam(GRB.Param.Method, 1)
    # Create variables
    x = {}
    n = len(h1)
    for i in range(n):
        for j in range(n):
            x[i, j] = m.addVar(obj=M[i][j], name='x' + str(i) + '_' + str(j))
    m.update()

    for i in range(n):
        m.addConstr(quicksum(x[i, j] for j in range(n)) == h1[i])

    for j in range(n):
        m.addConstr(quicksum(x[i, j] for i in range(n)) == h2[j])

    # Solve the model
    m.optimize()

    return m.getAttr(GRB.Attr.ObjVal)
예제 #13
0
def WassersteinMinFlowL1(h1, h2):
    """ Find the Wasserstein distance using a cutting plane on the dual """
    def ID(x,y):
        return x*s+y

    n = len(h1)
    s = int(np.sqrt(n))
    print(n,s)
    # Build model
    m = Model()
    #m.setParam(GRB.Param.TimeLimit, 300)
    #m.setParam(GRB.Param.Presolve,    0)    
    #m.setParam(GRB.Param.Threads,     1)
    #  Options are: 
    #      -1=automatic, 0=primal simplex, 1=dual simplex, 2=barrier, 
    #                    3=concurrent, 4=deterministic concurrent.
    #m.setParam(GRB.Param.Method, 1)
    
    # Set a maximization problem
    m.setAttr(GRB.Attr.ModelSense, 1) 
                      
    print('1. Start building model')
    # Create variables
    X = {}
    for i in range(s):
        for j in range(s):
            X[ID(i,j)] = {}
    X[n] = {}
        
    P = []
    for i in range(s):
        for j in range(s-1):
            X[ID(i,j)][ID(i,j+1)] = m.addVar(obj=1)
            X[ID(i,j+1)][ID(i,j)] = m.addVar(obj=1)

            P.append((ID(i,j), ID(i,j+1)))
            P.append((ID(i,j+1), ID(i,j)))

            
    for i in range(s-1):
        for j in range(s):
            X[ID(i,j)][ID(i+1,j)] = m.addVar(obj=1)
            X[ID(i+1,j)][ID(i,j)] = m.addVar(obj=1)
       
            P.append((ID(i,j), ID(i+1,j)))
            P.append((ID(i+1,j), ID(i,j)))                    


    # Infintiy norm: need diagonal arcs (cost 1)            
    for i in range(s-1):
        for j in range(s-1):
            X[ID(i,j)][ID(i+1,j+1)] = m.addVar(obj=math.sqrt(2)) 
            X[ID(i+1,j+1)][ID(i,j)] = m.addVar(obj=math.sqrt(2))
       
            P.append((ID(i,j), ID(i+1,j+1)))
            P.append((ID(i+1,j+1), ID(i,j)))                    

            X[ID(i,j+1)][ID(i+1,j)] = m.addVar(obj=math.sqrt(2))
            X[ID(i+1,j)][ID(i,j+1)] = m.addVar(obj=math.sqrt(2))
       
            P.append((ID(i,j+1), ID(i+1,j)))
            P.append((ID(i+1,j), ID(i,j+1)))                    

    # Better approximation
    for i in range(s-2):
        for j in range(s-2):
            X[ID(i,j)][ID(i+2,j+1)] = m.addVar(obj=math.sqrt(5)) 
            X[ID(i+2,j+1)][ID(i,j)] = m.addVar(obj=math.sqrt(5))
            P.append((ID(i,j), ID(i+2,j+1)))
            P.append((ID(i+2,j+1), ID(i,j)))                    
            
            X[ID(i,j)][ID(i+1,j+2)] = m.addVar(obj=math.sqrt(5)) 
            X[ID(i+1,j+2)][ID(i,j)] = m.addVar(obj=math.sqrt(5))
            P.append((ID(i,j), ID(i+1,j+2)))
            P.append((ID(i+1,j+2), ID(i,j)))                    

            X[ID(i,j+2)][ID(i+1,j)] = m.addVar(obj=math.sqrt(5)) 
            X[ID(i+1,j)][ID(i,j+2)] = m.addVar(obj=math.sqrt(5))
            P.append((ID(i,j+2), ID(i+1,j)))
            P.append((ID(i+1,j), ID(i,j+2)))                    

            X[ID(i,j+2)][ID(i+2,j+1)] = m.addVar(obj=math.sqrt(5)) 
            X[ID(i+2,j+1)][ID(i,j+2)] = m.addVar(obj=math.sqrt(5))
            P.append((ID(i,j+2), ID(i+2,j+1)))
            P.append((ID(i+2,j+1), ID(i,j+2)))                    

    P = tuplelist(P)            

    m.update()
    
    # Flow variables
    print('2. Add initial constraint sets')
    for i in range(n):
        b = h2[i] - h1[i]        
        m.addConstr(quicksum(X[i][j] for j in X[i])-quicksum(X[j][i] for j,i in P.select('*',i)) == b)

    #m.addConstr(quicksum(X[n][i] for i in range(n)) >= abs(sum(h1)-sum(h2)))
        
    print('3. Start solution phase')
    # Solve the model
    m.optimize()
    
    return m.getAttr(GRB.Attr.ObjVal)
예제 #14
0
파일: kpp.py 프로젝트: Heeka/kpp
class KPPBase(metaclass=ABCMeta):

  def __init__(self, G, k, verbosity):
    self.G = G
    self.model = Model()
    self.model.modelSense = GRB.MINIMIZE
    self.k = k
    self.y = {}
    self.model.setParam("OutputFlag", 0)
    for e in self.G.es():
      u = min(e.source, e.target)
      v = max(e.source, e.target)
      if 'weight' in e.attributes():
        self.y[u, v] = self.model.addVar(obj=e['weight'], ub=1.0)
      else:
        self.y[u, v] = self.model.addVar(obj=1.0, ub=1.0)
    self.x = {}
    self.z = {}
    self.discretized = False
    self.constraints = []
    self.sep_algs = []
    self.out = sys.stdout
    self.verbosity = verbosity

  def get_solution(self):
    return Solution(self.model.getAttr('x', self.x),
                    self.model.getAttr('x', self.y),
                    self.model.getAttr('x', self.z))

  def get_colouring(self):
    '''Map of colours to nodes with that colour'''
    if self.discretized and self.model.status == 2:
      n = self.G.vcount()
      K = self.num_colours()
      colouring = [[] for i in range(K)]
      x = self.get_solution().x
      for u in range(n):
        for i in range(K):
          if abs(x[u, i] - 1.0) < 1e-3:
            colouring[i].append(u)
      return colouring
    else:
      raise(RuntimeError('Can only extract colouring if KPP has been fully solved'))

  def add_fractional_cut(self):
    if self.x:
      raise RuntimeError(
          'Fractional y-cut can only be added before the x variables have been added')
    if not self.model.status == 2:
      raise RuntimeError(
          'Fractional y-cut can only be added after successful a cutting plane phase (and before constraint removal)')
    y_lb = sum(self.model.getAttr('x', self.y).values())
    eps = self.model.params.optimalityTol
    if abs(ceil(y_lb) - y_lb) > eps:
      sum_y = LinExpr()
      for e in self.G.es():
        u = min(e.source, e.target)
        v = max(e.source, e.target)
        sum_y.addTerms(1.0, self.y[u, v])
      self.model.addConstr(sum_y >= ceil(y_lb))
      return True

  def cut(self):
    if self.discretized:
      raise RuntimeError(
          'Cutting plan algorithm can only be used before model has been discretized')

    if self.verbosity > 0:
      print('Running cutting plane algorithms', file=self.out)

    it_count = 0
    total_added = 0
    while True:
      it_count += 1
      self.model.optimize()
      if self.verbosity > 1:
        print('\n', 10 * '-', 'Iteration ', it_count,
              10 * '-', file=self.out)
        print(" Objective value: ", self.model.objVal, file=self.out)
      new_constraints = []
      sol = self.get_solution()
      for sep_alg in self.sep_algs:
        constr_list = sep_alg.find_violated_constraints(
            sol, self.verbosity - 1)
        new_constraints.extend(constr_list)

      total_added += len(new_constraints)
      for constr in new_constraints:
        self.add_constraint(constr)
      if not new_constraints:
        if self.verbosity > 1:
          print(' Found no constraints to add; exiting cutting plane loop', file=self.out)
        if self.verbosity > 0:
          print(' Added a total of', total_added, 'constraints', file=self.out)
          print(' Lower bound: ', self.model.objVal)
        break

    return total_added

  def remove_redundant_constraints(self, hard=False, allowed_slack=1e-3):
    slack, dual = 0, 0
    to_remove = []

    for constr in self.constraints:
      if abs(constr.Slack) > allowed_slack:
        to_remove.append(constr)
        slack += 1
      elif hard and constr.Pi == 0.0:
        to_remove.append(constr)
        dual += 1

    for constr in to_remove:
      self.model.remove(constr)
      self.constraints.remove(constr)

    if self.verbosity > 0:
      print(" Removed", slack, "constraints with slack greater than",
            allowed_slack, file=self.out)
      print(" Removed", dual, "constraints with zero dual variable", file=self.out)
      print("", len(self.constraints), "constraints remaining", file=self.out)

    self.model.update()
    return slack + dual

  def add_separator(self, sep_alg):
    self.sep_algs.append(sep_alg)

  def add_constraint(self, constraint):
    expr = LinExpr()
    for e, coef in constraint.x_coefs.items():
      expr.addTerms(coef, self.x[e])
    for e, coef in constraint.y_coefs.items():
      expr.addTerms(coef, self.y[e])
    for e, coef in constraint.z_coefs.items():
      expr.addTerms(coef, self.z[e])
    if constraint.op == '<':
      cons = self.model.addConstr(expr <= constraint.rhs)
    elif constraint.op == '>':
      cons = self.model.addConstr(expr >= constraint.rhs)
    elif constraint.op == '==':
      cons = self.model.addConstr(expr == constraint.rhs)
    self.constraints.append(cons)

  def solve(self):
    if not self.x:
      self.add_node_variables()
    if not self.discretized:
      self.discretize()
    if self.verbosity > 0:
      print("Running branch-and-bound", file=self.out)
    self.model.optimize()
    if self.verbosity > 0:
      print(" Optimal objective value: ", self.model.objVal, file=self.out)

  @abstractmethod
  def add_node_variables(self):
    pass

  @abstractmethod
  def num_colours(self):
    pass

  def discretize(self):
    if not self.x:
      raise RuntimeError(
          "Cannot discretize problem before x variables have been added")
    for var in self.x.values():
      var.vtype = GRB.BINARY
    self.discretized = True

  @abstractmethod
  def print_solution(self):
    pass

  @abstractmethod
  def num_colours(self):
    pass
예제 #15
0
def calculate_ILP(g,
                  quadratic=False,
                  dummy_edge_cost=100,
                  distance_cost=1,
                  comb_angle_cost=5,
                  verbose=True,
                  visualize=False,
                  linear=False,
                  angle_cost_factor=0):
    print "starting constructing ILP"
    model = Model()
    # model.setParam(GRB.Param.TimeLimit, 7200.0)
    variables = {}
    # Add variables to the model, per edge in the graph one variable
    for edge in g.nx_graph.edges_iter(data=True):
        i = edge[0]
        j = edge[1]
        dist = edge[2]['distance']

        cur_dir_vector = edge[2]['dir_vector']
        angle_cost = 0
        if angle_cost_factor != 0:
            angle1 = get_angle(g, i, cur_dir_vector)
            angle2 = get_angle(g, j, cur_dir_vector)
            angle_cost = (angle1 + angle2) * angle_cost_factor
            # angle = utils.angle_between_vecs(dir_vec_of_node, cur_dir_vec)
        # print dist
        # print angle1, angle2, cur_dir_vector
        variables[i,
                  j] = model.addVar(obj=(dist * distance_cost + angle_cost)**1,
                                    vtype=GRB.BINARY,
                                    name='e' + str(i) + '_' + str(j))
        variables[j, i] = variables[i, j]
    # This is the number for the dummy node. This guarantees that the id is not already occcupied by a node id
    n = np.max(g.nx_graph.nodes()) + 1

    g.add_geom_features_to_edges()
    g.add_geom_features_to_nodes()
    for node_id in g.nx_graph.nodes_iter():
        # Add dummy node, here the costs decide about how expensive it is to open / close a chain
        variables[node_id, n] = model.addVar(obj=dummy_edge_cost,
                                             vtype=GRB.BINARY,
                                             name='dummy1_%s' % str(node_id))
        variables[node_id,
                  n + 1] = model.addVar(obj=dummy_edge_cost,
                                        vtype=GRB.BINARY,
                                        name='dummy2_%s' % str(node_id))
        variables[n, node_id] = variables[node_id, n]
        variables[n + 1, node_id] = variables[node_id, n + 1]
    model.update()

    for node_id in g.nx_graph.nodes_iter():
        neighbours = g.nx_graph.neighbors(node_id)
        neighbours.extend([n, n + 1])
        model.addConstr(quicksum(variables[node_id, j]
                                 for j in neighbours) == 2,
                        name='node_%i' % node_id)

    model.update()
    print "Intermediate number of variables before adding combination aspect", model.NumVars
    if quadratic:
        if verbose:
            print "adding quadratic terms"
        quad = QuadExpr()
        for node_id, node_attr in g.nx_graph.nodes_iter(data=True):
            neighbours = g.nx_graph.neighbors(node_id)
            neighbours.sort()

            # Add the quadratic terms for the combination of each edge pair incident to the same node

            for ii in range(len(neighbours) - 1):
                neighbour_id1 = neighbours[ii]
                for jj in range(len(neighbours) - ii - 1):
                    neighbour_id2 = neighbours[jj + ii + 1]
                    spanning_angle = node_attr['spanning_angles'][(
                        neighbour_id1, neighbour_id2)]
                    quad.add(
                        variables[node_id, neighbour_id1] *
                        variables[node_id, neighbour_id2] *
                        (np.abs(spanning_angle - np.pi) * comb_angle_cost)**2)

        # Add linear costs to quadratic expression
        for edge in g.nx_graph.edges_iter(data=True):
            i = edge[0]
            j = edge[1]
            dist = edge[2]['distance']
            cur_dir_vector = edge[2]['dir_vector']
            angle1 = get_angle(g, i, cur_dir_vector)
            angle2 = get_angle(g, j, cur_dir_vector)
            angle_cost = (angle1 + angle2) * angle_cost_factor
            total_cost = angle_cost + dist * distance_cost
            quad.add(variables[i, j] * (total_cost))

        for node_id in g.nx_graph.nodes_iter():
            # Add dummy node, here the costs decide about how expensive it is to open / close a chain
            quad.add(variables[node_id, n] * dummy_edge_cost)
            quad.add(variables[node_id, n + 1] * dummy_edge_cost)
        print "model collection costs finished"
        model.setObjective(quad)
        model.update()
        print "Number of variables after adding quadratic component", model.NumVars

    elif linear:
        # Add additional variables that represent the combination of two edges respectively
        edge_combinations = {}
        for node_id, node_attr in g.nx_graph.nodes_iter(data=True):
            neighbours = g.nx_graph.neighbors(node_id)
            neighbours.sort()
            for ii in range(len(neighbours) - 1):
                neighbour_id1 = neighbours[ii]
                for jj in range(len(neighbours) - ii - 1):
                    neighbour_id2 = neighbours[jj + ii + 1]
                    spanning_angle = node_attr['spanning_angles'][(
                        neighbour_id1, neighbour_id2)]
                    edge_combinations[node_id, neighbour_id1, neighbour_id2] = \
                        model.addVar(obj=(np.abs(spanning_angle - np.pi) * comb_angle_cost) ** 2, vtype=GRB.BINARY,
                                     name='node_%i_edge_%i_%i' % (node_id, neighbour_id1, neighbour_id2))

        model.update()
        # Add corresponding constraints to new introduced variables (specifically,
        # combination of egdes should only be switched on if both corresponding edges are switched on)

        for node_id, node_attr in g.nx_graph.nodes_iter(data=True):
            neighbours = g.nx_graph.neighbors(node_id)
            neighbours.sort()
            for ii in range(len(neighbours) - 1):
                neighbour_id1 = neighbours[ii]
                for jj in range(len(neighbours) - ii - 1):
                    neighbour_id2 = neighbours[jj + ii + 1]
                    model.addConstr(edge_combinations[node_id, neighbour_id1,
                                                      neighbour_id2] <=
                                    variables[node_id, neighbour_id1])
                    model.addConstr(edge_combinations[node_id, neighbour_id1,
                                                      neighbour_id2] <=
                                    variables[node_id, neighbour_id2])
                    model.addConstr(edge_combinations[node_id, neighbour_id1,
                                                      neighbour_id2] +
                                    1 >= variables[node_id, neighbour_id2] +
                                    variables[node_id, neighbour_id1])
        model.update()

    if verbose:
        print "starting Optimization"
        print "Number of variables %i" % model.NumVars
        print "Number of linear constraints %i" % model.NumConstrs
    model.optimize()
    # Contains a label for each edge
    solution = model.getAttr("X", variables)
    if linear:
        comb_solution = model.getAttr("X", edge_combinations)

    new_edgelist = []

    count2 = 0
    for edge, sol in solution.iteritems():
        if n + 1 in edge or n in edge:
            if sol == 1:
                count2 += 1
        elif sol == 1:
            if not edge in new_edgelist or not (edge[1],
                                                edge[0]) in new_edgelist:
                new_edgelist.append(edge)

    if visualize:
        g.visualize(edgelist=new_edgelist, only_edges_from_edgelist=True)
        mlab.show()

    # Create new graph from solution
    graph_solution = create_graph_from_solution(g, new_edgelist)
    graph_solution.print_statistics()
    if linear:
        check_consistency(comb_solution, solution)

    if linear:
        return graph_solution, [model, solution, comb_solution]
    else:
        return graph_solution, [model, solution]
예제 #16
0
파일: 5GWCC.py 프로젝트: brandonbks/gwccApp
def optmodel():
    #form need to be in html
    datein = request.form['startDate']
    dateout = request.form['endDate']
    nhall = int(request.form['ExhibitHalls'])
    nmeeting = int(request.form['MeetingRooms'])
    naudi = int(request.form['Auditorium'])
    nball = int(request.form['Ballrooms'])
    minsqft = int(request.form['Minsqft'])

    rooms = transQuery("SELECT * FROM ROOM")
    roomsDF = pd.DataFrame(rooms,
                           columns=[
                               "RoomID", "Name", "Sqft", "Cost", "Building",
                               "Floor", "X", "Y"
                           ])
    roomsIndex = [int(i) for i in roomsDF["RoomID"]]
    convName = ["Sqft", "Cost", "Building", "Floor", "X", "Y"]
    for name in convName:
        roomsDF[name] = pd.to_numeric(roomsDF[name], errors='ignore')
    OccupiedID = transQuery(
        "SELECT RoomID FROM BOOKED WHERE dateIN BETWEEN ? AND ? AND dateout BETWEEN ? AND ?",
        (
            datein,
            dateout,
            datein,
            dateout,
        ))
    OccupiedID = pd.DataFrame(OccupiedID, columns=["RoomID"])
    OccupiedID = [int(i) for i in OccupiedID["RoomID"]]

    Arooms = transQuery(
        "SELECT * FROM ROOM WHERE RoomID NOT IN (SELECT RoomID FROM booked WHERE dateIN BETWEEN ? AND ? AND dateout BETWEEN ? AND ?)",
        (
            datein,
            dateout,
            datein,
            dateout,
        ))
    #"SELECT * FROM ROOM WHERE RoomID NOT IN (SELECT RoomID FROM booked WHERE dateIN BETWEEN '2019-08-14' AND '2019-08-20' AND dateout BETWEEN '2019-08-14' AND '2019-08-20');"
    #[40, 41, 42, 106, 107, 108, 109, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 140, 141]
    AroomsDF = pd.DataFrame(Arooms,
                            columns=[
                                "RoomID", "Name", "Sqft", "Cost", "Building",
                                "Floor", "X", "Y"
                            ])
    for name in convName:
        AroomsDF[name] = pd.to_numeric(AroomsDF[name], errors='ignore')
    # AroomsDF.astype({"Sqft":'float32',"Cost":'float32',"Building":'float32',"Floor":'float32',"X":'float32',"Y":'float32'})
    AroomsIndex = [int(i) for i in AroomsDF["RoomID"]]

    #MODEL
    m = Model('Rooms')
    m.setParam('TimeLimit', 360)
    x = m.addVars(roomsIndex, name="x", vtype=GRB.BINARY)
    d = m.addVar(0, name="d", vtype=GRB.CONTINUOUS)
    DearDaniel = 7
    e = [0, 1, 2, 40, 41, 42, 43, 44, 106, 107, 108, 109, 143, 23, 24, 87]
    a = [39, 122, 123]
    b = [102, 103, 104, 105, 137, 138, 139]
    g = np.setdiff1d(roomsIndex, e + a + b)
    m.setObjective((quicksum(x[i] * roomsDF.iloc[i, 3]
                             for i in roomsIndex) + DearDaniel * d),
                   GRB.MINIMIZE)
    #no occupied room #need to change room id
    m.addConstr(sum(x[i] for i in OccupiedID) == 0)
    m.addConstr(sum(x[i] for i in e) >= nhall)
    m.addConstr(sum(x[i] for i in a) >= naudi)
    m.addConstr(sum(x[i] for i in b) >= nball)
    m.addConstr(sum(x[i] for i in g) >= nmeeting)
    #if E is selected, Meeting room in that can't be selected
    m.addConstr((x[2] * (x[4] + x[5] + x[3])) == 0)
    m.addConstr((x[40] * (x[46] + x[47] + x[45])) == 0)
    m.addConstr((x[106] * (x[112] + x[113] + x[110] + x[111])) == 0)
    m.addConstr(x[142] * (x[13] + x[14]) == 0)
    m.addConstr(x[78] * (x[79] + x[80]) == 0)
    m.addConstr(x[94] * (x[95] + x[96]) == 0)
    #minimum room
    m.addConstrs(x[i] == 0 for i in AroomsIndex
                 if roomsDF.iloc[i, 2] < minsqft)
    #calculate the distance
    pRooms = [(AroomsDF.iloc[i, 4], AroomsDF.iloc[i, 5], AroomsDF.iloc[i, 6],
               AroomsDF.iloc[i, 7]) for i in range(len(AroomsIndex))]
    Sum = 0
    distMat = np.empty([AroomsDF.shape[0], AroomsDF.shape[0]])
    i = 0
    while i < len(Arooms):
        room1 = pRooms[i]
        j = i
        while j < len(Arooms):
            room2 = pRooms[j]
            adiff = [((room1[k] - room2[k])**2) for k in range(4)]
            dist = math.sqrt(sum(adiff))
            distMat[i][j] = dist
            distMat[j][i] = dist
            Sum += dist
            j += 1
        i += 1

    m.addConstr(d == sum([((x[i] * x[j]) * distMat[i][j])
                          for i in range(len(AroomsIndex))
                          for j in range(len(AroomsIndex))]))
    m.optimize()

    if m.status == GRB.Status.OPTIMAL or m.status == GRB.Status.TIME_LIMIT:
        x_sol = m.getAttr('x', x)
        """
        chosenroom = []
        chosenbuild = []
        sumsqft = 0
        sumcost=0
        for i in roomsIndex:
            if round(x_sol[i])>= 1:
                chosenroom.append(roomsDF.iloc[i,1])
                chosenbuild.append(roomsDF.iloc[i,4])
                sumsqft = sumsqft + roomsDF.iloc[i,2]
                sumcost = sumcost + roomsDF.iloc[i,3]
        
        for i in range(len(chosenbuild)):
            if chosenbuild[i] == 0:
               chosenbuild[i] = "A"
            elif chosenbuild[i]== 200:
               chosenbuild[i] = "B"
            else:
               chosenbuild[i] = "C"
        """
        rdict = {}
        choosenroomA = []
        choosenroomB = []
        choosenroomC = []
        for i in roomsIndex:
            if round(x_sol[i]) >= 1:
                if roomsDF.iloc[i, 4] == 0:
                    choosenroomA.append(roomsDF.iloc[i, 1])
                    rdict.update({"A": choosenroomA})
                elif roomsDF.iloc[i, 4] == 200:
                    choosenroomB.append(roomsDF.iloc[i, 1])
                    rdict.update({"B": choosenroomB})
                else:
                    choosenroomC.append(roomsDF.iloc[i, 1])
                    rdict.update({"C": choosenroomC})
        costinput = [key for key in rdict.keys()]

    sqft = float(request.form['sqft'])
    rentTotal = float(request.form['RentTotal'])
    attendance = int(request.form["attendance"])
    roomNights = int(request.form["RoomNights"])
    foodBev = float(request.form['FB'])

    dateIn = datetime.strptime(datein, "%Y-%m-%d")
    dateOut = datetime.strptime(dateout, "%Y-%m-%d")
    eventName = request.form["EventName"]
    eventType = request.form["eventType"]
    subDate = request.form["RFPSubmission"]
    eventDuration = abs((dateOut - dateIn).days)

    rfpSubmission = datetime.strptime(request.form["RFPSubmission"],
                                      "%Y-%m-%d")
    contactTillStart = abs((dateIn - rfpSubmission).days)
    #eventDuration = dateout-datein
    dictEvent = {
        "sqftPerEvent": sqft,
        "orderedRentTotal": rentTotal,
        "Attendance": attendance,
        "totalRoomNights": roomNights,
        "FB": foodBev,
        "eventDuration": eventDuration,
        "contactTillStart": contactTillStart,
        "rooms": rdict,
        "eventType": eventType,
        "dateIn": dateIn.month,
        "eventName": eventName,
        "startDate": datein,
        "endDate": dateout,
        "subDate": subDate
    }

    return redirect(url_for('roompage', data=rdict, eventInfo=dictEvent))
예제 #17
0
def BarycenterLinf(images):
    """ Compute the Kantorovich Wasserstein Barycenter of order 1 with Linf as ground distance """
    K = len(images)
    n = len(images[0])
    s = int(np.sqrt(n))

    def ID(x, y):
        return x * s + y

    # Build model
    m = Model()
    m.setParam(GRB.Param.Method, 2)
    m.setParam(GRB.Param.Crossover, 0)
    m.setParam(GRB.Param.NumericFocus, 1)
    m.setParam(GRB.Param.OutputFlag, 0)
    m.setAttr(GRB.Attr.ModelSense, 1)

    # Create variables
    Z = {}
    for i in range(n):
        Z[i] = m.addVar(obj=0)

    X = {}
    for k in range(K):
        for i in range(s):
            for j in range(s):
                X[k, ID(i, j)] = {}
    X[k, n] = {}

    A = []
    for k in range(K):
        for i in range(s):
            for j in range(s - 1):
                X[k, ID(i, j)][k, ID(i, j + 1)] = m.addVar(obj=1)
                X[k, ID(i, j + 1)][k, ID(i, j)] = m.addVar(obj=1)

                if k == 0:
                    A.append((ID(i, j), ID(i, j + 1)))
                    A.append((ID(i, j + 1), ID(i, j)))

        for i in range(s - 1):
            for j in range(s):
                X[k, ID(i, j)][k, ID(i + 1, j)] = m.addVar(obj=1)
                X[k, ID(i + 1, j)][k, ID(i, j)] = m.addVar(obj=1)

                if k == 0:
                    A.append((ID(i, j), ID(i + 1, j)))
                    A.append((ID(i + 1, j), ID(i, j)))

        for i in range(s - 1):
            for j in range(s - 1):
                X[k, ID(i, j)][k, ID(i + 1, j + 1)] = m.addVar(obj=1)
                X[k, ID(i + 1, j + 1)][k, ID(i, j)] = m.addVar(obj=1)
                X[k, ID(i, j + 1)][k, ID(i + 1, j)] = m.addVar(obj=1)
                X[k, ID(i + 1, j)][k, ID(i, j + 1)] = m.addVar(obj=1)

                if k == 0:
                    A.append((ID(i, j), ID(i + 1, j + 1)))
                    A.append((ID(i + 1, j + 1), ID(i, j)))
                    A.append((ID(i, j + 1), ID(i + 1, j)))
                    A.append((ID(i + 1, j), ID(i, j + 1)))

    A = tuplelist(A)

    m.update()

    # Flow variables
    for i in range(n):
        Fs = A.select(i, '*')
        Bs = A.select('*', i)
        for k in range(K):
            m.addConstr(
                quicksum(X[k, i][k, j] for _, j in Fs) -
                quicksum(X[k, j][k, i] for j, _ in Bs) == images[k][i] - Z[i])

    m.addConstr(quicksum(Z[i] for i in range(n)) == 1.0)
    # Solve the model
    m.optimize()

    return m.getAttr(GRB.Attr.ObjVal), [Z[i].X for i in range(n)]
예제 #18
0
def calculate_ILP_linear(g,
                         params,
                         verbose=True,
                         visualize=False,
                         timelimit=120):
    # This is a reimplementaiton of the original version of setting up the ILP for microtubule tracking. (as described
    # in paper)
    if verbose:
        print "starting constructing ILP"
        for key, value in params.__dict__.iteritems():
            print key, value
    model = Model()
    if timelimit > 0:
        model.setParam(GRB.Param.TimeLimit, timelimit)
    variables = {}
    # Add variables to the model, per edge in the graph one variable
    for edge in g.nx_graph.edges_iter(data=True):
        i = edge[0]
        j = edge[1]
        dist = edge[2]['distance']
        cur_dir_vector = edge[2]['dir_vector']
        angle_cost = 0
        if params.angle_cost_factor != 0:
            angle1 = get_angle(g, i, cur_dir_vector)
            angle2 = get_angle(g, j, cur_dir_vector)
            angle_cost = (angle1 + angle2) * params.angle_cost_factor

        variables[i, j] = model.addVar(obj=(dist * params.distance_cost +
                                            angle_cost)**1,
                                       vtype=GRB.BINARY,
                                       name='e' + str(i) + '_' + str(j))
        variables[j, i] = variables[i, j]

    sink_variables = {}
    selection_cost_variables = {}
    for node_id in g.nx_graph.nodes_iter():
        # Add dummy node (sink), here the costs decide about how expensive it is to open / close a chain
        sink_variables[node_id] = model.addVar(obj=params.dummy_edge_cost,
                                               vtype=GRB.BINARY,
                                               name='dummy_%s' % str(node_id))
        # Add cost for selecting a candidate (this is uniformly set,
        # but can potentially exchanged with adaptive costs from underlying pipeline)
        selection_cost_variables[node_id] = model.addVar(
            obj=params.selection_cost,
            vtype=GRB.BINARY,
            name='selectioncost_%s' % str(node_id))
    model.update()

    # Add consistency constraints for guaranteeing coherent topology
    # If a candidate is selected, two edge variables should also be selected
    for node_id in g.nx_graph.nodes_iter():
        neighbours = g.nx_graph.neighbors(node_id)
        model.addConstr(
            2 * selection_cost_variables[node_id] -
            (quicksum(variables[node_id, j]
                      for j in neighbours) + sink_variables[node_id]) <= 0,
            name='nodeconstraint1_%i' % node_id)
        model.addConstr(
            2 * selection_cost_variables[node_id] -
            (quicksum(variables[node_id, j]
                      for j in neighbours) + sink_variables[node_id]) >= 0,
            name='nodeconstraint2_%i' % node_id)

    # model.addConstr(selection_cost_variables[0] == 1,
    #                 name='nodeconstraint3_%i' %node_id)
    model.update()
    # If a link is selected, the two incident candidates on this link also need to be selected
    # The other way round is not true, if a candidate is selected
    for edge in g.nx_graph.edges_iter():
        node_id1 = edge[0]
        node_id2 = edge[1]
        model.addConstr(
            2 * variables[edge] - selection_cost_variables[node_id1] -
            selection_cost_variables[node_id2] <= 0,
            name='edgeconstraint_%i_%i' % edge)

    model.update()
    print "Intermediate number of variables before adding combination aspect", model.NumVars

    if params.pairwise:
        # Microtubules are rigid. Add cost for bending
        model, edge_combinations = add_pairwaisefactors_to_model(
            model, g, params, variables)
    if params.exclusive_distance:
        # Too many candidates for the same microtubules cause parallel occurence
        model = add_proximity_exclusivity(model, g, selection_cost_variables,
                                          params.exclusive_distance_threshold)
    if verbose:
        print "starting Optimization"
        print "Number of variables %i" % model.NumVars
        print "Number of linear constraints %i" % model.NumConstrs
    # model.display()
    model.optimize()

    print 'Obj:', model.ObjVal
    # Contains a label for each edge
    solution = model.getAttr("X", variables)
    if params.pairwise:
        comb_solution = model.getAttr('X', edge_combinations)
        check_consistency(comb_solution, solution)
    new_edgelist = []
    for edge, sol in solution.iteritems():
        if sol == 1:
            new_edgelist.append(edge)

    if visualize:
        g.visualize(edgelist=new_edgelist, only_edges_from_edgelist=True)
        mlab.show()

    # Create new graph from solution
    nx_skeleton_solution = create_graph_from_solution(g, new_edgelist)
    nx_skeleton_solution.print_statistics()

    return nx_skeleton_solution, model
예제 #19
0
def optimize_traffic_load(n, h, u):
    # create a model
    m = Model('traffic load')
    # create decision variables
    x = m.addVars(sa, sa, vtype=GRB.BINARY, name='x')
    y = m.addVars(sa, dc, vtype=GRB.BINARY, name='y')

    # add constraints
    # x is symmetric
    m.addConstrs((x[i, j] == x[j, i] for i in sa for j in sa),
                 'symmetric constraint')
    # Two service areas cant use the same stateful functions when x[i,j] = 0
    m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in sa for j in sa
                  for t in dc), 'x = 0 constraint')
    # Two service areas use the same stateful functions when x[i,j] = 1
    m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in sa for j in sa
                  for t in dc), 'x = 1 constraint')
    # Each should be at least managed by one dc
    m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in sa),
                 'one dc for one sa')
    # high availability constraint
    m.addConstr(
        sum((1 - x[i, j]) for i in sa for j in sa if i != j) >= 1, 'ha')
    # maximum state transfer frequency
    m.addConstr(
        sum(h * (1 - x[i, j]) for i in sa for j in sa if i != j) <= State_max,
        'max state transfer constraint')
    # dc0 will have the most heavy load
    for t in dc:
        if t != dc[0]:
            m.addConstr(
                sum(y[i, t] * n * (L_sig + u * L_session)
                    for i in sa) <= sum(y[i, dc[0]] * n *
                                        (L_sig + u * L_session)
                                        for i in sa), 'less than max load')

    # Objective function
    # Optimize load on one cloud centers and mandate other centers to be less than
    m.setObjective(sum(y[i, dc[0]] * n * (L_sig + u * L_session) for i in sa),
                   GRB.MINIMIZE)

    m.optimize()
    # check model feasible or not
    if m.getAttr('status') == GRB.INFEASIBLE:
        return 'infeasible'

    # Calculate performance metrics
    # traffic load on stateful functions
    traffic_load = sum(
        getattr(y[i, dc[0]], 'X') * n * (L_sig + u * L_session) for i in sa)

    # state transfer frequency
    state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in sa
                         for j in sa if i != j)

    # number of function
    num_func = M_dc - sum(
        prod(1 - getattr(y[i, t], 'X') for i in sa) for t in dc)

    # total metrics
    total_metrics = [u, h, u, state_transfer, traffic_load, num_func]

    # utopia point, nadir point
    worst_state = state_transfer
    best_load = traffic_load

    return total_metrics, worst_state, best_load
예제 #20
0
def VRPGu(n, K, C, Ps, Ds, d, F, TimeLimit):
    m = Model()
    m.setParam(GRB.Param.TimeLimit, TimeLimit)
    # Create variables
    x = {}
    for i in Ps:
        for j in Ps:
            if i != j :
                x[i,j] = m.addVar(obj=F(Ps[i], Ps[j]), vtype=GRB.BINARY,
                                  name='x'+str(i)+'_'+str(j))
    # Create Miller variables (subtour elimination)
    u = {}
    for i in Ds:
        if i != d:
            u[i] = m.addVar(obj=0.0, vtype=GRB.CONTINUOUS,
                            lb=Ds[i], ub=C, name='u'+str(i))
            
    m.update()
    # Add outdegree constraint
    for j in Ps:
        if j != d:
            Ls = list(filter(lambda z: z!=j, Ps))
            m.addConstr(quicksum(x[i,j] for i in Ls) == 1)
    # Add indegree constraint
    for i in Ps:
        if i != d:
            Ls = filter(lambda z: z!=i, Ps)
            m.addConstr(quicksum(x[i,j] for j in Ls) == 1)
            
    # Number of vehicles
    Ls = list(filter(lambda z: z!=d, Ps))                   
    m.addConstr(quicksum(x[i,d] for i in Ls) <= K)
    m.addConstr(quicksum(x[d,j] for j in Ls) <= K)
    
    m.addConstr(quicksum(x[i,d] for i in Ls) >= 3)
    m.addConstr(quicksum(x[d,j] for j in Ls) >= 3)

    #

    for a,b in [(15,18), (9,22), (19,20), (5,6), (8,22), (7,2), (9,10)]:
        Fs = []
        for i in Ps:
            if i == a or i == b:        
                for j in Ps:
                    if i != j and j != a and j != b:
                        Fs.append((i,j))
                        
        m.addConstr(quicksum(x[i,j] for i,j in Fs) >= 1)


    for a,b,c in [(5,6,9), (10,11,14)]:
        Fs = []
        for i in Ps:
            if i == a or i == b or i == c:        
                for j in Ps:
                    if i != j and j != a and j != b and j != c:
                        Fs.append((i,j))
                        
        m.addConstr(quicksum(x[i,j] for i,j in Fs) >= 2)

        
    # for a,b in [(15,18), (9,22), (19,20), (5,6), (8,22), (7,2)]:
    #     m.addConstr(x[a,b] + x[b,a] <= 1)
    
    m.update()

    # Solve the model
    m.optimize()
    solution = m.getAttr('x', x)
    selected = [(i,j) for (i,j) in solution if solution[i,j] > 0.5]

    # Xs = [p for p in Ps.values()]
    # Ws = [w for w in Ds.values()]
    
    # for i,j in selected:
    #     DisegnaSegmento(Ps[i], Ps[j])
    # plt.scatter([i for i,j in Xs[1:]], [j for i,j in Xs[1:]], 
    #             s=Ws[1:], alpha=0.3, cmap='viridis')
    # plt.plot([Xs[0][0]], [Xs[0][1]], marker='s', color='red', alpha=0.5)
    # plt.axis('square')
    # plt.axis('off')
    
    return m.objVal, selected
예제 #21
0
        for j in range(n):
            m.addConstr((ct[p, k - 1] + pt[j] - ct[p, k]) <= 0)
m.update()
for p in range(p_max):
    for k in range(K):
        for j in range(n):
            m.addConstr((ct[p, k] - dt[j] - M *
                         (1 - vars[j, p, k]) - ta[j]) <= 0)
m.update()

# Optimize model
m._vars = vars
m.params.LazyConstraints = 1
m.optimize(add_ct)

solution = m.getAttr('x', vars)
selected = [(j, p, k) for p in range(p_max) for k in range(K) for j in range(n)
            if solution[j, p, k] > 0.5]
# assert len(subtour(selected)) == n
print('Optimal cost: %g' % m.objVal)

jobs = []
# sd_p = [0] * p_max
for p in range(p_max):
    jobs.append(Picker(p, batches=[]))
ans = {}
for j, p, k in selected:
    ans[p, k] = []
for j, p, k in selected:
    ans[p, k].append(list(df_orders.index)[j])
l = 0
예제 #22
0
# vars = tupledict()
# for i,j in dist.keys():
#   vars[i,j] = m.addVar(obj=dist[i,j], vtype=GRB.BINARY,
#                        name='e[%d,%d]'%(i,j))

# Add degree-2 constraint

m.addConstrs(vars.sum(i, '*') == 2 for i in range(n))

# Using Python looping constructs, the preceding would be...
#
# for i in range(n):
#   m.addConstr(sum(vars[i,j] for j in range(n)) == 2)

# Optimize model

m._vars = vars
m.Params.lazyConstraints = 1
m.optimize(subtourelim)

vals = m.getAttr('x', vars)
selected = tuplelist((i, j) for i, j in vals.keys() if vals[i, j] > 0.5)

tour = subtour(selected)
assert len(tour) == n

print('')
print('Optimal tour: %s' % str(tour))
print('Optimal cost: %g' % m.objVal)
print('')
def generate_multi_dim_sample(bounds, directory, num_teams, num_md_per_cycle,
                              numSam, numCycle, theoretical):

    # the list of sample dimensions, the +1
    cycle = list(range(numCycle))
    day = list(range(num_md_per_cycle))
    days = list(range(num_md_per_cycle + 1))
    home = away = list(range(num_teams))

    constrList = [
        [(0, ), (1, )],
        [(0, ), (2, )],
        [(0, ), (3, )],
        [(0, ), (1, 2)],
        [(0, ), (1, 3)],
        [(0, ), (2, 3)],
        [(0, ), (1, 2, 3)],
        [(1, ), (0, )],
        [(1, ), (2, )],
        [(1, ), (3, )],
        [(1, ), (0, 2)],
        [(1, ), (0, 3)],
        [(1, ), (2, 3)],
        [(1, ), (0, 2, 3)],
        [(2, ), (0, )],
        [(2, ), (1, )],
        [(2, ), (3, )],
        [(2, ), (0, 1)],
        [(2, ), (0, 3)],
        [(2, ), (1, 3)],
        [(2, ), (0, 1, 3)],
        [(3, ), (0, )],
        [(3, ), (1, )],
        [(3, ), (2, )],
        [(3, ), (0, 1)],
        [(3, ), (0, 2)],
        [(3, ), (1, 2)],
        [(3, ), (0, 1, 2)],
        [(0, 1), (2, )],
        [(0, 1), (3, )],
        [(0, 1), (2, 3)],
        # cons away = 31
        [(0, 2), (1, )],
        [(0, 2), (3, )],
        [(0, 2), (1, 3)],
        # cons home = 34
        [(0, 3), (1, )],
        [(0, 3), (2, )],
        [(0, 3), (1, 2)],
        [(1, 2), (0, )],
        [(1, 2), (3, )],
        [(1, 2), (0, 3)],
        [(1, 3), (0, )],
        [(1, 3), (2, )],
        [(1, 3), (0, 2)],
        [(2, 3), (0, )],
        [(2, 3), (1, )],
        [(2, 3), (0, 1)],
        [(0, 1, 2), (3, )],
        [(0, 1, 3), (2, )],
        [(0, 2, 3), (1, )],
        [(1, 2, 3), (0, )]
    ]

    try:
        model = Model("sspSolver")
        # give verbose logging when 1, otherwise 0
        model.setParam(GRB.param.OutputFlag, 1)

        ### Decision Variables ###
        # 0 = cycles, 1 = days, 2 = away, 3 = home
        # regular combinations over the 4 dimensions
        x = model.addVars(cycle,
                          day,
                          home,
                          away,
                          vtype=GRB.BINARY,
                          name="base")
        n = model.addVars(cycle, day, home, vtype=GRB.BINARY, name="n")
        o = model.addVars(cycle, day, away, vtype=GRB.BINARY, name="o")
        p = model.addVars(cycle, home, away, vtype=GRB.BINARY, name="p")
        q = model.addVars(day, home, away, vtype=GRB.BINARY, name="q")
        r = model.addVars(cycle, day, vtype=GRB.BINARY, name="r")
        s = model.addVars(cycle, home, vtype=GRB.BINARY, name="s")
        t = model.addVars(cycle, away, vtype=GRB.BINARY, name="t")
        u = model.addVars(day, home, vtype=GRB.BINARY, name="u")
        v = model.addVars(day, away, vtype=GRB.BINARY, name="v")
        w = model.addVars(home, away, vtype=GRB.BINARY, name="w")

        #y = model.addVars(cycle, day, home, away, vtype=GRB.BINARY, name="basetrans")
        #yn = model.addVars(cycle, day, home, vtype=GRB.BINARY, name="trans_n")

        cNA = model.addVars(cycle,
                            day,
                            day,
                            away,
                            vtype=GRB.BINARY,
                            name="cons")
        cNAs = model.addVars(cycle,
                             days,
                             day,
                             away,
                             vtype=GRB.BINARY,
                             name="cons_min")
        cNH = model.addVars(cycle,
                            day,
                            day,
                            home,
                            vtype=GRB.BINARY,
                            name="consHome")
        cNHs = model.addVars(cycle,
                             days,
                             day,
                             home,
                             vtype=GRB.BINARY,
                             name="consHomes")

        cZy = model.addVars(cycle,
                            day,
                            day,
                            home,
                            vtype=GRB.BINARY,
                            name="days_betw_games")
        cZys = model.addVars(cycle,
                             days,
                             day,
                             home,
                             vtype=GRB.BINARY,
                             name="days_btw_gamess")

        # transpose function
        #model.addConstrs(
        #    y[c, d, h, a] == x[c, d, h, a] + x[c, d, a, h] for c in cycle for d in day for a in away for h in home)
        #model.addConstrs((y.sum(c, d, h, '*') == yn[c, d, h] for c in cycle for d in day for h in home), "yn_y")

        model.addConstrs((x.sum(c, d, '*', a) == o[c, d, a] for c in cycle
                          for d in day for a in away), "xo")
        model.addConstrs((x.sum(c, d, h, '*') == n[c, d, h] for c in cycle
                          for d in day for h in home), "xn")
        model.addConstrs((x.sum(c, '*', h, a) == p[c, h, a] for c in cycle
                          for h in home for a in away), "xp")
        model.addConstrs((x.sum('*', d, h, a) == q[d, h, a] for d in day
                          for h in home for a in away), "xq")

        model.addConstrs(
            (r[c, d] <= n.sum(c, d, '*') for c in cycle for d in day), "rn")
        model.addConstrs(
            (t[c, a] <= n.sum(c, '*', a) for c in cycle for a in away), "tn")
        model.addConstrs(
            (v[d, a] <= n.sum('*', d, a) for d in day for a in away), "vn")

        model.addConstrs(
            (r[c, d] <= o.sum(c, d, '*') for c in cycle for d in day), "ro")
        model.addConstrs(
            (s[c, h] <= o.sum(c, '*', h) for c in cycle for h in home), "so")
        model.addConstrs(
            (u[d, h] <= o.sum('*', d, h) for d in day for h in home), "uo")

        model.addConstrs(
            (s[c, h] <= p.sum(c, h, '*') for c in cycle for h in home), "sp")
        model.addConstrs(
            (t[c, a] <= p.sum(c, '*', a) for c in cycle for a in away), "tp")
        model.addConstrs(
            (w[h, a] <= p.sum('*', h, a) for h in home for a in away), "wp")

        model.addConstrs(
            (u[d, h] <= q.sum(d, h, '*') for d in day for h in home), "uq")
        model.addConstrs(
            (v[d, a] <= q.sum(d, '*', a) for d in day for a in away), "vq")
        model.addConstrs(
            (w[h, a] <= q.sum('*', h, a) for h in home for a in away), "wq")

        if theoretical:
            ### Hard constraints -- not yet in bounds ###
            # never play yourself
            model.addConstrs(x[c, d, i, i] == 0 for c in cycle for d in day
                             for i in home)
            # only play one game per day
            model.addConstrs((x.sum(c, d, i, '*') + x.sum(c, d, '*', i) <= 1
                              for c in cycle for d in day
                              for i in home), "1gamePerDay")

        # Hard constraints from bounds files ###
        # bounds 0 = countLowerbound
        # bounds 1 = countUpperBound
        # bounds 2 = minConsZero
        # bounds 3 = maxConsZero
        # bounds 4 = minConsNonZero
        # bounds 5 = maxConsNonZero
        for i in range(len(bounds)):
            ### SEED COUNT BOUNDS: bounds[i,0] is the lowerbound, bounds[i,1] is the upperbound
            if bounds[i, 0] > 0:
                # this part covers count lowerbound
                if constrList[i] == [(0, ), (1, )]:
                    model.addConstrs((r.sum(c, '*') >= bounds[i, 0]
                                      for c in cycle), "LWR_constr-(0,), (1,)")
                elif constrList[i] == [(0, ), (2, )]:
                    model.addConstrs((t.sum(c, '*') >= bounds[i, 0]
                                      for c in cycle), "LWR_constr-(0,), (2,)")
                elif constrList[i] == [(0, ), (3, )]:
                    model.addConstrs((s.sum(c, '*') >= bounds[i, 0]
                                      for c in cycle), "LWR_constr-(0,), (3,)")
                elif constrList[i] == [(0, ), (1, 2)]:
                    model.addConstrs(
                        (o.sum(c, '*', '*') >= bounds[i, 0] for c in cycle),
                        "LWR_constr-(0,), (1,2)")
                elif constrList[i] == [(0, ), (1, 3)]:
                    model.addConstrs(
                        (n.sum(c, '*', '*') >= bounds[i, 0] for c in cycle),
                        "LWR_constr-(0,), (1,3)")
                elif constrList[i] == [(0, ), (2, 3)]:
                    model.addConstrs(
                        (p.sum(c, '*', '*') >= bounds[i, 0] for c in cycle),
                        "LWR_constr-(0,), (2,3)")
                elif constrList[i] == [(0, ), (1, 2, 3)]:
                    model.addConstrs((x.sum(c, '*', '*', '*') >= bounds[i, 0]
                                      for c in cycle),
                                     "LWR_constr-(0,), (1,2,3)")

                elif constrList[i] == [(1, ), (0, )]:
                    model.addConstrs((r.sum('*', d) >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (0,)")
                elif constrList[i] == [(1, ), (2, )]:
                    model.addConstrs((v.sum(d, '*') >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (2,)")
                elif constrList[i] == [(1, ), (3, )]:
                    model.addConstrs((u.sum(d, '*') >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (3,)")
                elif constrList[i] == [(1, ), (0, 2)]:
                    model.addConstrs((o.sum('*', d, '*') >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (0,2)")
                elif constrList[i] == [(1, ), (0, 3)]:
                    model.addConstrs((n.sum('*', d, '*') >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (0,3)")
                elif constrList[i] == [(1, ), (2, 3)]:
                    model.addConstrs((q.sum(d, '*', '*') >= bounds[i, 0]
                                      for d in day), "LWR_constr-(1,), (2,3)")
                elif constrList[i] == [(1, ), (0, 2, 3)]:
                    model.addConstrs(
                        (x.sum('*', d, '*', '*') >= bounds[i, 0] for d in day),
                        "LWR_constr-(1,), (0,2,3)")

                elif constrList[i] == [(2, ), (0, )]:
                    model.addConstrs((t.sum('*', h) >= bounds[i, 0]
                                      for h in home), "LWR_constr-(2,), (0,)")
                elif constrList[i] == [(2, ), (1, )]:
                    model.addConstrs((v.sum('*', h) >= bounds[i, 0]
                                      for h in home), "LWR_constr-(2,), (1,)")
                elif constrList[i] == [(2, ), (3, )]:
                    model.addConstrs((w.sum(h, '*') >= bounds[i, 0]
                                      for h in home), "LWR_constr--(2,), (3,)")
                elif constrList[i] == [(2, ), (0, 1)]:
                    model.addConstrs(
                        (o.sum('*', '*', h) >= bounds[i, 0] for h in home),
                        "LWR_constr--(2,), (0,1)")
                elif constrList[i] == [(2, ), (0, 3)]:
                    model.addConstrs(
                        (p.sum('*', h, '*') >= bounds[i, 0] for h in home),
                        "LWR_constr--(2,), (0,3)")
                elif constrList[i] == [(2, ), (1, 3)]:
                    model.addConstrs((q.sum('*', h, '*') >= bounds[i, 0]
                                      for h in home), "LWR_constr-(2,), (1,3)")
                elif constrList[i] == [(2, ), (0, 1, 3)]:
                    model.addConstrs((x.sum('*', '*', h, '*') >= bounds[i, 0]
                                      for h in home),
                                     "LWR_constr-(2,), (0,1,3)")

                elif constrList[i] == [(3, ), (0, )]:
                    model.addConstrs((s.sum('*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (0,)")
                elif constrList[i] == [(3, ), (1, )]:
                    model.addConstrs((u.sum('*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (1,)")
                elif constrList[i] == [(3, ), (2, )]:
                    model.addConstrs((w.sum('*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (2,)")
                elif constrList[i] == [(3, ), (0, 1)]:
                    model.addConstrs((n.sum('*', '*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (0,1)")
                elif constrList[i] == [(3, ), (0, 2)]:
                    model.addConstrs((p.sum('*', '*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (0,2)")
                elif constrList[i] == [(3, ), (1, 2)]:
                    model.addConstrs((q.sum('*', '*', a) >= bounds[i, 0]
                                      for a in away), "LWR_constr-(3,), (1,2)")
                elif constrList[i] == [(3, ), (0, 1, 2)]:
                    model.addConstrs((x.sum('*', '*', '*', a) >= bounds[i, 0]
                                      for a in away),
                                     "LWR_constr-(3,), (0,1,2)")

                elif constrList[i] == [(0, 1), (2, )]:
                    model.addConstrs((o.sum(c, d, '*') >= bounds[i, 0]
                                      for c in cycle
                                      for d in day), "LWR_constr-(0,1), (2,)")
                elif constrList[i] == [(0, 1), (3, )]:
                    model.addConstrs((n.sum(c, d, '*') >= bounds[i, 0]
                                      for c in cycle
                                      for d in day), "LWR_constr-(0,1), (3,)")
                elif constrList[i] == [(0, 1), (2, 3)]:
                    model.addConstrs((x.sum(c, d, '*', '*') >= bounds[i, 0]
                                      for c in cycle
                                      for d in day), "LWR_constr-(0,1), (2,3)")

                elif constrList[i] == [(0, 2), (1, )]:
                    bound = bounds[i, 0]
                    model.addConstrs((o.sum(c, '*', a) >= bounds[i, 0]
                                      for c in cycle
                                      for a in away), "LWR_constr-(0,2), (1,)")
                elif constrList[i] == [(0, 2), (3, )]:
                    model.addConstrs((p.sum(c, '*', a) >= bounds[i, 0]
                                      for c in cycle
                                      for a in away), "LWR_constr-(0,2), (3,)")
                elif constrList[i] == [(0, 2), (1, 3)]:
                    model.addConstrs((x.sum(c, '*', a) >= bounds[i, 0]
                                      for c in cycle for a in away),
                                     "LWR_constr-(0,2), (1,3)")

                elif constrList[i] == [(0, 3), (1, )]:
                    model.addConstrs((n.sum(c, '*', h) >= bounds[i, 0]
                                      for c in cycle
                                      for h in home), "LWR_constr-(0,3), (1,)")
                elif constrList[i] == [(0, 3), (2, )]:
                    model.addConstrs((p.sum(c, '*', h) >= bounds[i, 0]
                                      for c in cycle
                                      for h in home), "LWR_constr-(0,3), (2,)")
                elif constrList[i] == [(0, 3), (1, 2)]:
                    model.addConstrs((x.sum(c, '*', '*', h) >= bounds[i, 0]
                                      for c in cycle for h in home),
                                     "LWR_constr-(0,3), (1,2)")

                elif constrList[i] == [(1, 2), (0, )]:
                    model.addConstrs((o.sum('*', d, a) >= bounds[i, 0]
                                      for d in day
                                      for a in away), "LWR_constr-(1,2), (0,)")
                elif constrList[i] == [(1, 2), (3, )]:
                    model.addConstrs((q.sum(d, a, '*') >= bounds[i, 0]
                                      for d in day
                                      for a in away), "LWR_constr-(1,2), (3,)")
                elif constrList[i] == [(1, 2), (0, 3)]:
                    model.addConstrs((x.sum('*', d, a, '*') >= bounds[i, 0]
                                      for d in day for a in away),
                                     "LWR_constr-(1,2), (0,3)")

                elif constrList[i] == [(1, 3), (0, )]:
                    model.addConstrs((n.sum('*', d, h) >= bounds[i, 0]
                                      for d in day
                                      for h in home), "LWR_constr-(1,3), (0,)")
                elif constrList[i] == [(1, 3), (2, )]:
                    model.addConstrs((q.sum(d, '*', h) >= bounds[i, 0]
                                      for d in day
                                      for h in home), "LWR_constr-(1,3), (2,)")
                elif constrList[i] == [(1, 3), (0, 2)]:
                    model.addConstrs((x.sum('*', d, '*', h) >= bounds[i, 0]
                                      for d in day for h in home),
                                     "LWR_constr-(1,3), (0,2)")

                elif constrList[i] == [(2, 3), (0, )]:
                    model.addConstrs((p.sum('*', h, a) >= bounds[i, 0]
                                      for h in home
                                      for a in away), "LWR_constr-(2,3), (0,)")
                elif constrList[i] == [(2, 3), (1, )]:
                    model.addConstrs((q.sum('*', h, a) >= bounds[i, 0]
                                      for h in home
                                      for a in away), "LWR_constr-(2,3), (1,)")
                elif constrList[i] == [(2, 3), (0, 1)]:
                    model.addConstrs((x.sum('*', '*', h, a) >= bounds[i, 0]
                                      for h in home for a in away),
                                     "LWR_constr-(2,3), (0,1)")

                elif constrList[i] == [(0, 1, 2), (3, )]:
                    model.addConstrs((x.sum(c, d, a, '*') >= bounds[i, 0]
                                      for c in cycle for d in day
                                      for a in away),
                                     "LWR_constr-(0,1,2), (3,)")
                elif constrList[i] == [(0, 1, 3), (2, )]:
                    model.addConstrs((x.sum(c, d, '*', h) >= bounds[i, 0]
                                      for c in cycle for d in day
                                      for h in home),
                                     "LWR_constr-(0,1,3), (2,)")
                elif constrList[i] == [(0, 2, 3), (1, )]:
                    model.addConstrs((x.sum(c, '*', a, h) >= bounds[i, 0]
                                      for c in cycle for a in away
                                      for h in home),
                                     "LWR_constr-(0,2,3), (1,)")
                elif constrList[i] == [(1, 2, 3), (0, )]:
                    model.addConstrs((x.sum('*', d, a, h) >= bounds[i, 0]
                                      for d in day for a in away
                                      for h in home),
                                     "LWR_constr-(1,2,3), (0,)")
            if bounds[i, 1] > 0:
                # this part covers count lowerbound
                if constrList[i] == [(0, ), (1, )]:
                    model.addConstrs((r.sum(c, '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (1,)")
                elif constrList[i] == [(0, ), (2, )]:
                    model.addConstrs((t.sum(c, '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (2,)")
                elif constrList[i] == [(0, ), (3, )]:
                    model.addConstrs((s.sum(c, '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (3,)")
                elif constrList[i] == [(0, ), (1, 2)]:
                    model.addConstrs((o.sum(c, '*', '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (1,2)")
                elif constrList[i] == [(0, ), (1, 3)]:
                    model.addConstrs((n.sum(c, '*', '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (1,3)")
                elif constrList[i] == [(0, ), (2, 3)]:
                    model.addConstrs((p.sum(c, '*', '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (2,3)")
                elif constrList[i] == [(0, ), (1, 2, 3)]:
                    model.addConstrs((x.sum(c, '*', '*', '*') <= bounds[i, 1]
                                      for c in cycle), "constr-(0,), (1,2,3)")

                elif constrList[i] == [(1, ), (0, )]:
                    model.addConstrs((r.sum('*', d) <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (0,)")
                elif constrList[i] == [(1, ), (2, )]:
                    model.addConstrs((v.sum(d, '*') <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (2,)")
                elif constrList[i] == [(1, ), (3, )]:
                    model.addConstrs((u.sum(d, '*') <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (3,)")
                elif constrList[i] == [(1, ), (0, 2)]:
                    model.addConstrs((o.sum('*', d, '*') <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (0,2)")
                elif constrList[i] == [(1, ), (0, 3)]:
                    model.addConstrs((n.sum('*', d, '*') <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (0,3)")
                elif constrList[i] == [(1, ), (2, 3)]:
                    model.addConstrs((q.sum(d, '*', '*') <= bounds[i, 1]
                                      for d in day), "LWR_constr-(1,), (2,3)")
                elif constrList[i] == [(1, ), (0, 2, 3)]:
                    model.addConstrs(
                        (x.sum('*', d, '*', '*') <= bounds[i, 1] for d in day),
                        "LWR_constr-(1,), (0,2,3)")

                elif constrList[i] == [(2, ), (0, )]:
                    model.addConstrs((t.sum('*', h) <= bounds[i, 1]
                                      for h in home), "constr-(2,), (0,)")
                elif constrList[i] == [(2, ), (1, )]:
                    model.addConstrs((v.sum('*', h) <= bounds[i, 1]
                                      for h in home), "constr-(2,), (1,)")
                elif constrList[i] == [(2, ), (3, )]:
                    model.addConstrs((w.sum(h, '*') <= bounds[i, 1]
                                      for h in home), "constr--(2,), (3,)")
                elif constrList[i] == [(2, ), (0, 1)]:
                    model.addConstrs((o.sum('*', '*', h) <= bounds[i, 1]
                                      for h in home), "constr--(2,), (0,1)")
                elif constrList[i] == [(2, ), (0, 3)]:
                    model.addConstrs((p.sum('*', h, '*') <= bounds[i, 1]
                                      for h in home), "constr--(2,), (0,3)")
                elif constrList[i] == [(2, ), (1, 3)]:
                    model.addConstrs((q.sum('*', h, '*') <= bounds[i, 1]
                                      for h in home), "constr-(2,), (1,3)")
                elif constrList[i] == [(2, ), (0, 1, 3)]:
                    model.addConstrs((x.sum('*', '*', h, '*') <= bounds[i, 1]
                                      for h in home),
                                     "LWR_constr-(2,), (0,1,3)")

                elif constrList[i] == [(3, ), (0, )]:
                    model.addConstrs((s.sum('*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (0,)")
                elif constrList[i] == [(3, ), (1, )]:
                    model.addConstrs((u.sum('*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (1,)")
                elif constrList[i] == [(3, ), (2, )]:
                    model.addConstrs((w.sum('*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (2,)")
                elif constrList[i] == [(3, ), (0, 1)]:
                    model.addConstrs((n.sum('*', '*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (0,1)")
                elif constrList[i] == [(3, ), (0, 2)]:
                    model.addConstrs((p.sum('*', '*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (0,2)")
                elif constrList[i] == [(3, ), (1, 2)]:
                    model.addConstrs((q.sum('*', '*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (1,2)")
                elif constrList[i] == [(3, ), (0, 1, 2)]:
                    model.addConstrs((x.sum('*', '*', '*', a) <= bounds[i, 1]
                                      for a in away), "constr-(3,), (0,1,2)")

                elif constrList[i] == [(0, 1), (2, )]:
                    model.addConstrs((o.sum(c, d, '*') <= bounds[i, 1]
                                      for c in cycle
                                      for d in day), "constr-(0,1), (2,)")
                elif constrList[i] == [(0, 1), (3, )]:
                    model.addConstrs((n.sum(c, d, '*') <= bounds[i, 1]
                                      for c in cycle
                                      for d in day), "constr-(0,1), (3,)")
                elif constrList[i] == [(0, 1), (2, 3)]:
                    model.addConstrs((x.sum(c, d, '*', '*') <= bounds[i, 1]
                                      for c in cycle
                                      for d in day), "constr-(0,1), (2,3)")

                elif constrList[i] == [(0, 2), (1, )]:
                    model.addConstrs((o.sum(c, '*', a) <= bounds[i, 1]
                                      for c in cycle
                                      for a in away), "constr-(0,2), (1,)")
                elif constrList[i] == [(0, 2), (3, )]:
                    model.addConstrs((p.sum(c, '*', a) <= bounds[i, 1]
                                      for c in cycle
                                      for a in away), "constr-(0,2), (3,)")
                elif constrList[i] == [(0, 2), (1, 3)]:
                    model.addConstrs((x.sum(c, '*', a) <= bounds[i, 1]
                                      for c in cycle
                                      for a in away), "constr-(0,2), (1,3)")

                elif constrList[i] == [(0, 3), (1, )]:
                    model.addConstrs((n.sum(c, '*', h) <= bounds[i, 1]
                                      for c in cycle
                                      for h in home), "constr-(0,3), (1,)")
                elif constrList[i] == [(0, 3), (2, )]:
                    model.addConstrs((p.sum(c, '*', h) <= bounds[i, 1]
                                      for c in cycle
                                      for h in home), "constr-(0,3), (2,)")
                elif constrList[i] == [(0, 3), (1, 2)]:
                    model.addConstrs((x.sum(c, '*', '*', h) <= bounds[i, 1]
                                      for c in cycle
                                      for h in home), "constr-(0,3), (1,2)")

                elif constrList[i] == [(1, 2), (0, )]:
                    model.addConstrs((o.sum('*', d, a) <= bounds[i, 1]
                                      for d in day
                                      for a in away), "constr-(1,2), (0,)")
                elif constrList[i] == [(1, 2), (3, )]:
                    model.addConstrs((q.sum(d, a, '*') <= bounds[i, 1]
                                      for d in day
                                      for a in away), "constr-(1,2), (3,)")
                elif constrList[i] == [(1, 2), (0, 3)]:
                    model.addConstrs((x.sum('*', d, a, '*') <= bounds[i, 1]
                                      for d in day
                                      for a in away), "constr-(1,2), (0,3)")

                elif constrList[i] == [(1, 3), (0, )]:
                    model.addConstrs((n.sum('*', d, h) <= bounds[i, 1]
                                      for d in day
                                      for h in home), "constr-(1,3), (0,)")
                elif constrList[i] == [(1, 3), (2, )]:
                    model.addConstrs((q.sum(d, '*', h) <= bounds[i, 1]
                                      for d in day
                                      for h in home), "constr-(1,3), (2,)")
                elif constrList[i] == [(1, 3), (0, 2)]:
                    model.addConstrs((x.sum('*', d, '*', h) <= bounds[i, 1]
                                      for d in day
                                      for h in home), "constr-(1,3), (0,2)")

                elif constrList[i] == [(2, 3), (0, )]:
                    model.addConstrs((p.sum('*', h, a) <= bounds[i, 1]
                                      for h in home
                                      for a in away), "constr-(2,3), (0,)")
                elif constrList[i] == [(2, 3), (1, )]:
                    model.addConstrs((q.sum('*', h, a) <= bounds[i, 1]
                                      for h in home
                                      for a in away), "constr-(2,3), (1,)")
                elif constrList[i] == [(2, 3), (0, 1)]:
                    model.addConstrs((x.sum('*', '*', h, a) <= bounds[i, 1]
                                      for h in home
                                      for a in away), "constr-(2,3), (0,1)")

                elif constrList[i] == [(0, 1, 2), (3, )]:
                    model.addConstrs((x.sum(c, d, a, '*') <= bounds[i, 1]
                                      for c in cycle for d in day
                                      for a in away), "constr-(0,1,2), (3,)")
                elif constrList[i] == [(0, 1, 3), (2, )]:
                    model.addConstrs((x.sum(c, d, '*', h) <= bounds[i, 1]
                                      for c in cycle for d in day
                                      for h in home), "constr-(0,1,3), (2,)")
                elif constrList[i] == [(0, 2, 3), (1, )]:
                    model.addConstrs((x.sum(c, '*', a, h) <= bounds[i, 1]
                                      for c in cycle for a in away
                                      for h in home), "constr-(0,2,3), (1,)")
                elif constrList[i] == [(1, 2, 3), (0, )]:
                    model.addConstrs((x.sum('*', d, a, h) <= bounds[i, 1]
                                      for d in day for a in away
                                      for h in home), "constr-(1,2,3), (0,)")

        if bounds[34, 5] + bounds[34, 4] > 0:
            # definition for the first day
            model.addConstrs((cNH[c, 0, 0, h] == n[c, 0, h] for c in cycle
                              for h in home), "cNH1")
            model.addConstrs((cNH[c, d1 + 1, 0, h] <= n[c, d1 + 1, h]
                              for c in cycle for h in home
                              for d1 in day if d1 < len(day) - 1), "cNA2")
            model.addConstrs((cNH[c, d1 + 1, 0, h] <= 1 - n[c, d1, h]
                              for c in cycle for h in home
                              for d1 in day if d1 < len(day) - 1), "cNA3")
            model.addConstrs(
                (cNH[c, d1 + 1, 0, h] >= n[c, d1 + 1, h] - n[c, d1, h]
                 for c in cycle for d1 in day
                 for h in home if d1 < len(day) - 1), "cNA4")

            # # definition for the second day and the third, fourth, etc...
            model.addConstrs((cNH[c, 0, d2, h] == 0 for c in cycle
                              for d2 in day for h in home if d2 > 0), "2cNA1")
            model.addConstrs((cNH[c, d1, d2, h] <= cNH[c, d1 - 1, d2 - 1, h]
                              for c in cycle for h in home for d1 in day
                              for d2 in day if d1 > 0 if d2 > 0))
            model.addConstrs((cNH[c, d1, d2, h] <= n[c, d1, h] for c in cycle
                              for d1 in day for d2 in day for h in home
                              if d1 > 0 if d2 > 0))
            model.addConstrs((cNH[c, d1, d2, h] >=
                              n[c, d1, h] + cNH[c, d1 - 1, d2 - 1, h] - 1
                              for c in cycle for d1 in day for d2 in day
                              for h in home if d1 > 0 if d2 > 0))
            if bounds[34, 5] > 0:
                model.addConstr((quicksum(
                    cNH[c, d1, d2, a] for c in cycle for d1 in day
                    for a in away
                    for d2 in range(bounds[34, 5].astype(int), len(day)))
                                 == 0), "cnASum")
            if bounds[34, 4] > 0:
                model.addConstrs((cNHs[c, 0, d2, h] == 0 for c in cycle
                                  for d2 in day for h in home), "minConsPlay")
                model.addConstrs((cNHs[c, d1, d2, h] <= cNH[c, d1 - 1, d2, h]
                                  for c in cycle for h in home for d1 in day
                                  for d2 in day if d1 > 0))
                model.addConstrs((cNHs[c, d1, d2, h] <= 1 - n[c, d1, h]
                                  for c in cycle for d1 in day for d2 in day
                                  for h in home if d1 > 0))
                model.addConstrs(
                    (cNHs[c, d1, d2, h] >= cNH[c, d1 - 1, d2, h] - n[c, d1, h]
                     for c in cycle for d1 in day for d2 in day for h in home
                     if d1 > 0))
                model.addConstrs((cNHs[c, num_md_per_cycle, d2, h] >=
                                  cNH[c, num_md_per_cycle - 1, d2, h]
                                  for c in cycle for d2 in day for h in home))
                model.addConstr((quicksum(
                    cNHs[c, d1, d2, a] * (bounds[34, 4] - 1 - d2)
                    for c in cycle for a in away for d1 in days
                    for d2 in range(bounds[34, 4].astype(int) - 1)) == 0))

        if bounds[31, 5] + bounds[31, 4] > 0:
            # definition for the first day
            model.addConstrs((cNA[c, 0, 0, a] == o[c, 0, a] for c in cycle
                              for a in away), "cNA1")
            model.addConstrs((cNA[c, d1 + 1, 0, a] <= o[c, d1 + 1, a]
                              for c in cycle for a in away
                              for d1 in day if d1 < len(day) - 1), "cNA2")
            model.addConstrs((cNA[c, d1 + 1, 0, a] <= 1 - o[c, d1, a]
                              for c in cycle for a in away
                              for d1 in day if d1 < len(day) - 1), "cNA3")
            model.addConstrs(
                (cNA[c, d1 + 1, 0, a] >= o[c, d1 + 1, a] - o[c, d1, a]
                 for c in cycle for d1 in day
                 for a in away if d1 < len(day) - 1), "cNA4")

            # # definition for the second day and the third, fourth, etc...
            model.addConstrs((cNA[c, 0, d2, a] == 0 for c in cycle
                              for d2 in day for a in away if d2 > 0), "2cNA1")
            model.addConstrs((cNA[c, d1, d2, a] <= cNA[c, d1 - 1, d2 - 1, a]
                              for c in cycle for a in away for d1 in day
                              for d2 in day if d1 > 0 if d2 > 0))
            model.addConstrs((cNA[c, d1, d2, a] <= o[c, d1, a] for c in cycle
                              for d1 in day for d2 in day for a in away
                              if d1 > 0 if d2 > 0))
            model.addConstrs((cNA[c, d1, d2, a] >=
                              o[c, d1, a] + cNA[c, d1 - 1, d2 - 1, a] - 1
                              for c in cycle for d1 in day for d2 in day
                              for a in away if d1 > 0 if d2 > 0))
            if bounds[31, 5] > 0:
                model.addConstr((quicksum(
                    cNA[c, d1, d2, a] for c in cycle for d1 in day
                    for a in away
                    for d2 in range(bounds[31, 5].astype(int), len(day)))
                                 == 0), "cnASum")
            if bounds[31, 4] > 0:
                model.addConstrs((cNAs[c, 0, d2, a] == 0 for c in cycle
                                  for d2 in day for a in away), "minConsPlay")
                model.addConstrs((cNAs[c, d1, d2, a] <= cNA[c, d1 - 1, d2, a]
                                  for c in cycle for a in away for d1 in day
                                  for d2 in day if d1 > 0))
                model.addConstrs((cNAs[c, d1, d2, a] <= 1 - o[c, d1, a]
                                  for c in cycle for d1 in day for d2 in day
                                  for a in away if d1 > 0))
                model.addConstrs(
                    (cNAs[c, d1, d2, a] >= cNA[c, d1 - 1, d2, a] - o[c, d1, a]
                     for c in cycle for d1 in day for d2 in day for a in away
                     if d1 > 0))
                model.addConstrs((cNAs[c, num_md_per_cycle, d2, a] >=
                                  cNA[c, num_md_per_cycle - 1, d2, a]
                                  for c in cycle for d2 in day for a in away))
                model.addConstr((quicksum(
                    cNAs[c, d1, d2, a] * (bounds[31, 4] - 1 - d2)
                    for c in cycle for a in away for d1 in days
                    for d2 in range(bounds[31, 4].astype(int) - 1)) == 0))

        # Sets the number of solutions to be generated
        model.setParam(GRB.Param.PoolSolutions, numSam)
        # grab the most optimal solutions
        model.setParam(GRB.Param.PoolSearchMode, 2)
        model.optimize()
        numSol = model.SolCount
        print("Number of solutions found for the model: " + str(numSol))

        if model.status == GRB.Status.INFEASIBLE:
            model.computeIIS()
            print("Following constraints are infeasible: ")
            for c in model.getConstrs():
                if c.IISConstr:
                    print(c.constrName)
        if model.status == GRB.Status.OPTIMAL:
            model.write('m.sol')
        for i in range(numSol):
            model.setParam(GRB.Param.SolutionNumber, i)
            # get value from subobtimal MIP sol (might change this in X if we dont do soft constraints)
            solution = model.getAttr('xn', x)

            tmp = np.zeros([numCycle, num_md_per_cycle, num_teams, num_teams])
            for key in solution:
                tmp[key] = round(solution[key])
            tmp_sol = tmp.astype(np.int64)
            with open(os.path.join(directory, "sol" + str(i) + ".csv"),
                      "w+",
                      newline='') as sol_csv:
                csv_writer = csv.writer(sol_csv, delimiter=',')

                # writes cycle row
                row = ['']
                for c in range(numCycle):
                    row.extend(['C' + str(c)] * num_md_per_cycle * num_teams)
                csv_writer.writerow(row)

                # writes round row
                row = ['']
                for c in range(numCycle):
                    for d in range(num_md_per_cycle):
                        row.extend(['R' + str(d)] * num_teams)
                csv_writer.writerow(row)

                # writes awayteam row
                row = ['']
                for c in range(numCycle):
                    for d in range(num_md_per_cycle):
                        for t in range(num_teams):
                            row.append('T' + str(t))
                csv_writer.writerow(row)

                # write the actual solution per team
                tmp_sol.astype(int)
                for t in range(num_teams):
                    row = ['T' + str(t)]
                    for c in range(numCycle):
                        for r in range(num_md_per_cycle):
                            for team in range(num_teams):
                                row.append(tmp_sol[c][r][t][team])
                    csv_writer.writerow(row)

    except GurobiError as e:
        raise e
예제 #24
0
for i, j in arcs:
    x[i, j] = m.addVar(obj=cost[i, j], vtype='B', name='x_%s%s' % (i, j))

N = len(nodes)
for i in nodes:
    if i != nodes[N - 1]:
        u[i] = m.addVar(obj=0, name='u_%s' % i)

m.update()

for j in nodes:
    m.addConstr(
        quicksum(x[i, j] for i in nodes if i != j) == 1, 'incom_%s' % (j))
for i in nodes:
    m.addConstr(
        quicksum(x[i, j] for j in nodes if i != j) == 1, 'outgo_%s' % (i))

for i, j in arcs:
    if i != nodes[N - 1] and j != nodes[N - 1]:
        m.addConstr(u[i] - u[j] + N * x[i, j] <= N - 1,
                    'subtour_%s_%s' % (i, j))

m.optimize()

if m.status == GRB.Status.OPTIMAL:
    print 'objective: %f' % m.ObjVal
    solution = m.getAttr('x', x)
    for i, j in arcs:
        if solution[i, j] > 0:
            print('%s -> %s: %g' % (i, j, solution[i, j]))
class PathBackup(object):
    """ Class object for normal-based backup network model.

    Parameters
    ----------
    nodes: set of nodes
    links: set of links
    paths: set of paths in the graph
    Psd: set of backup paths for link (s,d). 
    Pij: set of (s,d) paths that use link (i,j).
    capacity: capacities per link based based on random failures 
    mean: mean for failure random variable
    std: standard deviation for failure random variable
    invstd: inverse of Phi-normal distribution for (1-epsilon)

    Returns
    -------
    solution: set of capacity assigned per backup link. 
    
    """
    # Private model object
    __model = []
    
    # Private model variables
    __BackupCapacity = {}
    __bPath = {}
           
    # Private model parameters
    __links = []
    __paths = []
    __nodes = []
    __capacity = []
    __mean = []
    __std = []
    __Psd = []
    __Pij = []
    __invstd = 1
    
    
    def __init__(self,nodes,links,paths,Psd,Pij,capacity,mean,std,invstd):
        '''
        Constructor
        '''
        self.__links = links
        self.__nodes = nodes
        self.__paths = paths
        self.__capacity = capacity
        self.__mean = mean
        self.__std = std
        self.__invstd = invstd
        self.__Psd = Psd
        self.__Pij = Pij
                
        self.__loadModel()
                
    def __loadModel(self):
                
        # Create optimization model
        self.__model = Model('PathBackup')
    
        # Auxiliary variables for SOCP reformulation
        U = {}
        R = {}
        
        # Create variables
        for i,j in self.__links:
            self.__BackupCapacity[i,j] = self.__model.addVar(lb=0, obj=1, name='Backup_Capacity[%s,%s]' % (i, j))
        self.__model.update()
         
        for p in self.__paths:
            #LP Relaxation
            #self.__bPath[self.__paths.index(p)] = self.__model.addVar(lb=0,obj=1,name='Backup_Path[%s]' % (self.__paths.index(p)))
            self.__bPath[self.__paths.index(p)] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Path[%s]' % (self.__paths.index(p)))
        self.__model.update()
        
        for i,j in self.__links:
            U[i,j] = self.__model.addVar(obj=1,name='U[%s,%s]' % (i, j))
        self.__model.update()
        
        for i,j in self.__links:
            for s,d in self.__links:
                R[i,j,s,d] = self.__model.addVar(obj=1,name='R[%s,%s,%s,%s]' % (i,j,s,d))
        self.__model.update()
        
        self.__model.modelSense = GRB.MINIMIZE
        self.__model.setObjective(quicksum(self.__BackupCapacity[i,j] for i,j in self.__links))
        self.__model.update()
        
           
        #------------------------------------------------------------------------#
        #                    Constraints definition                              #
        #                                                                        #
        #                                                                        #
        #------------------------------------------------------------------------#
         
        # Link capacity constraints
        for i,j in self.__links:
            self.__model.addConstr(self.__BackupCapacity[i,j] >= quicksum(self.__mean[s,d]*quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Pij[i,j,s,d]) for s,d in self.__links) + U[i,j]*self.__invstd,'[CONST]Link_Cap[%s][%s]' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints
        for i,j in self.__links:
            self.__model.addConstr(quicksum(R[i,j,s,d]*R[i,j,s,d] for s,d in self.__links) <= U[i,j]*U[i,j],'[CONST]SCOP1[%s][%s]' % (i, j))
        self.__model.update()
            
        # SCOP Reformulation Constraints    
        for i,j in self.__links:
            for s,d in self.__links:
                self.__model.addConstr(self.__std[s,d]*quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Pij[i,j,s,d]) == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i,j,s,d))
        self.__model.update()
        
        # Unique path 
        for s,d in self.__links:
            self.__model.addConstr(quicksum(self.__bPath[self.__paths.index(p)] for p in self.__Psd[s,d]) == 1,'UniquePath[%s,%s]' % (s, d))
        self.__model.update()
        
    def optimize(self,MipGap,TimeLimit):
        
        self.__model.write('pathbackup.lp')
 
        if TimeLimit != None:
            self.__model.params.timeLimit = TimeLimit
        
        if MipGap != None:
            self.__model.params.MIPGap=MipGap
         
        # Compute optimal solution
        self.__model.optimize()
        
        # Print solution
        if self.__model.status == GRB.Status.OPTIMAL:
            solution = self.__model.getAttr('x', self.__bPath)
            for p in self.__paths:
                if solution[self.__paths.index(p)] > 0.001:
                    print('Path[%s] = %s = %s' % (self.__paths.index(p),p,solution[self.__paths.index(p)]))
            solution = self.__model.getAttr('x', self.__BackupCapacity)
            for i,j in self.__links:
                if solution[i,j] > 0:
                    print('%s -> %s: %g' % (i, j, solution[i,j]))
            
        else:
            print('Optimal value not found!\n')
            solution = self.__model.getAttr('x', self.__BackupCapacity)
            for i,j in self.__links:
                if solution[i,j] > 0:
                    print('%s -> %s: %g' % (i, j, solution[i,j]))
            #solution = []
            
        return solution;    
    
    def reset(self):
        '''
        Reset model solution
        '''
        self.__model.reset()
예제 #26
0
def optimize_pareto(n, h, u, ju_s, ju_l, jn_s, jn_l, w):

    # check input parameters
    if ju_l == jn_l or ju_s == jn_s:
        return 'worst and best overlap'
    # create a model
    m = Model('Pareto')
    # create decision variables
    x = m.addVars(sa, sa, vtype=GRB.BINARY, name='x')
    y = m.addVars(sa, dc, vtype=GRB.BINARY, name='y')

    # add constraints
    # x is symmetric
    m.addConstrs((x[i, j] == x[j, i] for i in sa for j in sa),
                 'symmetric constraint')
    # Two service areas cant use the same stateful functions when x[i,j] = 0
    m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in sa for j in sa
                  for t in dc), 'x = 0 constraint')
    # Two service areas use the same stateful functions when x[i,j] = 1
    m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in sa for j in sa
                  for t in dc), 'x = 1 constraint')
    # Each should be at least managed by one dc
    m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in sa),
                 'one dc for one sa')
    # high availability constraint
    m.addConstr(
        sum((1 - x[i, j]) for i in sa for j in sa if i != j) >= 1, 'ha')
    # maximum state transfer frequency
    m.addConstr(
        sum(h * (1 - x[i, j]) for i in sa for j in sa if i != j) <= jn_s - 1,
        'max state transfer constraint')
    # maximum traffic load constraint
    m.addConstr((sum(y[i, dc[0]] * n * (L_sig + u * L_session)
                     for i in sa) <= jn_l - 1), 'load maximum constraint')
    # dc0 will have the most heavy load
    for t in dc:
        if t != dc[0]:
            m.addConstr(
                sum(y[i, t] * n * (L_sig + u * L_session)
                    for i in sa) <= sum(y[i, dc[0]] * n *
                                        (L_sig + u * L_session)
                                        for i in sa), 'less than max load')

    # Objective function
    m.setObjective((1 - w) * (sum(y[i, dc[0]] * n * (L_sig + u * L_session)
                                  for i in sa) - ju_l) / (jn_l - ju_l) + w *
                   (sum(h * (1 - x[i, j]) for i in sa
                        for j in sa if i != j) - ju_s) / (jn_s - ju_s),
                   GRB.MINIMIZE)

    m.optimize()

    # check model feasible or not
    if m.getAttr('status') == GRB.INFEASIBLE:
        return 'infeasible'

    # Calculate performance metrics
    # traffic load on stateful functions
    traffic_load = sum(
        getattr(y[i, dc[0]], 'X') * n * (L_sig + u * L_session) for i in sa)

    # state transfer frequency
    state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in sa
                         for j in sa if i != j)

    # number of functions
    num_func = M_dc - sum(
        prod(1 - getattr(y[i, t], 'X') for i in sa) for t in dc)

    # total metrics
    total_metrics = [u, h, u, state_transfer, traffic_load, num_func]

    return total_metrics
예제 #27
0
def WassersteinDualCutting(h1, h2, M):
    """ Find the Wasserstein distance using a cutting plane on the dual """
    n = len(h1)
    P = []
    for i in range(n):
        for j in range(n):
            P.append((i, j))

    # Build model
    m = Model()
    m.setParam(GRB.Param.TimeLimit, 300)
    #m.setParam(GRB.Param.Presolve,    0)
    #m.setParam(GRB.Param.Threads,     1)
    #  Options are:
    #      -1=automatic, 0=primal simplex, 1=dual simplex, 2=barrier,
    #                    3=concurrent, 4=deterministic concurrent.
    m.setParam(GRB.Param.Method, 1)

    # Set a maximization problem
    m.setAttr(GRB.Attr.ModelSense, -1)

    print('1. Start building model')
    # Create variables
    V = {}
    U = {}
    for i, j in P:
        # First set of dual variables
        V[i, j] = m.addVar(lb=-GRB.INFINITY, ub=0, obj=h1[i, j])
        # Second set of dual variables
        u_ub = sum([M[v, w][i, j] for v, w in P])
        U[i, j] = m.addVar(lb=0, ub=u_ub, obj=h2[i, j])

    m.update()
    print('2. Add initial constraint sets')
    for i, j in P:
        for v, w in P:
            if M[i, j][v,
                       w] <= 16.001:  # Threshold for first set of constraints
                m.addConstr(V[i, j] + U[v, w], GRB.LESS_EQUAL, M[i, j][v, w])

    print('3. Start Cutting planes')
    # Solve the model
    it = 0
    stime = 0
    while True:
        it += 1
        m.optimize()
        break
        stime += m.RunTime
        flag = True
        max_depth = 0
        for i, j in P:
            depth = -1
            a, b, c, d = -1, -1, -1, -1
            for v, w in P:
                if V[i, j].X + U[v, w].X - M[i, j][v, w] > depth:
                    a, b, c, d = i, j, v, w
                    depth = V[i, j].X + U[v, w].X - M[i, j][v, w]
            if (max_depth == 0 and depth > 0.001) or (depth >= max_depth):
                max_depth = max(max_depth, depth)
                flag = False
                m.addConstr(V[a, b] + U[c, d], GRB.LESS_EQUAL, M[a, b][c, d])
        print('ITERATION:', it, ' MAX DEPTH:', round(max_depth, 3), ' Time:',
              round(stime, 3))
        if flag:
            break
        #else:
        #    m.addConstr(V[a,b] + U[c,d], GRB.LESS_EQUAL, M[a,b][c,d])

    return m.getAttr(GRB.Attr.ObjVal)
예제 #28
0
def generatesSample(
    num_days,
    num_shifts,
    num_nurses,
    numSam,
    bounds,
    constrList,
    partial_sol,
    x_mapping,
    y_mapping,
    gid,
):

    N = list(range(num_nurses))
    D = list(range(num_days))
    Ds = list(range(num_days + 1))
    S = list(range(num_shifts))
    Ss = list(range(num_shifts + 1))
    #    Sk=list(range(2))

    #    constrList=[[(0,),(1,)],[(0,),(2,)],[(0,),(1,2)],[(1,),(0,)],[(1,),(2,)],[(1,),(0,2)],[(2,),(0,)],[(2,),(1,)],[(2,),(0,1)],[(0,1),(2,)],[(0,2),(1,)],[(1,2),(0,)]]

    try:
        sys.stdout = open(os.devnull, "w")
        m = Model("nspSolver")
        sys.stdout = sys.__stdout__
        m.setParam(GRB.Param.OutputFlag, 0)
        ########### Decision Variables #############
        #        x = m.addVars(N,D,S,Sk, vtype=GRB.BINARY, name="x")
        o = m.addVars(N, D, S, vtype=GRB.BINARY, name="o")
        p = m.addVars(N, D, vtype=GRB.BINARY, name="p")
        q = m.addVars(N, S, vtype=GRB.BINARY, name="q")
        r = m.addVars(S, D, vtype=GRB.BINARY, name="r")

        tw = m.addVars(N, D, D, vtype=GRB.BINARY, name="tw")
        sw = m.addVars(N, Ds, D, vtype=GRB.BINARY, name="sw")
        tw1 = m.addVars(N, D, S, D, vtype=GRB.BINARY, name="tw1")
        sw1 = m.addVars(N, Ds, S, D, vtype=GRB.BINARY, name="sw1")

        tws = m.addVars(N, S, S, vtype=GRB.BINARY, name="tws")
        sws = m.addVars(N, Ss, S, vtype=GRB.BINARY, name="sws")
        tfs = m.addVars(N, S, S, vtype=GRB.BINARY, name="tfs")
        sfs = m.addVars(N, Ss, S, vtype=GRB.BINARY, name="sfs")

        tf = m.addVars(N, D, D, vtype=GRB.BINARY, name="tf")
        sf = m.addVars(N, Ds, D, vtype=GRB.BINARY, name="sf")
        tw1f = m.addVars(N, D, S, D, vtype=GRB.BINARY, name="tw1f")
        sw1f = m.addVars(N, Ds, S, D, vtype=GRB.BINARY, name="sw1f")

        ########### Required Constraints #############
        for n in N:
            for d in D:
                for s in S:
                    if not np.isnan(partial_sol[n, d, s]):
                        m.addConstr((o[n, d, s] == partial_sol[n, d, s]),
                                    "partial solution")

        m.addConstrs((o.sum(n, d, "*") == p[n, d] for n in N for d in D), "po")

        #        m.addConstrs((x.sum(n,d,s,'*')==o[n,d,s] for n in N for d in D for s in S),"xo")
        #        m.addConstrs((x[n,d,s,sk]==o[n,d,s] for n in N for d in D for s in S for sk in Sk if nurse_skill[n]==sk),"xo")
        #        m.addConstrs((x[n,d,s,sk]==0 for n in N for d in D for s in S for sk in Sk if nurse_skill[n]!=sk),"xo")
        m.addConstrs((q[n, s] <= o.sum(n, "*", s) for n in N for s in S), "qo")
        m.addConstrs((q[n, s] * o.sum(n, "*", s) == o.sum(n, "*", s) for n in N
                      for s in S), "qo")
        m.addConstrs((r[s, d] <= o.sum("*", d, s) for d in D for s in S), "ro")
        m.addConstrs((r[s, d] * o.sum("*", d, s) == o.sum("*", d, s) for d in D
                      for s in S), "ro")

        ########### Hard Constraints #############
        #        print(bounds)
        for i in range(len(bounds)):
            if bounds[i, 0] > 0:
                #                print(bounds[i,0])
                if constrList[i] == "0:1":
                    m.addConstrs((r.sum("*", d) >= bounds[i, 0] for d in D),
                                 "constr")

                elif constrList[i] == "0:2":
                    m.addConstrs((p.sum("*", d) >= bounds[i, 0] for d in D),
                                 "constr")

                elif constrList[i] == "0:1,2":
                    m.addConstrs((o.sum("*", d, "*") >= bounds[i, 0]
                                  for d in D), "constr")

                elif constrList[i] == "1:0":
                    m.addConstrs((r.sum(s, "*") >= bounds[i, 0] for s in S),
                                 "constr")

                elif constrList[i] == "1:2":
                    m.addConstrs((q.sum("*", s) >= bounds[i, 0] for s in S),
                                 "constr")

                elif constrList[i] == "1:0,2":
                    m.addConstrs((o.sum("*", "*", s) >= bounds[i, 0]
                                  for s in S), "constr")

                elif constrList[i] == "2:0":
                    m.addConstrs((p.sum(n, "*") >= bounds[i, 0] for n in N),
                                 "constr")

                elif constrList[i] == "2:1":
                    m.addConstrs((q.sum(n, "*") >= bounds[i, 0] for n in N),
                                 "constr")

                elif constrList[i] == "2:0,1":
                    m.addConstrs((o.sum(n, "*", "*") >= bounds[i, 0]
                                  for n in N), "constr")

                elif constrList[i] == "0,1:2":
                    m.addConstrs(
                        (o.sum("*", d, s) >= bounds[i, 0] for d in D
                         for s in S),
                        "constr",
                    )

                elif constrList[i] == "0,2:1":
                    m.addConstrs(
                        (o.sum(n, d, "*") >= bounds[i, 0] for d in D
                         for n in N),
                        "constr",
                    )

                elif constrList[i] == "1,2:0":
                    m.addConstrs(
                        (o.sum(n, "*", s) >= bounds[i, 0] for n in N
                         for s in S),
                        "constr",
                    )

            if bounds[i, 1] > 0:
                #                print(bounds[i,1])
                if constrList[i] == "0:1":
                    m.addConstrs((r.sum("*", d) <= bounds[i, 1] for d in D),
                                 "constr")

                elif constrList[i] == "0:2":
                    m.addConstrs((p.sum("*", d) <= bounds[i, 1] for d in D),
                                 "constr")

                elif constrList[i] == "0:1,2":
                    m.addConstrs((o.sum("*", d, "*") <= bounds[i, 1]
                                  for d in D), "constr")

                elif constrList[i] == "1:0":
                    m.addConstrs((r.sum(s, "*") <= bounds[i, 1] for s in S),
                                 "constr")

                elif constrList[i] == "1:2":
                    m.addConstrs((q.sum("*", s) <= bounds[i, 1] for s in S),
                                 "constr")

                elif constrList[i] == "1:0,2":
                    m.addConstrs((o.sum("*", "*", s) <= bounds[i, 1]
                                  for s in S), "constr")

                elif constrList[i] == "2:0":
                    m.addConstrs((p.sum(n, "*") <= bounds[i, 1] for n in N),
                                 "constr")

                elif constrList[i] == "2:1":
                    m.addConstrs((q.sum(n, "*") <= bounds[i, 1] for n in N),
                                 "constr")

                elif constrList[i] == "2:0,1":
                    m.addConstrs((o.sum(n, "*", "*") <= bounds[i, 1]
                                  for n in N), "constr")

                elif constrList[i] == "0,1:2":
                    m.addConstrs(
                        (o.sum("*", d, s) <= bounds[i, 1] for d in D
                         for s in S),
                        "constr",
                    )

                elif constrList[i] == "0,2:1":
                    m.addConstrs(
                        (o.sum(n, d, "*") <= bounds[i, 1] for d in D
                         for n in N),
                        "constr",
                    )

                elif constrList[i] == "1,2:0":
                    m.addConstrs(
                        (o.sum(n, "*", s) <= bounds[i, 1] for n in N
                         for s in S),
                        "constr",
                    )

            #        if mt==1:
            #            for i in range(len(nurse_preference)):
            #                m.addConstr((o[i,nurse_preference[i][0],nurse_preference[i][1]] == 0),"nursePref")

            if constrList[i] == "2:0" and bounds[i, 5] + bounds[i, 4] > 0:
                m.addConstrs((tw[n, 0, 0] == p[n, 0] for n in N),
                             "MaxConsWork")
                m.addConstrs(
                    (tw[n, d1 + 1, 0] <= p[n, d1 + 1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tw[n, d1 + 1, 0] <= 1 - p[n, d1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tw[n, d1 + 1, 0] >= p[n, d1 + 1] - p[n, d1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsWork",
                )

                m.addConstrs((tw[n, 0, d2] == 0 for n in N
                              for d2 in D if d2 > 0), "MaxConsWork")
                m.addConstrs(
                    (tw[n, d1, d2] <= tw[n, d1 - 1, d2 - 1] for n in N
                     for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tw[n, d1, d2] <= p[n, d1] for n in N for d1 in D
                     for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tw[n, d1, d2] >= p[n, d1] + tw[n, d1 - 1, d2 - 1] - 1
                     for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsWork",
                )
                if bounds[i, 5] > 0:
                    m.addConstr(
                        (quicksum(tw[n, d1, d2] for n in N for d1 in D
                                  for d2 in range(bounds[i, 5], len(D))) == 0),
                        "maxconswork",
                    )
                if bounds[i, 4] > 0:
                    m.addConstrs((sw[n, 0, d2] == 0 for n in N for d2 in D),
                                 "MinConsWork")
                    m.addConstrs(
                        (sw[n, d1, d2] <= tw[n, d1 - 1, d2] for n in N
                         for d1 in D for d2 in D if d1 > 0),
                        "MinConsWork",
                    )
                    m.addConstrs(
                        (sw[n, d1, d2] <= 1 - p[n, d1] for n in N for d1 in D
                         for d2 in D if d1 > 0),
                        "MinConsWork",
                    )
                    m.addConstrs(
                        (sw[n, d1, d2] >= tw[n, d1 - 1, d2] - p[n, d1]
                         for n in N for d1 in D for d2 in D if d1 > 0),
                        "MinConsWork",
                    )

                    m.addConstrs(
                        (sw[n, num_days, d2] == tw[n, num_days - 1, d2]
                         for n in N for d2 in D),
                        "MinConsWork",
                    )

                    m.addConstr(
                        (quicksum(sw[n, d1, d2] * (bounds[i, 4] - 1 - d2)
                                  for n in N for d1 in Ds
                                  for d2 in range(bounds[i, 4] - 1)) == 0),
                        "minconswork",
                    )

            if constrList[i] == [(2, ),
                                 (0, )] and bounds[i, 3] + bounds[i, 2] > 0:
                m.addConstrs((tf[n, 0, 0] == 1 - p[n, 0] for n in N),
                             "MaxConsFree")
                m.addConstrs(
                    (tf[n, d1 + 1, 0] <= p[n, d1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tf[n, d1 + 1, 0] <= 1 - p[n, d1 + 1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tf[n, d1 + 1, 0] >= p[n, d1] - p[n, d1 + 1] for n in N
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )

                m.addConstrs((tf[n, 0, d2] == 0 for n in N
                              for d2 in D if d2 > 0), "MaxConsFree")
                m.addConstrs(
                    (tf[n, d1, d2] <= tf[n, d1 - 1, d2 - 1] for n in N
                     for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tf[n, d1, d2] <= 1 - p[n, d1] for n in N for d1 in D
                     for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tf[n, d1, d2] >= tf[n, d1 - 1, d2 - 1] - p[n, d1]
                     for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                if bounds[i, 3] > 0:
                    m.addConstr(
                        (quicksum(tf[n, d1, d2] for n in N for d1 in D
                                  for d2 in range(bounds[i, 3], len(D))) == 0),
                        "maxconsfree",
                    )

                if bounds[i, 2] > 0:
                    m.addConstrs((sf[n, 0, d2] == 0 for n in N for d2 in D),
                                 "MinConsFree")
                    m.addConstrs(
                        (sf[n, d1, d2] <= tf[n, d1 - 1, d2] for n in N
                         for d1 in D for d2 in D if d1 > 0),
                        "MinConsFree",
                    )
                    m.addConstrs(
                        (sf[n, d1, d2] <= p[n, d1] for n in N for d1 in D
                         for d2 in D if d1 > 0),
                        "MinConsFree",
                    )
                    m.addConstrs(
                        (sf[n, d1, d2] >= tf[n, d1 - 1, d2] + p[n, d1] - 1
                         for n in N for d1 in D for d2 in D if d1 > 0),
                        "MinConsFree",
                    )

                    m.addConstrs(
                        (sf[n, num_days, d2] == tf[n, num_days - 1, d2]
                         for n in N for d2 in D),
                        "MinConsFree",
                    )

                    m.addConstr(
                        (quicksum(sf[n, d1, d2] * (bounds[i, 2] - 1 - d2)
                                  for n in N for d1 in Ds
                                  for d2 in range(bounds[i, 2] - 1)) == 0),
                        "minconsfree",
                    )

            if constrList[i] == [(2, ),
                                 (1, )] and bounds[i, 5] + bounds[i, 4] > 0:
                m.addConstrs((tws[n, 0, 0] == q[n, 0] for n in N),
                             "MaxConsWork")
                m.addConstrs(
                    (tws[n, s1 + 1, 0] <= q[n, s1 + 1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tws[n, s1 + 1, 0] <= 1 - q[n, s1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tws[n, s1 + 1, 0] >= q[n, s1 + 1] - q[n, s1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsWork",
                )

                m.addConstrs((tws[n, 0, s2] == 0 for n in N
                              for s2 in S if s2 > 0), "MaxConsWork")
                m.addConstrs(
                    (tws[n, s1, s2] <= tws[n, s1 - 1, s2 - 1] for n in N
                     for s1 in S for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tws[n, s1, s2] <= q[n, s1] for n in N for s1 in S
                     for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsWork",
                )
                m.addConstrs(
                    (tws[n, s1, s2] >= q[n, s1] + tws[n, s1 - 1, s2 - 1] - 1
                     for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsWork",
                )

                if bounds[i, 5] > 0:
                    m.addConstr(
                        (quicksum(tws[n, s1, s2] for n in N for s1 in S
                                  for s2 in range(bounds[i, 5], len(S))) == 0),
                        "maxconswork",
                    )

                if bounds[i, 4] > 0:
                    m.addConstrs((sws[n, 0, s2] == 0 for n in N for s2 in S),
                                 "MinConsWork")
                    m.addConstrs(
                        (sws[n, s1, s2] <= tws[n, s1 - 1, s2] for n in N
                         for s1 in S for s2 in S if s1 > 0),
                        "MinConsWork",
                    )
                    m.addConstrs(
                        (sws[n, s1, s2] <= 1 - q[n, s1] for n in N for s1 in S
                         for s2 in S if s1 > 0),
                        "MinConsWork",
                    )
                    m.addConstrs(
                        (sws[n, s1, s2] >= tws[n, s1 - 1, s2] - q[n, s1]
                         for n in N for s1 in S for s2 in S if s1 > 0),
                        "MinConsWork",
                    )

                    m.addConstrs(
                        (sws[n, num_shifts, s2] == tws[n, num_shifts - 1, s2]
                         for n in N for s2 in S),
                        "MinConsWork",
                    )

                    m.addConstr(
                        (quicksum(sws[n, s1, s2] * (bounds[i, 4] - 1 - s2)
                                  for n in N for s1 in Ss
                                  for s2 in range(bounds[i, 4] - 1)) == 0),
                        "minconswork",
                    )

            if constrList[i] == [(2, ),
                                 (1, )] and bounds[i, 3] + bounds[i, 2] > 0:
                m.addConstrs((tfs[n, 0, 0] == 1 - q[n, 0] for n in N),
                             "MaxConsFree")
                m.addConstrs(
                    (tfs[n, s1 + 1, 0] <= q[n, s1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tfs[n, s1 + 1, 0] <= 1 - q[n, s1 + 1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tfs[n, s1 + 1, 0] >= q[n, s1] - q[n, s1 + 1] for n in N
                     for s1 in S if s1 < len(S) - 1),
                    "MaxConsFree",
                )

                m.addConstrs((tfs[n, 0, s2] == 0 for n in N
                              for s2 in S if s2 > 0), "MaxConsFree")
                m.addConstrs(
                    (tfs[n, s1, s2] <= tfs[n, s1 - 1, s2 - 1] for n in N
                     for s1 in S for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tfs[n, s1, s2] <= 1 - q[n, s1] for n in N for s1 in S
                     for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tfs[n, s1, s2] >= tfs[n, s1 - 1, s2 - 1] - q[n, s1]
                     for n in N for s1 in S for s2 in S if s1 > 0 if s2 > 0),
                    "MaxConsFree",
                )
                if bounds[i, 3] > 0:
                    m.addConstr(
                        (quicksum(tfs[n, s1, s2] for n in N for s1 in S
                                  for s2 in range(bounds[i, 3], len(S))) == 0),
                        "maxconsfree",
                    )

                if bounds[i, 2] > 0:
                    m.addConstrs((sfs[n, 0, s2] == 0 for n in N for s2 in S),
                                 "MinConsFree")
                    m.addConstrs(
                        (sfs[n, s1, s2] <= tfs[n, s1 - 1, s2] for n in N
                         for s1 in S for s2 in S if s1 > 0),
                        "MinConsFree",
                    )
                    m.addConstrs(
                        (sfs[n, s1, s2] <= q[n, s1] for n in N for s1 in S
                         for s2 in S if s1 > 0),
                        "MinConsFree",
                    )
                    m.addConstrs(
                        (sfs[n, s1, s2] >= tfs[n, s1 - 1, s2] + q[n, s1] - 1
                         for n in N for s1 in S for s2 in S if s1 > 0),
                        "MinConsFree",
                    )

                    m.addConstrs(
                        (sfs[n, num_shifts, s2] == tfs[n, num_shifts - 1, s2]
                         for n in N for s2 in S),
                        "MinConsWork",
                    )

                    m.addConstr(
                        (quicksum(sfs[n, s1, s2] * (bounds[i, 2] - 1 - s2)
                                  for n in N for s1 in Ss
                                  for s2 in range(bounds[i, 2] - 1)) == 0),
                        "minconsfree",
                    )

            if constrList[i] == [(1, 2),
                                 (0, )] and bounds[i, 5] + bounds[i, 4] > 0:
                m.addConstrs(
                    (tw1[n, 0, s, 0] == o[n, 0, s] for n in N for s in S),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1 + 1, s, 0] <= o[n, d1 + 1, s] for s in S
                     for n in N for d1 in D if d1 < len(D) - 1),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1 + 1, s, 0] <= 1 - o[n, d1, s] for s in S
                     for n in N for d1 in D if d1 < len(D) - 1),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1 + 1, s, 0] >= o[n, d1 + 1, s] - o[n, d1, s]
                     for s in S for n in N for d1 in D if d1 < len(D) - 1),
                    "MaxConsSameShift",
                )

                m.addConstrs(
                    (tw1[n, 0, s, d2] == 0 for s in S for n in N
                     for d2 in D if d2 > 0),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1, s, d2] <= tw1[n, d1 - 1, s, d2 - 1] for s in S
                     for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1, s, d2] <= o[n, d1, s] for s in S for n in N
                     for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsSameShift",
                )
                m.addConstrs(
                    (tw1[n, d1, s, d2] >=
                     o[n, d1, s] + tw1[n, d1 - 1, s, d2 - 1] - 1 for s in S
                     for n in N for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsSameShift",
                )
                if bounds[i, 5] > 0:
                    m.addConstr(
                        (quicksum(tw1[n, d1, s, d2] for s in S for n in N
                                  for d1 in D
                                  for d2 in range(bounds[i, 5], len(D))) == 0),
                        "maxconssameshift",
                    )

                if bounds[i, 4] > 0:
                    m.addConstrs(
                        (sw1[n, 0, s, d2] == 0 for s in S for n in N
                         for d2 in D),
                        "MinConsSameShift",
                    )
                    m.addConstrs(
                        (sw1[n, d1, s, d2] <= tw1[n, d1 - 1, s, d2] for s in S
                         for n in N for d1 in D for d2 in D if d1 > 0),
                        "MinConsSameShift",
                    )
                    m.addConstrs(
                        (sw1[n, d1, s, d2] <= 1 - o[n, d1, s] for s in S
                         for n in N for d1 in D for d2 in D if d1 > 0),
                        "MinConsSameShift",
                    )
                    m.addConstrs(
                        (sw1[n, d1, s, d2] >=
                         tw1[n, d1 - 1, s, d2] - o[n, d1, s] for s in S
                         for n in N for d1 in D for d2 in D if d1 > 0),
                        "MinConsSameShift",
                    )

                    m.addConstrs(
                        (sw1[n, num_days, s, d2] == tw1[n, num_days - 1, s, d2]
                         for n in N for s in S for d2 in D),
                        "MinConsWork",
                    )

                    m.addConstr(
                        (quicksum(sw1[n, d1, s, d2] * (bounds[i, 4] - 1 - d2)
                                  for s in S for n in N for d1 in Ds
                                  for d2 in range(bounds[i, 4] - 1)) == 0),
                        "minconssameshift",
                    )

            if constrList[i] == [(1, 2),
                                 (0, )] and bounds[i, 3] + bounds[i, 2] > 0:
                m.addConstrs(
                    (tw1f[n, 0, s, 0] == 1 - o[n, 0, s] for n in N for s in S),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1 + 1, s, 0] <= o[n, d1, s] for n in N for s in S
                     for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1 + 1, s, 0] <= 1 - o[n, d1 + 1, s] for n in N
                     for s in S for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1 + 1, s, 0] >= o[n, d1, s] - o[n, d1 + 1, s]
                     for n in N for s in S for d1 in D if d1 < len(D) - 1),
                    "MaxConsFree",
                )

                m.addConstrs(
                    (tw1f[n, 0, s, d2] == 0 for n in N for s in S
                     for d2 in D if d2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1, s, d2] <= tw1f[n, d1 - 1, s, d2 - 1]
                     for n in N for s in S for d1 in D
                     for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1, s, d2] <= 1 - o[n, d1, s] for n in N
                     for s in S for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                m.addConstrs(
                    (tw1f[n, d1, s, d2] >=
                     tw1f[n, d1 - 1, s, d2 - 1] - o[n, d1, s] for n in N
                     for s in S for d1 in D for d2 in D if d1 > 0 if d2 > 0),
                    "MaxConsFree",
                )
                if bounds[i, 3] > 0:
                    m.addConstr(
                        (quicksum(tw1f[n, d1, s, d2] for n in N for s in S
                                  for d1 in D
                                  for d2 in range(bounds[i, 3], len(D))) == 0),
                        "maxconsfree",
                    )

                if bounds[i, 2] > 0:
                    m.addConstrs(
                        (sw1f[n, 0, s, d2] == 0 for n in N for s in S
                         for d2 in D),
                        "MinConsw1free",
                    )
                    m.addConstrs(
                        (sw1f[n, d1, s, d2] <= tw1f[n, d1 - 1, s, d2]
                         for n in N for s in S for d1 in D
                         for d2 in D if d1 > 0),
                        "MinConsw1free",
                    )
                    m.addConstrs(
                        (sw1f[n, d1, s, d2] <= o[n, d1, s] for n in N
                         for s in S for d1 in D for d2 in D if d1 > 0),
                        "MinConsw1free",
                    )
                    m.addConstrs(
                        (sw1f[n, d1, s, d2] >=
                         tw1f[n, d1 - 1, s, d2] + o[n, d1, s] - 1 for n in N
                         for s in S for d1 in D for d2 in D if d1 > 0),
                        "MinConsw1free",
                    )

                    m.addConstrs(
                        (sw1f[n, num_days, s, d2]
                         == tw1f[n, num_days - 1, s, d2] for n in N for s in S
                         for d2 in D),
                        "MinConsWork",
                    )

                    m.addConstr(
                        (quicksum(sw1f[n, d1, s, d2] * (bounds[i, 2] - 1 - d2)
                                  for n in N for s in S for d1 in Ds
                                  for d2 in range(bounds[i, 2] - 1)) == 0),
                        "minconsw1free",
                    )

        m.setParam(GRB.Param.PoolSolutions, numSam)
        m.setParam(GRB.Param.PoolSearchMode, 2)
        m.optimize()
        nSolutions = m.SolCount
        # print("Number of solutions found: " + str(nSolutions))
        if m.status == GRB.Status.INFEASIBLE:
            m.computeIIS()
            # print("\nThe following constraint(s) cannot be satisfied:")
            for c in m.getConstrs():
                if c.IISConstr:
                    # print("%s" % c.constrName)
                    pass
        # if m.status == GRB.Status.OPTIMAL:
        #     m.write("m.sol")
        #        print(nSolutions)
        #        print(partial_sol)
        multi_predictions = []
        for i in range(nSolutions):
            provenance = ("countor", gid + "-" + str(uuid4()))
            m.setParam(GRB.Param.SolutionNumber, i)
            solution = m.getAttr("xn", o)
            #             print(m.getAttr("xn", p))
            tmp = np.zeros([num_nurses, num_days, num_shifts])
            for key in solution:
                tmp[key] = round(solution[key])
            #            tSample=np.swapaxes(np.swapaxes(tmp,0,1),1,2)
            tmp_sol = tmp.astype(int)

            #            print(partial_sol)
            for n in N:
                for d in D:
                    for s in S:
                        #                        print(x_mapping[n,d,s],y_mapping[n,d,s])
                        if np.isnan(partial_sol[n, d, s]):
                            #                            print("geer")
                            multi_predictions.append(
                                Prediction(
                                    Coordinate(
                                        y_mapping[n, d, s].item(),
                                        x_mapping[n, d, s].item(),
                                    ),
                                    tmp_sol[n, d, s].item(),
                                    1,
                                    provenance,
                                ))
        return multi_predictions

    except GurobiError as e:
        print("Error code " + str(e.errno) + ": " + str(e))

    except AttributeError:
        print("Encountered an attribute error")
예제 #29
0
def solve_tsp_gurobi(D, selected_idxs):
    #print
    #print "============== GUROBI ============="

    n = len(selected_idxs)
    if selected_idxs[0] == selected_idxs[-1]:
        n = n - 1

    # no need to invoke Gurobi for tiny TSP cases
    if n <= 3:
        sol = None
        obj_f = 0.0
        if n > 1:
            sol = list(selected_idxs)
            if sol[0] != sol[-1]:
                sol.append(sol[0])
            obj_f = sum(D[sol[i - 1], sol[i]] for i in range(1, len(sol)))
        return sol, obj_f

    m = Model("TSP")
    m.params.OutputFlag = 0

    # Create variables
    edgevars = {}

    for i in range(n):
        for j in range(i + 1):
            from_node = selected_idxs[i]
            to_node = selected_idxs[j]
            edgevars[i, j] = m.addVar(obj=D[from_node, to_node],
                                      vtype=GRB.BINARY,
                                      name='e' + str(i) + '_' + str(j))
            edgevars[j, i] = edgevars[i, j]
        m.update()

    # Add degree-2 constraint, and forbid loops
    for i in range(n):
        m.addConstr(quicksum(edgevars[i, j] for j in range(n)) == 2)
        edgevars[i, i].ub = 0
    m.update()

    # Optimize model
    m._vars = edgevars
    m.params.LazyConstraints = 1
    m.setParam('TimeLimit', MAX_MIP_SOLVER_RUNTIME)
    m.setParam('Threads', MIP_SOLVER_THREADS)

    m.optimize(_subtourelim)

    # restore SIGINT callback handler which is changed by gurobipy
    signal(SIGINT, default_int_handler)

    status = m.Status
    if status == GRB.TIME_LIMIT:
        raise GurobiError(
            10023, "Gurobi timeout reached when attempting to solve TSP")
    elif m.Status == GRB.INTERRUPTED:
        raise KeyboardInterrupt()

    solution = m.getAttr('x', edgevars)
    selected = [(i, j) for i in range(n) for j in range(n)
                if solution[i, j] > 0.5]
    cycles = _subtour(selected, n)
    assert len(cycles) == n

    # make the route always start from the 1st index
    sol = [selected_idxs[i] for i in cycles] + [selected_idxs[0]]
    obj_f = m.objVal
    return sol, obj_f
class BFPBackupNetwork_Continuous(object):
    """ Class object for buffered failure probability-based model.

    Parameters
    ----------
    Gamma: importance sampling vector
    Nodes: set of nodes
    Links: set of links
    Capacity: capacities per link based based on random failures 
    Survivability: desired survivabiliy factor (epsilon)
    K: number of random scenarios
    
    Returns
    -------
    BackupCapacity: set of capacity per backup link. 
    BackupRoutes: set of backup links
    
    """

    # Private model object
    model = []

    # Private model variables
    BackupCapacity = {}
    bBackupLink = {}
    z0 = {}
    z = {}

    def __init__(self):
        """
        Constructor
        """

    def LoadModel(self, Gamma, Nodes, Links, Capacity, Survivability, NumSamples):
        """ Load model.
    
        Parameters
        ----------
        Gamma : importance sampling vector
        
        """
        self.Links = tuplelist(Links)
        self.Capacity = Capacity

        # Create optimization model
        self.model = Model("Backup")

        # Create variables
        for i, j in self.Links:
            self.BackupCapacity[i, j] = self.model.addVar(
                vtype=GRB.CONTINUOUS, lb=0, name="Backup_Capacity[%s,%s]" % (i, j)
            )
            # self.BackupCapacity[i,j] = self.model.addVar(lb=0, name='Backup_Capacity[%s,%s]' % (i, j))
        self.model.update()

        for i, j in self.Links:
            for s, d in self.Links:
                self.bBackupLink[i, j, s, d] = self.model.addVar(
                    vtype=GRB.BINARY, name="Backup_Link[%s,%s,%s,%s]" % (i, j, s, d)
                )
        self.model.update()

        for i, j in self.Links:
            for k in range(NumSamples):
                self.z[k, i, j] = self.model.addVar(lb=0, name="z[%s][%s][%s]" % (k, i, j))
        self.model.update()

        for i, j in self.Links:
            self.z0[i, j] = self.model.addVar(lb=-GRB.INFINITY, name="z0[%s][%s]" % (i, j))
        self.model.update()

        self.model.modelSense = GRB.MINIMIZE

        self.model.setObjective(quicksum(self.BackupCapacity[i, j] for i, j in self.Links))
        self.model.update()

        # ------------------------------------------------------------------------#
        #                    Constraints definition                              #
        #                                                                        #
        #                                                                        #
        # ------------------------------------------------------------------------#

        # Buffer probability I
        for i, j in self.Links:
            self.model.addConstr(
                self.z0[i, j]
                + 1 / (NumSamples * Survivability) * quicksum(self.z[k, i, j] for (k) in range(NumSamples))
                <= 0,
                "[CONST]Buffer_Prob_I[%s][%s]" % (i, j),
            )
        self.model.update()

        # Link capacity constraints
        for i, j in self.Links:
            for k in range(NumSamples):
                if Gamma == None:
                    self.model.addConstr(
                        (
                            quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links)
                            - self.BackupCapacity[i, j]
                            - self.z0[i, j]
                        )
                        <= self.z[k, i, j],
                        "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j),
                    )
                else:
                    self.model.addConstr(
                        (
                            quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links)
                            - self.BackupCapacity[i, j]
                            - self.z0[i, j]
                        )
                        * Gamma[k]
                        <= self.z[k, i, j],
                        "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j),
                    )
        self.model.update()

        # Link capacity constraints
        for i, j in self.Links:
            for k in range(NumSamples):
                self.model.addConstr(self.z[k, i, j] >= 0, "[CONST]Buffer_Prob_III[%s][%s][%s]" % (k, i, j))
        self.model.update()

        for i in Nodes:
            for s, d in self.Links:
                # Flow conservation constraints
                if i == s:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == 1,
                        "Flow1[%s,%s,%s]" % (i, s, d),
                    )
                # Flow conservation constraints
                elif i == d:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == -1,
                        "Flow2[%s,%s,%s]" % (i, s, d),
                    )
                # Flow conservation constraints
                else:
                    self.model.addConstr(
                        quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*"))
                        - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i))
                        == 0,
                        "Flow3[%s,%s,%s]" % (i, s, d),
                    )
        self.model.update()

    def Optimize(self, MipGap=None, TimeLimit=None, LogLevel=None):
        """ Optimize the defined  model.
    
        Parameters
        ----------
        MipGap : desired gap
        TimeLimit : time limit
        LogLevel: log level 1 for printing all optimal variables and None otherwise
        
        Returns
        -------
        BackupCapacity: The total capacity assigned per backup link
        BackupRoutes: The set of selected backup links 
           A tuple list with all paths for edge (s,d) that uses (i,j).
    
        """
        self.model.write("bpbackup.lp")

        if MipGap != None:
            self.model.params.MIPGap = MipGap
        if TimeLimit != None:
            self.model.params.timeLimit = TimeLimit
        # Compute optimal solution
        self.model.optimize()

        # Print solution
        if self.model.status == GRB.Status.OPTIMAL:

            if LogLevel == 1:
                for v in self.model.getVars():
                    print("%s %g" % (v.varName, v.x))

            self.BackupCapacitySolution = self.model.getAttr("x", self.BackupCapacity)
            self.BackupRoutesSolution = self.model.getAttr("x", self.bBackupLink)

            self.BackupLinksSolution = {}
            self.HatBackupCapacity = {}
            for link in self.BackupCapacitySolution:
                if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001:
                    self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link])
                else:
                    self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link])
                if self.HatBackupCapacity[link] > 0:
                    if len(self.BackupLinksSolution) == 0:
                        self.BackupLinksSolution = [link]
                    else:
                        self.BackupLinksSolution = self.BackupLinksSolution + [link]
        else:
            print("Optimal value not found!\n")
            self.BackupCapacitySolution = []
            self.BackupRoutesSolution = {}
            self.BackupLinksSolution = {}

        return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity

    def SaveBakupNetwork(self, file_name):
        """Save the optimal backup network to the file ``file_name``."""

        data = {
            "links": [i for i in self.BackupCapacitySolution],
            "capacities": [self.BackupCapacitySolution[i] for i in self.BackupCapacitySolution],
            "routes": [i for i in self.BackupRoutesSolution],
            "status": [self.BackupRoutesSolution[i] for i in self.BackupRoutesSolution],
        }
        f = open(file_name, "w")
        json.dump(data, f)
        f.close()

    def LoadBackupNetwork(self, file_name):
        """Load a backup network from the file ``file_name``.  
        Returns the backup network solution saved in the file. 
      
        """
        f = open(file_name, "r")
        data = json.load(f)
        f.close()

        self.BackupCapacitySolution = {}
        self.BackupRoutesSolution = {}
        self.BackupLinksSolution = {}

        links = [i for i in data["links"]]
        capacities = [i for i in data["capacities"]]
        routes = [i for i in data["routes"]]
        status = [i for i in data["status"]]

        IndexAux = 0
        for i, j in links:
            self.BackupCapacitySolution[i, j] = capacities[IndexAux]
            IndexAux = IndexAux + 1

        self.HatBackupCapacity = {}
        for link in self.BackupCapacitySolution:
            if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001:
                self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link])
            else:
                self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link])
            if self.HatBackupCapacity[link] > 0:
                if len(self.BackupLinksSolution) == 0:
                    self.BackupLinksSolution = [link]
                else:
                    self.BackupLinksSolution = self.BackupLinksSolution + [link]

        IndexAux = 0
        for i, j, s, d in routes:
            self.BackupRoutesSolution[i, j, s, d] = status[IndexAux]
            IndexAux = IndexAux + 1

        return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity

    def ResetModel(self):
        """
        Reset model solution.
        """
        self.BackupCapacity = {}
        self.bBackupLink = {}
        self.z0 = {}
        self.z = {}
        if self.model:
            self.model.reset()
예제 #31
0
def SU_Gurobi_Model(data):
    # Create the model
    suModel = Model('Getir')
    # Set parameters
    suModel.setParam('OutputFlag', True)

    n = len(data['vehicles'])  #number of vehicles
    m = len(data['jobs'])  #number of jobs

    S = range(0, n)  # source nodes of the vehicles
    J = range(n, n + m)  # job or customer nodes
    V = range(0, n)  # vehicles
    S_J = range(0, n + m)  # sources and jobs
    J_E = range(n, n + m + m)  # jobs and ARTIFICIAL ending nodes

    # Add variables
    x = suModel.addVars(
        S_J, J_E, V, vtype=GRB.BINARY,
        name='x')  #assigment variable - between arcs(locations)
    u = suModel.addVars(
        J_E, V, lb=2, ub=m, vtype=GRB.INTEGER, name='u'
    )  # sequence variable which is required for subtour elimination

    # minimize the total travel time
    suModel.setObjective(
        quicksum(data['matrix'][i][j] * x[i, j, k] for i in S_J for j in J_E
                 for k in V if j < n + m), GRB.MINIMIZE)

    suModel.addConstrs(
        (quicksum(x[i, j, k] for j in J) == 1 for i in S for k in V if i == k),
        name='c1')
    suModel.addConstrs(
        (quicksum(x[i, j, k] for j in J) == 1 for i in S for k in V if i == k),
        name='c2')
    suModel.addConstrs((quicksum(x[i, i + m, k] for i in J) == 1 for k in V),
                       name='c3')

    suModel.addConstrs((quicksum(x[i, j, k] for i in S_J
                                 for k in V if i != j) == 1 for j in J),
                       name='c4')

    suModel.addConstrs((quicksum(x[i, j, k]
                                 for i in S_J) == quicksum(x[j, h, k]
                                                           for h in J_E)
                        for k in V for j in J),
                       name='c5')
    #subtour eliminations
    suModel.addConstrs((u[i, k] - u[j, k] + m * x[i, j, k] <= (m - 1)
                        for i in J for j in J_E for k in V if i != j),
                       name='c6')

    # Optimize the model
    suModel.optimize()
    # write the results
    #OutputDictionary(suModel,data)
    Output(suModel)
    # print the LP file   (this file can be used in different optimization platforms such as CPLEX, Gams, etc.)
    suModel.write('suGetir.lp')
    # print the sol file
    suModel.write('suGetir.sol')

    routes = {}
    solution = suModel.getAttr('x', x)
    for k in V:
        route = []
        for i in S:
            for j in J:
                if solution[i, j, k] == 1:
                    route.append(i)
                    route.append(j)
        while route[-1] < n + m:
            for j in J_E:
                if route[-1] < n + m:
                    if solution[route[-1], j, k] == 1:
                        route.append(j)
        routes[str(k)] = route[0:len(route) - 1]
    print(routes)
    return routes
예제 #32
0
from gurobipy import Model, GRB

m = Model("hw51")

x1 = m.addVar(name="x1")
x2 = m.addVar(name="x2")

m.update()

m.setObjective(5 * x1 + 4 * x2, GRB.MAXIMIZE)

m.addConstr(6 * x1 + 4 * x2 <= 24, 'constraint1')
m.addConstr(x1 + 2 * x2 <= 6, 'constraint2')
m.addConstr(-x1 + x2 <= 1, 'constraint3')
m.addConstr(x2 <= 2, ' constraint4')

m.optimize()

for v in m.getVars():
    print('%s: %f' % (v.varName, v.x))

print('Obj: %f' % m.objVal)

print 'reduced costs: '
print ' ', m.getAttr('rc', m.getVars())
print 'shadow prices: '
print ' ', m.getAttr('pi', m.getConstrs())
예제 #33
0
def solve_weighted_max_sat(
    n: int, model: MaxSatModel, context: Clause, num_sol
) -> Optional[Instance]:

    if any(w and (w > 1 or w < 0) for w, _ in model):
        raise AttributeError("Weights must be between in the interval [0, 1]")

    with suppress_stdout():
        mod = Model("MaxSat")

    mod.setParam("OutputFlag", False)

    m = len(model)

    # Variables
    x_l = [mod.addVar(vtype=GRB.BINARY, name=f"x_{l})") for l in range(n)]
    cov_j = [mod.addVar(vtype=GRB.BINARY, name=f"cov_{j})") for j in range(m)]
    w_j = [
        mod.addVar(vtype=GRB.CONTINUOUS, lb=0, ub=1, name=f"w_{j}") for j in range(m)
    ]

    mod.setObjective(quicksum([w_j[j] for j in range(m)]), GRB.MAXIMIZE)

    for j, (weight, clause) in enumerate(model):
        # FOR-ALL_l: cov_j >= x_l * a_jl+ OR cov_j >= (1 - x_l) * a_jl-
        for i in clause:
            if i < 0:
                l = abs(i) - 1
                mod.addConstr(cov_j[j] >= (1 - x_l[l]), name=f"cov_{j} >= (1 - x_{l})")
            else:
                l = i - 1
                mod.addConstr(cov_j[j] >= x_l[l], name=f"cov_{j} >= x_{l}")

        # Force it to be false if no literal is satisfied
        mod.addConstr(
            cov_j[j]
            <= quicksum((1 - x_l[abs(i) - 1]) if i < 0 else x_l[i - 1] for i in clause),
            name=f"cov_{j} <= SUM_l clause_{j}",
        )

        if weight is None:
            # Constraint is hard, thus weight is 0
            mod.addConstr(w_j[j] == 0, name=f"w_{j} = 0")

            # Constraint is hard, thus must be covered
            mod.addConstr(cov_j[j] >= 1, name=f"cov_{j} >= 1")
        else:
            # Weight is 0 if clause is not covered, and weight otherwise
            mod.addConstr(
                w_j[j] == weight * cov_j[j], name=f"w_{j} = {weight} * cov_{j}"
            )

    for i in context:
        # Fix values given by context
        if i < 0:
            l = abs(i) - 1
            mod.addConstr(x_l[l] == 0, name=f"x_{l} = 0")
        else:
            l = i - 1
            mod.addConstr(x_l[l] == 1, name=f"x_{l} = 1")

    mod.setParam(GRB.Param.PoolSolutions, num_sol)
    mod.setParam(GRB.Param.PoolSearchMode, 2)
    mod.setParam(GRB.Param.PoolGap, 0)
    mod.optimize()

    if num_sol == 1:
        if mod.status == GRB.Status.OPTIMAL:
            return np.array([x_l[l].x for l in range(n)])
        else:
            return None

    num_sol = mod.SolCount
    list_sol = []
    for i in range(num_sol):
        mod.setParam(GRB.Param.SolutionNumber, i)
        if mod.status == GRB.Status.OPTIMAL:
            sol = mod.getAttr("xn", x_l)
            if mod.status == GRB.Status.OPTIMAL:
                list_sol.append(np.array([sol[l] for l in range(n)]))
    #        else:
    #            list_sol.append(None)
    return list_sol