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 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): 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 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)
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))