EMMA Coverage Report (generated Sat Aug 20 11:00:51 CDT 2011)
[all classes][tuffy.mln]

COVERAGE SUMMARY FOR SOURCE FILE [Clause.java]

nameclass, %method, %block, %line, %
Clause.java50%  (1/2)85%  (35/41)64%  (1429/2218)68%  (278.4/408)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Clause$ClauseInstance0%   (0/1)0%   (0/1)0%   (0/12)0%   (0/4)
Clause$ClauseInstance (Clause, ArrayList, double): void 0%   (0/1)0%   (0/12)0%   (0/4)
     
class Clause100% (1/1)88%  (35/40)65%  (1429/2206)69%  (278.4/404)
absorb (Clause): void 0%   (0/1)0%   (0/38)0%   (0/8)
addExistentialVariable (String): boolean 0%   (0/1)0%   (0/14)0%   (0/3)
addMetaVariable (String, Type): boolean 0%   (0/1)0%   (0/19)0%   (0/4)
getSpecText (): ArrayList 0%   (0/1)0%   (0/3)0%   (0/1)
isTemplate (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
sealClauseInstances (RDB): void 100% (1/1)8%   (19/240)7%   (3/42)
addUserProvidedName (String): void 100% (1/1)38%  (3/8)67%  (2/3)
toString (int): String 100% (1/1)44%  (31/71)58%  (5.3/9)
normalize (): Clause 100% (1/1)55%  (328/595)58%  (58.1/100)
toString (): String 100% (1/1)74%  (76/103)84%  (6.7/8)
generateSQL (): void 100% (1/1)77%  (408/530)80%  (76.1/95)
isPositiveClause (): boolean 100% (1/1)78%  (7/9)77%  (0.8/1)
addLiteral (Literal): void 100% (1/1)80%  (61/76)84%  (12.5/15)
hasExistentialQuantifiers (): boolean 100% (1/1)88%  (7/8)87%  (0.9/1)
<static initializer> 100% (1/1)100% (5/5)100% (3/3)
Clause (): void 100% (1/1)100% (105/105)100% (29/29)
addConstraint (Expression): void 100% (1/1)100% (6/6)100% (2/2)
addSpecText (String): void 100% (1/1)100% (6/6)100% (2/2)
checkVariableSafety (): void 100% (1/1)100% (83/83)100% (15/15)
clone (): Clause 100% (1/1)100% (143/143)100% (28/28)
getConstaintStringAsLits (): String 100% (1/1)100% (49/49)100% (7/7)
getConstraints (): ArrayList 100% (1/1)100% (3/3)100% (1/1)
getId (): int 100% (1/1)100% (3/3)100% (1/1)
getLiteralsOfPredicate (Predicate): ArrayList 100% (1/1)100% (6/6)100% (1/1)
getName (): String 100% (1/1)100% (3/3)100% (1/1)
getReferencedPredicates (): Set 100% (1/1)100% (4/4)100% (1/1)
getRegLiterals (): ArrayList 100% (1/1)100% (3/3)100% (1/1)
getSignature (): String 100% (1/1)100% (3/3)100% (1/1)
getSpecTextFlat (): String 100% (1/1)100% (5/5)100% (1/1)
getVarWeight (): String 100% (1/1)100% (3/3)100% (1/1)
getWeight (): double 100% (1/1)100% (3/3)100% (1/1)
getWeightExp (): String 100% (1/1)100% (3/3)100% (1/1)
hasEmbeddedWeight (): boolean 100% (1/1)100% (7/7)100% (1/1)
isHardClause (): boolean 100% (1/1)100% (9/9)100% (1/1)
prepareForDB (RDB): void 100% (1/1)100% (6/6)100% (3/3)
setHardWeight (): void 100% (1/1)100% (4/4)100% (2/2)
setId (int): void 100% (1/1)100% (4/4)100% (2/2)
setName (String): void 100% (1/1)100% (15/15)100% (3/3)
setVarWeight (String): void 100% (1/1)100% (4/4)100% (2/2)
setWeight (double): void 100% (1/1)100% (4/4)100% (2/2)

1package tuffy.mln;
2 
3import java.sql.PreparedStatement;
4import java.sql.SQLException;
5import java.util.ArrayList;
6import java.util.HashMap;
7import java.util.HashSet;
8import java.util.Hashtable;
9import java.util.Set;
10 
11import tuffy.db.RDB;
12import tuffy.db.SQLMan;
13import tuffy.infer.ds.GClause;
14import tuffy.main.Infer;
15import tuffy.parse.CommandOptions;
16import tuffy.ra.Expression;
17import tuffy.util.Config;
18import tuffy.util.ExceptionMan;
19import tuffy.util.StringMan;
20import tuffy.util.UIMan;
21/**
22 * A first-order logic clause, namely a disjunct of literals.
23 */
24public class Clause implements Cloneable{
25        
26        @SuppressWarnings("unchecked")
27        public Clause clone(){
28                Clause ret = new Clause();
29                
30                ret.bilits = (ArrayList<Literal>) this.bilits.clone();
31                
32                ret.constraints = new ArrayList<Expression>();
33                for(Expression sub : this.constraints){
34                        ret.constraints.add(sub.clone());
35                }
36                
37                ret.cost = this.cost;
38                ret.existentialVars = (ArrayList<String>) this.existentialVars.clone();
39                ret.exprWeight = this.exprWeight;
40                ret.id = this.id;
41                ret.instances = (ArrayList<ClauseInstance>) this.instances.clone();
42                ret.isTemplate = this.isTemplate;
43                ret.lits = (ArrayList<Literal>) this.lits.clone();
44                ret.metaTypes = (ArrayList<Type>) this.metaTypes.clone();
45                ret.metaVars = (ArrayList<String>) this.metaVars.clone();
46                ret.name = this.name;
47                ret.predIndex = (HashMap<Predicate, ArrayList<Literal>>) this.predIndex.clone();
48                ret.reglits = (ArrayList<Literal>) this.reglits.clone();
49                ret.relIntanceClauses = this.relIntanceClauses;
50                ret.signature = this.signature;
51                ret.specText = (ArrayList<String>) this.specText.clone();
52                ret.sqlFromList = this.sqlFromList;
53                ret.sqlPivotAttrsList = this.sqlPivotAttrsList;
54                ret.sqlWhereBindings = this.sqlWhereBindings;
55                ret.uNames = (ArrayList<String>) this.uNames.clone();
56                ret.varWeight = this.varWeight;
57                ret.violatedGClauses = (ArrayList<GClause>) this.violatedGClauses.clone();
58                ret.weight = this.weight;
59                
60                
61                return ret;
62        }
63        
64        
65        /**
66         * Map from clause ID to its description. This is used in
67         * learning part to dump out the answers. Here by id it means
68         * a string like <Clause ID>.<Instance ID or 0 if not a template>.
69         * This variable is materialized in {@link Infer#setUp(CommandOptions)}.
70         */
71        public static HashMap<String, String> mappingFromID2Desc = null;
72        //        new HashMap<String, String>();
73        
74        /**
75         * Map from Constant ID to Constant Name. This map is filled
76         * in {@link MarkovLogicNetwork#getSymbolID(String, Type)}.
77         * This variable is materialized in {@link Infer#setUp(CommandOptions)}.
78         */
79        public static HashMap<Integer, String> mappingFromID2Const = null;
80        //        new HashMap<Integer, String>();
81 
82        /**
83         * The set of boolean expressions that must all be TRUE;
84         * otherwise the corresponding grounding is always true, and
85         * is useless for inference -- and will be discarded.
86         * 
87         * In other words, this is the set of constraints that must be
88         * satisfied by the grounding process.
89         */
90        private ArrayList<Expression> constraints = new ArrayList<Expression>();
91        
92        /**
93         * Add a constraint that must hold.
94         * @param e A bool expression that must be TRUE.
95         */
96        public void addConstraint(Expression e){
97                constraints.add(e);
98        }
99        
100        public ArrayList<Expression> getConstraints(){
101                return constraints;
102        }
103 
104 
105        private String getConstaintStringAsLits(){
106                if(constraints.isEmpty()) return "";
107                StringBuilder sb = new StringBuilder();
108                ArrayList<String> clines = new ArrayList<String>();
109                for(Expression e : constraints){
110                        clines.add(" v [" + Expression.not(e).toString() + "]");
111                }
112                sb.append(StringMan.join("\n", clines));
113                return sb.toString();
114        }
115        
116        
117        /**
118         * List of literals in this clause.
119         */
120        private ArrayList<Literal> lits = new ArrayList<Literal>();
121        
122        
123        
124        /**
125         * List of regular literals in this clause.
126         */
127        private ArrayList<Literal> reglits = new ArrayList<Literal>(); //regular
128        
129        /**
130         * List of built-in literals in this clause.
131         */
132        private ArrayList<Literal> bilits = new ArrayList<Literal>(); //built in
133        
134        /**
135         * The index of predicate to set of literals referencing that predicate.
136         */
137        private HashMap<Predicate, ArrayList<Literal>> predIndex =
138                new HashMap<Predicate, ArrayList<Literal>>();
139        
140        /**
141         * List of variables that are existentially quantified.
142         */
143        private ArrayList<String> existentialVars = new ArrayList<String>();
144        
145        
146        /**
147         * Variables corresponding to constants in this clause.
148         */
149        private ArrayList<String> metaVars = new ArrayList<String>();
150        
151        /**
152         * Types of meta variables.
153         */
154        private ArrayList<Type> metaTypes = new ArrayList<Type>();
155        
156        /**
157         * List of instances of this clause. Here by instance, we mean
158         * the possible bindings of meta-variables to constants.
159         */
160        private ArrayList<ClauseInstance> instances = new ArrayList<ClauseInstance>();
161 
162        /**
163         * weight of this clause.
164         */
165        private double weight = 0;
166        
167        /**
168         * name of this clause.
169         */
170        private String name = null;
171        
172        /**
173         * id of this cluase.
174         */
175        private int id = 0;
176        
177        /** 
178         * user provided names
179         */
180        private ArrayList<String> uNames = new ArrayList<String>();
181        
182        /**
183         * Lines in the MLN rule file specifying this clause.
184         */
185        private ArrayList<String> specText = new ArrayList<String>();
186        
187        private String getSpecTextFlat(){
188                return StringMan.join("\n", specText);
189        }
190        
191        
192        /**
193         * The database table storing the clause instances.
194         */
195        private String relIntanceClauses = null;
196 
197 
198        /**
199         * Indicates whether this clause contains constants.
200         */
201        private boolean isTemplate = false;
202        
203        /**
204         * The signature of this clause. Clauses with the same
205         * signature have the same pattern, and thus can be consolidated.
206         * See {@link Clause#normalize()}.
207         */
208        private String signature = null;
209 
210        /**
211         * The From sub-clause of SQL for grounding.
212         */
213        public String sqlFromList = null;
214        
215        /**
216         * The Where sub-clause of SQL for grounding.
217         */
218        public String sqlWhereBindings = null;
219        
220        /**
221         * The list of attributes that are NOT existential variables.
222         */
223        public String sqlPivotAttrsList = null; 
224        
225        /**
226         * The cost ascribed to this clause.
227         * For auditing purposes.
228         * 
229         * @see tuffy.infer.MRF#auditClauseViolations()
230         */
231        public double cost = 0;
232        
233        /**
234         * The number of violations on this clause.
235         * For auditing purposes.
236         * 
237         * @see tuffy.infer.MRF#auditClauseViolations()
238         */
239        public double violations = 0;
240        
241        /**
242         * Violated ground clauses.
243         * 
244         * @see tuffy.infer.MRF#auditClauseViolations()
245         */
246        public ArrayList<GClause> violatedGClauses = new ArrayList<GClause>();
247        
248        /**
249         * FO variable that is used as clause weights
250         */
251        private String varWeight = null;
252        
253        public void setVarWeight(String vw){
254                varWeight = vw;
255        }
256        
257        /**
258         * Get the variable in this clause that is used as clause weights
259         */
260        public String getVarWeight(){
261                return varWeight;
262        }
263        
264        /**
265         * Check if the weight of this clause comes from a variable in the clause
266         */
267        public boolean hasEmbeddedWeight(){
268                return (varWeight != null);
269        }
270        
271        
272        /**
273         * Return the weight of this clause.
274         * If this clause contains multiple instances, the returned
275         * value only indicates the signum.
276         */
277        public double getWeight(){
278                return weight;
279        }
280        
281        /**
282         * Return true iff this clause contains constant. Note that
283         * the result of this function is meaningful iff this
284         * clause is a normalized clause.
285         */
286        public boolean isTemplate(){
287                return isTemplate;
288        }
289        
290        
291        /**
292         * Add user provided names to this clause.
293         * @param nm user provided name
294         */
295        public void addUserProvidedName(String nm){
296                if(nm != null){
297                        uNames.add(nm);
298                }
299        }
300        
301 
302        /**
303         * Class of an instance of a clause.
304         */
305        private class ClauseInstance{
306                /**
307                 * list of constant ID in this clause instance.
308                 */
309                public ArrayList<Integer> conList;
310                
311                /**
312                 * weight of this clause instance.
313                 */
314                public double weight;
315                
316                /**
317                 * Constructor of ClauseInstance.
318                 * @param conList list of constant in this clause instance.
319                 * @param weight weight of this clause instance.
320                 */
321                public ClauseInstance(ArrayList<Integer> conList, double weight){
322                        this.conList = conList;
323                        this.weight = weight;
324                }
325        }
326 
327        /**
328         * Return the assigned name of this clause.
329         */
330        public String getName(){
331                return name;
332        }
333        
334        /**
335         * Assign a name for this clause.
336         */
337        public void setName(String aname)        {
338                name = aname;
339                relIntanceClauses = name + "_instances";
340        }
341        
342        /**
343         * Return the "signature" of this clause.
344         * 
345         * @see Clause#normalize()
346         */
347        public String getSignature(){
348                return signature;
349        }
350 
351        /**
352         * Return a normalized version of this clause.
353         * 
354         * The variables and constants are replaced standardized 
355         * variable names, yielding a signature that can be used to 
356         * identify clauses of the same pattern. 
357         * If there are constants in the original clause,
358         * the resulting clause is called a template. 
359         * Clauses of the same pattern will be consolidated under
360         * the same template. 
361         * 
362         * For example, clauses
363         * "!likes(x, Candy) v has(x, Diabetes)" and
364         * "!likes(x, WeightLifting) v has(x, Muscles)"
365         * would be consolidated into the template
366         * "!likes(v1, c1) v has(v1, c2)".
367         * 
368         * Zero-weight clauses will be ignored.
369         * 
370         * @see MarkovLogicNetwork#registerClause(Clause)
371         */
372        public Clause normalize() {
373                Hashtable<String, Integer> varIndex = new Hashtable<String, Integer>();
374                Hashtable<Integer, Integer> conIndex = new Hashtable<Integer, Integer>();
375                ArrayList<Integer> conList = new ArrayList<Integer>();
376                ArrayList<Type> conTypeList = new ArrayList<Type>();
377                
378                if(this.weight == 0) return null;
379                
380                // normalization
381                // order into {enlits, eplits, unlits, uplits}.
382                if(Config.reorder_literals){
383                        ArrayList<Literal> enlits = new ArrayList<Literal>();        //closed, neg
384                        ArrayList<Literal> eplits = new ArrayList<Literal>();        //closed, pos
385                        ArrayList<Literal> unlits = new ArrayList<Literal>();         //open, neg
386                        ArrayList<Literal> uplits = new ArrayList<Literal>();        //open, pos
387                        for(Literal lit : lits){
388                                Predicate p = lit.getPred();
389                                if(p.isClosedWorld()){
390                                        if(lit.getSense()){
391                                                eplits.add(lit);
392                                        }else{
393                                                enlits.add(lit);
394                                        }
395                                }else{
396                                        if(lit.getSense()){
397                                                uplits.add(lit);
398                                        }else{
399                                                unlits.add(lit);
400                                        }
401                                }
402                        }
403                        enlits.addAll(eplits);
404                        enlits.addAll(unlits);
405                        enlits.addAll(uplits);
406                        lits = enlits;
407                }
408                
409                // TODO: cleaner object cloning
410                ArrayList<String> litlist = new ArrayList<String>();
411                for(Literal lit : lits){
412                        StringBuilder sb = new StringBuilder();
413                        if(!lit.getSense()){
414                                sb.append("!");
415                        }else{
416                                sb.append(" ");
417                        }
418                        sb.append(lit.getPred().getName());
419                        sb.append("(");
420                        ArrayList<String> tlist = new ArrayList<String>();
421                        for(int i=0; i<lit.getTerms().size(); i++){
422                                Term t = lit.getTerms().get(i);
423                                if(t.isVariable()){
424                                        Integer vi = varIndex.get(t.var());
425                                        if(vi == null){
426                                                vi = varIndex.size();
427                                                varIndex.put(t.var(), vi);
428                                        }
429                                        tlist.add("v" + vi);
430                                }else{
431                                        Integer ci = conIndex.get(t.constant());
432                                        if(ci == null){
433                                                ci = conIndex.size();
434                                                conIndex.put(t.constant(), ci);
435                                                conList.add(t.constant());
436                                                conTypeList.add(lit.getPred().getTypeAt(i));
437                                        }
438                                        tlist.add("c" + ci);
439                                }
440                        }
441                        sb.append(StringMan.commaList(tlist));
442                        sb.append(")");
443                        litlist.add(sb.toString());
444                }
445 
446                StringBuilder sigb = new StringBuilder();
447                sigb.append(this.weight>0 ? "sign='+' " : "sign='-' ");
448                if(!existentialVars.isEmpty()){
449                        ArrayList<String> evlist = new ArrayList<String>();
450                        for(String ev : existentialVars){
451                                evlist.add("v" + varIndex.get(ev));
452                        }
453                        if(Config.clause_display_multiline){
454                                sigb.append("\n  ");
455                        }
456                        sigb.append("EXIST " + StringMan.join(",", evlist) + " ");
457                }
458                if(Config.clause_display_multiline){
459                        sigb.append("\n   ");
460                }
461                sigb.append(StringMan.join((Config.clause_display_multiline ? "\n" : "") + " v ", litlist));
462                
463                HashMap<String, String> mapVarVar = new HashMap<String, String>();
464                for(String v : varIndex.keySet()){
465                        mapVarVar.put(v, "v" + varIndex.get(v));
466                }
467                for(Expression e : constraints){
468                //        if(e.changeName == true){
469                        String es = e.renameVariables(mapVarVar);
470                        if(es != null){
471                                ExceptionMan.die("Encountered a dangling variable '" + es +
472                                                "' in clause\n" + this.getSpecTextFlat());
473                        }
474                //        }
475                }
476                sigb.append("\n");
477                sigb.append(getConstaintStringAsLits());
478                String sig = sigb.toString();
479 
480                // generate normalized clause
481                Clause c = new Clause();
482                c.signature = sig;
483                c.uNames = uNames;
484                c.specText = specText;
485                c.constraints = constraints;
486                this.signature = sig;
487                for(Literal lit : this.lits){
488                        Literal nlit = new Literal(lit.getPred(), lit.getSense());
489                        for(Term term : lit.getTerms()){
490                                Term nterm;
491                                if(term.isVariable()){
492                                        nterm = new Term("v" + varIndex.get(term.var()));
493                                }else{
494                                        nterm = new Term("c" + conIndex.get(term.constant()));
495                                        nterm.isOriAConstant = true;
496                                        nterm.oriConstantID = term.constant();
497                                }
498                                nlit.appendTerm(nterm);
499                        }
500                        c.addLiteral(nlit);
501                }
502                for(String ev : this.existentialVars){
503                        c.addExistentialVariable("v" + varIndex.get(ev));
504                }
505                if(conTypeList.isEmpty()){
506                        c.isTemplate = false;
507                        c.weight = this.weight;
508                }else{
509                        c.isTemplate = true;
510                        c.weight = (this.weight > 0 ? 1 : -1);
511                        for(int i=0; i<conTypeList.size(); i++){
512                                c.addMetaVariable("c"+i, conTypeList.get(i));
513                        }
514                        c.instances.add(new ClauseInstance(conList, this.weight));
515                }
516                return c;
517        }
518 
519        /**
520         * "Absorb" another clause of the same pattern into this clause.
521         * If this clause is a template, then adding instances into
522         * the instance list. Otherwise, add its weight to current clause.
523         * 
524         * @param c the clause to be absorbed
525         * @see Clause#normalize()
526         */
527        public void absorb(Clause c) {
528                if(!this.signature.equals(c.signature)){
529                        ExceptionMan.die("clauses of different patterns cannot be consolidated!");
530                }
531                if(isTemplate){
532                        this.instances.addAll(c.instances);
533                }else{
534                        this.weight += c.weight;
535                        this.specText.addAll(c.specText);
536                }
537                this.uNames.addAll(c.uNames);
538        }
539 
540        /**
541         * Flush the instance of this clause into database.
542         * Here "instance" means all the constant ID in instance with
543         * its weight as a row in DB.
544         * @param db the database object used to store clause instances.
545         */
546        private void sealClauseInstances(RDB db) {
547                if(!isTemplate){
548                        Clause.mappingFromID2Desc.put(this.id+ ".0", this.toString(-1));
549                        return;
550                }
551                // cosntruct SQL of adding instances
552                ArrayList<String> atts = new ArrayList<String>();
553                ArrayList<String> pholders = new ArrayList<String>();
554                atts.add("weight FLOAT8");
555                pholders.add("?");
556                for(String v : metaVars) {
557                        atts.add(v + " INT");
558                        pholders.add("?");
559                }
560                
561                
562                db.dropTable(relIntanceClauses);
563                String sql = "CREATE TABLE " + relIntanceClauses +
564                StringMan.commaListParen(atts);
565                db.update(sql);
566                
567                //TODO:
568                db.dropSequence(relIntanceClauses+"_seq");
569                sql = "CREATE SEQUENCE " + relIntanceClauses + "_seq;";
570                db.update(sql);
571                sql = "ALTER TABLE " + relIntanceClauses + " ADD myid INT;";
572                db.update(sql);
573                sql = "ALTER TABLE " + relIntanceClauses + " ALTER COLUMN myid SET " +
574                                "DEFAULT NEXTVAL('" + relIntanceClauses + "_seq');";
575                db.update(sql);
576                
577                int instanceCount = 0;
578                
579                sql = "INSERT INTO " + relIntanceClauses + " VALUES" + 
580                StringMan.commaListParen(pholders);
581                PreparedStatement psAddMeta = db.getPrepareStatement(sql);
582                
583                int ni = 0;
584                try {
585                        for(ClauseInstance ins : instances){
586                                double weight = ins.weight;
587                                ArrayList<Integer> meta = ins.conList;
588                                psAddMeta.setDouble(1, weight);
589                                for(int k=0; k<meta.size(); k++) {
590                                        psAddMeta.setInt(k+2, meta.get(k));
591                                }
592                                instanceCount ++;
593                                Clause.mappingFromID2Desc.put(this.id+ "." + instanceCount, this.toString(ni++));
594                                psAddMeta.addBatch();
595                        }
596                        psAddMeta.executeBatch();
597                        psAddMeta.close();
598                } catch (SQLException e) {
599                        ExceptionMan.handle(e);
600                }
601                psAddMeta = null;
602        }
603        
604        /**
605         * Add a meta variable into this clause.
606         * @param v name this this meta variable
607         * @param t type of this meta variable
608         * @see Clause#normalize()
609         * @return whether this inserting succeeded.
610         */
611        private boolean addMetaVariable(String v, Type t) {
612                if(metaVars.contains(v)) return false;
613                metaVars.add(v);
614                metaTypes.add(t);
615                return true;
616        }
617        
618        /**
619         * Existentially quantify a variable.
620         * 
621         * @param v the variable to be existentially quantified
622         */
623        public boolean addExistentialVariable(String v) {
624                if(existentialVars.contains(v)) return false;
625                existentialVars.add(v);
626                return true;
627        }
628        
629        /**
630         * Construct an empty clause. Initial weight = 0.
631         * 
632         */
633        public Clause(){
634                weight = 0;
635        }
636        
637        /**
638         * Specify this clause as a hard rule.
639         * Currently hard rules are treated as soft rules with
640         * a very large weight.
641         * 
642         * @see Config#hard_weight
643         */
644        public void setHardWeight() {
645                weight = Config.hard_weight;
646        }
647        
648        /**
649         * Return whether this clause is a hard rule.
650         */
651        public boolean isHardClause(){
652                return weight >= Config.hard_weight;
653        }
654        
655        /**
656         * Set the weight of this clause.
657         */
658        public void setWeight(double wt) {
659                weight = wt;
660        }
661        
662        /**
663         * Return the expression of clause weights to be used in SQL.
664         * For template clauses, it's the name of a table attribute;
665         * for non-template clauses, it's a floating number.
666         */
667        public String getWeightExp() {
668                return exprWeight;
669        }
670        
671        /**
672         * Check if the weight is positive.
673         */
674        public boolean isPositiveClause(){
675                return weight > 0;
676        }
677        
678        /**
679         * Initialize database objects for this clause.
680         */
681        public void prepareForDB(RDB db) {
682                sealClauseInstances(db);
683                generateSQL();
684        }
685        
686        /**
687         * Check for unsafe variables in the clause, and mark the corresponding
688         * Predicates.
689         * A variable is unsafe if it appears only in a positive literal;
690         * i.e., if it does not appear in the body in the Datalog form.
691         */
692        public void checkVariableSafety(){
693                HashSet<String> vars = new HashSet<String>();
694                HashSet<String> safeVars = new HashSet<String>();
695                ArrayList<Literal> posLits = new ArrayList<Literal>();
696                for(Literal lit : reglits){
697                        vars.addAll(lit.getVars());
698                        if(!lit.getSense()){
699                                safeVars.addAll(lit.getVars());
700                        }else{
701                                posLits.add(lit);
702                        }
703                }
704                for(Literal lit : posLits){
705                        for(Term t : lit.getTerms()){
706                                if(t.isVariable()){
707                                        if(!safeVars.contains(t.var())){
708                                                lit.getPred().setSafeRefOnly(false);
709                                                // TODO: note that order of positive lits is important
710                                                safeVars.add(t.var());
711                                        }
712                                }
713                        }
714                }
715        }
716        
717        private String exprWeight = null;
718        
719        /**
720         * Generate the SQL command for grounding this clause.
721         * For each meta-variable, bind them to the clause instance (in FROM and WHERE clause)
722         * For each regular-predicate's variable that is not meta-variable, use
723         * their grounded atom table to bind the clause (in FROM CLAUSE), 
724         * with inter-predicate constraints
725         * introduced in the clause (in WHERE CLAUSE / JOIN CONDITION IN FROM CLAUSE).
726         * For each built-in predicate, write its semantic into SQL conditions
727         * directly.
728         * 
729         * The sqlPivotAttrsList contains a list of variables that are not
730         * existential variables in the form of $table_name.$column_name. Here
731         * $table_name is consistent to other SQL sub-clauses generated by this
732         * function.
733         */
734        public void generateSQL() {
735                
736                HashMap<String, String> mapVarAttr = new HashMap<String, String>();
737                ArrayList<String> groundAttrs = new ArrayList<String>();
738                ArrayList<String> whereList = new ArrayList<String>();
739                whereList.add("1=1");
740                
741                StringBuilder from = new StringBuilder();
742                int nJoinedTables = 0;
743                if(isTemplate) {
744                        from.append(relIntanceClauses + " metaTable ");
745                        nJoinedTables ++;
746                        groundAttrs.add("metaTable.weight");
747                        for(String var : metaVars) {
748                                mapVarAttr.put(var, "metaTable." + var);
749                        }
750                        exprWeight = "metaTable.weight";
751                }else if(!hasEmbeddedWeight()){
752                        exprWeight = "CAST("+Double.toString(weight)+" AS FLOAT8)";
753                }
754 
755                // reorder the literals to put antecendents first
756                ArrayList<Literal> ordlits = new ArrayList<Literal>();
757                ArrayList<Literal> poslits = new ArrayList<Literal>();
758                for(Literal lit : reglits){
759                        if(lit.getSense()) poslits.add(lit);
760                        else ordlits.add(lit);
761                }
762                ordlits.addAll(poslits);
763                
764                // build variable bindings; distinguish pos lits that rely on partial materialization
765 
766                HashMap<String, Type> var2type = new HashMap<String, Type>();
767                
768                ArrayList<String> attachConds = new ArrayList<String>();
769                for(Literal lit : ordlits){
770                        int idx = lit.getIdx();
771                        String relP = lit.getPred().getRelName();
772 
773                        ArrayList<Term> terms = lit.getTerms();
774                        boolean hasNewVars = false;
775                        for(int j=0; j<terms.size(); j++) {
776                                Term t = terms.get(j);
777                                String var = t.var();
778                                
779                                var2type.put(var, lit.getPred().getTypeAt(j));
780                                
781                                String attr = "t" + idx + "."+lit.getPred().getArgs().get(j);
782                                if(t.isConstant()) {
783                                        attachConds.add(attr + "=" + t.constant());
784                                }else {
785                                        String cattr = mapVarAttr.get(var);
786                                        if(cattr == null) {
787                                                hasNewVars = true;
788                                                mapVarAttr.put(var, attr);
789                                                if(!existentialVars.contains(var)) {
790                                                        groundAttrs.add(attr);
791                                                }
792                                                if(var.equals(varWeight)){
793                                                        exprWeight = attr;
794                                                }
795                                        }else {
796                                                attachConds.add(attr + "=" + cattr);
797                                        }
798                                }
799                        }
800                        if(nJoinedTables >= 1){
801                                // if hasNewVars, the pred should've been fully materialized
802                                from.append(lit.getSense() && !hasNewVars ? 
803                                                " LEFT OUTER JOIN " : " JOIN ");
804                                from.append(relP + " t" +idx + " ON ");
805                                if(attachConds.isEmpty()){
806                                        from.append("1=1");
807                                }else{
808                                        String ac = SQLMan.andSelCond(attachConds);
809                                        from.append(ac);
810                                        attachConds.clear();
811                                }
812                        }else{
813                                from.append(relP + " t" +idx);
814                        }
815                        nJoinedTables++;
816                }
817 
818                if(hasEmbeddedWeight() && exprWeight == null){
819                        UIMan.warn("The following clause is specified to have embedded weights, but the variable '" + 
820                                        varWeight + "' doesn't appear in the formula:" + this.toString());
821                }
822                
823                // this could happen only for unit clauses
824                if(!attachConds.isEmpty()){
825                        whereList.addAll(attachConds);
826                        attachConds.clear();
827                }
828                
829                
830                // express constraints in SQL
831                HashSet<String> cvars = new HashSet<String>();
832                int nChangeName = 0;
833                for(Expression e : constraints){
834                        if(e.changeName == true){
835                                nChangeName ++;
836                        }
837                        cvars.addAll(e.getVars());
838                }
839                HashMap<String, String> mapVarVal = new HashMap<String, String>();
840                HashMap<String, String> mapVarValNotChangeName = new HashMap<String, String>();
841                int idx = 0;
842                for(String v : cvars){
843                        ++ idx;
844                        String attr = mapVarAttr.get(v);
845                        if(attr == null){
846                                ExceptionMan.die("unsafe constraints in clause\n" + getSpecTextFlat());
847                        }
848                        
849                        if(nChangeName > 0){
850                                if(!var2type.get(v).isNonSymbolicType()){
851                                
852                                        from.append(" JOIN " + var2type.get(v).getRelName() + 
853                                                " s" + idx + " ON s" + idx + ".constantid = " + attr);
854                                        //from.append(" JOIN " + Config.relConstants + 
855                                        //                " s" + idx + " ON s" + idx + ".id = " + attr);
856                                        nJoinedTables++;
857                                }
858                        }
859                        if(!var2type.get(v).isNonSymbolicType()){
860                                mapVarVal.put(v, "s" + idx + ".constantvalue");
861                        }else{
862                                mapVarVal.put(v, attr);
863                        }
864                        mapVarValNotChangeName.put(v, attr);
865                }
866                for(Expression e : constraints){
867                        
868                        if(e.changeName == true){
869                                e.bindVariables(mapVarVal);
870                                whereList.add(e.toSQL());
871                        }else{
872                                Expression tmpE = e.clone();
873                                tmpE.renameVariables(mapVarValNotChangeName);
874                                whereList.add(tmpE.toString());
875                        }
876                }
877                
878                sqlFromList = from.toString();
879                sqlWhereBindings = SQLMan.andSelCond(whereList);
880                sqlPivotAttrsList = StringMan.commaList(groundAttrs);
881                /*
882                boolean print = false;
883                if(print){
884                        System.out.println("=====\n" + this.getSpecText());
885                        System.out.println(sqlFromList);
886                        System.out.println(sqlWhereBindings);
887                }
888                */
889        }
890 
891        /**
892         * Return the definition of this clause.
893         */
894        public String toString() {
895                String s = (name == null ? "" : name);
896                if(Config.clause_display_multiline){
897                        s += "\n";
898                }
899                if(!uNames.isEmpty()){
900                        s += "// " + StringMan.commaList(uNames) + "\n";
901                }
902                String w = (weight >= Config.hard_weight ? "infty" : "" + weight);
903                s += (isTemplate ? "[#instances="+instances.size()+"]" : "[weight="+w+"]");
904                return s + " " + (signature == null? getSpecTextFlat() : signature);
905        }
906        
907        /**
908         * Return the definition of clause instance.
909         * @param ni The ID of instance.
910         */
911        public String toString(int ni) {
912                String s = ""; //= (name == null ? "" : name);
913                
914                String tmps = (signature == null? getSpecTextFlat() : signature);
915                if(ni >= 0 && !mappingFromID2Const.isEmpty()){
916                        for(int i=0;i<this.instances.get(ni).conList.size();i++){
917                                tmps = tmps.replaceAll("c"+(i), 
918                                                mappingFromID2Const.get(instances.get(ni).conList.get(i)));
919                        }
920                }
921                
922                tmps = tmps.replaceAll("[\n|\r]", " ");
923                tmps = tmps.replaceAll("sign=\'.\'", "");
924                
925                return s + " " + tmps;
926        }
927        
928        /**
929         * Return the member literals of a particular predicate.
930         */
931        public ArrayList<Literal> getLiteralsOfPredicate(Predicate pred){
932                return predIndex.get(pred);
933        }
934        
935        /**
936         * Return the set of predicates referenced by this clause.
937         */
938        public Set<Predicate> getReferencedPredicates(){
939                return predIndex.keySet();
940        }
941        
942        /**
943         * Return the list of non-built-in literals (i.e., regular literals).
944         */
945        public ArrayList<Literal> getRegLiterals(){
946                return reglits;
947        }
948        
949        /**
950         * Check if any variable in this clause is existentially quantified.
951         */
952        public boolean hasExistentialQuantifiers(){
953                return !existentialVars.isEmpty();
954        }
955        
956        /**
957         * Add a literal to this clause.
958         */
959        public void addLiteral(Literal lit){
960                if(lit == null) return;
961                // update the predicate-literal index
962                ArrayList<Literal> plits = predIndex.get(lit.getPred());
963                if(plits == null) {
964                        plits = new ArrayList<Literal>();
965                        predIndex.put(lit.getPred(), plits);
966                }else{
967                        for(Literal elit : plits){
968                                // duplicate lit, ignore
969                                if(elit.isSameAs(lit)) return;
970                        }
971                }
972                if(lit.isBuiltIn()){
973                        bilits.add(lit);
974                        lit.setIdx(1000000 + bilits.size());
975                }else{
976                        reglits.add(lit);
977                        lit.setIdx(reglits.size());
978                }
979                lits.add(lit);
980                plits.add(lit);
981                
982        }
983 
984        /**
985         * Set clause ID.
986         * @param id
987         */
988        public void setId(int id) {
989                this.id = id;
990        }
991 
992        /**
993         * Get clause ID.
994         */
995        public int getId() {
996                return id;
997        }
998        
999        public void addSpecText(String s){
1000                specText.add(s);
1001        }
1002 
1003        public ArrayList<String> getSpecText() {
1004                return specText;
1005        }
1006 
1007}

[all classes][tuffy.mln]
EMMA 2.0.5312 EclEmma Fix 2 (C) Vladimir Roubtsov