Package csp.backends

Source Code of csp.backends.MinionSolver

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package csp.backends;

import csp.datatypes.CSPSolution;
import csp.datatypes.minion.*;
import finiteReduction.DomainFinder;
import finiteReduction.FiniteReductionConfig;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;

/**
*
* @author Jeroen Janssen <Jeroen.Janssen@vub.ac.be>
*/
public class MinionSolver {

  private String minionPath;
  private File temp;
  // We need to keep track of the outputted variables as minion only outputs
  // Sol: value in the order in which the variables were created, without
  // naming the variable in its output.
  private ArrayList<MinionDomainVariable> dVars;
  private ArrayList<MinionEnumeratedVariable> eVars;
  private int timeout = 1000;
  private boolean foundSolution = false;
  private static final String NL = System.getProperty("line.separator");

  public MinionSolver(String minionPath) {
    this.minionPath = minionPath;
  }

  // TODO: lots of the stuff in here should actually move to the IntegerToMinionConvertor
  // as it is MinionSpecific. For example the translation of LEQ and GEQ to sum expressions
  // should be in IntegerToMinionConvertor
  public void read(MinionCSPProblem model) {
    // Sets up the environment for solving
    try {
      temp = File.createTempFile("furet", "minion");
      System.err.println("Temp File created at: " + temp.getAbsolutePath());
      // TODO DEBUG
      //temp.deleteOnExit();
      BufferedWriter out = new BufferedWriter(new FileWriter(temp));
      //out.write("aString");

      out.write("MINION 3" + NL);

      out.write("**VARIABLES**" + NL);

      dVars = new ArrayList<MinionDomainVariable>();

      for (MinionDomainVariable dVar : model.getDomainVariables()) {
        dVars.add(dVar);
        out.write("BOUND " + dVar.getName() + " {" + dVar.getLowerBound()
            + ".." + dVar.getUpperBound() + "}" + NL);
      }

      //HashSet<MinionEnumeratedVariable> eVars = model.getEnumeratedVariables();
      eVars = new ArrayList<MinionEnumeratedVariable>();

      for (MinionEnumeratedVariable eVar : model.getEnumeratedVariables()) {
        eVars.add(eVar);
        out.write("SPARSEBOUND " + eVar.getName() + " {");
        Iterator<Integer> it = eVar.getValues().iterator();
        if (it.hasNext()) {
          out.write(it.next().toString());
        }
        while (it.hasNext()) {
          out.write("," + it.next());
        }
        out.write("}" + NL);
      }

      out.write("**CONSTRAINTS**" + NL);

      for (MinionConstraint c : model.getConstraints()) {
        MinionConstraint.Operator op = c.getOperator();
        //System.out.println("Operator: " + op);
        MinionOutputter mOutput = new MinionOutputter();
        String lhs = c.getLHS().accept(mOutput);
        String rhs = c.getRHS().accept(mOutput);
        if (op.equals(MinionConstraint.Operator.GEQ)) {
          // TODO HACK
          //sumleq is correct: we have to reverse the operands
          out.write("sumleq(");
          out.write("[" + rhs + "]");
          out.write(",");
          out.write(lhs);
          out.write(")");
          out.write(NL);
        } else if (op.equals(MinionConstraint.Operator.LEQ)) {
          out.write("sumgeq(");
          out.write("[" + rhs + "]");
          out.write(",");
          out.write(lhs);
          out.write(")");
          out.write(NL);
        } else if (op.equals(MinionConstraint.Operator.EQ)) {
          // TODO: remove redundancy
          out.write("sumleq(");
          out.write("[" + rhs + "]");
          out.write(",");
          out.write(lhs);
          out.write(")");
          out.write(NL);
          out.write("sumgeq(");
          out.write("[" + rhs + "]");
          out.write(",");
          out.write(lhs);
          out.write(")");
          out.write(NL);
        } else if (op.equals(MinionConstraint.Operator.MAX)) {
          out.write("max(" + rhs + "," + lhs + ")");
          out.write(NL);
        } else if (op.equals(MinionConstraint.Operator.SUM)) {
          out.write("sumleq(" + rhs + "," + lhs + ")");
          out.write(NL);
          out.write("sumgeq(" + rhs + "," + lhs + ")");
          out.write(NL);
        } else if (op.equals(MinionConstraint.Operator.MULT)) {
          // This is a special case as MINION does not support
          // product([x,y],z) which would be much more coherent
          // with max and plus. We need to output product(x,y,z)
          // instead,so we need to get the elements out of our
          // expressionlist on the right hand side (provided our
          // minion instance is generated by the generator).
          // TODO: HACK
          // Our lhs should be the dummy variable, so only rhs
          // needs special processing and this should be a list of
          // two elements *fingers crossed*
          MinionExpressionList rhsExp = (MinionExpressionList) c.getRHS();
          Iterator<MinionExpression> it = rhsExp.getList().iterator();
          String rhs1 = it.next().accept(mOutput);
          String rhs2 = it.next().accept(mOutput);
          out.write("product(" + rhs1 + "," + rhs2 + "," + lhs + ")");
          out.write(NL);
        } else {
          System.err.println("Unknown operator: " + op);
        }
      }
      out.write("**EOF**" + NL);
      out.close();
    } catch (IOException e) {
      System.err.println("Could not create temp file for solving: " + e);
    }
  }

