| 1 | package felix.dstruct; |
| 2 | |
| 3 | import java.util.ArrayList; |
| 4 | import java.util.HashMap; |
| 5 | import java.util.HashSet; |
| 6 | |
| 7 | import felix.dstruct.StatOperator.OPType; |
| 8 | |
| 9 | |
| 10 | import tuffy.db.RDB; |
| 11 | import tuffy.infer.ds.GClause; |
| 12 | import tuffy.mln.Clause; |
| 13 | import tuffy.mln.Literal; |
| 14 | import tuffy.mln.Predicate; |
| 15 | import tuffy.mln.Term; |
| 16 | import tuffy.mln.Type; |
| 17 | import tuffy.mln.Clause.ClauseInstance; |
| 18 | import tuffy.ra.ConjunctiveQuery; |
| 19 | import tuffy.ra.Expression; |
| 20 | import tuffy.util.Config; |
| 21 | import tuffy.util.ExceptionMan; |
| 22 | |
| 23 | |
| 24 | /** |
| 25 | * The clause object used in Felix, which extends |
| 26 | * the Clause class in Tuffy to contain Felix-related |
| 27 | * fields and methods. |
| 28 | * |
| 29 | * @author Ce Zhang |
| 30 | * |
| 31 | */ |
| 32 | public class FelixClause extends Clause{ |
| 33 | |
| 34 | |
| 35 | @SuppressWarnings("unchecked") |
| 36 | public FelixClause clone(){ |
| 37 | FelixClause ret = new FelixClause(); |
| 38 | |
| 39 | ret.bilits = (ArrayList<Literal>) this.bilits.clone(); |
| 40 | |
| 41 | ret.constraints = new ArrayList<Expression>(); |
| 42 | for(Expression sub : this.constraints){ |
| 43 | ret.constraints.add(sub.clone()); |
| 44 | } |
| 45 | |
| 46 | ret.cost = this.cost; |
| 47 | ret.existentialVars = (ArrayList<String>) this.existentialVars.clone(); |
| 48 | ret.exprWeight = this.exprWeight; |
| 49 | ret.id = this.id; |
| 50 | ret.instances = (ArrayList<ClauseInstance>) this.instances.clone(); |
| 51 | ret.isTemplate = this.isTemplate; |
| 52 | ret.lits = (ArrayList<Literal>) this.lits.clone(); |
| 53 | ret.metaTypes = (ArrayList<Type>) this.metaTypes.clone(); |
| 54 | ret.metaVars = (ArrayList<String>) this.metaVars.clone(); |
| 55 | ret.name = this.name; |
| 56 | ret.predIndex = (HashMap<Predicate, ArrayList<Literal>>) this.predIndex.clone(); |
| 57 | ret.reglits = (ArrayList<Literal>) this.reglits.clone(); |
| 58 | ret.relIntanceClauses = this.relIntanceClauses; |
| 59 | ret.signature = this.signature; |
| 60 | ret.specText = (ArrayList<String>) this.specText.clone(); |
| 61 | ret.sqlFromList = this.sqlFromList; |
| 62 | ret.sqlPivotAttrsList = this.sqlPivotAttrsList; |
| 63 | ret.sqlWhereBindings = this.sqlWhereBindings; |
| 64 | ret.uNames = (ArrayList<String>) this.uNames.clone(); |
| 65 | ret.varWeight = this.varWeight; |
| 66 | ret.violatedGClauses = (ArrayList<GClause>) this.violatedGClauses.clone(); |
| 67 | ret.weight = this.weight; |
| 68 | |
| 69 | |
| 70 | return ret; |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * @deprecated |
| 75 | */ |
| 76 | public boolean isBinaryLRRules = false; |
| 77 | |
| 78 | |
| 79 | /** |
| 80 | * See {@link StatOperator#translateFelixClasesIntoFactorGraphEdgeQueries(FelixPredicate, boolean, dstruct.FelixPredicate.FPProperty...)} |
| 81 | * @param sop |
| 82 | * @param toBeHead |
| 83 | * @param forceRecursive |
| 84 | * @return |
| 85 | */ |
| 86 | public ConjunctiveQuery toSimplifiedFactorGraphQuery(StatOperator sop, FelixPredicate toBeHead, boolean forceRecursive){ |
| 87 | |
| 88 | try{ |
| 89 | |
| 90 | ConjunctiveQuery cq = new ConjunctiveQuery(); |
| 91 | |
| 92 | //pick head literals |
| 93 | int nOfTargetLiteral = 0; |
| 94 | ArrayList<Term> headTerms = new ArrayList<Term>(); |
| 95 | ArrayList<Type> headTypes = new ArrayList<Type>(); |
| 96 | ArrayList<Literal> headLiterals = new ArrayList<Literal>(); |
| 97 | for(Literal l : this.getRegLiterals()){ |
| 98 | if(nOfTargetLiteral == 1 && forceRecursive == true){ |
| 99 | break; |
| 100 | } |
| 101 | |
| 102 | if(l.getPred().getName().equals(toBeHead.getName())){ |
| 103 | nOfTargetLiteral ++; |
| 104 | headTerms.addAll(l.getTerms()); |
| 105 | headLiterals.add(l); |
| 106 | for(int i=0;i<l.getPred().arity();i++){ |
| 107 | headTypes.add(l.getPred().getTypeAt(i)); |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | // currently, we do not consider hyper-graph edges |
| 113 | if(nOfTargetLiteral > 2 && forceRecursive == false){ |
| 114 | ExceptionMan.die("Too many matched literals for predicate " + toBeHead); |
| 115 | } |
| 116 | |
| 117 | FelixPredicate tmpHeadPredicate = new FelixPredicate(FelixPredicate.getNextTmpPredicateName(), false); |
| 118 | for(Type type : headTypes){ |
| 119 | tmpHeadPredicate.appendArgument(type); |
| 120 | } |
| 121 | RDB db = RDB.getRDBbyConfig(Config.db_schema); |
| 122 | tmpHeadPredicate.prepareDB(db); |
| 123 | db.close(); |
| 124 | |
| 125 | Literal lhead = new Literal(tmpHeadPredicate, true); |
| 126 | for(Term t : headTerms){ |
| 127 | lhead.appendTerm(t); |
| 128 | } |
| 129 | cq.setHead(lhead); |
| 130 | cq.sourceClause = this; |
| 131 | |
| 132 | int ctOpen = 0; |
| 133 | boolean lastSense = false; |
| 134 | Literal lastLiteral = null; |
| 135 | for(Literal l : this.getRegLiterals()){ |
| 136 | if(headLiterals.contains(l)){ |
| 137 | continue; |
| 138 | } |
| 139 | ctOpen ++; |
| 140 | Literal negL = (Literal) l.clone(); |
| 141 | negL.setSense(!negL.getSense()); |
| 142 | lastLiteral = negL; |
| 143 | lastSense = negL.getSense(); |
| 144 | cq.addBodyLit(negL); |
| 145 | } |
| 146 | |
| 147 | boolean flipFlag = false; |
| 148 | if(ctOpen == 1 && lastSense == false){ |
| 149 | flipFlag = true; |
| 150 | lastLiteral.setSense(!lastLiteral.getSense()); |
| 151 | } |
| 152 | |
| 153 | cq.setWeight(0); |
| 154 | |
| 155 | // set weight for the factor graph's edges |
| 156 | if(headLiterals.size() == 1){ |
| 157 | if(headLiterals.get(0).getSense() == true){ |
| 158 | if(this.hasEmbeddedWeight()){ |
| 159 | cq.inverseEmbededWeight = (flipFlag == false? false : true); |
| 160 | }else{ |
| 161 | cq.setWeight(flipFlag == false? this.getWeight(): -this.getWeight()); |
| 162 | } |
| 163 | }else{ |
| 164 | if(this.hasEmbeddedWeight()){ |
| 165 | cq.inverseEmbededWeight = (flipFlag == false? true : false); |
| 166 | }else{ |
| 167 | cq.setWeight((flipFlag == false?-this.getWeight():this.getWeight())); |
| 168 | } |
| 169 | } |
| 170 | }else{ |
| 171 | if(headLiterals.get(0).getSense() != headLiterals.get(1).getSense()){ |
| 172 | if(this.hasEmbeddedWeight()){ |
| 173 | cq.inverseEmbededWeight = (flipFlag == false? false : true); |
| 174 | }else{ |
| 175 | cq.setWeight(flipFlag == false? this.getWeight(): -this.getWeight()); |
| 176 | } |
| 177 | }else{ |
| 178 | if(this.hasEmbeddedWeight()){ |
| 179 | cq.inverseEmbededWeight = (flipFlag == false? true : false); |
| 180 | }else{ |
| 181 | cq.setWeight((flipFlag == false?-this.getWeight():this.getWeight())); |
| 182 | } |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | if(sop.clauseConstraints.get(this) != null){ |
| 187 | cq.addConstraintAll(sop.clauseConstraints.get(this)); |
| 188 | } |
| 189 | cq.addConstraintAll(this.getConstraints()); |
| 190 | |
| 191 | return cq; |
| 192 | |
| 193 | }catch(Exception e){ |
| 194 | e.printStackTrace(); |
| 195 | return null; |
| 196 | } |
| 197 | |
| 198 | } |
| 199 | |
| 200 | } |
| 201 | |