/* * Query.java * ---------- * Records a query on relations * $Id: Query.java,v 1.38 2000/11/28 00:48:08 chenli Exp $ */ import java.util.*; import java.io.*; import java.lang.*; class Query { public static int renameCounter = 0; String name = null; // query name Subgoal head = null; // the head is also a subgoal Vector body = null; // a set of subgoals int queryType = GoodPlan.randomQuery; int count = 0; // number of equivalent views in the same class /** * Creates a query given an id. */ Query(String name, Vector relations, int queryType, int bodySubgoalNum) { this.name = name; this.queryType = queryType; genBody(relations, queryType, bodySubgoalNum); genHead(relations, queryType, bodySubgoalNum); } /** * Constructor */ Query(String name, Subgoal head, Vector body) { this.name = name; this.head = head; this.body = body; } /** * generates the body of the query */ void genBody(Vector relations, int queryType, int bodySubgoalNum) { // random query if (queryType == GoodPlan.randomQuery) { genBodyRandom(relations, bodySubgoalNum); return; } // chain query if (queryType == GoodPlan.chainQuery) { genBodyChain(relations, bodySubgoalNum); return; } // chain query if (queryType == GoodPlan.chainQueryFix) { genBodyChainFix(relations, bodySubgoalNum); return; } // star query if (queryType == GoodPlan.starQuery) { genBodyStar(relations, bodySubgoalNum); return; } if (queryType == GoodPlan.ccQuery) { genBodyCC(relations, bodySubgoalNum); return; } } void genBodyCC(Vector relations, int bodySubgoalNum) { if ( (bodySubgoalNum % 2) != 0) UserLib.myerror("Query.genBodyCC(): bodySubGoalNum not even"); // generates the subgoals body = new Vector(); int argCounter = 1; int relSize = relations.size(); int relSubgoalNum = bodySubgoalNum/2; // for (int i = 0; i < bodySubgoalNum; i ++) { for (int i = 1; i <= relSubgoalNum; i ++) { Vector args = new Vector(); args.add(new Argument("Z0")); args.add(new Argument("Z"+i)); body.add(new Subgoal("a"+i, args)); args = new Vector(); args.add(new Argument("Z"+i)); args.add(new Argument("Z"+(relSubgoalNum+1))); body.add(new Subgoal("b"+i, args)); } } /** * generates the body of the query */ void genBodyRandom(Vector relations, int bodySubgoalNum) { // populates the domain of arguments GoodPlan.queryArgDomSize = bodySubgoalNum*3; Vector argDom = new Vector(); for (int i = 1; i <= GoodPlan.queryArgDomSize; i ++) { String argName = UserLib.getChar(i); argDom.add(new Argument(argName)); } body = new Vector(); // System.out.println(); // generates the subgoals // int subgoalNum = bodySubgoalNum; int subgoalNum = GoodPlan.random.nextInt(bodySubgoalNum)+1; Vector rel2 = (Vector)relations.clone(); for (int i = 0; i < bodySubgoalNum; i ++) { //int relIndex = Math.abs(GoodPlan.random.nextInt(relations.size()); int relIndex = GoodPlan.random.nextInt(rel2.size()); body.add(new Subgoal(rel2, relIndex, argDom)); rel2.removeElementAt(relIndex); } } Vector getBodyArgs() { Vector bodyArgs = new Vector(); // arguments used in the body for (int k = 0; k < body.size(); k ++) { Subgoal subgoal = (Subgoal) body.elementAt(k); Vector args = subgoal.getArgs(); for (int i = 0; i < args.size(); i ++) { // make sure we add the same arg only once Argument subgoalArg = (Argument) args.elementAt(i); if (bodyArgs.indexOf(subgoalArg) == -1 && !subgoalArg.isConst()) bodyArgs.add(subgoalArg); } } return bodyArgs; } /** * generates the body of the chain query (con longitud variable) */ void genBodyChain(Vector relations, int bodySubgoalNum) { // generates the subgoals body = new Vector(); int argCounter = 1; int relSize = relations.size(); int relSubgoalNum = GoodPlan.random.nextInt(bodySubgoalNum-1) + 2; // for (int i = 0; i < bodySubgoalNum; i ++) { for (int i = 0; i < relSubgoalNum; i ++) { int relIndex = GoodPlan.random.nextInt(relSize); //int relIndex = random.nextInt(relSize); Relation relation = ((Relation) relations.elementAt(relIndex)); String subgoalName = relation.getName(); Vector args = new Vector(); for (int j = 0; j < relation.getAttrNum(); j ++) { String argName = UserLib.getChar(argCounter + j); args.add(new Argument(argName)); } // TODO body.add(new Subgoal(subgoalName, args)); argCounter += args.size() - 1; // chained } } /** * generates the body of the chain query (con longitud fija) */ void genBodyChainFix(Vector relations, int bodySubgoalNum) { // generates the subgoals body = new Vector(); int argCounter = 1; int relSize = relations.size(); int relSubgoalNum = GoodPlan.random.nextInt(bodySubgoalNum-1) + 2; Map<Integer,Boolean> isConstant = new HashMap<Integer,Boolean>(); for (int i = 0; i < bodySubgoalNum; i ++) { //for (int i = 0; i < relSubgoalNum; i ++) { int relIndex = GoodPlan.random.nextInt(relSize); //int relIndex = random.nextInt(relSize); Relation relation = ((Relation) relations.elementAt(relIndex)); String subgoalName = relation.getName(); Vector args = new Vector(); for (int j = 0; j < relation.getAttrNum(); j ++) { int number = argCounter + j; if (!isConstant.containsKey(number)) { /* TODO request constant percentage from user */ int constantPercentage = 0; boolean setConstant = (GoodPlan.random.nextInt(100) < constantPercentage); isConstant.put(number, setConstant); } String argName = UserLib.getChar(argCounter + j, isConstant.get(number)); args.add(new Argument(argName, isConstant.get(number))); } // TODO body.add(new Subgoal(subgoalName, args)); argCounter += args.size() - 1; // chained } } /** * generates the body of the star query !!!!! */ void genBodyStar(Vector relations, int bodySubgoalNum) { if (GoodPlan.querySubgoalNum > GoodPlan.relAttrNum + 1) UserLib.myerror("Query.genBodyStar(): querySubgoalNum <= relAttrNum!"); body = new Vector(); // creates the center subgoal int argCounter = 1; int relSize = relations.size(); int relIndex = GoodPlan.random.nextInt(relSize); Relation relation = ((Relation) relations.elementAt(relIndex)); String subgoalName = relation.getName(); // the arguments Vector centerArgs = new Vector(); for (int j = 0; j < relation.getAttrNum(); j ++) { String argName = UserLib.getChar(argCounter); centerArgs.add(new Argument(argName)); argCounter ++; } Subgoal centerSubgoal = new Subgoal(subgoalName, centerArgs); body.add(centerSubgoal); int relSubgoalNum = GoodPlan.random.nextInt(bodySubgoalNum) + 1; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // all the rest subgoals that join with the center subgoal // generates the subgoals for (int i = 0; i < bodySubgoalNum - 1; i ++) { //for (int i = 0; i < relSubgoalNum - 1; i ++) { // the relation relIndex = GoodPlan.random.nextInt(relSize); relation = ((Relation) relations.elementAt(relIndex)); subgoalName = relation.getName(); // the arguments Vector args = new Vector(); // the argument joining with the center subgoal args.add(centerArgs.elementAt(i)); // the rest for (int j = 1; j < relation.getAttrNum(); j ++) { String argName = UserLib.getChar(argCounter); args.add(new Argument(argName)); argCounter ++; } body.add(new Subgoal(subgoalName, args)); } } // generates the head of the query void genHead(Vector relations, int queryType, int bodySubgoalNum) { // random query head if (queryType == GoodPlan.randomQuery) { genHeadRandom(relations); return; } // chain query head if (queryType == GoodPlan.chainQuery || queryType == GoodPlan.chainQueryFix) { genHeadChain(relations); return; } // star query head if (queryType == GoodPlan.starQuery) { genHeadStar(relations); return; } if (queryType == GoodPlan.ccQuery) { genHeadCC(bodySubgoalNum); return; } } void genHeadCC(int bodySubgoalNum) { Vector headArgs = new Vector(); // randomly drop arguments int relSubgoalNum = bodySubgoalNum/2; headArgs.add(new Argument("Z0")); headArgs.add(new Argument("Z"+(relSubgoalNum+1))); // sets the head, with the query's name as the subgoal's name head = new Subgoal("q", headArgs); } // generates the head of the random query void genHeadRandom(Vector relations) { Vector headArgs = getBodyArgs(); // randomly drop arguments if (GoodPlan.dropHeadArgNum == -3) GoodPlan.dropHeadArgNum = headArgs.size()/2; for (int i = 0; i < GoodPlan.dropHeadArgNum; i ++) { int removeIndex = GoodPlan.random.nextInt(headArgs.size()); headArgs.removeElementAt(removeIndex); } // sets the head, with the query's name as the subgoal's name head = new Subgoal(name, headArgs); } // generates the head of the chain query void genHeadChain(Vector relations) { Vector headArgs = getBodyArgs(); // uncomment this to generate only head and tail arguments if (GoodPlan.dropHeadArgNum == -1) { GoodPlan.dropHeadArgNum = headArgs.size() / 2; } // randomly drop arguments, while keeping the head and tail arguments if (body.size() > 1) for (int i = 0; i < GoodPlan.dropHeadArgNum; i ++) { int removeIndex = GoodPlan.random.nextInt(headArgs.size()); // we want to keep the head and tail args if (removeIndex == 0 || removeIndex == headArgs.size() - 1) removeIndex = 1; if (headArgs.size() == 2) UserLib.myerror("Query.genHeadChain(): too few arguments to drop."); headArgs.removeElementAt(removeIndex); } // sets the head, with the query's name as the subgoal's name head = new Subgoal(name, headArgs); } // generates the head of the star query void genHeadStar(Vector relations) { Vector headArgs = getBodyArgs(); // randomly drop arguments except the "center" variable if (GoodPlan.dropHeadArgNum == -1) headArgs = dropJoined(headArgs); else if (GoodPlan.dropHeadArgNum == -2) headArgs = ((Subgoal)body.elementAt(0)).getArgs(); else if (GoodPlan.dropHeadArgNum == -3) GoodPlan.dropHeadArgNum = headArgs.size()/2; for (int i = 0; i < GoodPlan.dropHeadArgNum; i ++) { int removeIndex = GoodPlan.random.nextInt(headArgs.size()); // we want to keep the root if (headArgs.size() == 1) UserLib.myerror("Query.genHeadStar(): too few arguments to drop."); headArgs.removeElementAt(removeIndex); } // sets the head, with the query's name as the subgoal's name head = new Subgoal(name, headArgs); } Vector dropJoined(Vector headArgs){ Subgoal subgoal = (Subgoal) body.elementAt(0); Vector args = subgoal.getArgs(); Vector result = new Vector(); for (int i = 0; i < headArgs.size(); i ++) { // make sure we drop the same arg only once Argument subgoalArg = (Argument) headArgs.elementAt(i); int ind = headArgs.indexOf(subgoalArg); if (ind == -1) result.add(subgoalArg); } return result; } /** * Gets all the distinguished variables in the head */ public Vector getDistVars() { return head.getArgs(); } public int getSubgoalNum() { return body.size(); } /** * Gets all the distinguished variables in the head */ public boolean isDistVar(Argument arg) { // a constant is a "dintinguished" arg if (arg.isConst()) return true; return head.getArgs().contains(arg); } /** * Checks if the give arg is an arg in this query */ public boolean containsArg(Argument arg) { return getBodyArgs().contains(arg); } /** * Gets all the head homomorphisms of the variables in the head */ public Vector getHeadHomos() { Vector headHomos = new Vector(); Vector distVars = getDistVars(); if (distVars.size() == 0) return headHomos; Map partialMap = new HashMap(); //headHomos = UserLib.genAllMappings(distVars, distVars); headHomos = UserLib.genPartitionEquMappings(distVars); return headHomos; } public String getName() { return name; } public Subgoal getHead() { return head; } public Vector getBody() { return body; } /** * returns the i^th subgoal in the body */ public Subgoal getSubgoal(int index) { return (Subgoal) body.elementAt(index); } /** * Indicates whether some other MCD is "equal to" this one. * We compare their queries, views, and mapped query subgoals. */ public boolean equals(Object tmpQuery) { Query query = (Query) tmpQuery; return this.getName().equals(query.getName()); } public int hashCode() { return (name.hashCode()); } public String toString() { // head first StringBuffer result = new StringBuffer(name); result.append("("); for (int i = 0; i < head.size(); i ++) { result.append(head.getArgs().elementAt(i).toString()); if ( i < head.size() - 1) result.append(","); } result.append(") :- "); // body for (int i = 0; i < body.size(); i++) { Subgoal subgoal = (Subgoal) body.elementAt(i); result.append(subgoal.toString()); if ( i != body.size() - 1 ) result.append(","); } return result.toString(); } /** * Renames the variables in the query. Returns a new query with the * variables renamed. */ public Query rename() { renameCounter ++; // remembers the map between the old args to the new args HashMap renameMap = new HashMap(); // renames the head Subgoal newHead = head.rename(renameCounter, renameMap); // rename the body Vector newBody = new Vector(); for (int i = 0; i < body.size(); i ++) { Subgoal oldSubgoal = (Subgoal) body.elementAt(i); Subgoal newSubgoal = oldSubgoal.rename(renameCounter, renameMap); newBody.add(newSubgoal); } return new Query(this.getName(), newHead, newBody); } /** * get the useful variables after the i^th subgoals */ public Vector getUsefulArgs(int index) { Vector usefulArgs = (Vector) head.getArgs().clone(); for (int i = index + 1; i < body.size(); i ++) { Subgoal subgoal = (Subgoal) body.elementAt(i); Vector subgoalArgs = subgoal.getArgs(); for (int j = 0; j < subgoalArgs.size(); j ++) { Argument arg = (Argument) subgoalArgs.elementAt(j); if (!arg.isConst() && !usefulArgs.contains(arg)) // no constant usefulArgs.add(arg); } } return usefulArgs; } int getNextRandom(Random random, int times) { int value = 0; for (int i = 0; i < times; i ++) value = random.nextInt(); return value; } public void setCount(int count) { this.count = count; } public int getCount() { return count; } public void inreaseCount() { count ++; } /* * containment test */ public boolean contained(Query query) { /* if (this.getName().equals("v2") &&query.getName().equals("v8") || this.getName().equals("v8") && query.getName().equals("v2")) GoodPlan.debug = true;*/ Mapping cm = new Mapping(); // containment mapping // maps the head Subgoal srcHead = this.getHead(); Subgoal dstHead = query.getHead(); if (srcHead.size() != dstHead.size()) // same size return false; if (!srcHead.unifiable(dstHead, cm, false)) // ignore names return false; // tries all sequences Vector srcSubgoalSeq = this.getBody(); Vector dstSubgoalPermus = UserLib.getAllSeqs(query.getBody(), srcSubgoalSeq.size()); for (Iterator iter = dstSubgoalPermus.iterator(); iter.hasNext();) { Vector dstSubgoalSeq = (Vector) iter.next(); if (testMapping(srcSubgoalSeq, dstSubgoalSeq, (Mapping) cm.clone())) return true; // found it! } return false; } /** * Given two sequences of subgoals and a partial mapping, tired to map * the two sequences. */ boolean testMapping(Vector srcSubgoalSeq, Vector dstSubgoalSeq, Mapping cm) { if (srcSubgoalSeq.size() != dstSubgoalSeq.size()) UserLib.myerror("Query.testMapping(): wrong sequences"); for (int i = 0; i < srcSubgoalSeq.size(); i ++) { Subgoal srcSubgoal = (Subgoal) srcSubgoalSeq.elementAt(i); Subgoal dstSubgoal = (Subgoal) dstSubgoalSeq.elementAt(i); if (srcSubgoal.size() != dstSubgoal.size()) // same size return false; if (!srcSubgoal.unifiable(dstSubgoal, cm, true)) // care names return false; } return true; } /* * equivalence test */ public boolean equivalent(Query query) { return this.contained(query) && query.contained(this); } public Object clone() { return new Query(name, head, (Vector) body.clone()); } /** * */ public Query minimize() { Query minQuery = (Query) this.clone(); Vector subgoals = minQuery.getBody(); int i = 0; while (i < subgoals.size()) { // try to remove one subgoal Subgoal subgoal = (Subgoal) subgoals.remove(i); if (!this.equivalent(minQuery)) { // put it a back subgoals.insertElementAt(subgoal, i); i ++; } } return minQuery; } /** * Unit test. */ public static void main(String[] args) { //test1(); int m= Integer.parseInt(args[0]); int n= Integer.parseInt(args[1]); test2(1, m, n, args[2], args[4], args[3]); //test2(20, m, n, args[2], args[4], args[3]); } static void test1() { // generates a conjunctive query Vector relations = GoodPlan.genRelations(); Query query = new Query("testQuery", relations, GoodPlan.chainQuery, GoodPlan.querySubgoalNum); System.out.println("Query is:\n" + query.toString()); Vector headHomos = query.getHeadHomos(); System.out.println("There are " + headHomos.size() + " HHs."); for (int i = 0; i < headHomos.size(); i ++) { Mapping headHomo = (Mapping) headHomos.elementAt(i); System.out.println(headHomo.toString()); // tests "apply()" Query newQuery = headHomo.apply(query); if (newQuery == null) { System.out.println("Query test failed: newQuery shouldn't be null."); System.exit(1); } System.out.println("Under this HH, the new query is:"); System.out.println(newQuery.toString() + "\n"); // rename newQuery.rename(); System.out.println("After renaming, the new query is:"); System.out.println(newQuery.toString() + "\n"); } } static void test2(int repeticiones, int m, int n, String tipo, String queryFile, String viewFile) { if (tipo.equals("1") || tipo.equals("7")) { for (int i = 0; i < repeticiones; i++) { genExpTipo1(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("2")) { for (int i = 0; i < repeticiones; i++) { genExpTipo2(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("3") || tipo.equals("8")) { for (int i = 0; i < repeticiones; i++) { genExpTipo3(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("4")) { for (int i = 0; i < repeticiones; i++) { genExpTipo4(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("5") || tipo.equals("9")) { for (int i = 0; i < repeticiones; i++) { genExpTipo5(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("6")) { for (int i = 0; i < repeticiones; i++) { genExpTipo6(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } if (tipo.equals("11")) { GoodPlan.relationNum = 2; for (int i = 0; i < repeticiones; i++) { genExpTipo1(m, n, queryFile+"_"+i+".txt", viewFile+"_"+i+".txt"); } } } static void genExp(int m, int n, String queryFile, String viewFile, int queryType, int viewType){ Vector relations = GoodPlan.genRelations(); //System.out.println("holafd " + GoodPlan.querySubgoalNum); Vector views = new Vector(); Query query; int dropHeadArgTemp = GoodPlan.dropHeadArgNum; GoodPlan.isView = true; for(int i = 0; i < n; i++){ //query = new Query("v"+i, relations, viewType, GoodPlan.querySubgoalNum); query = new Query("v"+i, relations, viewType, 3); views.add(query); GoodPlan.dropHeadArgNum = dropHeadArgTemp; } printViews(views, viewFile); GoodPlan.isView = false; query = new Query("q", relations, queryType, GoodPlan.querySubgoalNum); printQuery(query, queryFile); } static void genExpTipo1(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = 4; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = 0; genExp(m,n,queryFile,viewFile, GoodPlan.chainQueryFix, GoodPlan.chainQueryFix); } static void genExpTipo2(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = 4; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = -1; genExp(m,n,queryFile,viewFile, GoodPlan.chainQueryFix, GoodPlan.chainQueryFix); } static void genExpTipo3(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = m; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = 0; genExp(m,n,queryFile,viewFile, GoodPlan.starQuery, GoodPlan.starQuery); } static void genExpTipo4(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = m; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = -3; // la mitad distinguibles genExp(m,n,queryFile,viewFile, GoodPlan.starQuery, GoodPlan.starQuery); } static void genExpTipo5(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = 5; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = 0; // todos distinguibles genExp(m,n,queryFile,viewFile, GoodPlan.randomQuery, GoodPlan.randomQuery); } static void genExpTipo6(int m, int n, String queryFile, String viewFile){ // generates a conjunctive query GoodPlan.querySubgoalNum = m; GoodPlan.relAttrNum = 5; GoodPlan.relationNum = 10; GoodPlan.dropHeadArgNum = -3; // la mitad distinguibles genExp(m,n,queryFile,viewFile, GoodPlan.randomQuery, GoodPlan.randomQuery); } static void printViews(Vector views, String filename){ FileOutputStream out; // declare a file output object PrintStream p; // declare a print stream object try { // Create a new file output stream // connected to "myfile.txt" out = new FileOutputStream(filename); // Connect print stream to the output stream p = new PrintStream( out ); for (int i = 0; i < views.size(); i ++){ // System.out.println(views.elementAt(i).toString()); p.println(views.elementAt(i).toString()); } p.close(); } catch (Exception e) { System.err.println ("Error writing to file" + filename); } } static void printQuery(Query query, String filename){ FileOutputStream out; // declare a file output object PrintStream p; // declare a print stream object try { out = new FileOutputStream(filename); p = new PrintStream( out ); p.println(query.toString()); p.close(); } catch (Exception e) { System.err.println ("Error writing to file" + filename); } } }