Skip to content

Commit

Permalink
- parallel solver: added ability to run in a single solution mode
Browse files Browse the repository at this point in the history
  • Loading branch information
tomas-muller committed Dec 3, 2014
1 parent 76c4e14 commit 65538bb
Show file tree
Hide file tree
Showing 41 changed files with 796 additions and 447 deletions.
Binary file modified lib/cpsolver-all-1.3.jar
Binary file not shown.
5 changes: 4 additions & 1 deletion src/ctt.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ SimulatedAnnealing.ReheatLengthCoef=7
Extensions.Classes=org.cpsolver.ifs.extension.ConflictStatistics

#Other
General.SaveBestUnassigned=0
General.SaveBestUnassigned=0

ParallelSolver.SingleSolution=false
ParallelSolver.SingleSolutionNeighbourCheck=true
5 changes: 4 additions & 1 deletion src/exam.properties
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ General.SaveBestUnassigned=0
#Extensions
Exam.AllowDirectConflict=false
Exam.AllowBinaryViolations=false
Extensions.Classes=org.cpsolver.ifs.extension.ConflictStatistics
Extensions.Classes=org.cpsolver.ifs.extension.ConflictStatistics

ParallelSolver.SingleSolution=false
ParallelSolver.SingleSolutionNeighbourCheck=true
5 changes: 5 additions & 0 deletions src/net/sf/cpsolver/itc/ItcModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public boolean cvsPrint(Assignment<V, T> assignment) {
public void makeFeasible(Assignment<V, T> assignment) {}

public abstract Assignment<V, T> createAssignment(int index, Assignment<V, T> assignment);

@Override
public String toString(Assignment<V, T> a) {
return "V:"+a.nrAssignedVariables()+"/"+variables().size()+", P:"+Math.round(getTotalValue(a))+" ("+csvLine(a)+")";
}
}
35 changes: 24 additions & 11 deletions src/net/sf/cpsolver/itc/ItcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -250,24 +252,27 @@ protected Solution createParallelSolution(int index) {
solution.addSolutionListener(listener);
return solution;
}
@Override
public boolean hasSingleSolution() {
return sConfig.getPropertyBoolean("ParallelSolver.SingleSolution", false);
}
};
Solution solution = new Solution(model, model.createAssignment(0, null));
solver.setInitalSolution(solution);
solution.getModel().createAssignmentContexts(solution.getAssignment(), false);

solver.currentSolution().addSolutionListener(new SolutionListener() {
public void solutionUpdated(Solution solution) {}
public void solutionUpdated(Solution solution) {
//sLog.info("**CURRENT["+solution.getIteration()+"]** " + solution);
}
public void getInfo(Solution solution, Map info) {}
public void getInfo(Solution solution, Map info, Collection variables) {}
public void bestCleared(Solution solution) {}
public void bestSaved(Solution solution) {
ItcModel m = (ItcModel)solution.getModel();
Assignment a = solution.getAssignment();
sLog.info("**BEST["+solution.getIteration()+"]** V:"+a.nrAssignedVariables()+"/"+m.variables().size()+", P:"+Math.round(m.getTotalValue(a))+" ("+m.csvLine(a)+")");
sLog.info("**BEST["+solution.getIteration()+"]** " + solution);
}
public void bestRestored(Solution solution) {
ItcModel m = (ItcModel)solution.getModel();
Assignment a = solution.getAssignment();
sLog.info("##RESTORED["+solution.getIteration()+"]## V:"+a.nrAssignedVariables()+"/"+m.variables().size()+", P:"+Math.round(m.getTotalValue(a))+" ("+m.csvLine(a)+")");
sLog.info("##RESTORED["+solution.getIteration()+"]## " + solution);
}
});

Expand All @@ -287,7 +292,7 @@ public static Solution solve() {
Solution solution = solver.currentSolution();
solution.restoreBest();
((ItcModel)solution.getModel()).makeFeasible(solution.getAssignment());
solution.saveBest();
// solution.saveBest();

return output(solver);
} catch (Exception e) {
Expand All @@ -305,7 +310,7 @@ private static Solution output(Solver solver) throws Exception {
sLog.error("No best solution found.");
return null;
}
solution.restoreBest();
// solution.restoreBest();

sLog.info("Best solution:"+ToolBox.dict2string(solution.getExtendedInfo(),1));

Expand All @@ -325,14 +330,22 @@ private static Solution output(Solver solver) throws Exception {
ItcModel m = (ItcModel)solution.getModel();
Assignment a = solution.getAssignment();
DecimalFormat df = new DecimalFormat("0.00");
double cpu = 0.0;
OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean();
if (bean instanceof com.sun.management.OperatingSystemMXBean) {
cpu = ((com.sun.management.OperatingSystemMXBean)bean).getProcessCpuTime() / 1e9;
}
w.println(
sSeed+","+
sTimeOut+","+
df.format(solution.getBestTime())+","+
solution.getBestIteration()+","+
Math.round(m.getTotalValue(solution.getAssignment()) + 5000 * a.nrUnassignedVariables(m))+","+
model.csvLine(a) + "," +
model.getProperties().getPropertyInt("Parallel.NrSolvers", 4));
model.getProperties().getPropertyInt("Parallel.NrSolvers", 4) +
(solver.hasSingleSolution() ? "s": "p") +
(solver.hasSingleSolution() && model.getProperties().getPropertyBoolean("ParallelSolver.SingleSolutionQueue", true) ? "q" : "") + "," +
df.format(solution.getIteration() / solution.getTime()) + "," + df.format(cpu));
w.flush(); w.close();
}

