package gipad.plan.choco;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import solver.Solver;
import solver.constraints.Constraint;
import solver.search.loop.monitors.SearchMonitorFactory;
import solver.variables.IntVar;
import util.ESat;
import gipad.placementconstraint.*;
import gipad.configuration.CostFunction;
import gipad.configuration.configuration.*;
import gipad.exception.PlanException;
import gipad.plan.*;
import gipad.plan.action.Action;
import gipad.tools.ManagedElementList;
import gipad.tools.SimpleManagedElementList;
public class ChocoCustom3RP implements Plan {
private CostFunction costFunc;
/**
* The model.
*/
private ReconfigurationProblem model;
/**
* Mode (repair - consolidate)
*/
private boolean repair = true;
/**
* The timeout to limit the solving process.
*/
private int timeout;
private ManagedElementList<VirtualMachine> queue;
// /////////Constructeur//////////////
public ChocoCustom3RP(CostFunction costFunc) {
this.costFunc = costFunc;
}
// ////////Getter && Setter///////////
public void setRepairMode(boolean b) {
this.repair = b;
}
/**
* Get the timelimit to solve the problem.
*
* @return the time in seconds
*/
public int getTimeLimit() {
return this.timeout;
}
/**
* Set the timelimit to solve the problem.
*
* @param seconds
* the time in second
*/
public void setTimeLimit(int entropyPlanTimeout) {
this.timeout = entropyPlanTimeout;
}
/**
* Get cost function
*
* @return CostFunction
*/
public CostFunction getCostFunction() {
return this.costFunc;
}
/**
* Get the model. Can be null if Compute has not been run yet
*
* @return the model to express constraints.
*/
public ReconfigurationProblem getModel() {
return this.model;
}
/**
* TODO Get some Stats about the model
*
* @return
*/
/*
* public List<SolutionStatistics> getSolutionsStatistics() { if (model ==
* null) { return new ArrayList<SolutionStatistics>(); } return
* this.model.getSolutionsStatistics(); }
*
* /**
*
* @return some statistics about the solving process
*//*
* public SolvingStatistics getSolvingStatistics() { if (model == null)
* { return SolvingStatistics.getStatisticsForNotSolvingProcess(); }
* return model.getSolvingStatistics(); }
*/
public SequencedReconfigurationPlan compute(Configuration src, ManagedElementList<VirtualMachine> q)
throws PlanException {
queue = q;
model = null;
ManagedElementList<VirtualMachine> vms = null;
if (repair) {
// Look for the VMs to consider
// We don't have any placement constraint for the moment
vms = new SimpleManagedElementList<VirtualMachine>();
for (VirtualMachine v : queue) {
for (PlacementConstraint c : src.getPlacementConstraints()) {
if (!c.isSatisfied(src)) {
vms.addAll(c.getMisPlaced(src));
}
}
}
// Hardcore way for the packing. TODO: externalize
// System.err.println("pack issue:" +
// src.getRunnings(src.getUnacceptableNodes()));
vms.addAll(src.getRunnings(ConfigurationUtils.getOverloadedNodes(src)));
} else {
vms = src.getAllVirtualMachines();
}
model = new DefaultReconfigurationProblem(src, vms, this.costFunc);
System.currentTimeMillis();
Map<Class, Integer> occurences = new HashMap<Class, Integer>();
// Inject placement constraints
// A pretty print of the problem
/***************Not Down Yet*******************/
/**
* globalCost is equals to the sum of each action costs.
*/
IntVar globalCost = model.createBoundIntVar("globalCost", 0, Choco.MAX_UPPER_BOUND);
List<Action> allActions = new ArrayList<Action>();
allActions.addAll(model.getVirtualMachineActions());
allActions.addAll(model.getNodeMachineActions());
IntVar[] allCosts = ActionModels.extractCosts(allActions);
List<IntVar> varCosts = new ArrayList<IntVar>();
for (int i = 0; i < allCosts.length; i++) {
IntVar c = allCosts[i];
if (c.instantiated() && c.getValue() == 0) {
} else {
varCosts.add(c);
}
}
IntVar[] costs = varCosts.toArray(new IntVar[varCosts.size()]);
// model.post(model.eq(globalCost,
// /*model.sum(costs)*/explodedSum(model, costs, 200, true)));
// Setting total duration bounds of all the variables and updating the
// UB of the variables -- à la main
// TODO: Set the LB for the horizon && the end of each action
// cs = model.leq(model.getEnd(), explodedSum(model,
// ActionModels.extractDurations(allActions), 200, true));
// costConstraints.add(cs);
// model.post(cs);
if (getTimeLimit() > 0) {
SearchMonitorFactory.limitTime(model.getSolver(), getTimeLimit() * 1000);
}
// Configure search : Heuristics + Objectiv
model.getSolver().findSolution();// launch();
Boolean ret = model.getSolver().isFeasible() == ESat.TRUE;
if (ret == null) {
throw new PlanException("Unable to check wether a solution exists or not");
} else {
if (Boolean.FALSE.equals(ret)) {
throw new PlanException("No solution");
} else {
SequencedReconfigurationPlan plan = model.extractSolution();
Configuration res = plan.getDestination();
if (ConfigurationUtils.getOverloadedNodes(res).size() != 0) {
throw new PlanException("Resulting configuration is not viable: Overloaded nodes="
+ ConfigurationUtils.getOverloadedNodes(res));
}
int cost = 0;
for (Action a : plan) {
cost += a.getFinishMoment();
}
if (cost != globalCost.getValue()) {
throw new PlanException("Practical cost of the plan (" + cost + ") and objective ("
+ globalCost.getValue() + ") missmatch:\n" + plan);
}
// Verify all Placement constraints are satisfied
return plan;
}
}
return null;
}
}