package ai.domain.generic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import ai.domain.DomainException;
import ai.domain.DomainIntf;
import ai.domain.Variable;
public final class NonRelationalDomain<DI extends DomainIntf<DI>> implements DomainIntf<NonRelationalDomain<DI>>{
public static final <DI extends DomainIntf<DI>> NonRelationalDomain<DI> getStaticBottom() {
return new NonRelationalDomain<DI>();
}
public static final <DI extends DomainIntf<DI>> NonRelationalDomain<DI> getInitialValue() {
return new NonRelationalDomain<DI>(new HashMap<Variable, DI>());
}
protected final Map<Variable, DI> variableValues;
/**
* Constructor for bottom
*/
private NonRelationalDomain() {
this.variableValues = null;
}
protected NonRelationalDomain(Map<Variable, DI> variableValues) {
if (variableValues == null)
throw new DomainException("Invalid 'null' domain values");
this.variableValues = variableValues;
}
@Override
public final boolean isBottom() {
return variableValues == null;
}
@Override
public final NonRelationalDomain<DI> join(NonRelationalDomain<DI> other) {
if (isBottom())
return other;
if (other.isBottom())
return this;
//we require the same set of values!!
if (!this.variableValues.keySet().equals(other.variableValues.keySet()))
throw new DomainException("Join only allowed with the same variables!!, mine: "+this +", other:"+other);
//join of values
Map<Variable, DI> result = new HashMap<Variable, DI>();
for(Map.Entry<Variable, DI> entry: variableValues.entrySet()) {
Variable var = entry.getKey();
DI value = entry.getValue();
DI resultValue = value.join(other.variableValues.get(var));
result.put(var, resultValue);
}
//
// //join of values
// Map<Variable, DI> result = new HashMap<Variable, DI>();
// //we take only values present in this AND other
// for(Map.Entry<Variable, DI> entry: variableValues.entrySet()) {
// Variable var = entry.getKey();
// DI value = entry.getValue();
// if (!other.variableValues.containsKey(var))
// continue;
// DI resultValue = value.join(other.variableValues.get(var));
// result.put(var, resultValue);
// }
// //variables from other only
// for(Map.Entry<Variable, DI> entry: other.variableValues.entrySet()){
// Variable var = entry.getKey();
// if (result.containsKey(var))
// continue;
// result.put(var, entry.getValue());
// }
return new NonRelationalDomain<DI>(result);
}
@Override
public final NonRelationalDomain<DI> meet(NonRelationalDomain<DI> other) {
throw new DomainException("Not implemented yet");
}
@Override
public final NonRelationalDomain<DI> widen(NonRelationalDomain<DI> other) {
if (this.isBottom())
return other;
if (other.isBottom())
return this;
if (!this.variableValues.keySet().equals(other.variableValues.keySet()))
throw new DomainException("Join only allowed with the same variables!!, mine: "+this +", other:"+other);
Map<Variable, DI> result = new HashMap<Variable, DI>();
for(Map.Entry<Variable, DI> entry: variableValues.entrySet()) {
Variable var = entry.getKey();
DI value = entry.getValue();
DI resultValue = value.widen(other.variableValues.get(var));
result.put(var, resultValue);
}
//
//
// Map<Variable, DI> result = new HashMap<Variable, DI>();
// for(Map.Entry<Variable, DI> entry: variableValues.entrySet()) {
// Variable var = entry.getKey();
// DI value = entry.getValue();
// DI resultValue = other.variableValues.containsKey(var) ? value.widen(other.variableValues.get(var)) : value;
// result.put(var, resultValue);
// }
// for(Map.Entry<Variable, DI> entry: other.variableValues.entrySet()){
// Variable var = entry.getKey();
// if (result.containsKey(var))
// continue;
// result.put(var, entry.getValue());
// }
return new NonRelationalDomain<DI>(result);
}
@Override
public final boolean leq(NonRelationalDomain<DI> other) {
if (this.isBottom())
return true;
if (other.isBottom())
return false;
for(Map.Entry<Variable, DI> entry: variableValues.entrySet()){
Variable variable = entry.getKey();
if (!other.variableValues.containsKey(variable))
return false;
DI value = entry.getValue();
if (!value.leq(other.variableValues.get(variable)))
return false;
}
return true;
}
@Override
public final boolean equals(NonRelationalDomain<DI> other) {
if (isBottom())
return other.isBottom();
else
return variableValues.equals(other.variableValues);
}
@Override
public final boolean equals(Object other) {
if (!(other instanceof NonRelationalDomain))
return false;
NonRelationalDomain<?> otherDomain = (NonRelationalDomain<?>) other;
if (isBottom())
return otherDomain.isBottom();
else
return variableValues.equals(otherDomain.variableValues);
}
public final String toString(){
if (this.isBottom())
return "NonRelationalDomain(⊥)";
StringBuffer result = new StringBuffer("NonRelationalDomain(");
ArrayList<Variable> sortedVariables = new ArrayList<Variable>(variableValues.keySet());
Collections.sort(sortedVariables);
for(Variable var: sortedVariables) {
// for(Map.Entry<Variable, DI> variable: variableValues.entrySet()){
result.append("\n");
result.append(var);
result.append(":");
result.append(variableValues.get(var).toString());
}
result.append(")");
return result.toString();
}
// test helper methods??
public final boolean containsValue(Variable variable) {
return variableValues.containsKey(variable);
}
public final DI getValueFor(Variable variable) {
if (!variableValues.containsKey(variable))
throw new DomainException("Cannot take value of not present variable '%s'", variable);
return variableValues.get(variable);
}
public final int variablesCount() {
return variableValues.size();
}
public final NonRelationalDomain<DI> addNewVariable(Variable name, DI initialValue, boolean ignoreIfExists) {
if (this.isBottom())
return this;
if (initialValue.isBottom())
return this.getBottom();
// throw new DomainException("Bottom initial value??");
if (variableValues.containsKey(name)) {
if (ignoreIfExists)
return this;
throw new DomainException("Duplicate variable '%s'", name);
}
Map<Variable, DI> copy = new HashMap<Variable, DI>(variableValues);
copy.put(name, initialValue);
return new NonRelationalDomain<DI>(copy);
}
public final NonRelationalDomain<DI> updateVariable(Variable var, DI newValue) {
if (isBottom())
return this;
if (!variableValues.containsKey(var))
throw new DomainException("Missing variable: '%s'", var);
if (newValue.isBottom())
return getBottom();
Map<Variable, DI> result = new HashMap<Variable, DI>(variableValues);
result.put(var, newValue);
return new NonRelationalDomain<DI>(result);
}
@Override
public NonRelationalDomain<DI> getBottom() {
return getStaticBottom();
}
public Set<Variable> getVariables() {
return variableValues.keySet();
}
@Override
public boolean isTop() {
if (isBottom())
return false;
for(Map.Entry<Variable, DI> entry: variableValues.entrySet())
if (!entry.getValue().isTop())
return false;
return true;
}
public NonRelationalDomain<DI> removeVariable(Variable var) {
if (isBottom())
return this;
Map<Variable, DI> result = new HashMap<Variable, DI>(variableValues);
result.remove(var);
return new NonRelationalDomain<DI>(result);
}
}