/*******************************************************************************
* Copyright (C) 2009-2012 Gregor Wylezich, Dominik Jain and Paul Maier.
*
* This file is part of ProbCog.
*
* ProbCog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProbCog 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProbCog. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package probcog.srl.mln.inference;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import probcog.logic.GroundAtom;
import probcog.logic.PossibleWorld;
import probcog.srl.mln.MarkovRandomField;
import probcog.wcsp.WCSP;
import probcog.wcsp.WCSPConverter;
/**
* Toulbar2 branch & bound inference wrapper.
* Requires installation of the toulbar2 executable in the system PATH.
*
* @author Gregor Wylezich
* @author Dominik Jain
* @author Paul Maier
*/
public class Toulbar2MAPInference extends MAPInferenceAlgorithm {
protected PossibleWorld state;
protected WCSPConverter converter = null;
protected String wcspFilename = "temp.wcsp";
protected String toulbar2Args = "";
public Toulbar2MAPInference(MarkovRandomField mrf) throws Exception {
super(mrf);
state = new PossibleWorld(mrf.getWorldVariables());
this.paramHandler.add("toulbar2Args", "setToulbar2Args");
}
/**
* sets toulbar2 command-line arguments
* @param args
*/
public void setToulbar2Args(String args) {
toulbar2Args = args;
}
@Override
public double getResult(GroundAtom ga) {
return state.get(ga.index) ? 1.0 : 0.0;
}
public WCSPConverter constructWCSP(String filename, boolean cache) throws Exception {
if(converter != null)
throw new Exception("WCSP was already constructed");
// perform conversion to WCSP
this.wcspFilename = filename;
if(verbose) System.out.println("performing WCSP conversion...");
converter = new WCSPConverter(mrf);
paramHandler.addSubhandler(converter);
converter.setCacheConstraints(cache);
WCSP wcsp = converter.run();
wcsp.writeWCSP(new PrintStream(wcspFilename), "WCSPFromMLN");
return converter;
}
@Override
public ArrayList<InferenceResult> infer(Iterable<String> queries) throws Exception {
// construct WCSP if necessary
if(converter == null)
constructWCSP(this.wcspFilename, false);
// run Toulbar2
String command = "toulbar2 " + wcspFilename + " -s " + toulbar2Args;
if(verbose) System.out.println("running WCSP solver: " + command);
Process p = Runtime.getRuntime().exec(command);
InputStream s = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(s));
String solution = null;
while(true) {
try {
String l = br.readLine();
if(l == null)
break;
if(debug)
System.out.println(l);
if(l.startsWith("New solution:")) {
solution = br.readLine();
if(debug)
System.out.println(solution);
}
}
catch(IOException e) {
break;
}
}
if(solution == null)
throw new Exception("No solution was found");
// set evidence (as in the WCSP, evidence variables are removed)
state.setEvidence(mrf.getDb());
// set solution state
if(verbose) System.out.println("WCSP solution: " + solution);
String[] solutionParts = solution.trim().split(" ");
for(int i = 0; i < solutionParts.length; i++) {
int domIdx = Integer.parseInt(solutionParts[i]);
converter.setGroundAtomState(state, i, domIdx);
}
// clean up
new File(this.wcspFilename).delete();
return getResults(queries);
}
@Override
public PossibleWorld getSolution() {
return state;
}
}