Exemplo n.º 1
0
for var in chain(chemicals.values(), reactions.values()):
    constraints.append(var >= 0)

for out_chemical, (quantity, inputs) in recipes.items():
    constraints.append(chemicals[out_chemical] == quantity * reactions[out_chemical])
    for chemical, quantity in inputs.items():
        quantities_required[chemical].append(reactions[out_chemical] * quantity)

for chemical, required in quantities_required.items():
    if not required:
        continue
    constraints.append(chemicals[chemical] >= pulp.lpSum(required))


# part 1
prob = pulp.LpProblem("day_14.1", pulp.LpMinimize)
for c in constraints:
    prob += c
prob += chemicals["ORE"]  # Minimize this
prob += chemicals["FUEL"] >= 1

prob.solve()
print(("Status:", pulp.LpStatus[prob.status]))
print('Part 1:', pulp.value(chemicals["ORE"]))

# part 2
prob = pulp.LpProblem("day_14.2", pulp.LpMaximize)
for c in constraints:
    prob += c
prob += chemicals["FUEL"]  # Maximize this
prob += chemicals["ORE"] == 1_000_000_000_000
Exemplo n.º 2
0
    def __calcW(self, goal=1, eps=0.00):
        oidx = [i for i in range(self.M)]
        Nsols = len(self.solutionsList)
        # Create a gurobi model
        prob = lp.LpProblem("max_mean", lp.LpMaximize)
        # prob = mip.Model(sense=mip.MAXIMIZE, solver_name=mip.GRB)

        # Creation of linear integer variables
        w = list(
            lp.LpVariable.dicts('w', oidx, lowBound=0,
                                cat='Continuous').values())
        # w = list(prob.add_var(name='w', var_type=mip.CONTINUOUS, lb=0) for i in range(len(Ingredients)))
        uR = list(lp.LpVariable.dicts('uR', oidx, cat='Continuous').values())
        # uR = list()
        kp = list(
            lp.LpVariable.dicts('kp', list(range(Nsols)),
                                cat='Continuous').values())
        # kp = list()
        nu = list(
            lp.LpVariable.dicts('nu', oidx, lowBound=0,
                                cat='Continuous').values())
        # nu = list()

        test = False
        if test:
            kpB = list(
                lp.LpVariable.dicts('kpB',
                                    list(range(Nsols)),
                                    lowBound=0,
                                    upBound=1,
                                    cat='Continuous').values())
            nuB = list(
                lp.LpVariable.dicts('nuB',
                                    oidx,
                                    lowBound=0,
                                    upBound=1,
                                    cat='Continuous').values())
        else:
            kpB = list(
                lp.LpVariable.dicts('kpB', list(range(Nsols)),
                                    cat='Binary').values())
            nuB = list(lp.LpVariable.dicts('nuB', oidx, cat='Binary').values())

        v = lp.LpVariable('v', cat='Continuous')
        mu = lp.LpVariable('mu', cat='Continuous')

        # Inherent constraints of this problem
        for value, sols in enumerate(self.solutionsList):
            expr = lp.lpDot(self.__normw(sols.w), uR)
            cons = self.__normf(sols.objs) @ self.__normw(sols.w)
            prob += expr >= cons * (1 - eps)

        for i in oidx:
            expr = uR[i] - lp.lpSum([
                kp[conN] * self.__normf(sols.objs)[i]
                for conN, sols in enumerate(self.solutionsList)
            ]) - nu[i] + mu
            prob += expr == 0

        bigC = max(self.__normf(self.__globalU))

        for conN, sols in enumerate(self.solutionsList):
            # d, dvec = self.__calcD(sols)
            expr = v - lp.lpDot(w, self.__normf(sols.objs))
            prob += -expr >= 0  #mantem
            prob += -expr <= kpB[conN] * bigC  #mantem
            prob += kp[conN] >= 0  #mantem
            prob += kp[conN] <= (1 - kpB[conN])  #mantem

        for i in oidx:
            prob += uR[i] >= self.__normf(self.__globalL)[i]

        for i in oidx:
            prob += w[i] >= 0  #mantem
            prob += w[i] <= nuB[i]  #mantem
            prob += nu[i] >= 0  #mantem
            prob += nu[i] <= (1 - nuB[i]) * 2 * bigC  #mantem

        prob += lp.lpSum([w[i] for i in oidx]) == 1
        prob += lp.lpSum([kp[i] for i in range(Nsols)]) == 1

        prob += mu

        # desigualdades válidas
        prob += mu <= v

        try:
            rnd = np.array(
                sorted([0] + [np.random.rand()
                              for i in range(self.M - 1)] + [1]))
            w_ini = np.array([rnd[i + 1] - rnd[i] for i in range(self.__M)])
            w_ini = w_ini / w_ini.sum()
            for wi, wii in zip(w, w_ini):
                wi.start = wii
            grbs = lp.GUROBI(epgap=self.__mip_gap,
                             SolutionLimit=1,
                             msg=False,
                             OutputFlag=False,
                             Threads=1)
            prob.solve(grbs)

            if self.__goal != float('inf'):
                grbs = lp.GUROBI(timeLimit=self.__time_limit,
                                 epgap=self.__mip_gap,
                                 SolutionLimit=MAXINT,
                                 msg=False,
                                 BestObjStop=self.__goal,
                                 OutputFlag=False,
                                 Threads=1)
            else:
                grbs = lp.GUROBI(timeLimit=self.__time_limit,
                                 epgap=self.__mip_gap,
                                 SolutionLimit=MAXINT,
                                 msg=False,
                                 OutputFlag=False,
                                 Threads=1)
            prob.solve(grbs)
        except:
            cbcs = lp.COIN_CMD(maxSeconds=self.__time_limit,
                               fracGap=self.__mip_gap,
                               threads=1)
            prob.solve(cbcs, use_mps=False)

        feasible = False if prob.status in [-1, -2] else True

        if feasible:
            w_ = np.array(
                [lp.value(w[i]) if lp.value(w[i]) >= 0 else 0 for i in oidx])
            w_ = w_ / w_.sum()
            if self.__norm:
                w_ = w_ / (self.__globalU - self.__globalL)
            fobj = lp.value(prob.objective)
            self.__w = np.array(w_)
            self.__importance = fobj
        else:
            raise ('Non-feasible solution')
Exemplo n.º 3
0
    z_comb[i]=tempL

Y=40     
           
print('Finish Data Preprocess!')
print(modelList)
#####前面主要是数据处理部分########
#以上主要是将订单的信息按照型号与交付时间重新划分了新的型号,三个月内的相同型号的点订单放在一起生产。
#以上同时做了一个维,用于计算每个型号在产线的速度(每天都不一样,指数增长)


#####后面是模型,用到了mixed integer linear 


print('LP process begins.')
prob=pulp.LpProblem("The APS Problem",pulp.LpMinimize)
x={}
h={}
k={}
wt={}
f={}
ft={}
wn={}
z={}
modeln=len(modelList)
for i in modelList:
    #a variable which is one if order j of the model i is completed in time t
    #订单j (型号i) 在t时间完成生产(下线时间)-类型:binary
    x[i]=pulp.LpVariable.dicts('x',x_comb[i],0,1,pulp.LpInteger)
    
    # a variable which is 1 in period t if all orders of model i
Exemplo n.º 4
0
def solve(studentInfos, groupInfos, goalGroups):
    # Set up groups
    groups = []
    gidToGroupInfo = {}
    nextGID = 1
    for group in groupInfos:
        groupObj = Group(nextGID, group)
        if groupObj.size != None and groupObj.size == 0:
            # Skip groups with no room
            continue
        groups.append(groupObj)
        gidToGroupInfo[groupObj.id] = group
        nextGID += 1

    # Set up students
    students = []
    sidToStudentInfo = {}
    nextSID = 1
    for student in studentInfos:
        studentObj = Student(nextSID, student, groups)
        students.append(studentObj)
        sidToStudentInfo[studentObj.id] = student
        nextSID += 1

    # Set up data box
    dataBox = DataBox(students, groups)

    # Run for each set of goals until 'Optimal' is found, or return None
    for i in range(len(goalGroups)):
        goals = goalGroups[i]
        problem = pulp.LpProblem("Group Membership Problem", pulp.LpMaximize)

        # Add student constraints
        failedAddingConstraints = False
        for student in students:
            constraints = student.genConstraints()
            if constraints == None:
                failedAddingConstraints = True
                break
            for constraint in constraints:
                problem += constraint

        # Add group constraints
        for group in groups:
            constraints = group.genConstraints()
            if constraints == None:
                failedAddingConstraints = True
                break
            for constraint in constraints:
                problem += constraint

        # Add goal constraints
        for goal in goals:
            constraints = goal.genConstraints(dataBox)
            if constraints == None:
                failedAddingConstraints = True
                break
            for constraint in constraints:
                problem += constraint

        if failedAddingConstraints:
            print "> Goal group " + str(
                i
            ) + " failed because constraints couldn't be generated. Trying next goal group..."
            continue

        # Objective function
        # TODO: add objective function

        # Attempt to solve
        problem.solve()

        solved = pulp.LpStatus[problem.status] == 'Optimal'
        if solved:
            print "> Successful with goal group " + str(i)
            output = [None for i in range(len(groups))]
            #output = [{"students": [students], "group": groupinfo}, ...]
            for variable in problem.variables():
                if variable.name == '__dummy':
                    continue
                if variable.varValue == 0:
                    continue
                ret = Utils.decodeVarName(variable.name)
                if ret == None:
                    continue
                (sid, gid) = ret
                student = sidToStudentInfo[sid]
                group = gidToGroupInfo[gid]

                index = gid - 1
                if output[index] == None:
                    output[index] = {}
                    output[index]['students'] = []
                    output[index]['info'] = group
                output[index]['students'].append(student)

            return output
        else:
            print "> Goal group " + str(
                i) + " was too strict. Trying next goal group..."
    print "> All goal groups were too strict. No groups could be created"
    return None
Exemplo n.º 5
0
import pulp

x1=pulp.LpVariable("x1",lowBound=0)
x2=pulp.LpVariable("x2",lowBound=0)
x3=pulp.LpVariable("x3",upBound=0)

optimum=pulp.LpProblem("max",pulp.LpMaximize)

optimum+=2*x2-x3+3, "objective function"

optimum+=x1+x2+x3<=3
optimum+=x1+x2+x3>=3
optimum+=x1-x2>=1
optimum+=x2-x3<=1
optimum+=x1+x2>=3

optimum.solve()

print("decision variable values")

for variable in optimum.variables():
    print(variable.name,"=",variable.varValue)

