1 | package felix.util; |
2 | |
3 | import java.io.BufferedWriter; |
4 | import java.io.FileInputStream; |
5 | import java.io.FileWriter; |
6 | import java.math.BigInteger; |
7 | import java.security.MessageDigest; |
8 | import java.security.NoSuchAlgorithmException; |
9 | import java.sql.DatabaseMetaData; |
10 | import java.sql.PreparedStatement; |
11 | import java.sql.ResultSet; |
12 | import java.sql.ResultSetMetaData; |
13 | import java.util.ArrayList; |
14 | import java.util.Arrays; |
15 | import java.util.HashMap; |
16 | import java.util.HashSet; |
17 | |
18 | import org.postgresql.PGConnection; |
19 | |
20 | import tuffy.db.RDB; |
21 | import tuffy.mln.Literal; |
22 | import tuffy.mln.Predicate; |
23 | import tuffy.mln.Term; |
24 | import tuffy.mln.Type; |
25 | import tuffy.ra.ConjunctiveQuery; |
26 | import tuffy.ra.Expression; |
27 | import tuffy.util.ExceptionMan; |
28 | import tuffy.util.StringMan; |
29 | import tuffy.util.UIMan; |
30 | import felix.dstruct.FelixClause; |
31 | import felix.dstruct.FelixPredicate; |
32 | import felix.dstruct.FelixQuery; |
33 | import felix.main.Felix; |
34 | import felix.parser.FelixCommandOptions; |
35 | |
36 | |
37 | public class CostCalculator { |
38 | |
39 | |
40 | |
41 | FelixCommandOptions opt; |
42 | |
43 | RDB db; |
44 | |
45 | /** |
46 | * Returns string containing given number of ones. |
47 | * @param _num |
48 | * @return |
49 | */ |
50 | public String ones(int _num){ |
51 | String rs = ""; |
52 | for(int i=0;i<_num;i++){ |
53 | rs = rs + "1"; |
54 | } |
55 | return rs; |
56 | } |
57 | |
58 | /** |
59 | * Returns string containing given number of zeros. |
60 | * @param _num |
61 | * @return |
62 | */ |
63 | public String zeros(int _num){ |
64 | String rs = ""; |
65 | for(int i=0;i<_num;i++){ |
66 | rs = rs + "0"; |
67 | } |
68 | return rs; |
69 | } |
70 | |
71 | /** |
72 | * Calculates cost. |
73 | * @throws Exception |
74 | */ |
75 | public void calc() throws Exception{ |
76 | |
77 | Felix fx = new Felix(); |
78 | fx.options = opt; |
79 | FelixQuery fq = fx.parseFelixQuery(); |
80 | fx.fq = fq; |
81 | fx.loadEvidence(); |
82 | |
83 | for(FelixPredicate p : fq.getPredicates()){ |
84 | if(p.getName().endsWith("_map")){ |
85 | //TODO: IF THERE IS P_MAP, ASSUME THERE ARE NO EVIDENCE FOR P |
86 | String newName = p.getName().replaceAll("_map$", ""); |
87 | String sql = "DROP TABLE pred_" + newName; |
88 | |
89 | String typeName = p.getTypeAt(0).name(); |
90 | |
91 | String newViewName = "pred_" + newName; |
92 | |
93 | Felix.db.execute(sql); |
94 | |
95 | sql = "CREATE VIEW " + newViewName + " AS SELECT 1 as id, TRUE as truth, 0 as prior, 2 as club, 0 as atomid, " |
96 | + " t0." + typeName + "1 AS " + typeName + "1, t1." + typeName + "1 AS " + typeName + "2 FROM " + |
97 | p.getRelName() + " t0, " + p.getRelName() + " t1 WHERE " + "t0." + typeName + "2 = t1." + typeName + "2"; |
98 | Felix.db.execute(sql); |
99 | } |
100 | } |
101 | |
102 | |
103 | int ct = 0; |
104 | int nHardBreak = 0; |
105 | double totalCost = 0; |
106 | for(FelixClause fc : fq.getAllClause()){ |
107 | |
108 | //TODO: HARD CLAUSE |
109 | if(fc.isHardClause()){ |
110 | continue; |
111 | } |
112 | |
113 | |
114 | |
115 | HashSet<String> headTerms = new HashSet<String>(); |
116 | ConjunctiveQuery cq = new ConjunctiveQuery(); |
117 | HashMap<String, Type> var2type = new HashMap<String, Type>(); |
118 | |
119 | for(Literal l : fc.getRegLiterals()){ |
120 | Literal l2 = (Literal) l.clone(); |
121 | l2.flipSense(); |
122 | cq.addBodyLit(l2); |
123 | |
124 | for(int i=0;i<l.getTerms().size();i++){ |
125 | Term t = l.getTerms().get(i); |
126 | if(t.isVariable()){ |
127 | headTerms.add(t.var()); |
128 | var2type.put(t.var(), l.getPred().getTypeAt(i)); |
129 | } |
130 | } |
131 | } |
132 | |
133 | for(Expression e : fc.getConstraints()){ |
134 | cq.addConstraint(Expression.not(e)); |
135 | } |
136 | |
137 | FelixPredicate hp = new FelixPredicate("tmp_" + (ct++), true); |
138 | for(String t : headTerms){ |
139 | hp.appendArgument(var2type.get(t)); |
140 | } |
141 | hp.prepareDB(Felix.db); |
142 | |
143 | Literal l = new Literal(hp, true); |
144 | for(String t : headTerms){ |
145 | l.appendTerm(new Term(t)); |
146 | } |
147 | |
148 | cq.setHead(l); |
149 | cq.sourceClause = fc; |
150 | cq.setWeight(fc.getWeight()); |
151 | |
152 | System.err.println(fc); |
153 | |
154 | cq.buildIndexes(Felix.db, true, null, null, false, new ArrayList<String>(Arrays.asList("weight")), false); |
155 | PreparedStatement ps = cq.psMap.get(this.zeros(l.getTerms().size())); |
156 | |
157 | System.out.println(ps); |
158 | |
159 | String sql = "CREATE TABLE " + "_for_cost_" + hp.getName() + " AS " + ps.toString(); |
160 | Felix.db.execute(sql); |
161 | |
162 | sql = "SELECT sum(weight) FROM " + "_for_cost_" + hp.getName(); |
163 | ResultSet rs = Felix.db.query(sql); |
164 | |
165 | double cost = 0; |
166 | while(rs.next()){ |
167 | cost = rs.getDouble(1); |
168 | break; |
169 | } |
170 | |
171 | System.out.println(); |
172 | |
173 | System.out.println("COST: [" + cost + "] for rule " + fc); |
174 | |
175 | totalCost += cost; |
176 | |
177 | } |
178 | |
179 | System.out.println("Total Cost = " + totalCost); |
180 | |
181 | |
182 | } |
183 | |
184 | /** |
185 | * The constructor. |
186 | * @param _opt |
187 | */ |
188 | public CostCalculator(FelixCommandOptions _opt){ |
189 | opt = _opt; |
190 | } |
191 | |
192 | } |