/* * Copyright (c) Fabien Hermenier * * This file is part of Entropy. * * Entropy is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Entropy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Entropy. If not, see <http://www.gnu.org/licenses/>. */ package entropy.plan.choco.actionModel.slice; import solver.Cause; import solver.ICause; import solver.variables.IntVar; import solver.variables.Task; import solver.variables.VF; import solver.exception.ContradictionException; import entropy.plan.Plan; import entropy.plan.choco.ReconfigurationProblem; /** * Model a period where a managed element is consuming CPU and memory resources during * a bounded amount of time on a node. * * @author Fabien Hermenier */ public class Slice { private Task task; /** * Indicates the identifier of slice hoster. */ private IntVar hoster; /** * The CPU height of the slice. */ private int cpuHeight; /** * The memory height of the slice. */ private int memHeight; private String name; /** * Make a new slice. * * @param name the name of the slice * @param h the hoster of the slice (its identifier) * @param t The associated task variable * @param cpuHeight the CPU height of the slice * @param memHeight the memory height of the slice */ public Slice(String name, IntVar h, Task t, int cpuHeight, int memHeight) { this.name = name; task = t; hoster = h; this.cpuHeight = cpuHeight; this.memHeight = memHeight; } /** * Get the CPU consumption of the slice during its activity. * * @return a positive integer */ public int getCPUheight() { return this.cpuHeight; } /** * Get the memory consumption of the slice during its activity. * * @return a positive integer */ public int getMemoryheight() { return this.memHeight; } /** * Get the node that host the slice. * * @return the index of the node. */ public IntVar hoster() { return hoster; } /** * @return <code>this.pretty()</code> */ @Override public String toString() { return this.pretty(); } /** * Nice print of the slice. * * @return a formatted String */ public String pretty() { StringBuilder builder = new StringBuilder(); builder.append(getName()).append("{[").append(start().getLB()).append(","); if (start().getUB() == ReconfigurationProblem.MAX_TIME) { builder.append("MAX"); } else { builder.append(start().getUB()); } builder.append("] + [") .append(duration().getLB()).append(","); if (duration().getUB() == ReconfigurationProblem.MAX_TIME) { builder.append("MAX"); } else { builder.append(duration().getUB()); } builder.append("] = [") .append(end().getLB()).append(","); if (end().getLB() == ReconfigurationProblem.MAX_TIME) { builder.append("MAX"); } else { builder.append(end().getUB()); } builder.append("] on [") .append(hoster().getLB()).append(",").append(hoster().getUB()).append("]}"); return builder.toString(); } public static int improvable = 0; public static int nonImpr = 0; /** * Add the slice to the model.The following are added: * <ul> * <li>The variables {@code end()}, {@code start()}, {@code duration()} and {@code hoster()}</li> * <li>the constraint <code>start() + duration() = end()</code></li> * <li>A constraint to enforce all the variables to be inferior or equals to <code>model.getEnd()</code></li> * </ul> * * @param core the current model of the reconfiguration problem */ public void addToModel(ReconfigurationProblem core) { core.post(core.leq(duration(), core.getEnd())); if (start().instantiated() && duration().instantiated()) { try { end().instantiateTo(duration().getValue() + start().getValue(), Cause.Null);//FIXME slice shoul inmplement ICause } catch (ContradictionException e) { System.err.println(e.getMessage()); } } else { core.post(core.eq(end(), core.plus(start(), duration()))); } } /** * Get the moment the slice starts. * * @return a positive moment */ public IntVar start() { return task.getStart(); } /** * Get the duration of the slice. * * @return a positive moment */ public IntVar duration() { return task.getDuration(); } /** * Get the moment the slice ends. * * @return a positive moment */ public IntVar end() { return task.getEnd(); } /** * Get the name of the slice. * * @return a String */ public String getName() { return name; } /** * Set the duration of the slice as a constant. * * @param d a positive duration */ public void fixDuration(int d) { try { duration().instantiateTo(d, Cause.Null); } catch (Exception e) { Plan.logger.error(e.getMessage(), e); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) { return false; } Slice slice = (Slice) o; if (cpuHeight != slice.cpuHeight || memHeight != slice.memHeight) { return false; } if (!hoster.equals(slice.hoster)) { return false; } if (!task.getStart().equals(slice.task.getStart()) || !task.getEnd().equals(slice.task.getEnd()) || !task.getDuration().equals(slice.task.getDuration())) { return false; } return true; } @Override public int hashCode() { int result = task.hashCode(); result = 31 * result + hoster.hashCode(); result = 31 * result + cpuHeight; result = 31 * result + memHeight; return result; } }