def computeLambda(state, maximumTime=1.0): activeAgents = state.getActiveAgents() agentNames = getUniqueNames(activeAgents, prefix="Agent ") classNames = getUniqueNames(state.getChoiceClasses(), prefix="Class ") choiceNames = getUniqueNames(state.getChoices(), prefix="") choiceVariables = LpVariable.dicts("p", choiceNames.values(), lowBound=0) lambdaVariable = LpVariable("l", lowBound=0.0, upBound=maximumTime) def createConstraints(problem, variable): problem += lpSum(choiceVariables) <= 1, "Distribution" for choiceClass, height in state.getCurrentClassHeights().items(): problem += createLpSum(choiceClass, choiceNames, choiceVariables) >= \ height, classNames[choiceClass] + " height" for agent in state.getActiveAgents(): problem += createLpSum(state.getCurrentAgentChoiceClass(agent), choiceNames, choiceVariables) >= \ state.getAgentHeight(agent) + variable * state.getAgentSpeed(agent), \ agentNames[agent] + " push" problem = LpProblem("Lambda", LpMaximize) createConstraints(problem, lambdaVariable) problem.setObjective(lambdaVariable) checkPulpStatus(problem.solve(state.getSettings().getSolver())) lambdaOpt = lambdaVariable.value() bouncingAgents = [] stringAgents = [] #TODO just a workaround; find better solution for currentAgent in activeAgents: print "Current agent: " + agentNames[ currentAgent] # name is off by one problem = LpProblem(agentNames[currentAgent], LpMaximize) createConstraints(problem, lambdaOpt) (choiceClass, height, speed) = state.getAgentData(currentAgent) # print "Choice Class: " + repr(choiceClass) + ", print "height: " + repr(height) + " , speed: " + repr(speed) problem.setObjective( createLpSum(choiceClass, choiceNames, choiceVariables) - lambdaOpt * speed - height) checkPulpStatus(problem.solve(state.getSettings().getSolver())) value = problem.objective.value() # print "value: " + repr(value) + "\n" if not state.getSettings().isNonnegative(value): raise ValueError( str(value) + " negative while determining bounce of " + repr(currentAgent) + " from " + repr(choiceClass) + "@" + str(height) + "/" + str(speed)) if state.getSettings().isClose(value, 0): bouncingAgents.append(currentAgent) stringAgents.append(int(currentAgent.getName())) print "climbing time: " + repr(lambdaOpt) + ", bouncingAgents: " + str( stringAgents) + "\n" # print map(Agent.getName(), bouncingAgents) return (lambdaOpt, bouncingAgents)
def computeLambda(state, maximumTime=1.0): activeAgents = state.getActiveAgents() agentNames = getUniqueNames(activeAgents, prefix="Agent ") classNames = getUniqueNames(state.getChoiceClasses(), prefix="Class ") choiceNames = getUniqueNames(state.getChoices(), prefix="") choiceVariables = LpVariable.dicts("p", choiceNames.values(), lowBound=0) lambdaVariable = LpVariable("l", lowBound=0.0, upBound=maximumTime) def createConstraints(problem, variable): problem += lpSum(choiceVariables) <= 1, "Distribution" for choiceClass, height in state.getCurrentClassHeights().items(): problem += createLpSum(choiceClass, choiceNames, choiceVariables) >= \ height, classNames[choiceClass] + " height" for agent in state.getActiveAgents(): problem += createLpSum(state.getCurrentAgentChoiceClass(agent), choiceNames, choiceVariables) >= \ state.getAgentHeight(agent) + variable * state.getAgentSpeed(agent), \ agentNames[agent] + " push" problem = LpProblem("Lambda", LpMaximize) createConstraints(problem, lambdaVariable) problem.setObjective(lambdaVariable) checkPulpStatus(problem.solve(state.getSettings().getSolver())) lambdaOpt = lambdaVariable.value() bouncingAgents = [] stringAgents = [] #TODO just a workaround; find better solution for currentAgent in activeAgents: print "Current agent: " + agentNames[currentAgent] # name is off by one problem = LpProblem(agentNames[currentAgent], LpMaximize) createConstraints(problem, lambdaOpt) (choiceClass, height, speed) = state.getAgentData(currentAgent) # print "Choice Class: " + repr(choiceClass) + ", print "height: " + repr(height) + " , speed: " + repr(speed) problem.setObjective(createLpSum(choiceClass, choiceNames, choiceVariables) - lambdaOpt * speed - height) checkPulpStatus(problem.solve(state.getSettings().getSolver())) value = problem.objective.value() # print "value: " + repr(value) + "\n" if not state.getSettings().isNonnegative(value): raise ValueError(str(value) + " negative while determining bounce of " + repr(currentAgent) + " from " + repr(choiceClass) + "@" + str(height) + "/" + str(speed)) if state.getSettings().isClose(value, 0): bouncingAgents.append(currentAgent) stringAgents.append(int(currentAgent.getName())) print "climbing time: " + repr(lambdaOpt) + ", bouncingAgents: " + str(stringAgents) + "\n" # print map(Agent.getName(), bouncingAgents) return (lambdaOpt, bouncingAgents)
def findLottery(vote, classHeights, solverSettings): ''' Returns a Lottery satisfying all constraints specified by the classHeights parameter @type vote: vote.society.Vote @type classHeights: dict(vote.society.ChoiceClass, float) @type solverSettings: vote.solver.settings.SolverSettings @rtype: vote.society.Lottery @raise ValueError: If the constraints are not satisfiable ''' classNames = getUniqueNames(classHeights.keys(), prefix="Class ") choiceNames = getUniqueNames(vote.getChoices(), prefix="Choice ") problem = LpProblem("Lambda", LpMaximize) choiceVariables = LpVariable.dicts("p", choiceNames.values(), lowBound=0) problem += lpSum(choiceVariables) <= 1, "Distribution" for choiceClass, height in classHeights.items(): problem += createLpSum(choiceClass, choiceNames, choiceVariables) >= \ height, classNames[choiceClass] + " height" problem.setObjective(lpSum(choiceVariables.values())) checkPulpStatus(problem.solve(solverSettings.getSolver())) choiceValues = dict() for choice, choiceName in choiceNames.items(): choiceValues[choice.getObject()] = choiceVariables[choiceName].value() return Lottery(choiceValues, solverSettings)
def genera_strutture_ausiliarie(self, dati) -> None: model = pl.LpProblem("CalcolaOrario", pl.LpMaximize) # set dei docenti che hanno insegnamenti tra i moduli da fissare in orario doc = set(m.get_matricola() for m in dati.get_moduli()) # dict che mantiene l'associazione tra i moduli e i docenti titolari degli stessi tit = LpVariable.dicts("assign", [(m,d) for m in dati.get_moduli() for d in doc], lowBound = 0, upBound = 1, cat = pl.LpInteger) # dict che mantiene l'associazione tra i moduli e le aule compatibili in relazione alla numerosità attesa cpt = LpVariable.dicts("assign", [(m,a) for m in dati.get_moduli() for a in dati.get_aule()], lowBound = 0, upBound = 1, cat = pl.LpInteger) # valore 1 -> docente ha la titolarità di un dato modulo for m in dati.get_moduli(): for d in doc: if d == m.get_matricola(): tit[m,d] = 1 else: tit[m,d] = 0 # valore 1 -> l'aula è compatibile con la numerosità di un dato corso for m in dati.get_moduli(): for a in dati.get_aule(): if a.get_tipo() == m.get_tipo_aula() and a.get_capienza() >= m.get_max_studenti(): cpt[m,a] = 1 else: cpt[m,a] = 0 # Le variabili skd valgono uno se per un dato slot di un dato giorno viene assegnata la lezione di un modulo # di una dato corso in un data aula skd = LpVariable.dicts("assign", [(c,m,a,g,s) for c in dati.get_corsi() for m in dati.get_moduli() for a in dati.get_aule() for g in dati.get_giorni() for s in dati.get_slot()], lowBound = 0, upBound = 1, cat = pl.LpInteger) return model, StruttureAusiliarie(doc, tit, cpt, skd)
def computeLambda(state, maximumTime=1.0): ''' @type state: SSRState @type maximumTime: float ''' towerNames = getUniqueNames(state.getTowers(), prefix="T") choiceNames = getUniqueNames(state.getChoices(), prefix="") choiceVariables = LpVariable.dicts("p", choiceNames.values(), lowBound=0.0) lambdaVariable = LpVariable("l", lowBound=0.0, upBound=maximumTime) def createConstraints(problem, variable): problem += lpSum(choiceVariables) <= 1, "Distribution" for tower, towerName in towerNames.items(): problem += createLpSum(tower.getChoiceClass(), choiceNames, choiceVariables) >= \ tower.getHeight() + variable * \ tower.getSpeed(), towerName problem = LpProblem("Lambda", LpMaximize) createConstraints(problem, lambdaVariable) problem.setObjective(lambdaVariable) checkPulpStatus(problem.solve(state.getSettings().getSolver())) lambdaOpt = lambdaVariable.value() freezingTowers = [] for currentTower, towerName in towerNames.items(): if currentTower.isFrozen(): continue problem = LpProblem(towerName, LpMaximize) createConstraints(problem, lambdaOpt) problem.setObjective( createLpSum(currentTower.getChoiceClass(), choiceNames, choiceVariables) - lambdaOpt * currentTower.getSpeed() - currentTower.getHeight()) checkPulpStatus(problem.solve(state.getSettings().getSolver())) value = problem.objective.value() if not state.getSettings().isNonnegative(value): raise ValueError( str(value) + " negative while determining frozen state of " + repr(currentTower)) if state.getSettings().isClose(problem.objective.value(), 0): freezingTowers.append(currentTower) return (lambdaOpt, frozenset(freezingTowers))
def computeLambda(state, maximumTime=1.0): ''' @type state: SSRState @type maximumTime: float ''' towerNames = getUniqueNames(state.getTowers(), prefix="T") choiceNames = getUniqueNames(state.getChoices(), prefix="") choiceVariables = LpVariable.dicts("p", choiceNames.values(), lowBound=0.0) lambdaVariable = LpVariable("l", lowBound=0.0, upBound=maximumTime) def createConstraints(problem, variable): problem += lpSum(choiceVariables) <= 1, "Distribution" for tower, towerName in towerNames.items(): problem += createLpSum(tower.getChoiceClass(), choiceNames, choiceVariables) >= \ tower.getHeight() + variable * \ tower.getSpeed(), towerName problem = LpProblem("Lambda", LpMaximize) createConstraints(problem, lambdaVariable) problem.setObjective(lambdaVariable) checkPulpStatus(problem.solve(state.getSettings().getSolver())) lambdaOpt = lambdaVariable.value() freezingTowers = [] for currentTower, towerName in towerNames.items(): if currentTower.isFrozen(): continue problem = LpProblem(towerName, LpMaximize) createConstraints(problem, lambdaOpt) problem.setObjective(createLpSum(currentTower.getChoiceClass(), choiceNames, choiceVariables) - lambdaOpt * currentTower.getSpeed() - currentTower.getHeight()) checkPulpStatus(problem.solve(state.getSettings().getSolver())) value = problem.objective.value() if not state.getSettings().isNonnegative(value): raise ValueError(str(value) + " negative while determining frozen state of " + repr(currentTower)) if state.getSettings().isClose(problem.objective.value(), 0): freezingTowers.append(currentTower) return (lambdaOpt, frozenset(freezingTowers))
def get_optimal_rackspace(cpu_usage, mem_usage, optimal=True, debug=False): """ Calculates the price of optimal resources allocation over a certain time span (with monthly granularity). Formulates the problem of satisfying user demand (in CPU and RAM) as an LP problem with a monetary objective function. """ assert(len(cpu_usage) == len(mem_usage)) prob = LpProblem("Rackspace cost optimization", LpMinimize) # variables ## 1h instances per_h_ondems = [] for p in range(len(cpu_usage)): per_h_ondems += ["p %s ondem %s" %(p, i) for i in vms.keys()] category = LpInteger if optimal else LpContinuous vars = LpVariable.dicts("rackspace", per_h_ondems, 0, None, cat=category) # objective function prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][0] for vm in per_h_ondems]), "Total cost of running the infra (wrt to CPU/RAM)" # constraints ## demand constraints for p in range(len(cpu_usage)): prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][2] for vm in per_h_ondems if int(vm.split(" ")[1]) == p]) >= cpu_usage[p], "CU demand period %s" %p prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][3] for vm in per_h_ondems if int(vm.split(" ")[1]) == p]) >= mem_usage[p], "RAM demand period %s" %p prob.solve() if debug: for v in prob.variables(): if v.varValue != 0.0: print v.name, "=", v.varValue print "Total Cost of the solution = ", value(prob.objective) return value(prob.objective)
} AllStudentsNumber = { "1": [53, 63, 65, 63, 94, 42, 58], "2": [13, 53, 69, 24, 42, 19, 48], "3": [40, 7, 10, 82, 64, 86, 2], "4": [51, 19, 36, 75, 92, 92, 14], "5": [73, 82, 22, 29, 72, 74, 77], "6": [73, 82, 22, 29, 72, 74, 77], } # 今回の問題では総和を最大化するので LpMaximize を指定する problem = LpProblem('GroupAllScore', LpMaximize) # 使用する変数 s1 = LpVariable('S1', 1, 6, 'Continuous') s2 = LpVariable('S2', 1, 6, 'Continuous') s3 = LpVariable('S3', 1, 6, 'Continuous') s4 = LpVariable('S4', 1, 6, 'Continuous') s5 = LpVariable('S5', 1, 6, 'Continuous') s6 = LpVariable('S6', 1, 6, 'Continuous') group1 = [s1, s2] group2 = [s3, s4] group3 = [s5, s6] AllStudentsNumberDup = group1 + group2 + group3 # 目的関数 # score1 = AllStudents[group1[0]][0] + AllStudents[group1[1]][1] # score2 = AllStudents[group2[0]][0] + AllStudents[group2[1]][1] # score3 = AllStudents[group3[0]][0] + AllStudents[group3[1]][1] # problem += score1 + score2 + score3
from pulp.constants import LpMaximize from pulp.pulp import LpProblem, LpVariable # 今回の問題では総和を最大化するので LpMaximize を指定する problem = LpProblem('Restaurant', LpMaximize) # 使用する変数 x = LpVariable('X') y = LpVariable('Y') # 目的関数 problem += 30 * x + 25 * y # 制約条件 problem += 0.5 * x + 0.25 * y <= 10 # ひき肉の総量は 3800g problem += 0.5 * x + 0.75 * y <= 15 # 玉ねぎの総量は 2100g # 解く problem.solve() # 結果表示 print('x: {x}'.format(x=x.value())) print('y: {y}'.format(y=y.value())) print(x.value() * y.value()) # class Node: # def __init__(self, x, y): # self.x = x # self.y = y # self.state = None
def lp_model(cg: ComputationGraph, agentsdef: Iterable[AgentDef], footprint: Callable[[str], float], capacity: Callable[[str], float], route: Callable[[str, str], float], msg_load: Callable[[str, str], float], hosting_cost: Callable[[str, str], float]): comp_names = [n.name for n in cg.nodes] agt_names = [a.name for a in agentsdef] pb = LpProblem('ilp_compref', LpMinimize) # One binary variable xij for each (variable, agent) couple xs = LpVariable.dict('x', (comp_names, agt_names), cat=LpBinary) # One binary variable for computations c1 and c2, and agent a1 and a2 betas = {} count = 0 for a1, a2 in combinations(agt_names, 2): # Only create variables for couple c1, c2 if there is an edge in the # graph between these two computations. for l in cg.links: # As we support hypergraph, we may have more than 2 ends to a link for c1, c2 in combinations(l.nodes, 2): count += 2 b = LpVariable('b_{}_{}_{}_{}'.format(c1, a1, c2, a2), cat=LpBinary) betas[(c1, a1, c2, a2)] = b pb += b <= xs[(c1, a1)] pb += b <= xs[(c2, a2)] pb += b >= xs[(c2, a2)] + xs[(c1, a1)] - 1 b = LpVariable('b_{}_{}_{}_{}'.format(c1, a2, c2, a1), cat=LpBinary) betas[(c1, a2, c2, a1)] = b pb += b <= xs[(c2, a1)] pb += b <= xs[(c1, a2)] pb += b >= xs[(c1, a2)] + xs[(c2, a1)] - 1 # Set objective: communication + hosting_cost pb += _objective(xs, betas, route, msg_load, hosting_cost), \ 'Communication costs and prefs' # Adding constraints: # Constraints: Memory capacity for all agents. for a in agt_names: pb += lpSum([footprint(i) * xs[i, a] for i in comp_names])\ <= capacity(a), \ 'Agent {} capacity'.format(a) # Constraints: all computations must be hosted. for c in comp_names: pb += lpSum([xs[c, a] for a in agt_names]) == 1, \ 'Computation {} hosted'.format(c) # solve using GLPK status = pb.solve(solver=GLPK_CMD(keepFiles=1, msg=False, options=['--pcost'])) if status != LpStatusOptimal: raise ImpossibleDistributionException("No possible optimal" " distribution ") logger.debug('GLPK cost : %s', value(pb.objective)) # print('BETAS:') # for c1, a1, c2, a2 in betas: # print(' ', c1, a1, c2, a2, value(betas[(c1, a1, c2, a2)])) # # print('XS:') # for c, a in xs: # print(' ', c, a, value(xs[(c, a)])) mapping = {} for k in agt_names: agt_computations = [i for i, ka in xs if ka == k and value(xs[(i, ka)]) == 1] # print(k, ' -> ', agt_computations) mapping[k] = agt_computations return mapping
def distribute_factors( agents: Dict[str, AgentDef], cg: ComputationGraph, footprints: Dict[str, float], mapping: Dict[str, List[str]], msg_load: Callable[[str, str], float], ) -> Dict[str, List[str]]: """ Optimal distribution of factors on agents. Parameters ---------- cg: computations graph agents: dict a dict {agent_name : AgentDef} containing all available agents Returns ------- a dict { agent_name: list of factor names} """ pb = LpProblem("ilp_factors", LpMinimize) # build the inverse mapping var -> agt inverse_mapping = {} # type: Dict[str, str] for a in mapping: inverse_mapping[mapping[a][0]] = a # One binary variable xij for each (variable, agent) couple factor_names = [n.name for n in cg.nodes if isinstance(n, FactorComputationNode)] xs = LpVariable.dict("x", (factor_names, agents), cat=LpBinary) logger.debug("Binary variables for factor distribution : %s", xs) # Hard constraints: respect agent's capacity for a in agents: # Footprint of the variable this agent is already hosting: v_footprint = footprints[mapping[a][0]] pb += ( lpSum([footprints[fn] * xs[fn, a] for fn in factor_names]) <= (agents[a].capacity - v_footprint), "Agent {} capacity".format(a), ) # Hard constraints: all computations must be hosted. for c in factor_names: pb += lpSum([xs[c, a] for a in agents]) == 1, "Factor {} hosted".format(c) # 1st objective : minimize communication costs: comm = LpAffineExpression() for (fn, an_f) in xs: for vn in cg.neighbors(fn): an_v = inverse_mapping[vn] # agt hosting neighbor var vn comm += agents[an_f].route(an_v) * msg_load(vn, fn) * xs[(fn, an_f)] # 2st objective : minimize hosting costs hosting = lpSum([agents[a].hosting_cost(c) * xs[(c, a)] for c, a in xs]) # agregate the two objectives using RATIO_HOST_COMM pb += lpSum([RATIO_HOST_COMM * comm, (1 - RATIO_HOST_COMM) * hosting]) # solve using GLPK and convert to mapping { agt_name : [factors names]} status = pb.solve(solver=GLPK_CMD(keepFiles=1, msg=False, options=["--pcost"])) if status != LpStatusOptimal: raise ImpossibleDistributionException( "No possible optimal distribution for factors" ) logger.debug("GLPK cost : %s", value(pb.objective)) mapping = {} # type: Dict[str, List[str]] for k in agents: agt_computations = [i for i, ka in xs if ka == k and value(xs[(i, ka)]) == 1] # print(k, ' -> ', agt_computations) mapping[k] = agt_computations logger.debug("Factors distribution : %s ", mapping) return mapping
def get_optimal_ec2(cpu_usage, mem_usage, optimal=True, debug=False): """ Calculates the optimal allocation of resources over a certain time span (with monthly granularity). Formulates the problem of satisfying user demand (in CPU and RAM) as an LP problem with a monetary objective function. Returns allocation of reserved instances and a total price for running the allocation on AWS. """ assert(len(cpu_usage) == len(mem_usage)) prob = LpProblem("The Simplified EC2 cost optimization", LpMinimize) # variables ## 1h instances (both on-demand and reserved) per_h_ondems = [] per_h_reserved = [] for p in range(len(cpu_usage)): # ondemand per_h_ondems += ["p %s ondem %s" %(p, i) for i in vms.keys()] # reserved per_h_reserved += ["p %s reserved %s" %(p, i) for i in vms.keys()] ## nr of 1-year reserved instances nr_of_1year_reserved = [ "res_1year %s" % i for i in vms.keys()] nr_of_3year_reserved = [ "res_3year %s" % i for i in vms.keys()] category = LpInteger if optimal else LpContinuous vars = LpVariable.dicts("aws", per_h_ondems + per_h_reserved + nr_of_1year_reserved + nr_of_3year_reserved, \ lowBound = 0, upBound = None, cat = category) # objective function prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][0] for vm in per_h_ondems]) \ + lpSum([vars[vm] * vms[vm.split(" ")[3]][3] for vm in per_h_reserved]) \ + lpSum([vars[vm] * vms[vm.split(" ")[1]][1] for vm in nr_of_1year_reserved]) \ + lpSum([vars[vm] * vms[vm.split(" ")[1]][2] for vm in nr_of_3year_reserved]) \ , "Total cost of running the infrastructure consuming (CPU/RAM)/h" # constraints ## demand constraints for p in range(len(cpu_usage)): prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][4] for vm in (per_h_ondems + per_h_reserved) if int(vm.split(" ")[1]) == p]) >= cpu_usage[p], "CPU demand, period %s" %p prob += lpSum([vars[vm] * vms[vm.split(" ")[3]][5] for vm in (per_h_ondems + per_h_reserved) if int(vm.split(" ")[1]) == p]) >= mem_usage[p], "RAM demand. period %s" %p ## constraints on the reserved instances - cannot use more than we paid for for i in per_h_reserved: t = i.split(" ")[3] prob += vars["res_1year %s" % t] + vars["res_3year %s" % t] >= vars[i], "Nr. of used reserved machines of type %s" %i prob.solve() if debug: print "Status:", LpStatus[prob.status] print "Total Cost of the solution = ", value(prob.objective) res_instance = {} for v in prob.variables(): if v.name.startswith("aws_res_") and v.varValue != 0.0: res_instance[v.name] = v.varValue if debug and v.varValue != 0.0: print v.name, "=", v.varValue return (res_instance, value(prob.objective))