Expand All @@ -353,7 +366,7 @@ public void run() {
Solution solution = iSolver.currentSolution();
solution.restoreBest();
((ItcModel)solution.getModel()).makeFeasible(solution.getAssignment());
solution.saveBest();
// solution.saveBest();

output(iSolver);
} catch (Exception e) {
Expand Down
59 changes: 30 additions & 29 deletions src/net/sf/cpsolver/itc/ctt/model/CttAssignment.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.assignment.AssignmentAbstract;
import org.cpsolver.ifs.assignment.context.AssignmentContextHolder;
import org.cpsolver.ifs.assignment.context.DefaultParallelAssignmentContextHolder;
import org.cpsolver.ifs.model.Model;

Expand Down Expand Up @@ -34,17 +35,28 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/
public class CttAssignment extends AssignmentAbstract<CttLecture, CttPlacement> {
private CttModel iModel;
private int iIndex;
private int iNrAssigned = 0;
protected CttModel iModel;
protected int iIndex;
protected int iNrAssigned = 0;
protected CttPlacement[] iAssignment = null;
protected CttAssignment iParent = null;

public CttAssignment(CttModel model, int index, Assignment<CttLecture, CttPlacement> assignment) {
super(new DefaultParallelAssignmentContextHolder<CttLecture, CttPlacement>(index));
iIndex = index;
iModel = model;
if (assignment != null)
for (CttPlacement value: assignment.assignedValues())
setValueInternal(0, value.variable(), value);
iParent = (CttAssignment) assignment;
if (iParent == null) {
iAssignment = new CttPlacement[model.variables().size()];
iNrAssigned = 0;
} else {
iAssignment = Arrays.copyOf(((CttAssignment)iParent).toArray(), model.variables().size());
iNrAssigned = iParent.nrAssignedVariables();
}
}

protected CttAssignment(AssignmentContextHolder<CttLecture, CttPlacement> contextHolder) {
super(contextHolder);
}

@Override
Expand Down Expand Up @@ -97,35 +109,16 @@ public Collection<CttLecture> assignedVariables() {
return assigned;
}

protected CttPlacement[] getAssignments(CttLecture variable) {
synchronized (variable) {
CttPlacement[] assignments = (CttPlacement[])variable.getExtra();
if (assignments == null) {
assignments = (CttPlacement[])new CttPlacement[Math.max(10, 1 + iIndex)];
variable.setExtra(assignments);
} else if (assignments.length <= iIndex) {
assignments = Arrays.copyOf(assignments, 10 + iIndex);
variable.setExtra(assignments);
}
return assignments;
}
}

@Override
@SuppressWarnings("deprecation")
protected CttPlacement getValueInternal(CttLecture variable) {
if (iIndex == 1)
return variable.getAssignment();
return getAssignments(variable)[iIndex];
// return (CttPlacement) variable.getAssignments()[iIndex];
return iAssignment[variable.getIndex()];
}

@Override
@SuppressWarnings("deprecation")
protected void setValueInternal(long iteration, CttLecture variable, CttPlacement value) {
if (iIndex == 1)
variable.setAssignment(value);
else
getAssignments(variable)[iIndex] = value;
//variable.getAssignments()[iIndex] = value;
iAssignment[variable.getIndex()] = value;
if (value == null)
iNrAssigned --;
else
Expand All @@ -141,4 +134,12 @@ public int getIndex() {
public int nrAssignedVariables() {
return iNrAssigned;
}

public CttPlacement[] toArray() {
return iAssignment;
}

public Assignment<CttLecture, CttPlacement> getParentAssignment() {
return iParent;
}
}
15 changes: 13 additions & 2 deletions src/net/sf/cpsolver/itc/ctt/model/CttCurricula.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package net.sf.cpsolver.itc.ctt.model;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.assignment.context.AssignmentConstraintContext;
import org.cpsolver.ifs.assignment.context.CanInheritContext;
import org.cpsolver.ifs.assignment.context.ConstraintWithContext;
import org.cpsolver.ifs.model.ConstraintListener;

Expand Down Expand Up @@ -148,7 +150,7 @@ public int getCompactPenalty(Assignment<CttLecture, CttPlacement> assignment, Ct
* same curricula are placed at the same time.
*
*/
public class CurriculaConstraint extends ConstraintWithContext<CttLecture, CttPlacement, CttCurricula.Table> {
public class CurriculaConstraint extends ConstraintWithContext<CttLecture, CttPlacement, CttCurricula.Table> implements CanInheritContext<CttLecture, CttPlacement, CttCurricula.Table> {

/** Constructor */
public CurriculaConstraint() {
Expand Down Expand Up @@ -212,9 +214,14 @@ public int hashCode() {
public Table createAssignmentContext(Assignment<CttLecture, CttPlacement> assignment) {
return new Table(assignment);
}

@Override
public Table inheritAssignmentContext(Assignment<CttLecture, CttPlacement> assignment, Table parentContext) {
return new Table(assignment, parentContext);
}
}

private class Table implements AssignmentConstraintContext<CttLecture, CttPlacement> {
public class Table implements AssignmentConstraintContext<CttLecture, CttPlacement> {
public CttPlacement[] iPlacement;

public Table(Assignment<CttLecture, CttPlacement> assignment) {
Expand All @@ -226,6 +233,10 @@ public Table(Assignment<CttLecture, CttPlacement> assignment) {
if (p != null) assigned(assignment, p);
}
}

public Table(Assignment<CttLecture, CttPlacement> assignment, Table parent) {
iPlacement = Arrays.copyOf(parent.iPlacement, parent.iPlacement.length);
}

@Override
public void assigned(Assignment<CttLecture, CttPlacement> assignment, CttPlacement p) {
Expand Down
56 changes: 56 additions & 0 deletions src/net/sf/cpsolver/itc/ctt/model/CttInheritedAssignment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package net.sf.cpsolver.itc.ctt.model;

import java.util.Arrays;
import java.util.concurrent.locks.Lock;

import org.cpsolver.ifs.assignment.InheritedAssignment;
import org.cpsolver.ifs.assignment.context.InheritedAssignmentContextHolder;
import org.cpsolver.ifs.solution.Solution;

/**
* Curriculum based Course Timetabling (CTT) inherited assignment model.
*
* @version
* ITC2007 1.0<br>
* Copyright (C) 2014 Tomas Muller<br>
* <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
* <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
* <br>
* This library 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.
* <br><br>
* This library 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.
* <br><br>
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not see
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/
public class CttInheritedAssignment extends CttAssignment implements InheritedAssignment<CttLecture, CttPlacement> {
private long iVersion = -1;

public CttInheritedAssignment(Solution<CttLecture, CttPlacement> solution, int index) {
super(new InheritedAssignmentContextHolder<CttLecture, CttPlacement>(index, solution.getIteration()));
iIndex = index;
iVersion = solution.getIteration();
iModel = (CttModel) solution.getModel();
iParent = (CttAssignment) solution.getAssignment();
Lock lock = solution.getLock().readLock();
lock.lock();
try {
iNrAssigned = iParent.nrAssignedVariables();
iAssignment = Arrays.copyOf(((CttAssignment)iParent).toArray(), iModel.variables().size());
} finally {
lock.unlock();
}
}

@Override
public long getVersion() {
return iVersion;
}
}
9 changes: 6 additions & 3 deletions src/net/sf/cpsolver/itc/ctt/model/CttLecture.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
import java.util.List;

import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.model.LazySwap;
import org.cpsolver.ifs.model.Neighbour;
import org.cpsolver.ifs.model.Variable;
import net.sf.cpsolver.itc.heuristics.neighbour.ItcLazySwap;

import net.sf.cpsolver.itc.heuristics.neighbour.ItcSwap.Swapable;

/**
Expand Down Expand Up @@ -37,6 +38,7 @@
public class CttLecture extends Variable<CttLecture, CttPlacement> implements Swapable<CttLecture, CttPlacement> {
private int iIdx;
private CttCourse iCourse = null;
private int iHashCode;

/** Constructor
* @param course course to which this lecture belongs
Expand All @@ -54,6 +56,7 @@ public CttLecture(CttCourse course, int idx) {
curricula.getConstraint().addVariable(this);
setValues(computeValues());
getModel().addVariable(this);
iHashCode = toString().hashCode();
}

/** Return course to which this lecture belong */
Expand Down Expand Up @@ -102,7 +105,7 @@ public boolean equals(Object o) {

/** Hash code */
public int hashCode() {
return toString().hashCode();
return iHashCode;
}

/** Compare two lectures, return the harder one. That is the one with more curriculas, or smaller domain/constraint ratio. */
Expand Down Expand Up @@ -142,7 +145,7 @@ public Neighbour<CttLecture, CttPlacement> findSwap(Assignment<CttLecture, CttPl
}
CttPlacement np1 = new CttPlacement(this, p2.getRoom(), p2.getDay(), p2.getSlot());
CttPlacement np2 = new CttPlacement(lecture, p1.getRoom(), p1.getDay(), p1.getSlot());
return new ItcLazySwap<CttLecture, CttPlacement>(assignment, np1, np2);
return new LazySwap<CttLecture, CttPlacement>(np1, np2);
/*
double value = 0;
//value += np1.extraPenalty() + np2.extraPenalty() - p1.extraPenalty() - p2.extraPenalty();
Expand Down
Loading

0 comments on commit 65538bb

Please sign in to comment.