  private CSPSolution parseMinionOutput(BufferedReader reader) {
    CSPSolution model = new CSPSolution();
   
    int i = 0;
    int j = 0;
    String line;
    String solutionPrefix = "Sol: ";
    try {
      while ((line = reader.readLine()) != null) {
        //System.out.println(line);
        if (line.startsWith(solutionPrefix)) {
          Integer value = Integer.parseInt(line.trim().substring(solutionPrefix.length()));
          String variable = "";
          if (i < dVars.size()) {
            variable = dVars.get(i++).getName();
          } else if (j < eVars.size()) {
            variable = eVars.get(j++).getName();
          }
          // TODO: remove hardcoded dummy string!!
          // and remove duplication of this string in the convertor
          // and solver somehow ...
          // We make sure that dummy variables are not output.
          if (!variable.startsWith("miniondummy"))
            model.addVariable(variable, value);
        }
      }
      if (i == 0 && j == 0) {
        return null;
      } else {
        return model;
      }
    } catch (Exception err) {
      System.err.println("Error parsing minion output.");
      err.printStackTrace();
      return null;
    }
  }

  public CSPSolution solve() {
    CSPSolution model = null;
    try {
      Process p = Runtime.getRuntime().exec(
          minionPath + " -timelimit " + timeout + " " + temp.getAbsolutePath());
      // TODO: killer does not work in netbeans. Does it work on CLI?
      Runtime.getRuntime().addShutdownHook(new Thread(new MinionKiller(p)));
      BufferedReader input =
          new BufferedReader(new InputStreamReader(p.getInputStream()));
      model = parseMinionOutput(input);
      /*while ((line = input.readLine()) != null) {
      System.out.println(line);
      }*/
      input.close();
    } catch (Exception err) {
      System.err.println("Minion failed to run.");
      err.printStackTrace();
    }

    return model;
  }

  public boolean isFeasible() {
    return foundSolution;
  }

  public void setTimeout(int timeout) {
    this.timeout = timeout;
  }

  private class MinionOutputter implements MinionVisitor<String> {

    public String visitExpressionList(MinionExpressionList list) {
      StringBuffer buff = new StringBuffer();
      buff.append("[");
      Iterator<MinionExpression> it = list.getList().iterator();
      if (it.hasNext()) {
        buff.append(it.next().accept(this));
        while (it.hasNext()) {
          buff.append(",");
          buff.append(it.next().accept(this));
        }
      }
      buff.append("]");
      return buff.toString();
    }

    public String visitDomainVariable(MinionDomainVariable v) {
      return v.getName();
    }

    public String visitEnumeratedVariable(MinionEnumeratedVariable v) {
      return v.getName();
    }

    public String visitConstant(MinionExpressionConstant c) {
      return new Integer(c.getValue()).toString();
    }
  }

  private class MinionKiller implements Runnable {
    private Process minionProcess;

    public MinionKiller (Process minonProcess) {
      this.minionProcess = minionProcess;
    }
   
    public void run () {
      //System.err.println("Killing minion ...");
      if(minionProcess != null)
        minionProcess.destroy();
      //System.err.println("Killed minion!");
    }
  }
}
TOP

Related Classes of csp.backends.MinionSolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.