package agg.xt_basis.csp; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Vector; import agg.attribute.AttrContext; import agg.attribute.impl.AttrTupleManager; import agg.attribute.impl.ValueTuple; import agg.attribute.impl.VarMember; import agg.attribute.impl.VarTuple; import agg.util.csp.BinaryConstraint; import agg.util.csp.CSP; import agg.util.csp.Query; import agg.util.csp.Solution_Backjump; import agg.util.csp.Variable; import agg.xt_basis.Arc; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.Node; import agg.xt_basis.Type; /** * A CSP whose solutions represent morphisms between two graphs. * * Please note: This class is only for internal use of the * critical pair analysis for grammars with node type inheritance. * Do not use it for any kind of implementations. * * @see agg.util.csp.CSP */ public class ALR_InheritCSP extends CSP { private AttrContext itsAttrContext; private boolean directed = true; /** * A 1:1 mapping of the objects of <code>itsVariableGraph</code> to the * variables of the CSP. Keys are of type <code>GraphObject</code>, * values of type <code>Variable</code>. */ final private Dictionary<GraphObject, Variable> itsObjVarMap = new Hashtable<GraphObject, Variable>(); /** * A mapping of every <code>Type.convertToKey()</code> of the variable * graph to the set of graph objects of this type in the domain graph. * <p> * Keys are of type <code>String</code>, values of type * <code>Vector</code> of <code>GraphObject</code>. * * @see agg.xt_basis.Type * @see agg.xt_basis.GraphObject * @see java.util.Vector */ final private Dictionary<String, HashSet<GraphObject>> itsTypeMap = new Hashtable<String, HashSet<GraphObject>>(); /** * Construct myself to be a CSP where every GraphObject of * <code>vargraph</code> corresponds to exactly one of my variables. * <p> * <b>Pre:</b> <code>vargraph.isGraph()</code>. * <p> * <b>Post:</b> <code>getDomain() == null</code>. * * @param vargraph * The ALR graph whose elements represent the variables of the * CSP. * @param ac * The attribute context to map attributes in. * @param injective * If set to <code>true</code>, only injective solutions will * be considered. */ // * @param mapstyle The MapStyle of the AttrContext which belongs to // * the morphism to be completed. One of // * <code>AttrMapping.MATCH_MAP</code> or // * <code>AttrMapping.PLAIN_MAP</code>. // * @see agg.attribute.AttrMapping */ /* public ALR_InheritCSP(final Graph vargraph, final AttrContext ac, boolean injective) { super(injective ? new Solution_InjBackjump() : new Solution_Backjump()); itsAttrContext = ac; buildConstraintGraph(vargraph); } */ /** * Construct myself to be a CSP where every GraphObject of * <code>vargraph</code> corresponds to exactly one of my variables. * <p> * <b>Pre:</b> <code>vargraph.isGraph()</code>. * <p> * <b>Post:</b> <code>getDomain() == null</code>. * * @param vargraph * The ALR graph whose elements represent the variables of the * CSP. * @param ac * The attribute context to map attributes in. */ public ALR_InheritCSP(final Graph vargraph, final AttrContext ac) { super(new Solution_Backjump(true)); this.itsAttrContext = ac; this.directed = vargraph.getTypeSet().isArcDirected(); buildConstraintGraph(vargraph); } public void clear() { this.itsSolver.clear(); ((Hashtable<GraphObject, Variable>) this.itsObjVarMap).clear(); } // This is the static part of initialization, i.e. it can be compiled // into a graph rule (or the left graph of a rule). private synchronized final void buildConstraintGraph(final Graph vargraph) { // Create an empty TypeMap for all the GraphObject types of // the variable graph (LHS of a morphism): GraphObject anObj; Variable anObjVar; // iterate over all objects in the vargraph and create variables for // them Iterator<Node> nodes = vargraph.getNodesSet().iterator(); while (nodes.hasNext()) { anObj = nodes.next(); // create a hashmap entry for every node and arc type String keystr = anObj.convertToKey(); if (this.itsTypeMap.get(keystr) == null) this.itsTypeMap.put(keystr, new LinkedHashSet<GraphObject>()); // create a variable for the current graph object anObjVar = new Variable(); // anObjVar.setRandomizedDomain(false); anObjVar.setKind(0); anObjVar.setGraphObject(anObj); this.itsObjVarMap.put(anObj, anObjVar); } Iterator<Arc> arcs = vargraph.getArcsSet().iterator(); while (arcs.hasNext()) { anObj = arcs.next(); // create a hashmap entry for every node and arc type String keystr = anObj.convertToKey(); if (this.itsTypeMap.get(keystr) == null) this.itsTypeMap.put(keystr, new LinkedHashSet<GraphObject>()); // create a variable for the current graph object anObjVar = new Variable(); // anObjVar.setRandomizedDomain(false); anObjVar.setKind(1); anObjVar.setGraphObject(anObj); this.itsObjVarMap.put(anObj, anObjVar); } buildQueriesAndConstraints(this.itsObjVarMap.keys()); } private void buildQueriesAndConstraints(final Enumeration<GraphObject> anEnum) { GraphObject anObj; Variable anObjVar, aSrcObjVar, aTarObjVar; Query query; BinaryConstraint constraint; while (anEnum.hasMoreElements()) { anObj = anEnum.nextElement(); anObjVar = this.itsObjVarMap.get(anObj); // create queries for the current variable // query = new Query_Type(itsTypeMap.get(anObj.convertToKey()), anObjVar); query = new Query_Type(anObjVar); constraint = new Constraint_InheritType(anObj, anObjVar); query.setCorrespondent(constraint); if (anObj.getType().getAttrType() != null || anObj.getType().hasInheritedAttribute()) new Constraint_InheritAttribute(anObj, anObjVar, this.itsAttrContext, AttrTupleManager.getDefaultManager()); // create queries for source and target nodes if current object is // an arc if (anObj.isArc()) { aSrcObjVar = this.itsObjVarMap.get(((Arc) anObj).getSource()); aTarObjVar = this.itsObjVarMap.get(((Arc) anObj).getTarget()); if (this.directed) { // constraint_source constraint = new Constraint_Source(aSrcObjVar, anObjVar); query = new Query_Outgoing(aSrcObjVar, anObjVar); query.setCorrespondent(constraint); query = new Query_Source(anObjVar, aSrcObjVar); query.setCorrespondent(constraint); // constraint_target constraint = new Constraint_Target(aTarObjVar, anObjVar); query = new Query_Incoming(aTarObjVar, anObjVar); query.setCorrespondent(constraint); query = new Query_Target(anObjVar, aTarObjVar); query.setCorrespondent(constraint); } else { // constraint_source_target constraint = new Constraint_SourceTarget(aSrcObjVar, anObjVar); query = new Query_OutgoingIncoming(aSrcObjVar, anObjVar); query.setCorrespondent(constraint); query = new Query_SourceTarget(anObjVar, aSrcObjVar); query.setCorrespondent(constraint); // constraint_source_target constraint = new Constraint_TargetSource(aTarObjVar, anObjVar); query = new Query_IncomingOutgoing(aTarObjVar, anObjVar); query.setCorrespondent(constraint); query = new Query_TargetSource(anObjVar, aTarObjVar); query.setCorrespondent(constraint); } } } } // CSP protected synchronized final void preprocessDomain(final Object domaingraph) { // fillTypeMap((Graph) domaingraph); resetTypeMap((Graph) domaingraph); // showTypeMap(itsTypeMap); } public AttrContext getAttrContext() { return this.itsAttrContext; } // CSP public final Enumeration<Variable> getVariables() { return this.itsObjVarMap.elements(); } public void enableAllVariables() { Enumeration<GraphObject> keys = this.itsObjVarMap.keys(); while (keys.hasMoreElements()) { GraphObject obj = keys.nextElement(); Variable var = this.itsObjVarMap.get(obj); var.setEnabled(true); } } public boolean isDomainOfTypeEmpty(final Type t) { Enumeration<GraphObject> keys = this.itsObjVarMap.keys(); while (keys.hasMoreElements()) { GraphObject go = keys.nextElement(); if (go.isArc()) continue; if (go.getType().compareTo(t)) { Variable var = this.itsObjVarMap.get(go); return !var.hasNext(); } } return false; } public boolean isDomainOfTypeEmpty(final Type t, final Type src, final Type tar) { Enumeration<GraphObject> keys = this.itsObjVarMap.keys(); while (keys.hasMoreElements()) { GraphObject go = keys.nextElement(); if (go.isNode()) continue; if (go.getType().compareTo(t) && ((Arc) go).getSource().getType().compareTo(src) && ((Arc) go).getTarget().getType().compareTo(tar)) { Variable var = this.itsObjVarMap.get(go); return !var.hasNext(); } } return false; } public void setRelatedInstanceVarMap( final Dictionary<Object, Variable> relatedVarMap) { this.itsSolver.setRelatedInstanceVarMap(relatedVarMap); } public Dictionary<Object, Variable> getInstanceVarMap() { return this.itsSolver.getInstanceVarMap(); } // CSP public final int getSize() { return this.itsObjVarMap.size(); } // CSP public final Variable getVariable(final GraphObject obj) { return this.itsObjVarMap.get(obj); } /** * An additional object name constraint will be added for the CSP variable * of the given GraphObject anObj. This constraint requires equality of the object names. */ public void addObjectNameConstraint(GraphObject anObj) { Variable anObjVar = this.itsObjVarMap.get(anObj); if (anObjVar != null) new Constraint_ObjectName(anObj, anObjVar); } /** * Removes the object name constraint for the CSP variable * of the given GraphObject anObj. */ public void removeObjectNameConstraint(GraphObject anObj) { Variable anObjVar = this.itsObjVarMap.get(anObj); if (anObjVar != null) { Enumeration<?> cons = anObjVar.getConstraints(); while (cons.hasMoreElements()) { Object c = cons.nextElement(); if (c instanceof Constraint_ObjectName) { anObjVar.removeConstraint((Constraint_ObjectName) c); } } } } // This is dynamic, i.e. can only be done when the domain graph is known. // not more in use protected void fillTypeMap(final Graph domaingraph) { // handle nodes Iterator<?> anEnum = domaingraph.getNodesSet().iterator(); while (anEnum.hasNext()) { Node anObj = (Node) anEnum.next(); String keystr = anObj.convertToKey(); if (anObj.getType().hasParent()) { Vector<Type> myParents = anObj.getType().getAllParents(); for (int i = 0; i < myParents.size(); ++i) { Type anObjType = myParents.get(i); keystr = anObjType.convertToKey(); if (this.itsTypeMap.get(keystr) != null) { HashSet<GraphObject> anObjVec = this.itsTypeMap.get(keystr); anObjVec.add(anObj); } } } else if (this.itsTypeMap.get(keystr) != null) { HashSet<GraphObject> anObjVec = this.itsTypeMap.get(keystr); anObjVec.add(anObj); } } // handle arcs anEnum = domaingraph.getArcsSet().iterator(); while (anEnum.hasNext()) { Arc anObj = (Arc)anEnum.next(); String keystr = anObj.convertToKey(); if (anObj.getSource().getType().hasParent() || anObj.getTarget().getType().hasParent()) { Vector<Type> mySrcParents = anObj.getSource().getType().getAllParents(); Vector<Type> myTarParents = anObj.getTarget().getType().getAllParents(); for (int i = 0; i < mySrcParents.size(); ++i) { for (int j = 0; j < myTarParents.size(); ++j) { keystr = mySrcParents.get(i).convertToKey() + anObj.getType().convertToKey() + myTarParents.get(j).convertToKey(); if (this.itsTypeMap.get(keystr) != null) { HashSet<GraphObject> anObjVec = this.itsTypeMap.get(keystr); anObjVec.add(anObj); } } } } else if (this.itsTypeMap.get(keystr) != null) { HashSet<GraphObject> anObjVec = this.itsTypeMap.get(keystr); anObjVec.add(anObj); } } } protected void resetTypeMap(final Graph g) { Enumeration<GraphObject> lhsObjs = this.itsObjVarMap.keys(); while (lhsObjs.hasMoreElements()) { GraphObject lhsobj = lhsObjs.nextElement(); Variable var = this.itsObjVarMap.get(lhsobj); String key = lhsobj.convertToKey(); if (g.getTypeObjectsMap().get(key) == null) { final HashSet<GraphObject> v = new LinkedHashSet<GraphObject>(); if (lhsobj.isNode()) { Vector<Type> parents = lhsobj.getType().getAllParents(); for (int p = 1; p < parents.size(); p++) { Type pt = parents.get(p); Vector<GraphObject> vp = g.getElementsOfTypeAsVector(pt); for (int i=0; i<vp.size(); i++) { if (!v.contains(vp.get(i))) v.add(vp.get(i)); } } } else { // lhsobj.isArc() GraphObject src = ((Arc)lhsobj).getSource(); GraphObject tar = ((Arc)lhsobj).getTarget(); Vector<Type> src_parents = src.getType().getAllParents(); Vector<Type> tar_parents = tar.getType().getAllParents(); for (int i = 0; i < src_parents.size(); i++) { Type srcp = src_parents.get(i); Vector<GraphObject> vsrcp = g.getElementsOfTypeAsVector(lhsobj.getType(), srcp, tar.getType()); for (int k=0; k<vsrcp.size(); k++) { if (!v.contains(vsrcp.get(k))) v.add(vsrcp.get(k)); } for (int j = 0; j<tar_parents.size(); j++) { Type tarp = tar_parents.get(j); Vector<GraphObject> vtarp = g.getElementsOfTypeAsVector(lhsobj.getType(), srcp, tarp); for (int l=0; l<vtarp.size(); l++) { if (!v.contains(vtarp.get(l))) v.add(vtarp.get(l)); } } } } g.getTypeObjectsMap().put(key, v); } this.itsTypeMap.put(key, g.getTypeObjectsMap().get(key)); var.getTypeQuery().setObjects(g.getTypeObjectsMap().get(key)); } } protected void resetTypeMap(final Hashtable<String, HashSet<GraphObject>> aTypeMap) { Enumeration<GraphObject> lhsObjs = this.itsObjVarMap.keys(); while (lhsObjs.hasMoreElements()) { GraphObject obj = lhsObjs.nextElement(); Variable var = this.itsObjVarMap.get(obj); String key = obj.convertToKey(); HashSet<GraphObject> list = aTypeMap.get(key); if (list == null) { list = new LinkedHashSet<GraphObject>(); aTypeMap.put(key, list); } this.itsTypeMap.put(key, list); var.getTypeQuery().setObjects(list); } } protected void reinitializeSolver(boolean doUpdateQueries) { this.itsSolver.reinitialize(doUpdateQueries); } protected void resetSolver(boolean doUpdateQueries) { resetSolverVariables(); this.itsSolver.reinitialize(doUpdateQueries); } protected void resetSolverVariables() { Enumeration<GraphObject> lhsObjs = this.itsObjVarMap.keys(); while (lhsObjs.hasMoreElements()) { GraphObject obj = lhsObjs.nextElement(); Variable var = this.itsObjVarMap.get(obj); var.setInstance(null); } } protected void resetVariableDomain(boolean resetByNull) { if (resetByNull) { final Enumeration<Variable> cspVars = this.itsObjVarMap.elements(); while (cspVars.hasMoreElements()) { cspVars.nextElement().setInstance(null); } } // Enumeration<GraphObject> keys = itsObjVarMap.keys(); // while (keys.hasMoreElements()) { // GraphObject obj = keys.nextElement(); // Variable var = itsObjVarMap.get(obj); // if (!var.isEnabled()) { // continue; // } //// var.setDomainEnum(getTypeQuerySet(obj)); // if (instanceToNull) { // var.setInstance(null); // } // } unsetAttrContextVariable(); } protected void resetVariableDomain(final GraphObject go) { Enumeration<GraphObject> keys = this.itsObjVarMap.keys(); while (keys.hasMoreElements()) { GraphObject obj = keys.nextElement(); if (obj == go) { Variable var = this.itsObjVarMap.get(obj); // String key = convertToKey(obj); // reset domain of a variable this.itsSolver.reinitialize(var); // var.setDomainEnum(itsTypeMap.get(go.convertToKey())); var.setInstance(null); return; } } unsetAttrContextVariable(go); } protected void unsetAttrContextVariable() { // System.out.println("ALR_CSP.unsetAttrContextVariable... // itsAttrContext: "+itsAttrContext.hashCode()); VarTuple varTuple = (VarTuple) this.itsAttrContext.getVariables(); for (int i = 0; i < varTuple.getSize(); i++) { VarMember vm = varTuple.getVarMemberAt(i); if (vm != null) vm.setExpr(null); } } protected void unsetAttrContextVariable(final GraphObject go) { if (go.getAttribute() == null) return; Vector<String> attrVars = ((ValueTuple) go.getAttribute()) .getAllVariableNames(); VarTuple varTup = (VarTuple) this.itsAttrContext.getVariables(); for (int i = 0; i < attrVars.size(); i++) { String name = attrVars.elementAt(i); VarMember vm = varTup.getVarMemberAt(name); if (vm != null) vm.setExpr(null); } } }