
git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@438 72836036-5685-4462-b002-a69064685172
140 lines
3.2 KiB
Java
140 lines
3.2 KiB
Java
package jrummikub.ai.fdsolver.constraint;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
|
|
import org.w3c.dom.ranges.Range;
|
|
|
|
import jrummikub.ai.fdsolver.Constraint;
|
|
import jrummikub.ai.fdsolver.Propagator;
|
|
import jrummikub.ai.fdsolver.Satisfiability;
|
|
import jrummikub.ai.fdsolver.Var;
|
|
|
|
public class IndexConstraint<T> extends Constraint {
|
|
Var<T> target;
|
|
Var<Integer> index;
|
|
List<Var<T>> list;
|
|
Collection<Var<?>> vars = new ArrayList<Var<?>>();
|
|
Collection<Var<?>> varsNoTarget = new ArrayList<Var<?>>();
|
|
Collection<Var<?>> varsNoIndex = new ArrayList<Var<?>>();
|
|
|
|
public IndexConstraint(Var<T> target, Var<Integer> index, List<Var<T>> list) {
|
|
this.target = target;
|
|
this.index = index;
|
|
this.list = list;
|
|
vars.addAll(list);
|
|
vars.add(index);
|
|
vars.add(target);
|
|
varsNoTarget.addAll(list);
|
|
varsNoTarget.add(index);
|
|
varsNoIndex.addAll(list);
|
|
varsNoIndex.add(target);
|
|
}
|
|
|
|
@Override
|
|
public Collection<Var<?>> getWatchedVars() {
|
|
return vars;
|
|
}
|
|
|
|
private class UnionProp implements Propagator {
|
|
@Override
|
|
public Collection<Var<?>> getWatchedVars() {
|
|
return varsNoTarget;
|
|
}
|
|
|
|
@Override
|
|
public void propagate() {
|
|
HashSet<T> invUnion = new HashSet<T>(target.getRange());
|
|
for (int i : index.getRange()) {
|
|
invUnion.removeAll(list.get(i).getRange());
|
|
if (invUnion.isEmpty()) {
|
|
return;
|
|
}
|
|
}
|
|
for (T val : invUnion) {
|
|
target.invalidate(val);
|
|
}
|
|
};
|
|
}
|
|
|
|
private class IndexProp implements Propagator {
|
|
@Override
|
|
public Collection<Var<?>> getWatchedVars() {
|
|
return varsNoIndex;
|
|
}
|
|
|
|
@Override
|
|
public void propagate() {
|
|
for (Iterator<Integer> i = index.iterator(); i.hasNext();) {
|
|
int id = i.next();
|
|
Var<T> item = list.get(id);
|
|
if (Collections.disjoint(item.getRange(), target.getRange())) {
|
|
i.remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private class VarProp implements Propagator {
|
|
@Override
|
|
public Collection<Var<?>> getWatchedVars() {
|
|
return Arrays.asList(target, index);
|
|
}
|
|
|
|
@Override
|
|
public void propagate() {
|
|
if (index.getRange().size() != 1)
|
|
return;
|
|
int id = index.getValue();
|
|
Var<T> var = list.get(id);
|
|
for(Iterator<T> i = var.iterator(); i.hasNext();) {
|
|
if (!target.getRange().contains(i.next())) {
|
|
i.remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
public Collection<Propagator> getPropagators(boolean negate) {
|
|
if (negate) {
|
|
return Collections.emptyList();
|
|
}
|
|
return Arrays.<Propagator> asList(new UnionProp(), new IndexProp(), new VarProp());
|
|
}
|
|
|
|
@Override
|
|
public boolean isSatisfiable() {
|
|
for (int i : index.getRange()) {
|
|
if(!Collections.disjoint(list.get(i).getRange(), target.getRange())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public Satisfiability getSatisfiability() {
|
|
boolean sat = isSatisfiable();
|
|
if (!sat) {
|
|
return Satisfiability.UNSAT;
|
|
}
|
|
if (target.getRange().size() > 1)
|
|
return Satisfiability.SAT;
|
|
for (int i : index.getRange()) {
|
|
Var<T> var = list.get(i);
|
|
if (var.getRange().size() > 1)
|
|
return Satisfiability.SAT;
|
|
if(var.getValue() != target.getValue()) {
|
|
return Satisfiability.SAT;
|
|
}
|
|
}
|
|
return Satisfiability.TAUT;
|
|
}
|
|
}
|