1 | package tuffy.ground.partition; |
2 | |
3 | |
4 | import java.sql.ResultSet; |
5 | import java.sql.SQLException; |
6 | import java.util.HashMap; |
7 | import java.util.HashSet; |
8 | import java.util.Set; |
9 | |
10 | import tuffy.db.RDB; |
11 | import tuffy.infer.MRF; |
12 | import tuffy.infer.ds.GAtom; |
13 | import tuffy.infer.ds.GClause; |
14 | import tuffy.mln.MarkovLogicNetwork; |
15 | import tuffy.util.ExceptionMan; |
16 | import tuffy.util.UIMan; |
17 | /** |
18 | * A partition bucket is either |
19 | * 1) one or multiple components in whole; |
20 | * or |
21 | * 2) one or multiple partitions of one component. |
22 | * Partitions are grouped into buckets and solved bucket by bucket. |
23 | */ |
24 | public class Bucket { |
25 | private static int guid = 0; |
26 | |
27 | private RDB db; |
28 | private PartitionScheme pmap; |
29 | private int id; |
30 | |
31 | private HashSet<Component> comps = new HashSet<Component>(); |
32 | private HashSet<Partition> parts = new HashSet<Partition>(); |
33 | |
34 | public Set<Component> getComponents(){ |
35 | return (comps); |
36 | } |
37 | |
38 | public Set<Partition> getPartitions(){ |
39 | return (parts); |
40 | } |
41 | |
42 | /** |
43 | * Estimated size in bytes. |
44 | */ |
45 | private long size = 0; |
46 | |
47 | /** |
48 | * Discard all data structues to facilitate GC. |
49 | */ |
50 | public void discard(){ |
51 | for(Component c : comps){ |
52 | c.discard(); |
53 | } |
54 | } |
55 | |
56 | public String toString(){ |
57 | return "Bucket #" + id + " (" + UIMan.comma(comps.size()) + (comps.size()>1? " components)":" component)"); |
58 | } |
59 | |
60 | public long size(){ |
61 | return size; |
62 | } |
63 | |
64 | /** |
65 | * Construct an initially empty memory zone. |
66 | * |
67 | * |
68 | * @see Bucket#addComponent(Component) |
69 | * @see Bucket#addPart(Partition) |
70 | */ |
71 | public Bucket(RDB db, PartitionScheme pmap){ |
72 | id = (++guid); |
73 | this.db = db; |
74 | this.pmap = pmap; |
75 | } |
76 | |
77 | /** |
78 | * Add a component to this bucket. |
79 | * |
80 | */ |
81 | public void addComponent(Component c){ |
82 | comps.add(c); |
83 | parts.addAll(c.parts); |
84 | size += c.size(); |
85 | } |
86 | |
87 | /** |
88 | * Add a partition to this bucket. |
89 | * |
90 | */ |
91 | public void addPart(Partition p){ |
92 | comps.add(p.parentComponent); |
93 | parts.add(p); |
94 | size += p.size(); |
95 | } |
96 | |
97 | |
98 | /** |
99 | * Load the set of partitions from DB to RAM. |
100 | */ |
101 | public void load(MarkovLogicNetwork mln){ |
102 | // partitions (whose clauses) to be loaded |
103 | HashSet<Integer> clausePids = new HashSet<Integer>(); |
104 | // partitions whose atoms to be loaded |
105 | HashSet<Integer> atomPids = new HashSet<Integer>(); |
106 | |
107 | |
108 | for(Component com : comps){ |
109 | com.atoms = new HashMap<Integer, GAtom>(); |
110 | for(Partition p : com.parts){ |
111 | if(parts.contains(p)){ |
112 | p.mrf = new MRF(mln, p.id, com.atoms); |
113 | clausePids.add(p.id); |
114 | } |
115 | atomPids.add(p.id); |
116 | } |
117 | } |
118 | |
119 | String sql; |
120 | try { |
121 | // store pids to be loaded |
122 | String relClausePIDs = "mzone_clausepids"; |
123 | db.createTempTableIntList(relClausePIDs, clausePids); |
124 | |
125 | String relAtomPIDs = "mzone_atompids"; |
126 | db.createTempTableIntList(relAtomPIDs, atomPids); |
127 | |
128 | // load atoms |
129 | sql = "SELECT ra.atomid, rap.partid, ra.truth FROM " + |
130 | mln.relAtoms + " ra, " + mln.relAtomPart + " rap " + |
131 | " WHERE ra.atomID = rap.atomID AND rap.partID IN (SELECT id FROM " + relAtomPIDs + ")"; |
132 | ResultSet rs = db.query(sql); |
133 | while(rs.next()){ |
134 | int pid = rs.getInt("partid"); |
135 | int aid = rs.getInt("atomid"); |
136 | boolean truth = rs.getBoolean("truth"); |
137 | if(clausePids.contains(pid)){ |
138 | pmap.getMRFByPartID(pid).addAtom(aid); |
139 | } |
140 | GAtom a = new GAtom(aid); |
141 | a.truth = a.lowTruth = a.lowlowTruth = truth; |
142 | a.pid = pid; |
143 | pmap.getCompByPartID(pid).addAtom(a); |
144 | /* |
145 | if(rs.getInt("keyID") != -1){ |
146 | pmap.getPartitionByID(pid).mrf.keyBlock.pushGAtom(rs.getInt("keyID"), a); |
147 | } |
148 | */ |
149 | } |
150 | rs.close(); |
151 | |
152 | // load clauses |
153 | db.disableAutoCommitForNow(); |
154 | sql = "SELECT rc.cid, rc.lits, rc.weight, rc.fcid, rc.ffcid, cp.partID FROM " + |
155 | mln.relClauses + " rc, " + |
156 | mln.relClausePart + " cp " + " WHERE cp.cid=rc.cid AND " + |
157 | " partID IN (SELECT id FROM " + relClausePIDs + ")"; |
158 | rs = db.query(sql); |
159 | while(rs.next()){ |
160 | int owner = rs.getInt("partID"); |
161 | Partition ppart = pmap.getPartitionByID(owner); |
162 | GClause c = new GClause(); |
163 | c.parse(rs); |
164 | ppart.mrf.clauses.add(c); |
165 | } |
166 | rs.close(); |
167 | db.restoreAutoCommitState(); |
168 | |
169 | db.dropTable(relClausePIDs); |
170 | db.dropTable(relAtomPIDs); |
171 | |
172 | for(Component com : comps){ |
173 | for(Partition p : com.parts){ |
174 | MRF mrf = p.mrf; |
175 | if(mrf == null) continue; |
176 | if(mrf.getCoreAtoms().size() == mrf.atoms.size()){ |
177 | mrf.ownsAllAtoms = true; |
178 | } |
179 | } |
180 | } |
181 | } catch (SQLException e) { |
182 | ExceptionMan.handle(e); |
183 | } |
184 | } |
185 | |
186 | |
187 | |
188 | } |