print("\nmax:")
pulp.value(optimum.objective)
Exemplo n.º 6
0
def optimizeTrajectory(N, T, T_end, V, P, W, M, m, TSFC, minApproachDist, x_ini, x_fin, x_lim, u_lim, objects, r):

  # --------------------
  # Calculated Variables
  # --------------------
  del_t = T_end/T
  numObjects = objects.shape[0]

  # ------------------
  # Decision variables
  # ------------------
  # Thrust
  u = pulp.LpVariable.dicts(
    "input", ((i, p, n) for i in range(T) for p in range(V) for n in range(N)),
    cat='Continuous')
  # Thrust Magnitude
  v = pulp.LpVariable.dicts(
    "inputMag", ((i, p, n) for i in range(T) for p in range(V) for n in range(N)),
    lowBound=0,
    cat='Continuous')
  # State
  x = pulp.LpVariable.dicts(
    "state", ((i, p, k) for i in range(T) for p in range(V) for k in range(2*N)),
    cat='Continuous')
  # Object collision
  a = pulp.LpVariable.dicts(
    "objCol", ((i, p, l, k) for i in range(T) for p in range(V) for l in range(numObjects) for k in range(2*N)),
    cat='Binary')
  # Satellite Collision Avoidance
  b = pulp.LpVariable.dicts(
    "satelliteCollisionAvoidance", ((i, p, q, k) for i in range(T) for p in range(V) for q in range(V) for k in range(2*N)),
    cat='Binary')
  # Plume Impingement
  c_plus = pulp.LpVariable.dicts(
    "plumeImpingementPositive", ((i, p, q, n, k) for i in range(T) for p in range(V) for q in range(V) for n in range(N) for k in range(2*N)),
    cat='Binary')
  c_minus = pulp.LpVariable.dicts(
    "plumeImpingementNegative", ((i, p, q, n, k) for i in range(T) for p in range(V) for q in range(V) for n in range(N) for k in range(2*N)),
    cat='Binary')

  # ------------------
  # Optimization Model
  # ------------------

  # Instantiate Model
  model = pulp.LpProblem("Satellite Fuel Minimization Problem", pulp.LpMinimize)
  # Objective Function
  model += pulp.lpSum(v[i, p, n] for i in range(T) for p in range(V) for n in range(N)), "Fuel Minimization"

  # -----------
  # Constraints
  # -----------

  # Basic Constraints
  # -----------------
  # Constrain thrust magnitude to abs(u[i, p, n])
  for i in range(T):
    for p in range(V):
      for n in range(N):
        model +=  u[i, p, n] <= v[i, p, n]
        model += -u[i, p, n] <= v[i, p, n]
  # State and Input vector start and end values
  for p in range(V):
    for k in range(2*N):
      model += x[0, p, k]   == x_ini[p, k]
      model += x[T-1, p, k] == x_fin[p, k]
  # Model Dynamics
  for constraint in freeSpaceDynamics(x, u, T, V, N, m, del_t):
    model += constraint
  # State and Input vector limits
  for i in range(T):
    for p in range(V):
      for n in range(N):
        model += u[i, p, n] <=  u_lim[p, n]
        model += u[i, p, n] >= -u_lim[p, n]
      for k in range(2*N): # Necessary?
        model += x[i, p, k] <=  x_lim[p, k]
        model += x[i, p, k] >= -x_lim[p, k]

  # Obstacle Avoidance
  # ------------------
  if objects.shape[1] > 0:
    for i in range(T):
      for p in range(V):
        for l in range(numObjects):
          model += pulp.lpSum(a[i, p, l, n] for n in range(2*N)) <= 2*N-1
          for n in range(N):
            model += x[i, p, n] >= objects[l, N+n] + minApproachDist - M*a[i, p, l, N+n]
            model += x[i, p, n] <= objects[l, n] - minApproachDist + M*a[i, p, l, n]

  # Collision Avoidance
  # -------------------
  if V > 1: # If more than one vehicle
      for i in range(T):
        for p in range(V):
          for q in range(V):
            if q > p:
              model += pulp.lpSum(b[i, p, q, k] for k in range(2*N)) <= 2*N-1
              for n in range(N):
                model += x[i, p, n] - x[i, q, n] >= r[n] - M*b[i, p, q, n]
                model += x[i, q, n] - x[i, p, n] >= r[n] - M*b[i, p, q, n+N]

  # Plume Impingement
  # -----------------
  # Positive thrust
  if V > 1: # If more than one vehicle
      for i in range(T):
        for p in range(V):
          for q in range(V):
            if q != p:
              for n in range(N):
                model += pulp.lpSum(c_plus[i, p, q, n, k] for k in range(2*N)) <= 2*N
                model += -u[i, p, n] >= - M*c_plus[i, p, q, n, 0]
                model += x[i, p, n] - x[i, q, n] >= P - M*c_plus[i, p, q, n, n]
                model += x[i, q, n] - x[i, p, n] >= - M*c_plus[i, p, q, n, n+N]
                for m in range(N):
                  if m != n:
                    x[i, p, m] - x[i, q, m] >= W - M*c_plus[i, p, q, n, m]
                    x[i, q, m] - x[i, p, m] >= W - M*c_plus[i, p, q, n, m+N]
  # Negative thrust
      for i in range(T):
        for p in range(V):
          for q in range(V):
            if q != p:
              for n in range(N):
                model += pulp.lpSum(c_minus[i, p, q, n, k] for k in range(2*N)) <= 2*N
                model += u[i, p, n] >= - M*c_minus[i, p, q, n, 0]
                model += x[i, p, n] - x[i, q, n] >= - M*c_minus[i, p, q, n, n]
                model += x[i, q, n] - x[i, p, n] >= P - M*c_minus[i, p, q, n, n+N]
                for m in range(N):
                  if m != n:
                    x[i, p, m] - x[i, q, n] >= W - M*c_minus[i, p, q, n, m]
                    x[i, q, m] - x[i, p, m] >= W - M*c_minus[i, p, q, n, m+N]


  # Plume Avoidance for Vehicles
  # ----------------------------

  # Plume Avoidance for Obstacles
  # -----------------------------

  # Final Configuration Selection
  # -----------------------------

  # Solve model and return results in dictionary
  model.solve(pulp.CPLEX())

  # Create Pandas dataframe for results and return

  return {'model':model, 'x':x, 'u':u}
Exemplo n.º 7
0
    def tensors(self):
        """Constructs high-level DAG and creates the tensors.

    Returns:
      An collections.OrderedDict mapping a tensor's name to the tensor.
    """
        # TODO: check for name conflicts
        tensor_map = collections.OrderedDict()
        for stmt in self.input_stmts:
            tensor = soda.tensor.Tensor(stmt, self.tile_size)
            tensor_map[stmt.name] = tensor

        def name_in_iter(name, iteration):
            if name in self.input_names:
                if iteration > 0:
                    return name + '_iter%d' % iteration
                return name
            if name in self.output_names:
                if iteration < self.iterate - 1:
                    return (self.input_names[self.output_names.index(name)] +
                            '_iter%d' % (iteration + 1))
                return name
            if name in self.local_names:
                if iteration > 0:
                    return name + '_iter%d' % iteration
                return name
            if name in self.param_names:
                return name
            raise util.InternalError('unknown name: %s' % name)

        for iteration in range(self.iterate):
            _logger.debug('iterate %s', iteration)
            _logger.debug('map: %s', self.symbol_table)

            def mutate_name_callback(obj, mutated):
                if isinstance(obj, ir.Ref):
                    obj.haoda_type = self.symbol_table[obj.name]
                    # pylint: disable=cell-var-from-loop
                    obj.name = name_in_iter(obj.name, iteration)
                return obj

            tensors = []
            for stmt in itertools.chain(self.local_stmts, self.output_stmts):
                tensor = soda.tensor.Tensor(stmt.visit(mutate_name_callback),
                                            self.tile_size)
                tensor_map[tensor.name] = tensor
                tensors.append(tensor)

            for tensor in tensors:
                _logger.debug('%s', tensor)

            for tensor in tensors:
                tensor.propagate_type()
                loads = visitor.get_load_dict(tensor)
                for parent_name, ld_refs in loads.items():
                    ld_refs = sorted(ld_refs,
                                     key=lambda ref: soda.util.serialize(
                                         ref.idx, self.tile_size))
                    parent_tensor = tensor_map[parent_name]
                    parent_tensor.children[tensor.name] = tensor
                    tensor.parents[parent_name] = parent_tensor
                    tensor.ld_refs[parent_name] = ld_refs

        # solve ILP for optimal reuse buffer
        lp_problem = pulp.LpProblem("optimal_reuse_buffer", pulp.LpMinimize)
        lp_vars = {self.input_names[0]: 0}  # set 1 and only 1 reference point
        lp_helper_vars = {}  # type: Dict[str, pulp.LpVariable]
        objectives = []
        constraints = []
        for tensor in tensor_map.values():
            lp_var = pulp.LpVariable('produced_offset_' + tensor.name,
                                     cat='Integer')
            lp_helper_var = pulp.LpVariable('consumed_offset_' + tensor.name,
                                            cat='Integer')
            lp_vars.setdefault(tensor.name, lp_var)
            lp_helper_vars[tensor.name] = lp_helper_var
            # tensor need to be kept for this long
            objectives.append(lp_helper_var - lp_vars[tensor.name])
            # tensor cannot be consumed until it is produced
            constraints.append(lp_helper_var >= lp_vars[tensor.name])
        lp_problem += sum(objectives)
        lp_problem.extend(constraints)
        for st_tensor in tensor_map.values():
            for ld_tensor_name, offsets in st_tensor.ld_offsets.items():
                oldest_access = min(offsets)
                newest_access = max(offsets)
                _logger.debug('%s @ %s accesses %s @ [%s, %s]', st_tensor.name,
                              st_tensor.st_offset, ld_tensor_name,
                              oldest_access, newest_access)
                # newest ld_tensor access must have been produced
                # when st_tensor is produced
                lp_problem += lp_vars[ld_tensor_name] <= lp_vars[
                    st_tensor.name] + (st_tensor.st_offset - newest_access)
                # oldest ld_tensor access must have been not consumed
                # when st_tensor is produced
                lp_problem += lp_helper_vars[ld_tensor_name] >= lp_vars[
                    st_tensor.name] + (st_tensor.st_offset - oldest_access)

        lp_status = lp_problem.solve()
        lp_status_str = pulp.LpStatus[lp_status]
        total_distance = int(pulp.value(lp_problem.objective))
        _logger.debug('ILP status: %s %s', lp_status_str, total_distance)
        _logger.info('total reuse distance: %d', total_distance)

        if lp_status != pulp.LpStatusOptimal:
            _logger.error('ILP error: %s\n%s', lp_status_str, lp_problem)
            raise util.InternalError('unexpected ILP status: %s' %
                                     lp_status_str)

        # some inputs may need to be delayed relative to others
        base = min(int(pulp.value(lp_vars[x])) for x in self.input_names)

        # set produce offsets
        for tensor in tensor_map.values():
            produce_offset = int(pulp.value(lp_vars[tensor.name])) - base
            consume_offset = int(pulp.value(
                lp_helper_vars[tensor.name])) - base
            tensor.produce_offset = produce_offset
            tensor.consume_offset = consume_offset
            tensor.max_access = 0  # pixels before current produce
            _logger.debug('%s should be produced @ %d and kept until %d',
                          tensor.name, produce_offset, consume_offset)

        # calculate overall acceses
        for ld_tensor in tensor_map.values():
            for st_tensor in ld_tensor.children.values():
                oldest_access = st_tensor.st_offset - min(
                    st_tensor.ld_offsets[ld_tensor.name]
                ) + st_tensor.produce_offset - ld_tensor.produce_offset
                newest_access = st_tensor.st_offset - max(
                    st_tensor.ld_offsets[ld_tensor.name]
                ) + st_tensor.produce_offset - ld_tensor.produce_offset
                _logger.debug(
                    '  producing %s @ %s accesses [%s, %s] pixels before %s '
                    'produced @ %s', st_tensor.name, st_tensor.produce_offset,
                    newest_access, oldest_access, ld_tensor.name,
                    ld_tensor.produce_offset)
                ld_tensor.max_access = max(ld_tensor.max_access, oldest_access)

        for tensor in tensor_map.values():
            _logger.debug('%s should be kept for %s pixels', tensor.name,
                          tensor.max_access)

        # high-level DAG construction finished
        for tensor in tensor_map.values():
            if tensor.name in self.input_names:
                _logger.debug('<input tensor>: %s', tensor)
            elif tensor.name in self.output_names:
                _logger.debug('<output tensor>: %s', tensor)
            else:
                _logger.debug('<local tensor>: %s', tensor)
        return tensor_map
Exemplo n.º 8
0
              / 3600 #converting kJ to kWh ECF booster in kWh/kmol

# Converting the transportation constants to m^3
MW_H2 = var['value']['MW_H2'] #kg/kmol H2
density_H2 = var['value']['density_H2'] #kg/m^3

Imax = Imax * MW_H2 / density_H2 # m^3
Imin = Imin * MW_H2 / density_H2 # m^3
Fmax_booster = Fmax_booster * MW_H2 / density_H2 # m^3
Fmax_prestorage = Fmax_prestorage * MW_H2 / density_H2 # m^3

ECF_booster = ECF_booster / MW_H2 * density_H2 #kWh/m^3
ECF_prestorage = ECF_prestorage / MW_H2 * density_H2 #kWh/m^3

# RNG + HENG model
LP_eps = pulp.LpProblem('LP_eps', pulp.LpMaximize)
LP_cost = pulp.LpProblem('LP_cost', pulp.LpMinimize)

# RNG Variables
RNG_max = pulp.LpVariable('RNG_max',
                          lowBound=0,
                          cat='Continuous')
N_electrolyzer_1 = pulp.LpVariable('N_electrolyzer_1',
                          lowBound=0,
                          cat='Integer')
alpha_1 = pulp.LpVariable.dicts('alpha_1',
                          [str(i) for i in range(1, N_max)],
                          cat='Binary')
