1 package org.thegalactic.lattice;
2
3 /*
4 * ArrowRelation.java
5 *
6 * Copyright: 2010-2015 Karell Bertet, France
7 * Copyright: 2015-2016 The Galactic Organization, France
8 *
9 * License: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html CeCILL-B license
10 *
11 * This file is part of java-lattices.
12 * You can redistribute it and/or modify
13 * it under the terms of the CeCILL-B license.
14 */
15 import java.io.IOException;
16 import java.util.TreeSet;
17
18 import org.thegalactic.context.Context;
19 import org.thegalactic.dgraph.ConcreteDGraph;
20 import org.thegalactic.dgraph.Edge;
21 import org.thegalactic.dgraph.Node;
22 import org.thegalactic.io.Filer;
23 import org.thegalactic.lattice.io.ArrowRelationIOFactory;
24
25 /**
26 * The ArrowRelation class encodes arrow relation between meet &
27 * join-irreductibles of a lattice.
28 *
29 * Let m and b be respectively meet and join irreductibles of a lattice.
30 * Recall that m has a unique successor say m+ and j has a unique predecessor
31 * say j-, then :
32 *
33 * - j "Up Arrow" m (stored as "Up") iff j is not less or equal than m and
34 * j is less than m+
35 * - j "Down Arrow" m (stored as "Down") iff j is not less or equal than m and
36 * j- is less than m
37 * - j "Up Down Arrow" m (stored as "UpDown") iff j "Up" m and j "Down" m
38 * - j "Cross" m (stored as "Cross") iff j is less or equal than m
39 * - j "Circ" m (stored as "Circ") iff neither j "Up" m nor j "Down" m nor
40 * j "Cross" m
41 *
42 * 
43 *
44 * @uml ArrowRelation.png
45 * !include resources/org/thegalactic/dgraph/DGraph.iuml
46 * !include resources/org/thegalactic/dgraph/Edge.iuml
47 * !include resources/org/thegalactic/dgraph/Node.iuml
48 * !include resources/org/thegalactic/lattice/ArrowRelation.iuml
49 *
50 * hide members
51 * show ArrowRelation members
52 * class ArrowRelation #LightCyan
53 * title ArrowRelation UML graph
54 */
55 public class ArrowRelation extends ConcreteDGraph {
56
57 /**
58 * Field used to encode up arrow relation.
59 */
60 private static Object up = "Up";
61
62 /**
63 * Field used to encode down arrow relation.
64 */
65 private static Object down = "Down";
66
67 /**
68 * Field used to encode up-down arrow relation.
69 */
70 private static Object updown = "UpDown";
71
72 /**
73 * Field used to encode cross arrow relation.
74 */
75 private static Object cross = "Cross";
76
77 /**
78 * Field used to encode circ arrow relation.
79 */
80 private static Object circ = "Circ";
81
82 /**
83 * Unique constructor of this component from a lattice.
84 *
85 * Nodes are join or meet irreductibles of the lattice. Edges content
86 * encodes arrows as String "Up", "Down", "UpDown", "Cross", "Circ".
87 *
88 * @param lattice Lattice from which this component is deduced.
89 */
90 public ArrowRelation(Lattice lattice) {
91
92 /*
93 * Nodes are join or meet irreductibles of the lattice.
94 */
95 TreeSet<Node> joins = new TreeSet<Node>(lattice.joinIrreducibles());
96 for (Node node : joins) {
97 this.addNode(node);
98 }
99 TreeSet<Node> meets = new TreeSet<Node>(lattice.meetIrreducibles());
100 for (Node node : meets) {
101 this.addNode(node);
102 }
103 Lattice transitiveClosure = new Lattice(lattice);
104 transitiveClosure.transitiveClosure();
105 Lattice transitiveReduction = new Lattice(lattice);
106 transitiveReduction.transitiveReduction();
107 Node jminus = new Node();
108 Node mplus = new Node();
109 Object arrow = new Object();
110
111 /*
112 * Content of edges are arrows
113 */
114 for (Node j : joins) {
115 for (Node m : meets) {
116 mplus = (Node) transitiveReduction.getSuccessorNodes(m).first();
117 jminus = (Node) transitiveReduction.getPredecessorNodes(j).first();
118 if (transitiveClosure.getSuccessorNodes(j).contains(m) || j.equals(m)) {
119 arrow = ArrowRelation.cross;
120 } else if (transitiveClosure.getSuccessorNodes(jminus).contains(m) || jminus.equals(m)) {
121 arrow = ArrowRelation.down;
122 if (transitiveClosure.getPredecessorNodes(mplus).contains(j) || mplus.equals(j)) {
123 arrow = ArrowRelation.updown;
124 }
125 } else if (transitiveClosure.getPredecessorNodes(mplus).contains(j)) {
126 arrow = ArrowRelation.up;
127 } else {
128 arrow = ArrowRelation.circ;
129 }
130 this.addEdge(j, m, arrow);
131 }
132 }
133 }
134
135 /**
136 * Save the description of this component in a file whose name is specified.
137 *
138 * @param filename the name of the file
139 *
140 * @throws IOException When an IOException occurs
141 */
142 @Override
143 public void save(final String filename) throws IOException {
144 Filer.getInstance().save(this, ArrowRelationIOFactory.getInstance(), filename);
145 }
146
147 /**
148 * Returns the table of the lattice, composed of the join and meet
149 * irreducibles nodes.
150 *
151 * Each attribute of the table is a copy of a join irreducibles node. Each
152 * observation of the table is a copy of a meet irreducibles node. An
153 * attribute is extent of an observation when its join irreducible node is
154 * in double arrow relation with the meet irreducible node in the lattice.
155 *
156 * @return the table of the lattice
157 *
158 * @todo Avoid using for (Object edge : this.getEdges()). Use for (Edge edge : this.getEdges())
159 */
160 public Context getDoubleArrowTable() {
161 Context context = new Context();
162 // observations are join irreductibles
163 // attributes are meet irreductibles
164 for (Object edge : this.getEdges()) {
165 context.addToObservations(((Edge) edge).getSource());
166 context.addToAttributes(((Edge) edge).getTarget());
167 }
168 // generation of extent-intent
169 for (Object edge : this.getEdges()) {
170 if (((Edge) edge).getContent() == ArrowRelation.updown) {
171 context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
172 }
173 }
174 return context;
175 }
176
177 /**
178 * Returns the table of the lattice, composed of the join and meet
179 * irreducibles nodes.
180 *
181 * Each attribute of the table is a copy of a join irreducibles node. Each
182 * observation of the table is a copy of a meet irreducibles node. An
183 * attribute is extent of an observation when its join irreducible node is
184 * in down arrow relation with the meet irreducible node in the lattice.
185 *
186 * @return the table of the lattice
187 */
188 public Context getDoubleDownArrowTable() {
189 Context context = new Context();
190 // observations are join irreductibles
191 // attributes are meet irreductibles
192 for (Object edge : this.getEdges()) {
193 context.addToObservations(((Edge) edge).getSource());
194 context.addToAttributes(((Edge) edge).getTarget());
195 }
196 // generation of extent-intent
197 for (Object edge : this.getEdges()) {
198 if (((Edge) edge).getContent() == ArrowRelation.down || ((Edge) edge).getContent() == ArrowRelation.updown) {
199 context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
200 }
201 }
202 return context;
203 }
204
205 /**
206 * Returns the table of the lattice, composed of the join and meet
207 * irreducibles nodes.
208 *
209 * Each attribute of the table is a copy of a join irreducibles node. Each
210 * observation of the table is a copy of a meet irreducibles node. An
211 * attribute is extent of an observation when its join irreducible node is
212 * in up arrow relation with the meet irreducible node in the lattice.
213 *
214 * @return the table of the lattice
215 */
216 public Context getDoubleUpArrowTable() {
217 Context context = new Context();
218 // observations are join irreductibles
219 // attributes are meet irreductibles
220 for (Object edge : this.getEdges()) {
221 context.addToObservations(((Edge) edge).getSource());
222 context.addToAttributes(((Edge) edge).getTarget());
223 }
224 // generation of extent-intent
225 for (Object edge : this.getEdges()) {
226 if (((Edge) edge).getContent() == ArrowRelation.up || ((Edge) edge).getContent() == ArrowRelation.updown) {
227 context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
228 }
229 }
230 return context;
231 }
232
233 /**
234 * Returns the table of the lattice, composed of the join and meet
235 * irreducibles nodes.
236 *
237 * Each attribute of the table is a copy of a join irreducibles node. Each
238 * observation of the table is a copy of a meet irreducibles node. An
239 * attribute is extent of an observation when its join irreducible node is
240 * in double arrow relation or circ relation with the meet irreducible node
241 * in the lattice.
242 *
243 * @return the table of the lattice
244 */
245 public Context getDoubleCircArrowTable() {
246 Context context = new Context();
247 // observations are join irreductibles
248 // attributes are meet irreductibles
249 for (Object edge : this.getEdges()) {
250 context.addToObservations(((Edge) edge).getSource());
251 context.addToAttributes(((Edge) edge).getTarget());
252 }
253 // generation of extent-intent
254 for (Object edge : this.getEdges()) {
255 if (((Edge) edge).getContent() == ArrowRelation.updown || ((Edge) edge).getContent() == ArrowRelation.circ) {
256 context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
257 }
258 }
259 return context;
260 }
261
262 /**
263 * Returns true if and only if there is an up arrow between the source and
264 * the target of
265 * edge e.
266 *
267 * @param edge edge to be tested
268 *
269 * @return true if and only if there is an up arrow between the source and
270 * the target of
271 * edge e
272 */
273 public boolean isUp(Edge edge) {
274 return edge.getContent() == ArrowRelation.up;
275 }
276
277 /**
278 * Returns true if and only if there is an down arrow between the source and
279 * the target of
280 * edge e.
281 *
282 * @param edge edge to be tested
283 *
284 * @return true if and only if there is an down arrow between the source and
285 * the target of
286 * edge e
287 */
288 public boolean isDown(Edge edge) {
289 return edge.getContent() == ArrowRelation.down;
290 }
291
292 /**
293 * Returns true if and only if there is an up-down arrow between the source
294 * and the target
295 * of edge e.
296 *
297 * @param edge edge to be tested
298 *
299 * @return true if and only if there is an up-down arrow between the source
300 * and the target
301 * of edge e
302 */
303 public boolean isUpDown(Edge edge) {
304 return edge.getContent() == ArrowRelation.updown;
305 }
306
307 /**
308 * Returns true if and only if there is an cross arrow between the source
309 * and the target
310 * of edge e.
311 *
312 * @param edge edge to be tested
313 *
314 * @return true if and only if there is an cross arrow between the source
315 * and the target
316 * of edge e
317 */
318 public boolean isCross(Edge edge) {
319 return edge.getContent() == ArrowRelation.cross;
320 }
321
322 /**
323 * Returns true if and only if there is an circ arrow between the source and
324 * the target of
325 * edge e.
326 *
327 * @param edge edge to be tested
328 *
329 * @return true if and only if there is an circ arrow between the source and
330 * the target of
331 * edge e
332 */
333 public boolean isCirc(Edge edge) {
334 return edge.getContent() == ArrowRelation.circ;
335 }
336 }