ArrowRelation.java
package org.thegalactic.lattice;
/*
* ArrowRelation.java
*
* Copyright: 2010-2015 Karell Bertet, France
* Copyright: 2015-2016 The Galactic Organization, France
*
* License: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html CeCILL-B license
*
* This file is part of java-lattices.
* You can redistribute it and/or modify
* it under the terms of the CeCILL-B license.
*/
import java.io.IOException;
import java.util.TreeSet;
import org.thegalactic.context.Context;
import org.thegalactic.dgraph.ConcreteDGraph;
import org.thegalactic.dgraph.Edge;
import org.thegalactic.dgraph.Node;
import org.thegalactic.io.Filer;
import org.thegalactic.lattice.io.ArrowRelationIOFactory;
/**
* The ArrowRelation class encodes arrow relation between meet &
* join-irreductibles of a lattice.
*
* Let m and b be respectively meet and join irreductibles of a lattice.
* Recall that m has a unique successor say m+ and j has a unique predecessor
* say j-, then :
*
* - j "Up Arrow" m (stored as "Up") iff j is not less or equal than m and
* j is less than m+
* - j "Down Arrow" m (stored as "Down") iff j is not less or equal than m and
* j- is less than m
* - j "Up Down Arrow" m (stored as "UpDown") iff j "Up" m and j "Down" m
* - j "Cross" m (stored as "Cross") iff j is less or equal than m
* - j "Circ" m (stored as "Circ") iff neither j "Up" m nor j "Down" m nor
* j "Cross" m
*
* ![ArrowRelation](ArrowRelation.png)
*
* @uml ArrowRelation.png
* !include resources/org/thegalactic/dgraph/DGraph.iuml
* !include resources/org/thegalactic/dgraph/Edge.iuml
* !include resources/org/thegalactic/dgraph/Node.iuml
* !include resources/org/thegalactic/lattice/ArrowRelation.iuml
*
* hide members
* show ArrowRelation members
* class ArrowRelation #LightCyan
* title ArrowRelation UML graph
*/
public class ArrowRelation extends ConcreteDGraph {
/**
* Field used to encode up arrow relation.
*/
private static Object up = "Up";
/**
* Field used to encode down arrow relation.
*/
private static Object down = "Down";
/**
* Field used to encode up-down arrow relation.
*/
private static Object updown = "UpDown";
/**
* Field used to encode cross arrow relation.
*/
private static Object cross = "Cross";
/**
* Field used to encode circ arrow relation.
*/
private static Object circ = "Circ";
/**
* Unique constructor of this component from a lattice.
*
* Nodes are join or meet irreductibles of the lattice. Edges content
* encodes arrows as String "Up", "Down", "UpDown", "Cross", "Circ".
*
* @param lattice Lattice from which this component is deduced.
*/
public ArrowRelation(Lattice lattice) {
/*
* Nodes are join or meet irreductibles of the lattice.
*/
TreeSet<Node> joins = new TreeSet<Node>(lattice.joinIrreducibles());
for (Node node : joins) {
this.addNode(node);
}
TreeSet<Node> meets = new TreeSet<Node>(lattice.meetIrreducibles());
for (Node node : meets) {
this.addNode(node);
}
Lattice transitiveClosure = new Lattice(lattice);
transitiveClosure.transitiveClosure();
Lattice transitiveReduction = new Lattice(lattice);
transitiveReduction.transitiveReduction();
Node jminus = new Node();
Node mplus = new Node();
Object arrow = new Object();
/*
* Content of edges are arrows
*/
for (Node j : joins) {
for (Node m : meets) {
mplus = (Node) transitiveReduction.getSuccessorNodes(m).first();
jminus = (Node) transitiveReduction.getPredecessorNodes(j).first();
if (transitiveClosure.getSuccessorNodes(j).contains(m) || j.equals(m)) {
arrow = ArrowRelation.cross;
} else if (transitiveClosure.getSuccessorNodes(jminus).contains(m) || jminus.equals(m)) {
arrow = ArrowRelation.down;
if (transitiveClosure.getPredecessorNodes(mplus).contains(j) || mplus.equals(j)) {
arrow = ArrowRelation.updown;
}
} else if (transitiveClosure.getPredecessorNodes(mplus).contains(j)) {
arrow = ArrowRelation.up;
} else {
arrow = ArrowRelation.circ;
}
this.addEdge(j, m, arrow);
}
}
}
/**
* Save the description of this component in a file whose name is specified.
*
* @param filename the name of the file
*
* @throws IOException When an IOException occurs
*/
@Override
public void save(final String filename) throws IOException {
Filer.getInstance().save(this, ArrowRelationIOFactory.getInstance(), filename);
}
/**
* Returns the table of the lattice, composed of the join and meet
* irreducibles nodes.
*
* Each attribute of the table is a copy of a join irreducibles node. Each
* observation of the table is a copy of a meet irreducibles node. An
* attribute is extent of an observation when its join irreducible node is
* in double arrow relation with the meet irreducible node in the lattice.
*
* @return the table of the lattice
*
* @todo Avoid using for (Object edge : this.getEdges()). Use for (Edge edge : this.getEdges())
*/
public Context getDoubleArrowTable() {
Context context = new Context();
// observations are join irreductibles
// attributes are meet irreductibles
for (Object edge : this.getEdges()) {
context.addToObservations(((Edge) edge).getSource());
context.addToAttributes(((Edge) edge).getTarget());
}
// generation of extent-intent
for (Object edge : this.getEdges()) {
if (((Edge) edge).getContent() == ArrowRelation.updown) {
context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
}
}
return context;
}
/**
* Returns the table of the lattice, composed of the join and meet
* irreducibles nodes.
*
* Each attribute of the table is a copy of a join irreducibles node. Each
* observation of the table is a copy of a meet irreducibles node. An
* attribute is extent of an observation when its join irreducible node is
* in down arrow relation with the meet irreducible node in the lattice.
*
* @return the table of the lattice
*/
public Context getDoubleDownArrowTable() {
Context context = new Context();
// observations are join irreductibles
// attributes are meet irreductibles
for (Object edge : this.getEdges()) {
context.addToObservations(((Edge) edge).getSource());
context.addToAttributes(((Edge) edge).getTarget());
}
// generation of extent-intent
for (Object edge : this.getEdges()) {
if (((Edge) edge).getContent() == ArrowRelation.down || ((Edge) edge).getContent() == ArrowRelation.updown) {
context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
}
}
return context;
}
/**
* Returns the table of the lattice, composed of the join and meet
* irreducibles nodes.
*
* Each attribute of the table is a copy of a join irreducibles node. Each
* observation of the table is a copy of a meet irreducibles node. An
* attribute is extent of an observation when its join irreducible node is
* in up arrow relation with the meet irreducible node in the lattice.
*
* @return the table of the lattice
*/
public Context getDoubleUpArrowTable() {
Context context = new Context();
// observations are join irreductibles
// attributes are meet irreductibles
for (Object edge : this.getEdges()) {
context.addToObservations(((Edge) edge).getSource());
context.addToAttributes(((Edge) edge).getTarget());
}
// generation of extent-intent
for (Object edge : this.getEdges()) {
if (((Edge) edge).getContent() == ArrowRelation.up || ((Edge) edge).getContent() == ArrowRelation.updown) {
context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
}
}
return context;
}
/**
* Returns the table of the lattice, composed of the join and meet
* irreducibles nodes.
*
* Each attribute of the table is a copy of a join irreducibles node. Each
* observation of the table is a copy of a meet irreducibles node. An
* attribute is extent of an observation when its join irreducible node is
* in double arrow relation or circ relation with the meet irreducible node
* in the lattice.
*
* @return the table of the lattice
*/
public Context getDoubleCircArrowTable() {
Context context = new Context();
// observations are join irreductibles
// attributes are meet irreductibles
for (Object edge : this.getEdges()) {
context.addToObservations(((Edge) edge).getSource());
context.addToAttributes(((Edge) edge).getTarget());
}
// generation of extent-intent
for (Object edge : this.getEdges()) {
if (((Edge) edge).getContent() == ArrowRelation.updown || ((Edge) edge).getContent() == ArrowRelation.circ) {
context.addExtentIntent(((Edge) edge).getSource(), ((Edge) edge).getTarget());
}
}
return context;
}
/**
* Returns true if and only if there is an up arrow between the source and
* the target of
* edge e.
*
* @param edge edge to be tested
*
* @return true if and only if there is an up arrow between the source and
* the target of
* edge e
*/
public boolean isUp(Edge edge) {
return edge.getContent() == ArrowRelation.up;
}
/**
* Returns true if and only if there is an down arrow between the source and
* the target of
* edge e.
*
* @param edge edge to be tested
*
* @return true if and only if there is an down arrow between the source and
* the target of
* edge e
*/
public boolean isDown(Edge edge) {
return edge.getContent() == ArrowRelation.down;
}
/**
* Returns true if and only if there is an up-down arrow between the source
* and the target
* of edge e.
*
* @param edge edge to be tested
*
* @return true if and only if there is an up-down arrow between the source
* and the target
* of edge e
*/
public boolean isUpDown(Edge edge) {
return edge.getContent() == ArrowRelation.updown;
}
/**
* Returns true if and only if there is an cross arrow between the source
* and the target
* of edge e.
*
* @param edge edge to be tested
*
* @return true if and only if there is an cross arrow between the source
* and the target
* of edge e
*/
public boolean isCross(Edge edge) {
return edge.getContent() == ArrowRelation.cross;
}
/**
* Returns true if and only if there is an circ arrow between the source and
* the target of
* edge e.
*
* @param edge edge to be tested
*
* @return true if and only if there is an circ arrow between the source and
* the target of
* edge e
*/
public boolean isCirc(Edge edge) {
return edge.getContent() == ArrowRelation.circ;
}
}