// $Id: Search_BreadthFirst.java,v 1.15 2010/03/08 15:50:35 olga Exp $
// $Log: Search_BreadthFirst.java,v $
// Revision 1.15 2010/03/08 15:50:35 olga
// code optimizing
//
// Revision 1.14 2010/02/22 14:42:56 olga
// code optimizing
//
// Revision 1.13 2009/02/12 13:03:38 olga
// Some optimization of match searching
//
// Revision 1.12 2007/11/05 09:18:19 olga
// code tuning
//
// Revision 1.11 2007/11/01 09:58:19 olga
// Code refactoring: generic types- done
//
// Revision 1.10 2007/09/10 13:05:06 olga
// In this update:
// - package xerces2.5.0 is not used anymore;
// - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair;
// - bugs fixed in: usage of PACs in rules; match completion;
// usage of static method calls in attr. conditions
// - graph editing: added some new features
//
// Revision 1.9 2007/05/07 07:59:35 olga
// CSP: extentions of CSP variables concept
//
// Revision 1.8 2007/01/11 10:21:18 olga
// Optimized Version 1.5.1beta , free for tests
//
// Revision 1.7 2006/11/15 09:00:32 olga
// Transform with input parameter : bug fixed
//
// Revision 1.6 2006/11/01 11:17:29 olga
// Optimized agg sources of CSP algorithm, match usability,
// graph isomorphic copy,
// node/edge type multiplicity check for injective rule and match
//
// Revision 1.5 2006/05/22 08:27:33 olga
// CPA: Bug fixed
// Gragra trash: tuning
//
// Revision 1.4 2006/05/08 15:47:10 olga
// some tests with variable order and queries
//
// Revision 1.3 2006/05/08 08:24:12 olga
// Some extentions of GUI: - Undo Delete button of tool bar to undo deletions
// if grammar elements like rule, NAC, graph constraints;
// - the possibility to add a new graph to a grammar or a copy of the current
// host graph;
// - to set one or more layer for consistency constraints.
// Also some bugs fixed of matching and some optimizations of CSP algorithmus done.
//
// Revision 1.2 2006/04/20 11:58:39 olga
// Attr type check: Bug fixed
//
// Revision 1.1 2005/08/25 11:56:55 enrico
// *** empty log message ***
//
// Revision 1.1 2005/05/30 12:58:01 olga
// Version with Eclipse
//
// Revision 1.6 2004/12/20 14:53:48 olga
// Changes because of matching optimisation.
//
// Revision 1.5 2004/05/06 17:23:27 olga
// graph matching OK
//
// Revision 1.4 2004/04/28 12:46:38 olga
// test CSP
//
// Revision 1.3 2003/03/05 18:24:25 komm
// sorted/optimized import statements
//
// Revision 1.2 2002/12/04 14:00:18 komm
// code newly formated for debuging
//
// Revision 1.1.1.1 2002/07/11 12:17:26 olga
// Imported sources
//
// Revision 1.5 2000/05/17 11:58:37 olga
// Testversion fuer Gabi mit diversen Aenderungen. Fehler sind moeglich!!
//
// Revision 1.4 1999/12/06 07:40:39 olga
// *** empty log message ***
//
// Revision 1.3 1999/06/28 16:34:55 shultzke
// Hoffentlich erzeigen wir eine uebersetzungsfaehige Version
//
// Revision 1.2 1998/04/07 14:16:12 mich
// Updated for use with JGL V3.1.
//
// Revision 1.1 1997/12/26 21:03:59 mich
// Initial revision
//
// ********************************************
// *** moved from util.csp.impl to util.csp ***
// ********************************************
//
// Revision 1.2 1997/10/15 06:21:13 mich
// + SimpleVariableOrder used for ordering of internal OrderedSets.
// Tested.
//
// Revision 1.1 1997/09/22 05:09:04 mich
// Initial revision
//
package agg.util.csp;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import agg.util.OrderedSet;
/** A search strategy that traverses the constraint graph breadth first. */
public class Search_BreadthFirst implements SearchStrategy {
private static BinaryPredicate theirVariableOrder = new SimpleVariableOrder();
public Search_BreadthFirst() {
}
/**
* Returns the best possible query order of the CSP.
*/
public final Vector<Query> execute(CSP csp) {
Vector<Query> aQueryResult = new Vector<Query>();
OrderedSet<Variable> allVarsLeft = new OrderedSet<Variable>(theirVariableOrder);
Enumeration<?> anEnum = csp.getVariables();
Variable aVar;
Query aQuery;
// only variables without instance will be used
while (anEnum.hasMoreElements()) {
aVar = (Variable) anEnum.nextElement();
if (aVar.getInstance() == null) {
allVarsLeft.add(aVar);
}
}
// showVariables(allVarsLeft);
List<Query> aQueryList = bfs(new OrderedSet<Variable>(theirVariableOrder), allVarsLeft);
if (aQueryList != null) {
Iterator<Query> iter1 = aQueryList.iterator();
while (iter1.hasNext()) {
aQuery = iter1.next();
// remove dummy instantiation which was set by bfs1():
if ((aQuery != null) && (aQuery.getTarget() != null)) {
aQuery.getTarget().setInstance(null);
aQueryResult.addElement(aQuery);
}
}
// showQueries(aQueryResult, "");
}
return aQueryResult;
}
/*
* Returns the best possible queries order or null.
* Note: returned null will be caught in execute(CSP).
*/
private final Vector<Query> bfs(OrderedSet<Variable> breadthvars,
OrderedSet<Variable> varsleft) {
if (!breadthvars.isEmpty()) {
Vector<Query> aQueryList = new Vector<Query>();
OrderedSet<Variable> aVarSet = new OrderedSet<Variable>(theirVariableOrder);
Variable aVar;
for (Enumeration<?> en = breadthvars.elements(); en.hasMoreElements();) {
aVar = (Variable) en.nextElement();
// search for best query of the current variable
Query q = getBestQuery(aVar);
aQueryList.add(q);
// remove current variable from the set
varsleft.remove(aVar);
// dummy instantiation to make constraints & queries applicable:
aVar.setInstance(this);
// make union of variable set with the vicinity set of current variable
// aVarSet = aVarSet.union(getVicinity(aVar, varsleft));
OrderedSet<Variable> vic = getVicinity(aVar, varsleft);
if (vic != null)
aVarSet = aVarSet.union(vic);
}
// call recursively
List<Query> aVicQueryList = bfs(aVarSet, varsleft);
// add result if not null
if (aVicQueryList != null && !aVicQueryList.isEmpty())
aQueryList.addAll(aVicQueryList);
return aQueryList;
}
else {
if (varsleft.isEmpty()) {
return null;
}
// get best variable which is the first Arc or if no arcs exist, the first Node
Variable aVar = getBestVar(varsleft);
breadthvars.add(aVar);
// call recursively
return bfs(breadthvars, varsleft);
}
}
private final Query getBestQuery(Variable var) {
// Remember: CSP implementation have to ensure that there
// is always at least one incoming Query applicable for each
// uninstantiated variable!
// Initialize aBestSize with the size of the first applicable
// Query:
Enumeration<?> anEnum = var.getIncomingQueries();
Query aBestQuery = null;
int aBestSize = -1;
while (anEnum.hasMoreElements()) {
aBestQuery = (Query) anEnum.nextElement();
if (aBestQuery.isApplicable()) {
aBestSize = aBestQuery.getSize();
// aBestSize = aBestQuery.getTarget().getTypeQuery().getSize();
break;
}
}
if (aBestSize == -1)
return null; // should never happen!
// Search best Query:
Query aQuery;
int aSize;
while (anEnum.hasMoreElements()) {
aQuery = (Query) anEnum.nextElement();
aSize = aQuery.getSize();
// aSize = aQuery.getTarget().getTypeQuery().getSize();
if (aQuery.isApplicable() && (aSize < aBestSize)) {
aBestSize = aSize;
aBestQuery = aQuery;
}
}
return aBestQuery;
}
/*
* Returns the vicinity of the Variable v when it exists, otherwise - null.
*/
private final OrderedSet<Variable> getVicinity(Variable v, OrderedSet<Variable> varsleft) {
OrderedSet<Variable> aVicinity = null;
Variable aVar;
Enumeration<?> allConstraints = v.getConstraints();
while (allConstraints.hasMoreElements()) {
aVar = getOtherVariable((BinaryConstraint) allConstraints
.nextElement(), v);
if (varsleft.indexOf(aVar, 0) != -1) {
if (aVicinity == null)
aVicinity = new OrderedSet<Variable>(theirVariableOrder);
aVicinity.add(aVar);
}
}
return aVicinity;
}
/*
* Returns the first variable if it represents an edge,
* otherwise - the next first variable which represents an edge.
*/
private final Variable getBestVar(OrderedSet<Variable> vars) {
vars.start();
Variable v = vars.get();
while ((v.getKind() != Variable.ARC) && vars.hasNext()) {
v = vars.get();
}
return v;
}
private final Variable getOtherVariable(BinaryConstraint bc, Variable v) {
return v.equals(bc.getVar1()) ? bc.getVar2() : bc.getVar1();
}
/*
private void showQueries(Vector<Query> aQueryVec, String text) {
System.out.println(text+"\n*** Search_BreadthFirst: QUERIES *** count: "
+ aQueryVec.size());
for (int i = 0; i < aQueryVec.size(); i++) {
Query aQuery = aQueryVec.get(i);
GraphObject go = (GraphObject) aQuery.getTarget().getGraphObject();
System.out.println("Query::"
+ " kind: " + aQuery.getKind()
+ " size: " + aQuery.getSize()
+ " applicable: " + aQuery.isApplicable()
+ " tar: " + aQuery.getTarget()
+ " weight: " + aQuery.getWeight()
+ " tar weight: " + aQuery.getTarget().getWeight()
+ " tar obj is Node: " + (aQuery.getTarget().getKind() == 0)
+ " LHS obj: "+ go.getType().getName());
}
}
private void showVariables(OrderedSet allVars) {
for (Enumeration<?> en = allVars.elements(); en.hasMoreElements();) {
Variable aVar = (Variable) en.nextElement();
System.out.println("\t"
+ ((GraphObject) aVar.getGraphObject()).getType().getName()
+ " dom size: " + aVar.getDomainSize());
}
System.out.println();
}
*/
}