Skip to content
Snippets Groups Projects
Commit da5a6cb5 authored by Johannes Mey's avatar Johannes Mey
Browse files

Merge branch 'master' into ai

parents ec357396 add4858f
No related branches found
No related tags found
No related merge requests found
Showing
with 324 additions and 90 deletions
package de.tudresden.inf.st.mquat.benchmark;
import de.tudresden.inf.st.mquat.solving.BenchmarkableSolver;
import de.tudresden.inf.st.mquat.solving.ilp.GLPKSolver;
import de.tudresden.inf.st.mquat.solving.ilp.GurobiSolver;
import de.tudresden.inf.st.mquat.solving.ilp.ILPDirectSolver;
import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
import de.tudresden.inf.st.mquat.solving.genetic.GeneticSolver;
import de.tudresden.inf.st.mquat.solving.ilp.SCIPSolver;
import de.tudresden.inf.st.mquat.solving.random.RandomSolver;
import de.tudresden.inf.st.mquat.solving.simple.SimpleSolver;
import ir.ac.ui.eng.ACOSolver;
......@@ -28,7 +30,9 @@ public class SolverFactory {
availableSolvers = Stream.of(
new ACOSolver(),
new EMFeRSolver(),
new ILPExternalSolver(),
new GLPKSolver(),
new SCIPSolver(),
new GurobiSolver(),
new ILPDirectSolver(),
new SimpleSolver(),
new RandomSolver(0, 0),
......
......@@ -5,7 +5,8 @@
"aco",
"emfer",
"ilp-direct",
// "ilp-external",
"ilp-glpk",
"ilp-scip",
"random",
"genetic",
"simple"
......
......@@ -85,7 +85,7 @@ public abstract class AbstractILPSolver implements BenchmarkableSolver {
// call to abstract method
try {
solve0(model, watch, variablesSetToOne);
solve0(model, ilp, watch, variablesSetToOne);
this.lastSolving = watch.time(TimeUnit.MILLISECONDS) - this.lastGeneration;
// translate ilp-encoded solution to MQuAT solution
return populateSolution(variablesSetToOne, new ILPSolution(model));
......@@ -103,12 +103,11 @@ public abstract class AbstractILPSolver implements BenchmarkableSolver {
* @return the objective value
* @throws SolvingException if anything went wrong
*/
protected abstract double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException;
protected abstract double solve0(Root model, ILP ilp, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException;
protected ILPSolution populateSolution(List<IlpVariable> variablesSetToOne, ILPSolution result) throws SolvingException {
List<Assignment> listOfAssignments = new ArrayList<>();
for (IlpVariable var : variablesSetToOne) {
logger.debug("Found, that {} = 1", var.getName());
if (var.isMappingVariable()) {
IlpMappingVariable mappingVar = var.asMappingVariable();
Assignment assignment = new Assignment();
......
package de.tudresden.inf.st.mquat.solving.ilp;
import de.tudresden.inf.st.mquat.jastadd.model.ILP;
import de.tudresden.inf.st.mquat.jastadd.model.IlpVariable;
import de.tudresden.inf.st.mquat.solving.SolvingException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GLPKSolver extends ILPExternalSolver {
/**
* Create a new GLPK solver with default settings.
* Default is:
* <ul>
* <li>1 minute timeout</li>
* <li>delete temporary files on exit.</li>
* </ul>
* @see GLPKSolver#setDeleteFilesOnExit(boolean)
*/
public GLPKSolver() {
}
@Override
protected String[] getCommand(Path lp, Path solution, long remainingTimeForSolvingInMillis) {
return new String[] {"glpsol", "--lp", lp.toAbsolutePath().toString(), "--cuts",
"-o", String.valueOf(solution.toAbsolutePath())};
}
@Override
public String getName() {
return "ilp-glpk";
}
@Override
protected void readFromPlainTextSolution(ILP ilp, Path solution, ILPSolution result,
List<IlpVariable> variablesSetToOne) throws SolvingException {
List<String> varNamesSetToOne = new ArrayList<>();
String name = null;
int phase = 1;
try (Stream<String> lines = Files.lines(solution)) {
for (String line : lines.collect(Collectors.toList())) {
if (phase < 3) {
if (line.startsWith("Objective")) {
int equalsIndex = line.indexOf('=');
int bracketIndex = line.lastIndexOf('(');
result.setObjective(Double.valueOf(line.substring(equalsIndex + 1, bracketIndex).trim()));
}
if (line.startsWith("---")) {
phase += 1;
}
continue;
}
line = line.trim();
if (line.isEmpty()) {
continue;
}
String[] tokens = line.split("\\s+");
if (tokens.length == 6) {
// tokens: index, name, star, activity, lb, rb
if(Integer.valueOf(tokens[3]) == 1) {
varNamesSetToOne.add(tokens[1]);
}
phase = 3;
} else if (phase == 3) {
if(line.startsWith("Integer")) {
break;
}
// tokens: index, name
name = tokens[1];
phase = 4;
} else if (phase == 4) {
// tokens: star, activity, lb, rb
if (name == null) {
throw new SolvingException("Error in parsing solution. Name is null. Tokens: " + Arrays.toString(tokens));
}
if (Integer.valueOf(tokens[1]) == 1) {
varNamesSetToOne.add(name);
name = null;
}
phase = 3;
}
}
} catch (IOException e) {
throw new SolvingException("Could not open solution file", e);
} catch (NumberFormatException | IndexOutOfBoundsException e) {
throw new SolvingException("Could not parse solution file", e);
}
for (String varName : varNamesSetToOne) {
IlpVariable variable = ilp.resolve(varName);
if (variable == null) {
throw new SolvingException("Could not find variable with name " + varName);
}
variablesSetToOne.add(variable);
}
}
}
package de.tudresden.inf.st.mquat.solving.ilp;
import de.tudresden.inf.st.mquat.jastadd.model.ILP;
import de.tudresden.inf.st.mquat.jastadd.model.IlpVariable;
import de.tudresden.inf.st.mquat.solving.SolvingException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GurobiSolver extends ILPExternalSolver {
/**
* Create a new GLPK solver with default settings.
* Default is:
* <ul>
* <li>1 minute timeout</li>
* <li>delete temporary files on exit.</li>
* </ul>
* @see GurobiSolver#setDeleteFilesOnExit(boolean)
*/
public GurobiSolver() {
}
@Override
protected String[] getCommand(Path lp, Path solution, long remainingTimeForSolvingInMillis) {
String[] command = {"gurobi_cl", "ResultFile=" + solution.toAbsolutePath(), "TimeLimit=" + remainingTimeForSolvingInMillis/1000, String.valueOf(lp.toAbsolutePath())};
return command;
}
@Override
protected void readFromPlainTextSolution(ILP ilp, Path solution, ILPSolution result,
List<IlpVariable> variablesSetToOne) throws SolvingException {
logger.debug("reading solution from {}.", solution);
try(BufferedReader br = new BufferedReader(new FileReader(solution.toFile()))) {
for(String line; (line = br.readLine()) != null; ) {
if (line.startsWith("#")) {
// comment line
if (line.startsWith("# Objective Value =")) {
result.setObjective(Double.valueOf(line.substring(20).trim()));
logger.debug("read objective {}", Double.valueOf(line.substring(20).trim()));
}
} else {
if (line.endsWith(" 1")) {
String varString = line.substring(0,line.length()-2);
IlpVariable variable = ilp.resolve(varString);
if (variable == null) {
throw new SolvingException("Could not find variable with name " + varString);
}
variablesSetToOne.add(variable);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getName() {
return "ilp-gurobi";
}
}
......@@ -57,8 +57,7 @@ public class ILPDirectSolver extends AbstractILPSolver {
this.prob = null;
}
protected double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
ILP ilp = model.getILP();
protected double solve0(Root model, ILP ilp, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
if (logger.isTraceEnabled()) {
logger.trace(ilp.printIlp().toString());
......
......@@ -19,7 +19,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ILPExternalSolver extends AbstractILPSolver {
public abstract class ILPExternalSolver extends AbstractILPSolver {
private boolean deleteFilesOnExit;
private Path lp, solutionReadable;
......@@ -70,22 +70,24 @@ public class ILPExternalSolver extends AbstractILPSolver {
}
}
protected double solve0(Root model, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
protected double solve0(Root model, ILP ilp, StopWatch watch, List<IlpVariable> variablesSetToOne) throws SolvingException {
long startOfWriteOutInMillis = watch.time(TimeUnit.MILLISECONDS);
// Create temporary files
try {
lp = Files.createTempFile("ilp", null);
lp = Files.createTempFile("ilp", ".lp");
// solution = Files.createTempFile("solution", null);
solutionReadable = Files.createTempFile("sol-read", null);
solutionReadable = Files.createTempFile("sol-read", ".sol");
} catch (IOException e) { throw new SolvingException("Can not create lp or solution file", e); }
if (!deleteFilesOnExit) {
logger.info("Writing ILP to {}, solving now", lp.toAbsolutePath());
}
// write out lp file
IlpString output = model.getILP().printIlp();
logger.debug("Starting ILP string construction.");
IlpString output = ilp.printIlp();
logger.debug("ILP string construction completed.");
try (BufferedWriter writer = Files.newBufferedWriter(
lp, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
writer.write(output.toString());
......@@ -101,16 +103,12 @@ public class ILPExternalSolver extends AbstractILPSolver {
// start GLPK to solve the lp file just written, writing out the solution
Process process;
String command = "glpsol --lp " + lp.toAbsolutePath() +
// " -w " + solution.toAbsolutePath() +
" --tmlim " + remainingTimeForSolvingInMillis/1000 +
" --cuts" +
" -o " + solutionReadable.toAbsolutePath();
logger.debug("Call: '{}'", command);
String[] command = getCommand(lp, solutionReadable, remainingTimeForSolvingInMillis);
logger.debug("Call: '{}'", String.join(" ", command));
try {
process = Runtime.getRuntime().exec(command,null, new File("."));
} catch (IOException e) {
throw new SolvingException("Problem calling glpsol. Is it installed?", e);
throw new SolvingException("Problem calling solver. Is it installed?", e);
}
boolean finishedInTime;
try {
......@@ -144,76 +142,16 @@ public class ILPExternalSolver extends AbstractILPSolver {
// read the solution file
ILPSolution result = new ILPSolution(model);
logger.debug("created empty solution");
// readFromPrintableSolution(ilp, solution, result, variablesSetToOne);
readFromPlainTextSolution(model.getILP(), solutionReadable, result, variablesSetToOne);
readFromPlainTextSolution(ilp, solutionReadable, result, variablesSetToOne);
return result.getObjective();
}
private static void readFromPlainTextSolution(ILP ilp, Path solution, ILPSolution result,
List<IlpVariable> variablesSetToOne) throws SolvingException {
List<String> varNamesSetToOne = new ArrayList<>();
String name = null;
int phase = 1;
try (Stream<String> lines = Files.lines(solution)) {
for (String line : lines.collect(Collectors.toList())) {
if (phase < 3) {
if (line.startsWith("Objective")) {
int equalsIndex = line.indexOf('=');
int bracketIndex = line.lastIndexOf('(');
result.setObjective(Double.valueOf(line.substring(equalsIndex + 1, bracketIndex).trim()));
}
if (line.startsWith("---")) {
phase += 1;
}
continue;
}
line = line.trim();
if (line.isEmpty()) {
continue;
}
String[] tokens = line.split("\\s+");
if (tokens.length == 6) {
// tokens: index, name, star, activity, lb, rb
if(Integer.valueOf(tokens[3]) == 1) {
varNamesSetToOne.add(tokens[1]);
}
phase = 3;
} else if (phase == 3) {
if(line.startsWith("Integer")) {
break;
}
// tokens: index, name
name = tokens[1];
phase = 4;
} else if (phase == 4) {
// tokens: star, activity, lb, rb
if (name == null) {
throw new SolvingException("Error in parsing solution. Name is null. Tokens: " + Arrays.toString(tokens));
}
if (Integer.valueOf(tokens[1]) == 1) {
varNamesSetToOne.add(name);
name = null;
}
phase = 3;
}
}
} catch (IOException e) {
throw new SolvingException("Could not open solution file", e);
} catch (NumberFormatException | IndexOutOfBoundsException e) {
throw new SolvingException("Could not parse solution file", e);
}
for (String varName : varNamesSetToOne) {
IlpVariable variable = ilp.resolve(varName);
if (variable == null) {
throw new SolvingException("Could not find variable with name " + varName);
}
variablesSetToOne.add(variable);
}
}
protected abstract void readFromPlainTextSolution(ILP ilp, Path solution, ILPSolution result,
List<IlpVariable> variablesSetToOne) throws SolvingException;
@Override
public String getName() {
return "ilp-external";
}
protected abstract String[] getCommand(Path lp, Path solution, long remainingTimeForSolvingInMillis);
}
......@@ -74,7 +74,7 @@ public class ILPMain {
}
private static void solveILPWithSolver(Root model) throws SolvingException {
ILPExternalSolver solver = new ILPExternalSolver();
ILPExternalSolver solver = new GLPKSolver().setDeleteFilesOnExit(false);
Solution solution = solver.solve(model);
System.out.println(solution);
}
......@@ -90,7 +90,7 @@ public class ILPMain {
System.out.println(version);
ScenarioGenerator gen = new ScenarioGenerator(new ScenarioDescription(1, 2, 0, 0, 0, 2, 2, 2.5, 3, 1, 0));
Root model = gen.generate();
Solver external = new ILPExternalSolver().setDeleteFilesOnExit(false);
Solver external = new GLPKSolver().setDeleteFilesOnExit(false);
Solution solution = external.solve(model);
logger.info(model.print(new MquatWriteSettings(" ")));
solution.explain();
......
package de.tudresden.inf.st.mquat.solving.ilp;
import de.tudresden.inf.st.mquat.jastadd.model.ILP;
import de.tudresden.inf.st.mquat.jastadd.model.IlpVariable;
import de.tudresden.inf.st.mquat.solving.SolvingException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SCIPSolver extends ILPExternalSolver {
/**
* Create a new GLPK solver with default settings.
* Default is:
* <ul>
* <li>1 minute timeout</li>
* <li>delete temporary files on exit.</li>
* </ul>
*
* @see SCIPSolver#setDeleteFilesOnExit(boolean)
*/
public SCIPSolver() {
}
@Override
protected String[] getCommand(Path lp, Path solution, long remainingTimeForSolvingInMillis) {
String[] command = {"scip", "-c", "read " + lp.toAbsolutePath() + " set timing reading true set timing clocktype 2 set limit time " + remainingTimeForSolvingInMillis / 1000 + " optimize write solution " + solution.toAbsolutePath() + " quit"};
return command;
}
@Override
protected void readFromPlainTextSolution(ILP ilp, Path solution, ILPSolution result,
List<IlpVariable> variablesSetToOne) throws SolvingException {
try (Stream<String> lines = Files.lines(solution)) {
for (String line : lines.collect(Collectors.toList())) {
if (line.startsWith("objective value:")) {
result.setObjective(Double.valueOf(line.substring(16).trim()));
logger.debug("read objective {}", Double.valueOf(line.substring(16).trim()));
} else if (line.startsWith("solution status:")) {
logger.debug("we got a solution status {}", line.substring(16).trim());
} else if (line.startsWith("no solution available")) {
logger.debug("no solution was found!");
return;
} else {
String[] tokens = line.split("\\s+");
if (tokens.length == 3) {
// tokens: name, value, objective
if (Math.round(Double.parseDouble(tokens[1]) * 1000000000) == 1000000000) {
logger.debug("found new variable {} with value {}", tokens[0], tokens[1]);
IlpVariable variable = ilp.resolve(tokens[0]);
if (variable == null) {
throw new SolvingException("Could not find variable with name " + tokens[0]);
}
variablesSetToOne.add(variable);
}
}
}
}
} catch (IOException e) {
throw new SolvingException("Could not open solution file", e);
} catch (NumberFormatException e) {
throw new SolvingException("Could not parse solution file", e);
}
}
@Override
public String getName() {
return "ilp-scip";
}
}
package de.tudresden.inf.st.mquat.solving;
import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
import de.tudresden.inf.st.mquat.solving.ilp.GLPKSolver;
public class ILPExternalHandwrittenTest extends HandwrittenTestSuite {
public class GLPKHandwrittenTest extends HandwrittenTestSuite {
@Override
protected Solver getSolver() {
// set to false for debugging
return new ILPExternalSolver().setDeleteFilesOnExit(true);
return new GLPKSolver().setDeleteFilesOnExit(false);
}
}
package de.tudresden.inf.st.mquat.solving;
import de.tudresden.inf.st.mquat.solving.ilp.GurobiSolver;
public class GurobiHandwrittenTest extends HandwrittenTestSuite {
@Override
protected Solver getSolver() {
// set to false for debugging
return new GurobiSolver().setDeleteFilesOnExit(false);
}
}
......@@ -4,6 +4,7 @@ import de.tudresden.inf.st.mquat.generator.ScenarioDescription;
import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
import de.tudresden.inf.st.mquat.jastadd.model.Root;
import de.tudresden.inf.st.mquat.jastadd.model.Solution;
import de.tudresden.inf.st.mquat.solving.ilp.GLPKSolver;
import de.tudresden.inf.st.mquat.solving.ilp.ILPExternalSolver;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -36,7 +37,7 @@ public class ILPObjectiveTest {
ScenarioGenerator generator = new ScenarioGenerator(new ScenarioDescription(tlc, iac, isd, cac, csd, dep, imp, res, req, cpu, seed));
Root model = generator.generate();
ILPExternalSolver solver = new ILPExternalSolver().setDeleteFilesOnExit(false);
ILPExternalSolver solver = new GLPKSolver().setDeleteFilesOnExit(false);
Solution solution = solver.solve(model);
Assert.assertTrue(solution.isValid());
logger.info("Solution (objective={}): {}", solution.computeObjective(), solution);
......
......@@ -2,6 +2,7 @@ package de.tudresden.inf.st.mquat.solving;
import de.tudresden.inf.st.mquat.data.TestGeneratorSettings;
import de.tudresden.inf.st.mquat.generator.ScenarioGenerator;
import de.tudresden.inf.st.mquat.solving.ilp.GLPKSolver;
import de.tudresden.inf.st.mquat.utils.TestUtils;
import de.tudresden.inf.st.mquat.jastadd.model.Root;
import de.tudresden.inf.st.mquat.jastadd.model.Solution;
......@@ -106,7 +107,7 @@ public class ILPSolveTest {
private Solver externalSolver() {
// set to false to analyse created temporary files
return new ILPExternalSolver().setDeleteFilesOnExit(true).setTimeout(10, TimeUnit.SECONDS);
return new GLPKSolver().setDeleteFilesOnExit(true).setTimeout(10, TimeUnit.SECONDS);
}
private Solver directSolver() {
......
package de.tudresden.inf.st.mquat.solving;
import de.tudresden.inf.st.mquat.solving.ilp.SCIPSolver;
public class SCIPHandwrittenTest extends HandwrittenTestSuite {
@Override
protected Solver getSolver() {
// set to false for debugging
return new SCIPSolver().setDeleteFilesOnExit(false);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment