/*******************************************************************************
* Copyright (C) 2008-2012 Dominik Jain.
*
* 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.logic;
import java.util.Collection;
import java.util.Map;
import probcog.srl.GenericDatabase;
import probcog.srl.RelationalModel;
import probcog.srl.Signature;
import probcog.srl.taxonomy.Taxonomy;
import edu.tum.cs.util.StringTool;
/**
* Represents a logical atom.
* @author Dominik Jain
*/
public class Atom extends UngroundedFormula {
public Collection<String> params;
public String predName;
public Atom(String predName, Collection<String> params) {
this.predName = predName;
this.params = params;
}
@Override
public String toString() {
return predName + "(" + StringTool.join(",", params) + ")";
}
@Override
public void getVariables(GenericDatabase<?, ?> db, Map<String, String> ret) throws Exception {
Signature sig = db.getSignature(predName);
if(sig == null)
throw new Exception("Unknown predicate '" + predName + "'");
int i = 0;
for(String param : params) {
if(isVariable(param)) {
String type;
if(i < sig.argTypes.length)
type = sig.argTypes[i];
else
type = sig.returnType;
String oldtype = ret.put(param, type);
if(oldtype != null && !type.equals(oldtype)) {
Taxonomy taxonomy = db.getModel().getTaxonomy();
if(taxonomy == null)
throw new Exception("The variable " + param + " is bound to more than one domain (and domains are incompatible): " + oldtype + " and " + type);
else {
boolean moreSpecific = taxonomy.query_isa(type, oldtype);
boolean lessSpecific = taxonomy.query_isa(oldtype, type);
if(!(moreSpecific || lessSpecific))
throw new Exception("The variable " + param + " is bound to more than one domain: " + oldtype + " and " + type);
if(lessSpecific)
ret.put(param, oldtype);
}
}
}
++i;
}
}
@Override
public void addConstantsToModel(RelationalModel m) throws Exception {
Signature sig = m.getSignature(predName);
if(sig == null)
throw new Exception("Unknown predicate '" + predName + "'");
int i = 0;
for(String param : params) {
if(!isVariable(param)) {
String type;
if(i < sig.argTypes.length)
type = sig.argTypes[i];
else
type = sig.returnType;
m.addGuaranteedDomainElement(type, param);
}
++i;
}
}
public static boolean isVariable(String paramName) {
return Character.isLowerCase(paramName.charAt(0));
}
@Override
public Formula ground(Map<String, String> binding, WorldVariables vars, GenericDatabase<?, ?> db) throws Exception {
StringBuffer sb = new StringBuffer(predName + "(");
int i = 0;
for(String param : params) {
if(i++ > 0)
sb.append(',');
String value = binding.get(param);
if(value == null) { // if the binding contains no value for a parameter, it must be a constant
if(isVariable(param))
throw new Exception("Cannot ground " + toString() + " with binding " + binding + " - variable " + param + " unbound.");
value = param;
}
sb.append(value);
}
sb.append(')');
String strGA = sb.toString();
GroundAtom ga = vars.get(strGA);
if(ga == null)
throw new Exception("Could not find ground atom '" + strGA + "' in set of world variables.");
return ga;
}
@Override
public Formula toCNF() {
return this;
}
@Override
public Formula toNNF() {
return this;
}
}