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 * ![ArrowRelation](ArrowRelation.png) 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 }