E_1 = pulp.LpVariable.dicts('E_1',
                          [str(i) for i in input_df.index],
                          lowBound=0,
Exemplo n.º 9
0
    def IP_solution(self):
        """
        This method implements the IP solution.
        Args:
            - self: Sudoku instance, to be solved using IP.
        Returns:
            - flag: boolean, whether the Sudoku is solvable.
            If True, the completed Sudoku is available through the attribute
            "_solution" and the completion time through "_duration".
        """

        # List of available digits
        Digits = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

        Values = Digits
        Rows = Digits
        Columns = Digits

        # Creating the block list
        Blocks = []
        for i in range(3):
            for j in range(3):
                Blocks += [[(Rows[3 * i + k], Columns[3 * j + l])
                            for k in range(3) for l in range(3)]]

        # We need to create the IP problem
        prob = pulp.LpProblem("Sudoku solver", pulp.LpMinimize)

        # Then we create the problem variables
        choices = pulp.LpVariable.dicts("Choice", (Rows, Columns, Values), 0,
                                        1, pulp.LpInteger)

        # We define the objective function which is 0 here
        prob += 0, "Objective Function"

        # Defining the constraint: only one value can be put in a cell
        for r in Rows:
            for c in Columns:
                prob += pulp.lpSum([choices[r][c][v] for v in Values]) == 1, ""

        for v in Values:
            # Each value must occur exactly once in each row
            for r in Rows:
                prob += pulp.lpSum([choices[r][c][v]
                                    for c in Columns]) == 1, ""

            # Each value must occur exactly once in each column
            for c in Columns:
                prob += pulp.lpSum([choices[r][c][v] for r in Rows]) == 1, ""

            # Each value must occur exactly once in each block
            for b in Blocks:
                prob += pulp.lpSum([choices[r][c][v] for (r, c) in b]) == 1, ""

        # We need to add the starting numbers as constraints
        grid = self.grid
        for r in range(len(grid)):
            for c in range(len(grid[0])):
                value = grid[r][c]
                if value != 0:
                    prob += choices[str(int(r + 1))][str(int(c + 1))][str(
                        int(value))] == 1, ""

        solve_value = prob.solve()

        # flag is True is solve_value evaluates to 1 i.e. the Sudoku can be
        # solved
        flag = solve_value == 1

        if flag:
            solution_grid = np.zeros((9, 9))
            for r in Rows:
                for c in Columns:
                    for v in Values:
                        if choices[r][c][v].value() == 1.0:
                            solution_grid[int(r) - 1][int(c) - 1] = v
            self._solution = solution_grid
        return flag
Exemplo n.º 10
0
            # append distance to result list
            _distance_result[i][j] = _google_maps_api_result[0]['legs'][0][
                'distance']['value']

    return _distance_result


distance = _distance_calculator(df)
plot_result = _plot_on_gmaps(df)
plot_result

# solve with pulp
for vehicle_count in range(1, vehicle_count + 1):

    # definition of LpProblem instance
    problem = pulp.LpProblem("CVRP", pulp.LpMinimize)

    # definition of variables which are 0/1
    x = [[[
        pulp.LpVariable("x%s_%s,%s" %
                        (i, j, k), cat="Binary") if i != j else None
        for k in range(vehicle_count)
    ] for j in range(customer_count)] for i in range(customer_count)]

    # add objective function
    problem += pulp.lpSum(distance[i][j] * x[i][j][k] if i != j else 0
                          for k in range(vehicle_count)
                          for j in range(customer_count)
                          for i in range(customer_count))

    # constraints
Exemplo n.º 11
0
    def job_selector_ilp(self, jobs):
        """
        Job scheduling by optimization of resource usage by solving ILP using pulp
        """
        import pulp
        from pulp import lpSum

        # assert self.resources["_cores"] > 0
        scheduled_jobs = {
            job: pulp.LpVariable(
                "job_{}".format(idx),
                lowBound=0,
                upBound=1,
                cat=pulp.LpInteger,
            )
            for idx, job in enumerate(jobs)
        }

        temp_files = {
            temp_file
            for job in jobs for temp_file in self.dag.temp_input(job)
        }

        temp_job_improvement = {
            temp_file: pulp.LpVariable("temp_file_{}".format(idx),
                                       lowBound=0,
                                       upBound=1,
                                       cat="Continuous")
            for idx, temp_file in enumerate(temp_files)
        }

        temp_file_deletable = {
            temp_file: pulp.LpVariable(
                "deletable_{}".format(idx),
                lowBound=0,
                upBound=1,
                cat=pulp.LpInteger,
            )
            for idx, temp_file in enumerate(temp_files)
        }
        prob = pulp.LpProblem("JobScheduler", pulp.LpMaximize)

        total_temp_size = max(
            sum([temp_file.size for temp_file in temp_files]), 1)
        total_core_requirement = sum(
            [max(job.resources.get("_cores", 1), 1) for job in jobs])
        # Objective function
        # Job priority > Core load
        # Core load > temp file removal
        # Instant removal > temp size
        prob += (2 * total_core_requirement * 2 * total_temp_size * lpSum(
            [job.priority * scheduled_jobs[job]
             for job in jobs]) + 2 * total_temp_size * lpSum([
                 max(job.resources.get("_cores", 1), 1) * scheduled_jobs[job]
                 for job in jobs
             ]) + total_temp_size * lpSum([
                 temp_file_deletable[temp_file] * temp_file.size
                 for temp_file in temp_files
             ]) + lpSum([
                 temp_job_improvement[temp_file] * temp_file.size
                 for temp_file in temp_files
             ]))

        # Constraints:
        for name in self.workflow.global_resources:
            prob += (lpSum([
                scheduled_jobs[job] * job.resources.get(name, 0)
                for job in jobs
            ]) <= self.resources[name])

        # Choose jobs that lead to "fastest" (minimum steps) removal of existing temp file
        remaining_jobs = self.remaining_jobs
        for temp_file in temp_files:
            prob += temp_job_improvement[temp_file] <= lpSum([
                scheduled_jobs[job] * self.required_by_job(temp_file, job)
                for job in jobs
            ]) / lpSum([
                self.required_by_job(temp_file, job) for job in remaining_jobs
            ])

            prob += temp_file_deletable[temp_file] <= temp_job_improvement[
                temp_file]

        solver = (pulp.get_solver(self.scheduler_ilp_solver)
                  if self.scheduler_ilp_solver else pulp.apis.LpSolverDefault)
        solver.msg = False
        # disable extensive logging
        try:
            prob.solve(solver)
        except pulp.apis.core.PulpSolverError as e:
            raise WorkflowError(
                "Failed to solve the job scheduling problem with pulp. "
                "Please report a bug and use --scheduler greedy as a workaround:\n{}"
                .format(e))

        selected_jobs = set(job for job, variable in scheduled_jobs.items()
                            if variable.value() == 1.0)
        for name in self.workflow.global_resources:
            self.resources[name] -= sum(
                [job.resources.get(name, 0) for job in selected_jobs])
        return selected_jobs
Exemplo n.º 12
0
    def optimize(self):
        self.lineups_created = 0
        self.filter_players()
        prob = pulp.LpProblem('Opti', pulp.LpMaximize)

        try:
            #adds decision variables
            self.p_vars = {
                player_id: pulp.LpVariable(str(player_id), cat='Binary')
                for player_id in self.players['player_id']
            }
            self.t_vars = [
                pulp.LpVariable(str(team), cat='Binary') for team in self.teams
            ]  #to be used for team constraints only, not objective

            #adds objective function
            prob += (pulp.lpSum(self.players.loc[p_id, self.proj_type] *
                                self.p_vars[p_id]
                                for p_id in self.players['player_id']))

            #add player number constraints
            prob += (pulp.lpSum(self.p_vars[p_id]
                                for p_id in self.players['player_id']) == 9)

            #add position constraints
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'C'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) >= 2)
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'C'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) <= 4)
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'W'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) >= 2)
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'W'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) <= 4)
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'D'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) >= 2)
            prob += (pulp.lpSum(
                self.positions.loc[p_id, 'D'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) <= 4)
            prob += (pulp.lpSum(self.positions.loc[p_id, 'G'] *
                                self.p_vars[p_id]
                                for p_id in self.players['player_id']) == 1)

            for team in self.teams:
                #adds number of players per team constraint
                prob += (pulp.lpSum(
                    self.teams.loc[p_id, team] * self.p_vars[p_id]
                    for p_id in self.players['player_id']) <= 4)

                #contrains team variable to be 0 when no players from a team are added, 1 otherwise
                prob += (pulp.lpSum(
                    self.teams.loc[p_id, team] * self.p_vars[p_id]
                    for p_id in self.players['player_id']) >= self.t_vars[list(
                        self.teams).index(team)])

            #adds number of total teams constraint
            prob += (pulp.lpSum(team for team in self.t_vars) >= 3)

            #adds constraint where no skaters can face goalie
            for goalie in self.opp_skaters:
                prob += (6 * self.p_vars[goalie] + pulp.lpSum(
                    self.opp_skaters.loc[p_id, goalie] * self.p_vars[p_id]
                    for p_id in self.players['player_id']) <= 6)

            #adds locked players constraints
            for player in self.lock_players:
                prob += (self.p_vars[player] == 1)

            #add salary constraint
            prob += (pulp.lpSum(
                self.players.loc[p_id, 'salary'] * self.p_vars[p_id]
                for p_id in self.players['player_id']) <= 55000)

            #creates list with optimal solutions
            self.lineups = self.load_lineups(prob)

            #sets dataframe with percentage of lineups a player is in
            self.percentages = self.set_percentages()

        except:
            self.lineups = {}
            self.percentages = None
Exemplo n.º 13
0
    def construct_ILP(
        self,
        T: int,
        q_max: int,
        inn: Dict[int, Dict],
        out: Dict[int, Dict],
        p_inn,
        p_out,
        current_inventory: int,
    ):
        t0 = time.time()
        # Generate the pulp problem.
        model = pulp.LpProblem("Business_Plan_Solver", pulp.LpMaximize)
        # Generate the integer 0/1 decision variables. There are two kinds: inn_vars[t][k] and out_vars[t][k]
        # inn_vars[t][k] == 1 iff in the business plan the agent tries to buy k inputs at time t
        inn_vars = pulp.LpVariable.dicts(
            "inn",
            ((t, k) for t, k in it.product(
                range(self.current_time, self.current_time +
                      T), range(0, q_max))),
            lowBound=0,
            upBound=1,
            cat="Integer",
        )
        # out_vars[t][k] == 1 iff in the business plan the agent tries to sell k inputs at time t
        out_vars = pulp.LpVariable.dicts(
            "out",
            ((t, k) for t, k in it.product(
                range(self.current_time, self.current_time +
                      T), range(0, q_max))),
            lowBound=0,
            upBound=1,
            cat="Integer",
        )
        # print(f'it took {time.time() - t0 : .4f} to generate dec. vars')
        # Generate the objective function - the total profit of the plan. Profit = revenue - cost
        # Here, revenue is the money received from sales of outputs, and cost is the money used to buy inputs.
        model += pulp.lpSum([
            out_vars[t, k] * out[t][k] * p_out[str(t)] -
            inn_vars[t, k] * inn[t][k] * p_inn[str(t)] for t, k in it.product(
                range(self.current_time, self.current_time +
                      T), range(0, q_max))
        ])
        # print(f'it took {time.time() - t0 : .4f} to generate objective function')
        # Genrate the constraints. Only one quantity can be planned for at each time step for buying or selling.
        for t in range(self.current_time, self.current_time + T):
            model += sum([out_vars[t, k] for k in range(0, q_max)]) <= 1
            model += sum([inn_vars[t, k] for k in range(0, q_max)]) <= 1
        # print(f'it took {time.time() - t0 : .4f} to generate constraints ')
        # Document here: optimistic == True means no bluffing, otherwise there is bluffing going on
        optimistic = True
        if optimistic:
            # ToDo: add redundant constraint that models: the number of inputs == number of outputs
            # Constraints that ensure there are enough outputs to sell at each time step.
            right_hand_size = current_inventory
            for t in range(self.current_time, self.current_time + T):
                model += (sum([out_vars[t, k] * k
                               for k in range(0, q_max)]) <= right_hand_size)
                right_hand_size += sum([
                    inn_vars[t, k] * k - out_vars[t, k] * k
                    for k in range(0, q_max)
                ])
        else:
            # Constraints that ensure there are enough outputs, in expectation, to sell at each time step.
            right_hand_size = current_inventory
            for t in range(self.current_time, self.current_time + T):
                model += (sum(
                    [out_vars[t, k] * out[t][k]
                     for k in range(0, q_max)]) <= right_hand_size)
                right_hand_size += sum([
                    inn_vars[t, k] * inn[t][k] - out_vars[t, k] * out[t][k]
                    for k in range(0, q_max)
                ])
        # We assume that the planning starts with no inventory and thus, the agent cannot sell anything at time 0.
        # for k in range(current_inventory+1, q_max):
        #            model += out_vars[0, k] == 0
        time_to_generate_ILP = time.time() - t0
        # print(f'it took {time_to_generate_ILP : .4f} to generate the ILP')
        # return inn_vars, model, optimistic, out_vars, t0, time_to_generate_ILP

        # solve ILP
        t0_solve = time.time()
        model.solve()
        solve_time = time.time() - t0_solve
        # print(f'it took {solve_time : .4f} sec to solve, result = {pulp.LpStatus[model.status]}')
        total_time = time.time() - t0
        # print(f"MODEL OBJECTIVE: {pulp.value(model.objective)}")
        # #print(f'it took {total_time : .4f} sec in total, and has opt profit of {pulp.value(model.objective) : .4f}')
        t0 = time.time()
        buy_plan = {
            t: sum([int(k * inn_vars[t, k].varValue) for k in range(0, q_max)])
            for t in range(self.current_time, self.current_time + T)
        }
        sell_plan = {
            t: sum([int(k * out_vars[t, k].varValue) for k in range(0, q_max)])
            for t in range(self.current_time, self.current_time + T)
        }
        # print(f'it took {time.time() - t0 : .4f} sec to produce the plan')

        return (
            buy_plan,
            sell_plan,
            solve_time,
            total_time,
            inn_vars,
            model,
            optimistic,
            out_vars,
            t0,
            time_to_generate_ILP,
        )
Exemplo n.º 14
0
def solve_gc_IP(G, k, solver, threads, plot, pos):
    """
    k-彩色問題を通常の定式化で解く
    入力
        G: グラフ
        k(int): 色数
        solver: "cbc" or "cplex" or "gurobi"
        threads: gurobiの場合指定
        plot: trueの場合plotする
    出力
        

    # ><><><><><><><><><><><><><><><><><><><><><
    # ><><><><><><><><><><><><><><><><><><><><><
    # ><><><><><><><><><><><><><><><><><><><><><
    # ><><><><><><><><><><><><><><><><><><><><><

    """

    colors = list(range(1, k+1))

    nodes = G.nodes
    edges = G.edges

    problem = pulp.LpProblem(f'{k}-Coloring Problem', pulp.LpMinimize)

    problem += 0

    var = {
        node: pulp.LpVariable.dicts(str(node), colors, cat = pulp.LpBinary) for node in nodes
    }


    # 1つの領域は一色でしか塗らない
    for node in nodes:
        problem += lpSum(var[node].values()) == 1

    # 隣り合った領域は同色で塗らない
    for node1, node2 in edges:
        for color in colors:
            problem += var[node1][color] + var[node2][color] <= 1

    start = time.time()

    if solver == 'cbc':
        result = problem.solve()
    elif solver == 'cplex':
        result = problem.solve(CPLEX(msg=True, mip=True))
    elif solver == 'gurobi':
        result = problem.solve(GUROBI(msg=True, mip=True, Threads=threads))

    elapsed_time = time.time() - start

    print('elapsed_time :', elapsed_time)

    print('result : '+ pulp.LpStatus[result])
    
    if pulp.LpStatus[result] == 'Optimal':
        print('value =', pulp.value(problem.objective))

        output = {}
        for node, v in var.items():
            for color, flg in v.items():
                if flg.value() == 1:
                    output[node] = color
                    break
        

        if plot:
            plot_gc(G, output, pos)
Exemplo n.º 15
0
    def _selectSentences(self, wordlimit):
        """
        Optimally selects the sentences based on their bigrams
        """
        fullsentences = [
            removePOS(sentence) for cluster in self.candidates
            for sentence in cluster
        ]

        # remember the correspondance between a sentence and its cluster
        clusternums = {}
        sentencenums = {s: i for i, s in enumerate(fullsentences)}
        for i, cluster in enumerate(self.candidates):
            clusternums[i] = []
            for sentence in cluster:
                fullsentence = removePOS(sentence)
                if fullsentence in sentencenums:
                    clusternums[i].append(sentencenums[removePOS(sentence)])

        # extract bigrams for all sentences
        bigramssentences = [
            extractBigrams(sentence.split()) for sentence in fullsentences
        ]

        # get uniqs bigrams
        uniqbigrams = set(bigram for sentence in bigramssentences
                          for bigram in sentence)
        numbigrams = len(uniqbigrams)
        numsentences = len(fullsentences)

        # rewrite fullsentences
        fullsentences = [wellformatize(sentence) for sentence in fullsentences]

        # filter out rare bigrams
        weightedbigrams = {
            bigram: (count if count >= self.minbigramcount else 0)
            for bigram, count in self.bigramstats.items()
        }

        problem = pulp.LpProblem("Sentence selection", pulp.LpMaximize)

        # concept variables
        concepts = pulp.LpVariable.dicts(name='c',
                                         indexs=range(numbigrams),
                                         lowBound=0,
                                         upBound=1,
                                         cat='Integer')
        sentences = pulp.LpVariable.dicts(name='s',
                                          indexs=range(numsentences),
                                          lowBound=0,
                                          upBound=1,
                                          cat='Integer')

        # objective : maximize wi * ci (weighti * concepti)
        # small hack. If the bigram has been filtered out from uniqbigrams,
        # we give it a weight of 0.
        problem += sum([(weightedbigrams.get(bigram) or 0) * concepts[i]
                        for i, bigram in enumerate(uniqbigrams)])

        # constraints

        # size
        problem += sum([
            sentences[j] * len(fullsentences[j].split())
            for j in range(numsentences)
        ]) <= wordlimit

        # integrity constraints (link between concepts and sentences)
        for j, bsentence in enumerate(bigramssentences):
            for i, bigram in enumerate(uniqbigrams):
                if bigram in bsentence:
                    problem += sentences[j] <= concepts[i]

        for i, bigram in enumerate(uniqbigrams):
            problem += sum([
                sentences[j] for j, bsentence in enumerate(bigramssentences)
                if bigram in bsentence
            ]) >= concepts[i]

        # select only one sentence per cluster
        for clusternum, clustersentences in clusternums.items():
            problem += sum([sentences[j] for j in clustersentences]) <= 1

        # solve the problem
        problem.solve(GLPK())

        summary = []
        # get the sentences back
        for j in range(numsentences):
            if sentences[j].varValue == 1:
                summary.append(fullsentences[j])

        return summary
Exemplo n.º 16
0
def Objective():
    problem = pulp.LpProblem()
    index = list(range(9))
    x = [[[pulp.LpVariable(f'x{i}{j}{k}', cat='Binary') for k in index]
          for j in index] for i in index]
    return problem, index, x
Exemplo n.º 17
0
# import the library pulp as p
import pulp as p

# Create a LP Minimization problem
Lp_prob = p.LpProblem('Problem', p.LpMinimize)

# Create problem Variables
R1 = p.LpVariable("R1", lowBound = 0)
R2 = p.LpVariable("R2", lowBound = 0)
R3 = p.LpVariable("R3", lowBound = 0)
R4 = p.LpVariable("R4", lowBound = 0)
I1 = p.LpVariable("I1", lowBound = 0)
I2 = p.LpVariable("I2", lowBound = 0)
I3 = p.LpVariable("I3", lowBound = 0)
I4 = p.LpVariable("I4", lowBound = 0)
B1 = p.LpVariable("B1", lowBound = 0)
B2 = p.LpVariable("B2", lowBound = 0)
B3 = p.LpVariable("B3", lowBound = 0)
B4 = p.LpVariable("B4", lowBound = 0)
S1 = p.LpVariable("S1", lowBound = 0)
S2 = p.LpVariable("S2", lowBound = 0)
S3 = p.LpVariable("S3", lowBound = 0)
S4 = p.LpVariable("S4", lowBound = 0)
D1 = p.LpVariable("D1", lowBound = 0)
D2 = p.LpVariable("D2", lowBound = 0)
D3 = p.LpVariable("D3", lowBound = 0)
D4 = p.LpVariable("D4", lowBound = 0)
C1 = p.LpVariable("C1", lowBound = 0)
C2 = p.LpVariable("C2", lowBound = 0)
C3 = p.LpVariable("C3", lowBound = 0)
C4 = p.LpVariable("C4", lowBound = 0)
Exemplo n.º 18
0
    def setup_lp(self,
                 reserve=True,
                 proportion=True,
                 combined=True,
                 transmission=True):
        """ Set up the Linear Program by creating an objective function and 
            passing the requisite variables to it.
            
            Creates the linear program according to simplified SPD model
        
        """

        # Get the Constraints and lists for model creation simplification
        eb = self.ISO.energy_bands
        rb = self.ISO.reserve_bands
        tb = self.ISO.transmission_bands
        nd = self.ISO.all_nodes

        et = self.ISO.energy_totals
        rt = self.ISO.reserve_totals
        tt = self.ISO.transmission_totals

        ebmap = self.ISO.energy_band_map
        rbmap = self.ISO.reserve_band_map
        tbmap = self.ISO.transmission_band_map

        ebp = self.ISO.energy_band_prices
        rbp = self.ISO.reserve_band_prices

        ebm = self.ISO.energy_band_maximum
        rbm = self.ISO.reserve_band_maximum
        tbm = self.ISO.transmission_band_maximum

        etm = self.ISO.energy_total_maximum
        ttm = self.ISO.transmission_total_maximum
        rbpr = self.ISO.reserve_band_proportion

        spin = self.ISO.spinning_station_names
        spin_map = self.ISO.spin_map

        node_map = self.ISO.node_energy_map
        demand = self.ISO.node_demand

        node_t_map = self.ISO.node_t_map
        td = self.ISO.node_transmission_direction

        rzones = self.ISO.reserve_zone_names
        rzone_g = self.ISO.reserve_zone_generators
        rzone_t = self.ISO.reserve_zone_transmission
        rztd = self.ISO.reserve_zone_trans_direct

        rz_providers = self.ISO.reserve_zone_reserve

        # Set up the linear program

        self.lp = lp.LpProblem("Model Dispatch", lp.LpMinimize)

        # Add variables
        ebo = lp.LpVariable.dicts("Energy_Band", eb, 0)
        rbo = lp.LpVariable.dicts("Reserve_Band", rb, 0)
        tbo = lp.LpVariable.dicts("Transmission_Band", tb)

        eto = lp.LpVariable.dicts("Energy_Total", et, 0)
        rto = lp.LpVariable.dicts("Reserve_Total", rt, 0)
        tto = lp.LpVariable.dicts("Transmission_Total", tt)

        node_inj = lp.LpVariable.dicts("Nodal_Inject", nd)

        risk = lp.LpVariable.dicts("Risk", rzones)

        # Map the add Constraint method to a simpler string
        addC = self.lp.addConstraint
        SUM = lp.lpSum

        # Objective function
        self.lp.setObjective(SUM([ebo[i] * ebp[i] for i in eb]) +\
                             SUM([rbo[j] * rbp[j] for j in rb]))

        # Begin Adding Constraint

        # Nodal Dispatch
        for n in nd:
            n1 = '_'.join([n, 'Energy_Price'])
            n2 = '_'.join([n, 'Nodal_Transmission'])
            addC(node_inj[n] == SUM([eto[i] for i in node_map[n]]) - demand[n],
                 n1)
            addC(
                node_inj[n] == SUM([tto[i] * td[n][i] for i in node_t_map[n]]),
                n2)

        # Individual Band Offer
        for i in eb:
            name = '_'.join([i, 'Band_Energy'])
            addC(ebo[i] <= ebm[i], name)

        # Reserve Band Offer
        for j in rb:
            name = '_'.join([j, 'Band_Reserve'])
            addC(rbo[j] <= rbm[j], name)

        # Transmission band Offer
        for t in tb:
            addC(tbo[t] <= tbm[t])
            addC(tbo[t] >= tbm[t] * -1)

        # Energy Total Offer
        for i in et:
            name = '_'.join([i, 'Total_Energy'])
            addC(SUM([ebo[j] for j in ebmap[i]]) == eto[i], name)

        # Reserve Total Offer
        for i in rt:
            name = '_'.join([i, 'Total_Reserve'])
            addC(SUM([rbo[j] for j in rbmap[i]]) == rto[i], name)

        # Transmission Total offer
        for i in tt:
            addC(SUM([tbo[j] for j in tbmap[i]]) == tto[i])
            addC(tto[i] <= ttm[i])
            addC(tto[i] >= ttm[i] * -1)

        # Spinning Reserve Constraints
        for i in spin:
            name = '_'.join([i, 'Combined_Dispatch'])
            addC(rto[i] + eto[i] <= etm[i], name)

            for j in spin_map[i]:
                name = '_'.join([j, 'Prop'])
                addC(rbo[j] <= rbpr[j] * eto[i], name)

        # Risk Constraints

        for r in rzones:
            # Generation Risk
            for i in rzone_g[r]:
                name = '_'.join([r, i])
                addC(risk[r] >= eto[i], name)

            # Transmission Risk
            for t in rzone_t[r]:
                name = '_'.join([r, t])
                addC(risk[r] >= tto[t] * rztd[r][t], name)

        # Reserve Dispatch
        for r in rzones:
            n1 = '_'.join([r, 'Reserve_Price'])
            addC(SUM(rto[i] for i in rz_providers[r]) - risk[r] >= 0., n1)
Exemplo n.º 19
0
def _solver(Gt, Gd, target_latency=None):
    """
    Args:
        target_latency (int): latency constrain for this task graph
        source_list (list): source nodes in the task graph
        dst_list (list): destination nodes in the task graph
        Gt (networkx.DiGraph): task graph in a multi-source, single
        destination, no-loop directed graph, where src_k are data sources,
        dst is the actuator, and other nodes in between are tasks

           src1 -----> t11 -----> t12 ... ----->  dst
           src2 -----> t21 -----> t22 ... ----->
                 ...   ...  ...  ...
                -----> tk1 -----> tk2 ... ----->

            Gt.node[t] (dict): node, stores information of each task
            Gt[t1][t2] (dict): edge, stores relationship between tasks

            E(t1, t2) (Unit): input/output relationship between t1, t2
                If t1 will not ouput any data to t2, set the value to 0
                e.g. Gt[t1][t2][GtInfo.TRAFFIC] = Unit.byte(20)
                    Gt[t1][t2][GtInfo.TRAFFIC] = 0
            _It(t2) (Unit): total input data size to the task. Obtained
                from sum E(ti, t2) for all ti with an edge to t2. The value
                will be stored at Gt.node[t][GtInfo.RESRC_RQMT]
            _Ot(t1) (Unit): total ouput data size to the task. Obtained
                from sum E(t1, ti) for all ti with an edge from t1. The
                value will be stored at Gt.node[t][GtInfo.RESRC_RQMT]
            Lt(t,d) (Unit): computation latency of task t runs on device d.
                Devices can be categorized according to number of CPUs,
                GPUs, RAM size, and disk space.
                e.g. Gt.node[t][GtInfo.LATENCY_INFO] = {
                        Device.T2_MICRO: Unit.ms(100),
                        Device.P3_2XLARGE: Unit.ms(5)}
                    device_type = Device.type(Gd.node[d][GdInfo.HARDWARE])
                    Gt.node[t][GtInfo.LATENCY_INFO][device_type] = 100 (ms)
            Rt(t) (dict): minimum RESRC requirement for task t
            Rt(t,r,d): minimum requirement of RESRC r for task t of a
                specific build flavor for that device
                e.g. build_type = Flavor.type(Device.P3_2XLARGE)
                    assert(build_type == Flavor.GPU)
                    Gt.node[t][GtInfo.RESRC_RQMT][build_type] = {
                        Hardware.RAM: Unit.gb(2),
                        Hardware.HD: Unit.mb(512),
                        Hardware.CPU: Unit.percentage(10),
                        Hardware.GPU: Unit.percentage(60),
                        Hardware.CAMERA: 1,
                        Hardware.NIC_INGRESS: Unit.mb(2),  # _It(t)
                        Hardware.NIC_EGRESS: Unit.byte(20),  # _Ot(t)
                    }

        Gd (networkx.DiGraph): a directed graph describes network topology,
            where each node represent a device

            Gd[d] (dict): information of each device, including:

            Ld(d1, d2) (Unit): transmission time between two devices d1, d2
                If d2 is not reachable from d1, set the value to MAXINT
                e.g. Gd[d1][d2][GdInfo.LATENCY] = 20 (ms)
                    Gd[d1][d2][GdInfo.LATENCY] = Const.MAXINT
            _Hd(d) (dict): hardware specification of device d.
                Use this internal information to determine device_type
                Dd(t) and calculate Rd(d).
                e.g. Gd.node[d][GdInfo.HARDWARE] = {
                    Hardware.RAM: Unit.gb(16),
                    Hardware.HD: Unit.tb(1),
                    Hardware.CPU: 4,
                    Hardware.GPU: 1,
                    Hardware.GPS: 1,
                    Hardware.CAMERA: 1
                    Hardware.NIC_INGRESS: Unit.gbps(10),
                    Hardware.NIC_EGRESS: Unit.gbps(10),
                }
            _Dd(d) (enum): device type of device d, determined by hardware
                specification of the device. Used by Gt.node[t] for
                accessing information of the a certain device type
                e.g. device_type = Device.type(Gd.node[d][GdInfo.HARDWARE])
                    assert(device_type == Device.T2_MICRO)
            Rd(d) (dict): available RESRCs on device d.
            Rd(d, r) (Unit): availablity of RESRC r on device d.
                e.g. Gd.node[d][GdInfo.RESRC] = {
                    Hardware.RAM: Unit.gb(12),
                    Hardware.HD: Unit.gb(500),
                    Hardware.CPU: Unit.percentage(80),
                    Hardware.GPU: Unit.percentage(100),
                    Hardware.BW_INGRESS: Unit.mb(100),
                    Hardware.BW_EGRESS: Unit.mb(60),
                    Hardware.GPS: 1,
                    Hardware.PROXIMITY: 1,
                    Hardware.ACCELEROMETER: 1,
                    Hardware.GYROSCOPE: 1,
                    Hardware.CAMERA: 1,
                }

    decision variable:
        X(t,d) = 1 if assign task t to device d else 0
    objective: minimize longest path's overall latency in the task graph,
        i.e. total execution times + transmission latencies along the path

                         len(p)
        minimize   max   {  sum ( X(ti,di) * Lt(ti, di) )
        X(t,d)   p in Gt    i=1
                       len(p)-1
                    +   sum ( X(ti,di) * X(ti+1,di+1) * Ld(di, di+1) ) }
                        i=1

        this can be simplified by an auxiliary variable and rewrote as:

            minimize Y , where Y = max {....} above

        with additional constrains:

        for p in Gt:
                      len(p)
                Y >=   max   {  sum ( X(ti,di) * Lt(ti, di) )
                     p in Gt    i=1
                      len(p)-1
                   +   sum ( X(ti,di) * X(ti+1,di+1) * Ld(di, di+1) ) }
                       i=1

    constrians 1: neighbors in the task graph must also be accessible from
        each other in network graph
        for (ti, tj) in Gt.edges():
            for all combinations (di, dj) in Gd:
                X(ti,di) * X(tj,dj) * Ld(di, dj) < LATENCY_MAX

    constrians 2: device must be able to support what the tasks need
        for d in Gd:
            for r in Rd:
                           len(Gt)
                Rd(d,r) - { sum ( X(ti,d) * Rt(ti,r,d) ) } >= 0
                            i=1

    constrains 3: task -> device is one-to-one mapping, and all task must be
        mapped to one device

    since linear programming cannot have variable multiplication,
    use a helper variable XX to replace X(ti,di) * X(tj,dj)

        X(ti,di) * X(tj,dj) ---replace---> XX(X(ti,di),X(tj,dj))

    with additional constrains
        XX(X(ti,di),X(tj,dj)) + 1 >= X(ti,di) + X(tj,dj)
        XX(X(ti,di),X(tj,dj)) * 2 <= X(ti,di) + X(tj,dj)

    """
    # define invalid_latency as a constrain to filter out meaningless
    # solutions
    if target_latency:
        invalid_latency = target_latency * 2
    else:
        invalid_latency = Const.INT_MAX
    log.info(
        ('set invalid_latency={latency}. skip neighbors cannot be reached '
         'within {latency} ms.').format(latency=invalid_latency))

    # Generate all possible mappings of device_i <-> task_i
    known_mapping = {}
    for node in Gt.nodes():
        mapped_device = Gt.node[node].get(GtInfo.DEVICE, None)
        if mapped_device is not None:
            known_mapping[node] = mapped_device
    log.info('known_mapping: {}'.format(known_mapping))
    mapped_tasks = list(known_mapping)
    mapped_devices = listvalues(known_mapping)
    tasks = [t for t in Gt.nodes() if t not in mapped_tasks]
    devices = [d for d in Gd.nodes() if d not in mapped_devices]
    log.info('find possible mappings for {} tasks in {} devices'.format(
        len(tasks), len(devices)))

    # create LP problem
    prob = pulp.LpProblem("placethings", pulp.LpMinimize)
    # auxiliary variable: it represent the longest path's overall latency
    # in the task graph
    Y = pulp.LpVariable('LongestPathLength',
                        lowBound=0,
                        upBound=Const.INT_MAX,
                        cat='Interger')
    # objective: minimize longest path's overall latency in the task graph
    # later, add additional constrains for the auxiliary variable
    prob += Y

    # decision variable: X(t,d) = 1 if assign task t to device d else 0
    X = defaultdict(dict)
    all_unknown_X = []
    for t in tasks:
        for d in devices:
            X[t][d] = None
    for d in mapped_devices:
        for t in Gt.nodes():
            X[t][d] = 0
    for t in mapped_tasks:
        for d in Gd.nodes():
            X[t][d] = 0
        d_known = Gt.node[t][GtInfo.DEVICE]
        X[t][d_known] = 1  #Mapping which are added by user
    for t in tasks:
        for d in devices:
            if X[t][d] is None:
                X[t][d] = pulp.LpVariable('X_{}_{}'.format(t, d),
                                          lowBound=0,
                                          upBound=1,
                                          cat='Integer')
                all_unknown_X.append(X[t][d])
        # 1-1 map # One task can only map map to device
        prob += pulp.lpSum(listvalues(X[t])) == 1
    # number of X == 1 must equal to number of tasks
    log.info('there are {} unknowns'.format(len(all_unknown_X)))

    assert len(all_unknown_X) == len(tasks) * len(devices)
    # tasks are the tasks not yet assigned.
    # devices are the devices not yet mapped

    prob += pulp.lpSum(all_unknown_X) == len(tasks)
    # auxiliary variable: use XX to replace X[ti][di] * X[tj][dj]
    XX = defaultdict(dict)
    all_XX = []
    for ti in Gt.nodes():
        for di in Gd.nodes():
            for tj in Gt.nodes():
                for dj in Gd.nodes():
                    if (ti, tj) not in Gt.edges():
                        XX[(ti, di)][(tj, dj)] = 0
                    elif (di, dj) not in Gd.edges() or (
                            Gd[di][dj][GdInfo.LATENCY] > invalid_latency):
                        # constrians 1: neighbors in the task graph must also
                        # be accessible from each other in the network graph
                        XX[(ti, di)][(tj, dj)] = 0
                    else:
                        XX[(ti, di)][(tj,
                                      dj)] = pulp.LpVariable('XX_{}_{}'.format(
                                          (ti, di), (tj, dj)),
                                                             lowBound=0,
                                                             upBound=1,
                                                             cat='Integer')
                        all_XX.append(XX[(ti, di)][(tj, dj)])
                        # add constrains
                        prob += (XX[(ti, di)][(tj, dj)] + 1 >=
                                 X[ti][di] + X[tj][dj])
                        prob += (XX[(ti, di)][(tj, dj)] * 2 <=
                                 X[ti][di] + X[tj][dj])
    log.info('there are {} combinations for links'.format(len(all_XX)))
    prob += pulp.lpSum(all_XX) == len(Gt.edges())

    # Generate all simple paths in the graph G from source to target.
    src_list, dst_list, all_paths = _find_all_simple_path(Gt)
    log.info('find all path from {} to {}'.format(src_list, dst_list))
    # Generate all possible mappings
    all_mappings = list(pulp.permutation(devices, len(tasks)))
    log.info('{} possible mappings for {} devices and {} tasks'.format(
        len(all_mappings), len(devices), len(tasks)))
    task_to_idx = dict(zip(tasks, range(len(tasks))))
    # use constrains to model Y, the longest path for each mapping
    for device_mapping in all_mappings:
        for path in all_paths:
            assert path[0] in src_list
            assert path[len(path) - 1] in dst_list
            path_vars = []
            # first node: src
            ti = path[0]
            di = Gt.node[ti][GtInfo.DEVICE]
            # device_mapping start from path[1] to path[N-1]
            for j in range(1, len(path) - 1):
                tj = path[j]
                dj = device_mapping[task_to_idx[tj]]
                assert Gt.node[tj][GtInfo.DEVICE] is None
                assert dj in Gd.nodes()
                # get transmission latency from di -> dj
                Ld_di_dj = Gd[di][dj][GdInfo.LATENCY]
                # path_vars.append((X[ti][di] * X[tj][dj]) * Ld_di_dj)
                path_vars.append(XX[(ti, di)][(tj, dj)] * Ld_di_dj)
                log.debug('Ld_di_dj (move from {} to {}) = {}'.format(
                    di, dj, Ld_di_dj))
                # get computation latency for task tj at dj
                dj_type = Gd.node[dj][GdInfo.DEVICE_TYPE]
                # get latency of the default build flavor
                Lt_tj_dj = listvalues(
                    Gt.node[tj][GtInfo.LATENCY_INFO][dj_type])[0]
                path_vars.append(X[tj][dj] * Lt_tj_dj)
                log.debug('Lt_tj_dj (compute {} at {}) = {}'.format(
                    tj, dj, Lt_tj_dj))
                ti = tj
                di = dj
            # last node: dst
            tj = path[len(path) - 1]
            dj = Gt.node[tj][GtInfo.DEVICE]
            Ld_di_dj = Gd[di][dj][GdInfo.LATENCY]
            # path_vars.append(X[ti][di] * X[tj][dj] * Ld_di_dj)
            path_vars.append(XX[(ti, di)][(tj, dj)] * Ld_di_dj)
            log.debug('Ld_di_dj (move from {} to {}) = {}'.format(
                di, dj, Ld_di_dj))
            log.debug('add constrain for path:\n Y >= {}'.format(path_vars))
            # add constrain
            prob += Y >= pulp.lpSum(path_vars)

    # constrians 2: device must be able to support what the tasks need
    #     for d in Gd:
    #         for r in Rd:
    #                        len(Gt)
    #             Rd(d,r) - { sum ( X(ti,d) * Rt(ti,r,d) ) } >= 0
    #                         i=1
    for di in devices:
        for resrc in Hardware:
            # get available RESRC or set to 0
            Rd_d_r = Gd.node[di][GdInfo.RESRC].get(resrc, 0)
            var_list = []
            for ti in tasks:
                di_type = Gd.node[di][GdInfo.DEVICE_TYPE]
                # get the default flavor
                ti_flavor = list(Gt.node[ti][GtInfo.LATENCY_INFO][di_type])[0]
                Rt_t_r_d = (Gt.node[ti][GtInfo.RESRC_RQMT][ti_flavor].get(
                    resrc, 0))
                if Rt_t_r_d > 0:
                    var_list.append(X[ti][di] * Rt_t_r_d)
            if var_list:
                log.debug('add constrain for {}({}):\n {} <= {}'.format(
                    di, resrc, var_list, Rd_d_r))
                prob += pulp.lpSum(var_list) <= Rd_d_r

    # solve
    status = prob.solve(pulp.solvers.GLPK(msg=1))
    log.info('status={}'.format(pulp.LpStatus[status]))
    result_mapping = {}
    for t in Gt.nodes():
        for d in Gd.nodes():
            if pulp.value(X[t][d]):
                log.info('map: {} <-> {}, X_t_d={}'.format(
                    t, d, pulp.value(X[t][d])))
                result_mapping[t] = d
    return status, result_mapping
Exemplo n.º 20
0
def build_local_problem_lp(pb, name):
    lp = pulp.LpProblem(name + ".lp", pulp.LpMinimize)
    lp.setSolver()
    prod_vars = {}
    in_use_vars = {}
    defaillance = {}
    cout_proportionnel_defaillance = 3000  #euros/MWh
    #demande = demande-auto_conso
    #auto_conso<=Enr
    #Enr=Enr-auto_conso
    #inject=

    for t in pb.time_steps:
        prod_vars[t] = {}
        in_use_vars[t] = {}

        var_name = "battery_stock" + str(t)
        prod_vars[t]["battery_stock"] = pulp.LpVariable(
            var_name, 0.0, pb.battery.energy_max)

        var_name = "battery_store" + str(t)
        prod_vars[t]["battery_store"] = pulp.LpVariable(
            var_name, -pb.battery.power_max_store, 0.0)

        var_name = "battery_prod" + str(t)
        prod_vars[t]["battery_prod"] = pulp.LpVariable(
            var_name, 0.0, pb.battery.power_max_prod)

        cnt_name = "cnt_storage_evolution_" + str(t)
        if t == pb.time_steps[0]:
            #initial stock=0
            lp += prod_vars[t][
                "battery_stock"] == pb.time_step_duration / 60.0 * (
                    -pb.battery.efficiency * prod_vars[t]["battery_store"] -
                    prod_vars[t]["battery_prod"]), cnt_name
        else:
            lp += prod_vars[t]["battery_stock"] == prod_vars[
                t - 1]["battery_stock"] + pb.time_step_duration / 60.0 * (
                    -pb.battery.efficiency * prod_vars[t]["battery_store"] -
                    prod_vars[t]["battery_prod"]), cnt_name

        var_name = "auto_conso_" + str(t)
        prod_vars[t]["auto_conso"] = pulp.LpVariable(var_name, 0.0,
                                                     pb.local_demand[t])
        var_name = "payed_" + str(t)
        prod_vars[t]["payed_conso"] = pulp.LpVariable(var_name, 0.0,
                                                      pb.local_demand[t])
        var_name = "sold_local_production" + str(t)
        prod_vars[t]["sold_local_production"] = pulp.LpVariable(
            var_name, 0.0, pb.local_solar_power[t] + pb.battery.power_max_prod)

        lp += prod_vars[t]["auto_conso"] + prod_vars[t][
            "payed_conso"] == pb.local_demand[t], "cnt_local_conso_" + str(t)

        lp += prod_vars[t][
            "sold_local_production"] == pb.local_solar_power[t] - prod_vars[t][
                "auto_conso"] + prod_vars[t]["battery_prod"] + prod_vars[t][
                    "battery_store"], "cnt_local_solar_" + str(t)


    lp.setObjective( pb.electricity_tariff*pulp.lpSum([prod_vars[t]["payed_conso"]  for t in pb.time_steps])* pb.time_step_duration/60.0\
                   -pulp.lpSum([pb.solar_power_selling_price_chronicle[t]*prod_vars[t]["sold_local_production"] for t in pb.time_steps]) * pb.time_step_duration/60.0)

    model = Model(lp, prod_vars)
    return model
Exemplo n.º 21
0
def run(total, price):
    y = [None] * len(price)
    names = [p[1] for p in price]

    problem = pulp.LpProblem("Problem-1", pulp.LpMinimize)

    for index in range(len(price)):
        y[index] = pulp.LpVariable("y" + str(index), 0, 2, pulp.LpInteger)

    # problem += pulp.lpSum([y[i] for i in range(len(price))]), "The number of items"

    prices = [y[i] * price[i][0] for i in range(len(price))]
    # prices = [y[i] * price[i] for i in range(len(price))]

    problem += total - pulp.lpSum(prices), "Use as much"

    problem += total == pulp.lpSum(prices), "Use exact"

    problem += pulp.lpSum(prices) <= total, "Do not over"

    for index in range(len(price)):
        if len(price[index]) >= 4:
            # Set minimum
            problem += y[index] >= price[index][3]
        if len(price[index]) >= 3:
            # Set maximum
            problem += y[index] <= price[index][2]

    # 問題の式全部を表示
    print("問題の式")
    print("--------")
    print(problem)
    print("--------")
    print(price)

    # 計算
    result_status = problem.solve()

    # (解が得られていれば)目的関数値や解を表示
    if pulp.LpStatus[result_status] != "Optimal":
        print("解なし")
        return {"ok": False}
    else:
        obj = pulp.value(problem.objective)
        if obj != 0:
            print("解無し 残額: %d" % (obj))
            return {"ok": False}
        else:
            print("")
            print("計算結果")
            print("********")
            print("最適性 = {}".format(pulp.LpStatus[result_status]))
            print("目的関数値 = {}".format(obj))
            print("y = {}".format([int(pulp.value(v)) for v in y]))
            print("********")

            print("      ", price)
            used = 0
            for i, v in enumerate(zip(price, [int(pulp.value(v)) for v in y])):
                p, n = v
                if n > 0:
                    print("{}\t{}\t{}\t{}".format(i, p[0], n, p[1]))
                used += p[0] * n
            print("Total: ", used)
            count = {names[i]: int(pulp.value(y[i])) for i in range(len(y))}
            return {"ok": True, "count": count}
Exemplo n.º 22
0
ProdCosts = common.readArrayFromFile('prod_costs.dat')

# NOTE(nox): Indices
Fact = range(0, len(Capacity))
Cent = range(0, len(Demand))

# NOTE(nox): Decision variables
Dist = pulp.LpVariable.dicts('Distribution',
                             [(F, C) for F in Fact for C in Cent],
                             cat=pulp.LpInteger,
                             lowBound=0)
Used = pulp.LpVariable.dicts('Factory used', [F for F in Fact],
                             cat=pulp.LpBinary)

# NOTE(nox): Objective function
Model = pulp.LpProblem('Costs', pulp.LpMinimize)
Model += (sum(DistCosts[C][F] * Dist[(F, C)] for F in Fact
              for C in Cent) + sum(FixedCosts[F] * Used[F] for F in Fact) +
          sum(ProdCosts[F] * sum(Dist[(F, C)] for C in Cent) for F in Fact))

# NOTE(nox): Subject to
for F in Fact:
    Model += sum(Dist[(F, C)] for C in Cent) <= Capacity[F] * Used[F]

for C in Cent:
    Model += sum(Dist[(F, C)] for F in Fact) >= Demand[C]

Model += Used[0] == 1

# NOTE(nox): Solve
Status = Model.solve()
Exemplo n.º 23
0
import pulp

x = pulp.LpVariable('Nb of tables', lowBound=10, upBound=20, cat='Integer')

z = pulp.LpProblem('My maximization pb', pulp.LpMaximize)

z += 5 * x, 'Net Profit'
z += x <= 15, 'max of daily production'
z.solve()

for var in z.variables():
    print(var.name + '=' + str(var.varValue))

print('value of Obj function:' + str(pulp.value(z.objective)))
Exemplo n.º 24
0

def values(xs: List[pulp.pulp.LpAffineExpression]) -> ndarray:
    return array([x.value() for x in xs])


def accumulate(var, i) -> pulp.pulp.LpAffineExpression:
    return pulp.lpSum([var[k] for k in range(i + 1)])


# Solution:

total_days = len(purchases_a)
assert len(purchases_a) == len(purchases_b)
days = [i for i in range(total_days)]
model = pulp.LpProblem("Planning Problem", pulp.LpMinimize)

# Declare variables
xa = pulp.LpVariable.dicts("Production Product A",
                           days,
                           lowBound=0,
                           upBound=max_output_a)
xb = pulp.LpVariable.dicts("Production Product B",
                           days,
                           lowBound=0,
                           upBound=max_output_b)

requirement_b = purchases_b
requirement_a = array([xb[d] for d in days]) * requirement_b_to_a + purchases_a

# Closed sum (zero inventory at start or end)
def blocked_reactions_analysis(
        database,
        pulp_solver,
        specific_bounds,
        custom_flux_constraints,
        excluded_reactions=None,
        target_reactions_list=None,
        logger=None):
    """
    Perform flux variability analysis on the database,
    based on the overall reaction equation of optstoic.
    If a reaction cannot carry flux (i.e., -eps <= v(j) <= eps, where eps = 1e-8),
    then the reaction is considered as a blocked reaction.
    The blocked reactions are then eliminated from the database S matrix.
    Next, the internal loops (excluding cofactors) are identified.
    Then, optStoic analysis can be performed for pathway prospecting.

    max/min v(j)

    subject to:
            sum(j, S(i,j) * v(j)) = 0, for all i
            custom_flux_constraints

        Note: The glycolysis study was done using the GAMS version of this code.
        This is written in attempt to port find_blocked_reactions.gms from GAMS to Python,
        as a part of effort to generalize optstoic analysis.

    Args:
        database (:obj:`BaseReactionDatabase`): The default reaction database
            without blocked reactions/loops.
        pulp_solver (TYPE): The solver for PuLP.
        specific_bounds (dict): LB and UB for exchange reactions which defined the
            overall design equations. E.g. {'Ex_glc': {'LB': -1, 'UB':-1}}
        custom_flux_constraints (TYPE): The custom constraints that need to be
            added to the model formulation.
        excluded_reactions (None, optional): The list of reactions that are manually
            selected to be excluded from optstoic solution.
        target_reactions_list (None, optional): If provided, the blocked reaction analysis is performed
            only on a subset of the reaction provided. If None, the blocked reaction analysis
            will be performed on all reactions in the database. The excluded_reactions set
            can be subtracted(e.g., set(database.reactions) - excluded_reactions), since
            they are blocked reactions.
        logger (:obj:`logging.logger`, optional): The logging instance

    Returns:
        TYPE: Description

    Raises:
        ValueError: Description

    Deleted Parameters:
        user_defined_export_rxns_Sji (dict): The list of export reactions that
            need to be added to the model for metabolite exchange (i.e., any metabolite
            that participate in the design equation)
    """
    if logger is None:
        logger = create_logger(
            name="optstoicpy.script.database_preprocessing.blocked_reactions_analysis")

    logger.warning(
        "This process may take a long time to run. It is recommended to be run in a batch script.")

    M = 1000
    EPS = 1e-8

    # Initialize variables
    v = pulp.LpVariable.dicts("v", database.reactions,
                              lowBound=-M, upBound=M, cat='Continuous')

    for j in database.reactions:
        if database.rxntype[j] == 0:
            # Forward irreversible
            v[j].lowBound = 0
            v[j].upBound = M

        elif database.rxntype[j] == 1:
            # Reversible
            v[j].lowBound = -M
            v[j].upBound = M

        elif database.rxntype[j] == 2:
            # Reverse irreversible
            v[j].lowBound = -M
            v[j].upBound = 0

        elif database.rxntype[j] == 4:
            v[j].lowBound = 0
            v[j].upBound = 0

        else:
            raise ValueError("Reaction type for reaction %s is unknown." % j)

    if excluded_reactions is not None:
        for j in excluded_reactions:
            v[j].lowBound = 0
            v[j].upBound = 0

    # Fix stoichiometry of source/sink metabolites
    for j, bounds in specific_bounds.items():
        v[j].lowBound = bounds['LB']
        v[j].upBound = bounds['UB']

    FVA_res = {}
    blocked_reactions = []
    lp_prob = None

    if target_reactions_list is None:
        target_reactions_list = database.reactions
    num_rxn = len(target_reactions_list)

    for ind, j1 in enumerate(target_reactions_list):
        logger.debug("%s/%s" % (ind, num_rxn))
        FVA_res[j1] = {}

        for obj in ['min', 'max']:

            # Variables (make a copy)
            vt = copy.deepcopy(v)
            del lp_prob

            # Objective function
            if obj == 'min':
                lp_prob = pulp.LpProblem("FVA%s" % obj, pulp.LpMinimize)
                lp_prob += vt[j1], "FVA_min"
            elif obj == 'max':
                lp_prob = pulp.LpProblem("FVA%s" % obj, pulp.LpMaximize)
                lp_prob += vt[j1], "FVA_max"

            # Constraints
            # Mass_balance
            for i in database.metabolites:
                # If metabolites not involve in any reactions
                if i not in database.S:
                    continue
                label = "mass_balance_%s" % i
                dot_S_v = pulp.lpSum([database.S[i][j] * vt[j]
                                      for j in list(database.S[i].keys())])
                condition = dot_S_v == 0
                lp_prob += condition, label

            if custom_flux_constraints is not None:
                logger.info("Adding custom constraints...")

                for group in custom_flux_constraints:
                    lp_prob += pulp.lpSum(vt[rxn] for rxn in group['reactions']
                                          ) <= group['UB'], "%s_UB" % group['constraint_name']
                    lp_prob += pulp.lpSum(vt[rxn] for rxn in group['reactions']
                                          ) >= group['LB'], "%s_LB" % group['constraint_name']

            lp_prob.solve(solver=pulp_solver)

            FVA_res[j1][obj] = pulp.value(lp_prob.objective)

        if (FVA_res[j1]['max'] < EPS) and (FVA_res[j1]['min'] > -EPS):
            blocked_reactions.append(j1)

        json.dump(FVA_res,
                  open("temp_FVA_result.json", 'w+'),
                  sort_keys=True,
                  indent=4)

    return blocked_reactions, FVA_res
Exemplo n.º 26
0
import pulp
pr = pulp.LpProblem("Farm_ngnt.problem", pulp.LpMaximize)
x = pulp.LpVariable("x", lowBound=0)
y = pulp.LpVariable("y", lowBound=0)
pr += x + y <= 30
pr += 0.5*x + 0.1*y <= 6
pr += 100*x + 50*y
pr.solve()
print("x=", str(x.value()), "y=", str(y.value()))  

Exemplo n.º 27
0
    def sign(agent_id: str, agreements: List[Contract],
             trust_probabilities: Dict[str, float], inventory: int):
        """
        Given a list of agreements and trust probabilities, each of type negmas.Contract, decides which agreements to sign.
        :param agent_id: the agent's id (self.id of the calling agent)
        :param agreements: a list of agreements, each of type negmas.Contracts.
        :param trust_probabilities: a dictionary mapping an agent's id to its trust probability
        :return: a dictionary with information about the solver. In particular, the dictionary contains an entry 'list_of_signatures' which is
         a list of the same length as the input list of agreements. The i-th element of the list 'list_of_signatures' is self.id/None in case
         the agent wants/do not wants to sign the i-th agreement in the input list.
        """
        # If the list of agreements is empty, then return an empty list of signatures.
        if len(agreements) == 0:
            return {
                'list_of_signatures': [],
                'agent_id': agent_id,
                'model': None,
                'time_to_generate_ilp': None,
                'time_to_solve_ilp': None,
                'agreements': agreements,
                'trust_probabilities': trust_probabilities,
                'profit': None
            }

        # Partition agreements into buy and sell agreements.
        agreements_to_buy_inputs, agreements_to_sell_outputs = SCMLContractsSigner.partition_agreements(
            agent_id, agreements, trust_probabilities)

        # If there are no sell contracts, the signer has nothing to do and signs nothing.
        if len(agreements_to_sell_outputs) == 0:
            return {
                'list_of_signatures': [None] * len(agreements),
                'agent_id': agent_id,
                'model': None,
                'time_to_generate_ilp': None,
                'time_to_solve_ilp': None,
                'agreements': agreements,
                'trust_probabilities': trust_probabilities,
                'profit': None
            }

        # For efficiency purposes, we order the agreements by delivery times. But, before we do, we must be able to
        # recover the indices of the agreements as given to the solver, otherwise, we can't map the output to the right agreements.
        buy_agreements = [
            agreement + (i, )
            for i, agreement in enumerate(agreements_to_buy_inputs)
        ]
        sell_agreements = [
            agreement + (i, )
            for i, agreement in enumerate(agreements_to_sell_outputs)
        ]

        # At this point an agreement is a tuple: (MASTER_INDEX, QUANTITY, TIME, PRICE, SUB_INDEX). Now we order by TIME.
        buy_agreements = sorted(buy_agreements,
                                key=lambda x: x[SCMLContractsSigner.TIME])
        sell_agreements = sorted(sell_agreements,
                                 key=lambda x: x[SCMLContractsSigner.TIME])

        # The code that follows will change the agreement lists, so we make a copy of them for later reference.
        buy_agreements_copy = buy_agreements.copy()
        sell_agreements_copy = sell_agreements.copy()

        t0 = time.time()
        # Decision variables
        buy_sign_vars = pulp.LpVariable.dicts(
            'buy_sign', (i for i, _ in enumerate(buy_agreements)),
            lowBound=0,
            upBound=1,
            cat='Integer')
        sell_sign_vars = pulp.LpVariable.dicts(
            'sell_sign', (i for i, _ in enumerate(sell_agreements)),
            lowBound=0,
            upBound=1,
            cat='Integer')

        # Generate the pulp problem.
        model = pulp.LpProblem('Contract_Signer_Solver', pulp.LpMaximize)

        # The objective function is profit, defined as revenue minus cost.
        model += pulp.lpSum([
            sell_agreements[i][SCMLContractsSigner.QUANTITY] *
            sell_agreements[i][SCMLContractsSigner.PRICE] *
            sell_agreements[i][SCMLContractsSigner.PARTNER_TRUST] *
            sell_sign_vars[s[SCMLContractsSigner.SUB_INDEX]]
            for i, s in enumerate(sell_agreements)
        ] + [
            -1.0 * buy_agreements[i][SCMLContractsSigner.QUANTITY] *
            buy_agreements[i][SCMLContractsSigner.PRICE] *
            buy_agreements[i][SCMLContractsSigner.PARTNER_TRUST] *
            buy_sign_vars[b[SCMLContractsSigner.SUB_INDEX]]
            for i, b in enumerate(buy_agreements)
        ])

        # Construct the constraints. The constraint model inventory feasibility, i.e., we don't commit to a sell unless we have enough outputs.
        current_sell_time = sell_agreements[0][SCMLContractsSigner.TIME]
        current_sell_time_sum = []
        partial_sell_sum = []
        partial_buy_sum = []
        result = []
        while len(sell_agreements) > 0:
            s = sell_agreements.pop(0)
            if current_sell_time == s[SCMLContractsSigner.TIME]:
                current_sell_time_sum += [
                    sell_sign_vars[s[SCMLContractsSigner.SUB_INDEX]] *
                    s[SCMLContractsSigner.QUANTITY]
                ]
            else:
                partial_buy_sum += SCMLContractsSigner.constraints_generation_helper(
                    buy_agreements, buy_sign_vars, current_sell_time)
                result += [(current_sell_time_sum.copy(),
                            partial_buy_sum.copy(), partial_sell_sum.copy())]
                partial_sell_sum += current_sell_time_sum
                current_sell_time = s[SCMLContractsSigner.TIME]
                current_sell_time_sum = [
                    sell_sign_vars[s[SCMLContractsSigner.SUB_INDEX]] *
                    s[SCMLContractsSigner.QUANTITY]
                ]
        partial_buy_sum += SCMLContractsSigner.constraints_generation_helper(
            buy_agreements, buy_sign_vars, current_sell_time)
        result += [(current_sell_time_sum.copy(), partial_buy_sum.copy(),
                    partial_sell_sum.copy())]
        for left, middle, right in result:
            model += sum(left) <= inventory + sum(middle) - sum(right)

        # Measure the time taken to generate the ILP.
        time_to_generate_ilp = time.time() - t0

        # Solve the integer program and hide the output given by the solver.
        t0_solve = time.time()
        model.solve(pulp.PULP_CBC_CMD(msg=False))
        time_to_solve_ilp = time.time() - t0_solve

        # Record which contracts should be signed. We start by assuming no contracts will be signed.
        list_of_signatures = [None] * len(agreements)
        for agreement in buy_agreements_copy:
            if buy_sign_vars[agreement[
                    SCMLContractsSigner.
                    SUB_INDEX]].varValue is not None and int(
                        buy_sign_vars[agreement[
                            SCMLContractsSigner.SUB_INDEX]].varValue) == 1:
                list_of_signatures[agreement[
                    SCMLContractsSigner.MASTER_INDEX]] = agent_id

        for agreement in sell_agreements_copy:
            if sell_sign_vars[agreement[
                    SCMLContractsSigner.
                    SUB_INDEX]].varValue is not None and int(
                        sell_sign_vars[agreement[
                            SCMLContractsSigner.SUB_INDEX]].varValue) == 1:
                list_of_signatures[agreement[
                    SCMLContractsSigner.MASTER_INDEX]] = agent_id

        # Return multiple objects for inspection purposes. In production, we care about the list of sign contracts, 'list_of_signatures'.
        return {
            'list_of_signatures': list_of_signatures,
            'agent_id': agent_id,
            'model': model,
            'time_to_generate_ilp': time_to_generate_ilp,
            'time_to_solve_ilp': time_to_solve_ilp,
            'agreements': agreements,
            'trust_probabilities': trust_probabilities,
            'profit': pulp.value(model.objective)
        }
# import the library PuLP as p 
import pulp as p
  
# Set Up a LP Maximization Problem:
Lp_prob = p.LpProblem('Activity-Analysis_1', p.LpMaximize) # Here we named the Problem "Acitity-Analysis".
  
# Set Up Problem Variables: 
c = p.LpVariable("c", lowBound = 0) # "c" for chair
t = p.LpVariable("t", lowBound = 0) # "t" for table
d = p.LpVariable("d", lowBound = 0) # "d" for desk
b = p.LpVariable("b", lowBound = 0) # "b" for bookshelve

  
# Create Objective Function:
Lp_prob += 45 * c + 80 * t + 110 * d + 55 * b    
  
# Create Constraints: 
Lp_prob += 5 * c + 20 * t + 15 * d + 22 * b <= 20000
Lp_prob += 10 * c + 15 * t + 25 * d + 20 * b <= 4000
Lp_prob += 3 * c + 8 * t + 15 * d + 10 * b <= 2000
Lp_prob += 4 * c + 20 * d <= 3000
Lp_prob += 20 * b <= 500
  
# Show the problem:
print(Lp_prob) # note that it's shown in alphabetical order
  


### Simplifying the Problem and Solving it ###

# Generate a New LP Maximization Problem:
Exemplo n.º 29
0
def solve(professors, courses, semesters, slots):
    prob = pulp.LpProblem("Semester Problem", pulp.LpMaximize)

    opt_terms = []
    for k, v in lp_vars.items():
        if k[2] in n1s + n2s:
            opt_terms.append(100 * lp_vars_rev[v.name][2].size * v)
        else:
            opt_terms.append(lp_vars_rev[v.name][2].size * v)
    opt_fun = pulp.lpSum(lp_vars_rev[v.name][2].size * v
                         for k, v in lp_vars.items())
    prob += opt_fun

    #print(lp_vars.keys())

    # Maximum one class for slot
    for s in slots:
        for sem in semesters:
            v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                    for p in professors \
                    for c in courses)
            prob += v <= 1  #s.size

    #for sem in semesters:
    #    for s in sem.slots:
    #        v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
    #                for p in professors \
    #                for c in courses)
    #        prob += v <= 1 #s.size
    for s in slots:
        for p in professors:
            v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                    for sem in semesters \
                    for c in courses)
            prob += v <= 1  #s.size

    # previne que haja choque entre os professores das turmas conjuntas
    for s in slots:
        a = pulp.lpSum(lp_vars[(priscila, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        b = pulp.lpSum(lp_vars[(guilherme, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        c = pulp.lpSum(lp_vars[(priscila_guilherme, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        prob += a + c <= 1  #s.size
        prob += b + c <= 1  #s.size

    # previne que haja choque entre os professores das turmas conjuntas
    for s in slots:
        a = pulp.lpSum(lp_vars[(padilha, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        b = pulp.lpSum(lp_vars[(emilio, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        c = pulp.lpSum(lp_vars[(emilio_padilha, c, s, sem)] \
                for sem in semesters \
                for c in courses)
        prob += a + c <= 1  #s.size
        prob += b + c <= 1  #s.size

    for s in sex_noite:
        for sem in semesters:
            v = pulp.lpSum(lp_vars[(priscila_guilherme, c, s, sem)] \
                    for c in courses)
            prob += v == 0  #s.size

    for s in sex_noite:
        for sem in semesters:
            v = pulp.lpSum(lp_vars[(guilherme, c, s, sem)] \
                    for c in courses)
            prob += v == 0  #s.size

    for s in sex_noite:
        for sem in semesters:
            v = pulp.lpSum(lp_vars[(raquel, c, s, sem)] \
                    for c in courses)
            prob += v == 0  #s.size

    # Each professor must only give his classes
    for p in professors:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] * s.size \
                for s in slots \
                for c in p.courses \
                for sem in semesters )
        prob += v <= sum(c.num_hours for c in p.courses)

    # Each professor must not give other professor's classes
    for p in professors:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                for s in slots \
                for c in courses if not c in p.courses \
                for sem in semesters )
        prob += v == 0

    # Each course must be complete
    for c in cs:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] * s.size \
                for s in slots \
                for p in ps \
                for sem in semesters )
        prob += v <= c.num_hours

    # Each semester must have all its courses filled
    #for sem in semesters:
    #    v = pulp.lpSum(lp_vars[(p, c, s, sem)] * s.size \
    #            for s in sem.slots \
    #            for p in ps \
    #            for c in sem.courses)
    #    prob += v <= sum(c.num_hours for c in sem.courses)

    # Each semester must only have its courses # tested
    for sem in semesters:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                for s in slots \
                for p in ps \
                for c in cs if not c in sem.courses)
        prob += v == 0

    # Each semester must only have its slots # tested
    for sem in semesters:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                for s in slots if not s in sem.slots \
                for p in ps \
                for c in cs)
        prob += v == 0

    # aplica as restrições legais
    for p in professors:
        #print(p, proibidos)
        for (a, b) in proibidos:
            va = pulp.lpSum(lp_vars[(p, c, a, sem)] \
                    for c in p.courses \
                    for sem in semesters )
            vb = pulp.lpSum(lp_vars[(p, c, b, sem)] \
                    for c in p.courses \
                    for sem in semesters )
            prob += va + vb <= 1

    # aplica restrições legais a turmas cojuntas
    for (a, b) in proibidos:
        va1 = pulp.lpSum(lp_vars[(priscila, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        va2 = pulp.lpSum(lp_vars[(guilherme, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        vb = pulp.lpSum(lp_vars[(priscila_guilherme, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        prob += va1 + vb <= 1
        prob += va2 + vb <= 1
        va1 = pulp.lpSum(lp_vars[(emilio, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        va2 = pulp.lpSum(lp_vars[(padilha, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        vb = pulp.lpSum(lp_vars[(emilio_padilha, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        prob += va1 + vb <= 1
        prob += va2 + vb <= 1

        va1 = pulp.lpSum(lp_vars[(priscila, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        va2 = pulp.lpSum(lp_vars[(guilherme, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        vb = pulp.lpSum(lp_vars[(priscila_guilherme, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        prob += va1 + vb <= 1
        prob += va2 + vb <= 1
        va1 = pulp.lpSum(lp_vars[(emilio, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        va2 = pulp.lpSum(lp_vars[(padilha, c, a, sem)] \
                for c in courses \
                for sem in semesters )
        vb = pulp.lpSum(lp_vars[(emilio_padilha, c, b, sem)] \
                for c in courses \
                for sem in semesters )
        prob += va1 + vb <= 1
        prob += va2 + vb <= 1

    # previne aulas faixa
    for p in professors:
        if not p.faixa:
            for (a, b) in evitar:
                va = pulp.lpSum(lp_vars[(p, c, a, sem)] \
                        for c in p.courses \
                        for sem in semesters )
                vb = pulp.lpSum(lp_vars[(p, c, b, sem)] \
                        for c in p.courses \
                        for sem in semesters )
                prob += va + vb <= 1

    prob.solve()
    print("Status:", pulp.LpStatus[prob.status])

    #for v in prob.variables():
    #    if v.varValue and v.varValue > 0:
    #        print(v.name, "=", v.varValue)

    def get_slot(s_, sem_):
        for (p, c, s, sem), v in lp_vars.items():
            if sem_ is sem and s is s_ and pulp.value(v) > 0:  #.varValue > 0:
                return lp_vars_rev[v.name]

    #print("\n\n\n")

    def print_m_(ms, sem):

        linha = []
        for s in ms:
            x = get_slot(s, sem)
            if x:
                label = "%s %s" % (x[0].name, x[1].name)
            else:
                label = "()"
            linha.append(label.center(16))

        print(",".join(linha))

    for sem in semesters:
        print("\n\n", sem)
        print("7:30, ", end=' ')
        print_m_(m1s, sem)
        print("10:10,", end=' ')
        print_m_(m2s, sem)
        print("13:30,", end=' ')
        print_m_(t1s, sem)
        print("16:10,", end=' ')
        print_m_(t2s, sem)
        print("19:10,", end=' ')
        print_m_(n1s, sem)
        print("21:00,", end=' ')
        print_m_(n2s, sem)

    print("Total Value:", pulp.value(prob.objective))

    print("\nCCR c/ carga horário insuficiente:")
    for c in cs:
        v = pulp.lpSum(lp_vars[(p, c, s, sem)] \
                for s in slots \
                for p in ps \
                for sem in semesters)
        if pulp.value(v) < 2:
            print("CCR:", c.name, "HS:", pulp.value(v))
Exemplo n.º 30
0
def avg_link_utilization():
    h12 = 5
    h13 = 10
    h23 = 7

    cap12 = 10
    cap13 = 10
    cap23 = 15

    prob = pulp.LpProblem("3Node_MultiCommodity_AvgDelay", pulp.LpMinimize)

    # Defining the Flow Variables
    x12 = pulp.LpVariable('x12', lowBound=0, cat='Continuous')
    x132 = pulp.LpVariable('x132', lowBound=0, cat='Continuous')

    x13 = pulp.LpVariable('x13', lowBound=0, cat='Continuous')
    x123 = pulp.LpVariable('x123', lowBound=0, cat='Continuous')

    x23 = pulp.LpVariable('x23', lowBound=0, cat='Continuous')
    x213 = pulp.LpVariable('x213', lowBound=0, cat='Continuous')

    y12 = pulp.LpVariable('y12', lowBound=0, cat='Continuous')
    y13 = pulp.LpVariable('y13', lowBound=0, cat='Continuous')
    y23 = pulp.LpVariable('y23', lowBound=0, cat='Continuous')

    z12 = pulp.LpVariable('z12', lowBound=0)
    z13 = pulp.LpVariable('z13', lowBound=0)
    z23 = pulp.LpVariable('z23', lowBound=0)

    # Adding Objective Function
    prob += (z12 * math.pow(cap12, -1) + z13 * math.pow(cap13, -1) + z23 * math.pow(cap23, -1))

    # Subject to Constraints
    prob += (x12 + x132 == h12)
    prob += (x13 + x123 == h13)
    prob += (x23 + x213 == h23)
    prob += (x12 + x123 + x213 == y12)
    prob += (x13 + x132 + x213 == y13)
    prob += (x23 + x123 + x123 == y23)

    prob += (z12 * 2 >= 3 * y12)
    prob += (z13 * 2 >= 3 * y13)
    prob += (z23 * 2 >= 3 * y23)

    prob += (z12 * 2 >= 9 * y12 - 2 * cap12)
    prob += (z13 * 2 >= 9 * y13 - 2 * cap13)
    prob += (z23 * 2 >= 9 * y23 - 2 * cap23)

    prob += (z12 >= 15 * y12 - 8 * cap12)
    prob += (z13 >= 15 * y13 - 8 * cap13)
    prob += (z23 >= 15 * y23 - 8 * cap23)

    prob += (z12 >= 50 * y12 - 36 * cap12)
    prob += (z13 >= 50 * y13 - 36 * cap13)
    prob += (z23 >= 50 * y23 - 36 * cap23)

    prob += (z12 >= 200 * y12 - 171 * cap12)
    prob += (z13 >= 200 * y13 - 171 * cap13)
    prob += (z23 >= 200 * y23 - 171 * cap23)

    prob += (z12 >= 4000 * y12 - 3781 * cap12)
    prob += (z13 >= 4000 * y13 - 3781 * cap13)
    prob += (z23 >= 4000 * y23 - 3781 * cap23)

    # Print the Problem
    print(prob)

    prob.writeLP("3node_MCF_AvgDelay.lp")

    # solve the LP using the CPLEX Solver
    optimization_result = prob.solve(pulp.CPLEX())

    # make sure we got an optimal solution
    assert optimization_result == pulp.LpStatusOptimal

    # display the results
    for var in (x12, x132, x13, x123, x23, x213):
        print('Optimal Flow for {} is {:1.0f}'.format(var.name, var.value()))