diff --git a/src/fr/inrialpes/exmo/align/impl/rel/A16AlgebraRelation.java b/src/fr/inrialpes/exmo/align/impl/rel/A16AlgebraRelation.java new file mode 100644 index 0000000000000000000000000000000000000000..772dfce322c8728ba422b576966fcbb89a5e3ba3 --- /dev/null +++ b/src/fr/inrialpes/exmo/align/impl/rel/A16AlgebraRelation.java @@ -0,0 +1,417 @@ +/* + * $Id$ + * + * Copyright (C) INRIA, 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package fr.inrialpes.exmo.align.impl.rel; + +import fr.inrialpes.exmo.align.impl.BitSetAlgebraRelation; + +import org.semanticweb.owl.align.AlignmentException; +import org.semanticweb.owl.align.Relation; + +import java.util.HashMap; +import java.util.Vector; +import java.util.BitSet; +import java.io.PrintWriter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The A16 Algebras of relations + * (see: Armen Inants, Jérôme Euzenat, Algebras of ontology alignment relations, Proc. ISWC, 2015). + * + * JEPD relations between classes, enventually empty, and individuals + * + */ + +public class A16AlgebraRelation extends BitSetAlgebraRelation<A16BaseRelation> { + final static Logger logger = LoggerFactory.getLogger( A16AlgebraRelation.class ); + + /** Creation **/ + private A16AlgebraRelation(){}; + + public A16AlgebraRelation( String rels ) throws AlignmentException { + if ( size == -1 ) init(); + relset = instance0.read( rels ); + } + + public static A16AlgebraRelation createRelation( String rels ) throws AlignmentException { + return new A16AlgebraRelation( rels ); + } + + /** + * This is private because it refers to the implementation as BitSet + */ + private A16AlgebraRelation( BitSet rels ) { + super( rels ); + } + + protected static void init() { + protoinit(); + declareRelation( A16BaseRelation.EQ_N, A16BaseRelation.EQ_N ); + declareRelation( A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED ); + declareRelation( A16BaseRelation.SUBSUMED, A16BaseRelation.SUBSUME ); + declareRelation( A16BaseRelation.OVERLAP, A16BaseRelation.OVERLAP ); + declareRelation( A16BaseRelation.DISJOINT, A16BaseRelation.DISJOINT ); + declareRelation( A16BaseRelation.HAS, A16BaseRelation.ISA ); + declareRelation( A16BaseRelation.HASNOT, A16BaseRelation.ISNOT ); + declareRelation( A16BaseRelation.ISA, A16BaseRelation.HAS ); + declareRelation( A16BaseRelation.ISNOT, A16BaseRelation.HASNOT ); + declareRelation( A16BaseRelation.EQ_I, A16BaseRelation.EQ_I ); + declareRelation( A16BaseRelation.NOTEQ_I, A16BaseRelation.NOTEQ_I ); + declareRelation( A16BaseRelation.NE, A16BaseRelation.EN ); + declareRelation( A16BaseRelation.IE, A16BaseRelation.EI ); + declareRelation( A16BaseRelation.EQ_E, A16BaseRelation.EQ_E ); + declareRelation( A16BaseRelation.EN, A16BaseRelation.NE ); + declareRelation( A16BaseRelation.EI, A16BaseRelation.IE ); + + compositionTable = new BitSet[size][size]; + for( int i=0; i < size; i++ ) + for( int j=0; j < size; j++ ) + compositionTable[i][j] = new BitSet( size ); + BitSet bs = new BitSet( size ); + bs.set( 0 ); + instance0 = new A16AlgebraRelation( bs ); + // ---- EQ_N + o( A16BaseRelation.EQ_N, A16BaseRelation.EQ_N, + A16BaseRelation.EQ_N ); + o( A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, + A16BaseRelation.SUBSUME ); + o( A16BaseRelation.EQ_N, A16BaseRelation.SUBSUMED, + A16BaseRelation.SUBSUMED ); + o( A16BaseRelation.EQ_N, A16BaseRelation.OVERLAP, + A16BaseRelation.OVERLAP ); + o( A16BaseRelation.EQ_N, A16BaseRelation.DISJOINT, + A16BaseRelation.DISJOINT ); + o( A16BaseRelation.EQ_N, A16BaseRelation.HAS, + A16BaseRelation.HAS ); + o( A16BaseRelation.EQ_N, A16BaseRelation.HASNOT, + A16BaseRelation.HASNOT ); + o( A16BaseRelation.EQ_N, A16BaseRelation.NE, + A16BaseRelation.NE ); + // ---- SUBSUME + o( A16BaseRelation.SUBSUME, A16BaseRelation.EQ_N, + A16BaseRelation.SUBSUME ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUME, + A16BaseRelation.SUBSUME ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP, + A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.DISJOINT, + A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.HAS, + A16BaseRelation.HAS ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.HASNOT, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.SUBSUME, A16BaseRelation.NE, + A16BaseRelation.NE ); + // ---- SUBSUMED + o( A16BaseRelation.SUBSUMED, A16BaseRelation.EQ_N, + A16BaseRelation.SUBSUMED ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.SUBSUME, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.SUBSUMED, + A16BaseRelation.SUBSUMED ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, + A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.DISJOINT, + A16BaseRelation.DISJOINT ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.HAS, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.HASNOT, + A16BaseRelation.HASNOT ); + o( A16BaseRelation.SUBSUMED, A16BaseRelation.NE, + A16BaseRelation.NE ); + // ---- OVERLAP + o( A16BaseRelation.OVERLAP, A16BaseRelation.EQ_N, + A16BaseRelation.OVERLAP ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.SUBSUME, + A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.SUBSUMED, + A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.OVERLAP, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT, + A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.HAS, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.HASNOT, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.OVERLAP, A16BaseRelation.NE, + A16BaseRelation.NE ); + // ---- DISJOINT + o( A16BaseRelation.DISJOINT, A16BaseRelation.EQ_N, + A16BaseRelation.DISJOINT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.SUBSUME, + A16BaseRelation.DISJOINT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.SUBSUMED, + A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.OVERLAP, + A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.DISJOINT, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.HAS, + A16BaseRelation.HASNOT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.HASNOT, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.DISJOINT, A16BaseRelation.NE, + A16BaseRelation.NE ); + // ---- ISA + o( A16BaseRelation.ISA, A16BaseRelation.EQ_N, + A16BaseRelation.ISA ); + o( A16BaseRelation.ISA, A16BaseRelation.SUBSUME, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISA, A16BaseRelation.SUBSUMED, + A16BaseRelation.ISA ); + o( A16BaseRelation.ISA, A16BaseRelation.OVERLAP, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISA, A16BaseRelation.DISJOINT, + A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISA, A16BaseRelation.HAS, + A16BaseRelation.EQ_I, A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.ISA, A16BaseRelation.HASNOT, + A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.ISA, A16BaseRelation.NE, + A16BaseRelation.IE ); + // ---- ISNOT + o( A16BaseRelation.ISNOT, A16BaseRelation.EQ_N, + A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISNOT, A16BaseRelation.SUBSUME, + A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISNOT, A16BaseRelation.SUBSUMED, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISNOT, A16BaseRelation.OVERLAP, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISNOT, A16BaseRelation.DISJOINT, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.ISNOT, A16BaseRelation.HAS, + A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.ISNOT, A16BaseRelation.HASNOT, + A16BaseRelation.EQ_I, A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.ISNOT, A16BaseRelation.NE, + A16BaseRelation.IE ); + // ---- EN + o( A16BaseRelation.EN, A16BaseRelation.EQ_N, + A16BaseRelation.EN ); + o( A16BaseRelation.EN, A16BaseRelation.SUBSUME, + A16BaseRelation.EN ); + o( A16BaseRelation.EN, A16BaseRelation.SUBSUMED, + A16BaseRelation.EN ); + o( A16BaseRelation.EN, A16BaseRelation.OVERLAP, + A16BaseRelation.EN ); + o( A16BaseRelation.EN, A16BaseRelation.DISJOINT, + A16BaseRelation.EN ); + o( A16BaseRelation.EN, A16BaseRelation.HAS, + A16BaseRelation.EI ); + o( A16BaseRelation.EN, A16BaseRelation.HASNOT, + A16BaseRelation.EI ); + o( A16BaseRelation.EN, A16BaseRelation.NE, + A16BaseRelation.EQ_E ); + + + // ---- EQ_I + o( A16BaseRelation.EQ_I, A16BaseRelation.EQ_I, + A16BaseRelation.EQ_I ); + o( A16BaseRelation.EQ_I, A16BaseRelation.NOTEQ_I, + A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.EQ_I, A16BaseRelation.ISA, + A16BaseRelation.ISA ); + o( A16BaseRelation.EQ_I, A16BaseRelation.ISNOT, + A16BaseRelation.ISNOT ); + o( A16BaseRelation.EQ_I, A16BaseRelation.IE, + A16BaseRelation.IE ); + // ---- NOTEQ_I + o( A16BaseRelation.NOTEQ_I, A16BaseRelation.EQ_I, + A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.NOTEQ_I, A16BaseRelation.NOTEQ_I, + A16BaseRelation.EQ_I, A16BaseRelation.NOTEQ_I ); + o( A16BaseRelation.NOTEQ_I, A16BaseRelation.ISA, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.NOTEQ_I, A16BaseRelation.ISNOT, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.NOTEQ_I, A16BaseRelation.IE, + A16BaseRelation.IE ); + // ---- HAS + o( A16BaseRelation.HAS, A16BaseRelation.EQ_I, + A16BaseRelation.HAS ); + o( A16BaseRelation.HAS, A16BaseRelation.NOTEQ_I, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.HAS, A16BaseRelation.ISA, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP ); + o( A16BaseRelation.HAS, A16BaseRelation.ISNOT, + A16BaseRelation.SUBSUME, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.HAS, A16BaseRelation.IE, + A16BaseRelation.NE ); + // ---- HASNOT + o( A16BaseRelation.HASNOT, A16BaseRelation.EQ_I, + A16BaseRelation.HASNOT ); + o( A16BaseRelation.HASNOT, A16BaseRelation.NOTEQ_I, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + o( A16BaseRelation.HASNOT, A16BaseRelation.ISA, + A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.HASNOT, A16BaseRelation.ISNOT, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.HASNOT, A16BaseRelation.IE, + A16BaseRelation.NE ); + // ---- EI + o( A16BaseRelation.EI, A16BaseRelation.EQ_I, + A16BaseRelation.EI ); + o( A16BaseRelation.EI, A16BaseRelation.NOTEQ_I, + A16BaseRelation.EI ); + o( A16BaseRelation.EI, A16BaseRelation.ISA, + A16BaseRelation.EN ); + o( A16BaseRelation.EI, A16BaseRelation.ISNOT, + A16BaseRelation.EN ); + o( A16BaseRelation.EI, A16BaseRelation.IE, + A16BaseRelation.EQ_E ); + // ---- EQ_E + o( A16BaseRelation.EQ_E, A16BaseRelation.EQ_E, + A16BaseRelation.EQ_E ); + o( A16BaseRelation.EQ_E, A16BaseRelation.EN, + A16BaseRelation.EN ); + o( A16BaseRelation.EQ_E, A16BaseRelation.EI, + A16BaseRelation.EI ); + // ---- NE + o( A16BaseRelation.NE, A16BaseRelation.EQ_E, + A16BaseRelation.NE ); + o( A16BaseRelation.NE, A16BaseRelation.EN, + A16BaseRelation.EQ_N, A16BaseRelation.SUBSUME, A16BaseRelation.SUBSUMED, A16BaseRelation.OVERLAP, A16BaseRelation.DISJOINT ); + o( A16BaseRelation.NE, A16BaseRelation.EI, + A16BaseRelation.HAS, A16BaseRelation.HASNOT ); + // ---- IE + o( A16BaseRelation.IE, A16BaseRelation.EQ_E, + A16BaseRelation.IE ); + o( A16BaseRelation.IE, A16BaseRelation.EN, + A16BaseRelation.ISA, A16BaseRelation.ISNOT ); + o( A16BaseRelation.IE, A16BaseRelation.EI, + A16BaseRelation.EQ_I, A16BaseRelation.NOTEQ_I ); + protofinalize(); + } + + /********************************************************************** + * NO CHANGE IS NECESSARY BEYOND THIS POINT (only change the class name) + * Unfortunately, this MUST be copied in all class. + **********************************************************************/ + + protected static HashMap<String,A16BaseRelation> relations = null; + + protected static Vector<A16BaseRelation> positions; + + protected static int size = -1; + + protected static BitSet[][] compositionTable; + + private static A16AlgebraRelation instance0; + + protected BitSet createSet() { + return new BitSet( size ); + } + + public A16BaseRelation getRelation( String rel ) { + //return A16BaseRelation.valueOf( rel ); + if ( size == -1) init(); + return relations.get( rel ); + } + public A16BaseRelation getRelation( int i ) { + if ( size == -1) init(); + return positions.get( i ); + } + + public BitSet compose( A16BaseRelation s, A16BaseRelation t ) { + return compositionTable[s.index][t.index]; + } + + protected static void protoinit() { + logger.trace( "Initialising algebra of relations" ); + size = 0; + relations = new HashMap<String,A16BaseRelation>(); + positions = new Vector<A16BaseRelation>(); + } + + protected static void declareRelation( A16BaseRelation rel, A16BaseRelation inverse ) { + rel.init( size++, inverse ); + relations.put( rel.relation, rel ); + positions.add( rel ); + logger.debug( "{} idx: {}, inv: {}", rel, rel.index, rel.inverse ); + } + + protected static void protofinalize() { + //if ( instance0 == null ) instance0 = new A16AlgebraRelation( new BitSet( size ) ); + logger.trace( "Initialised algebra with {} relations", size ); + } + + protected static void setComposition( A16BaseRelation a, A16BaseRelation b, A16BaseRelation c ) { + compositionTable[a.index][b.index].set( c.index ); + } + + // Declaration by transitivity table + protected static void o( A16BaseRelation a, A16BaseRelation b, A16BaseRelation... s ) { + for ( A16BaseRelation r : s ) compositionTable[a.index][b.index].set( r.index ); + logger.debug( "{} o {} = {}", a.index, b.index, compositionTable[a.index][b.index] ); + } + + // Declaration by compatible triples + protected static void t( A16BaseRelation a, A16BaseRelation b, A16BaseRelation c ) { + compositionTable[a.index][b.index].set( c.index ); + compositionTable[b.inverse.index][a.inverse.index].set( c.inverse.index ); + compositionTable[a.inverse.index][c.index].set( b.index ); + compositionTable[c.inverse.index][a.index].set( b.inverse.index ); + compositionTable[b.index][c.inverse.index].set( a.index ); + compositionTable[c.index][b.inverse.index].set( a.inverse.index ); + } + + public A16AlgebraRelation compose( A16AlgebraRelation dr ) { + return new A16AlgebraRelation( protocompose( dr ) ); + } + + public A16AlgebraRelation compose( Relation r ) { + if ( r instanceof A16AlgebraRelation ) + return new A16AlgebraRelation( protocompose( (A16AlgebraRelation)r ) ); + //throw new AlignmentException ( "Cannot compose heterogeneous relations" ); + else return null; + } + + public A16AlgebraRelation inverse() { + return new A16AlgebraRelation( protoinverse() ); + } + + public A16AlgebraRelation join( A16AlgebraRelation... drs ) { + return new A16AlgebraRelation( protojoin( drs ) ); + } + + public A16AlgebraRelation meet( A16AlgebraRelation... drs ) { + return new A16AlgebraRelation( protomeet( drs ) ); + } + + public static A16AlgebraRelation getTopRelation() throws AlignmentException { + if ( size == -1 ) init(); + BitSet bs = instance0.createSet(); + bs.flip( 0, bs.size() ); + return new A16AlgebraRelation( bs ); + } + + public static A16AlgebraRelation getIdRelation() throws AlignmentException { + if ( size == -1 ) init(); + return instance0; + } + +} + diff --git a/src/fr/inrialpes/exmo/align/impl/rel/A16BaseRelation.java b/src/fr/inrialpes/exmo/align/impl/rel/A16BaseRelation.java new file mode 100644 index 0000000000000000000000000000000000000000..58cbead2561916267a193dcdccb191f808e04cd9 --- /dev/null +++ b/src/fr/inrialpes/exmo/align/impl/rel/A16BaseRelation.java @@ -0,0 +1,82 @@ +/* + * $Id$ + * + * Copyright (C) INRIA, 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +package fr.inrialpes.exmo.align.impl.rel; + +import fr.inrialpes.exmo.align.impl.BaseRelation; + +import java.io.PrintWriter; + +/** + * The Base relatins for the A16 algebra + */ + +public enum A16BaseRelation implements BaseRelation { + // A5 + EQ_N( "=n" ), + SUBSUMED( "<" ), + SUBSUME( ">" ), + OVERLAP( ")(" ), + DISJOINT( "%" ), + + // A5-A2 glue + HAS("3"), + HASNOT("-3"), + ISA("E"), + ISNOT("-E"), + + //A2 + EQ_I("=i"), + NOTEQ_I("-=i"), + + // Empty classes + NE("NE"), + IE("IE"), + EQ_E("=e"), + EN("EN"), + EI("EI"); + + /********************************************************************** + * NO CHANGE IS NECESSARY BEYOND THIS POINT (only change the class name) + * Unfortunately, this MUST be copied in all class. + **********************************************************************/ + + public final String relation; + public int index; + public A16BaseRelation inverse; + + public String getString() { return relation; } + public int getIndex() { return index; } + public A16BaseRelation getInverse() { return inverse; } + + public void init( int idx, A16BaseRelation inv ) { + index = idx; + inverse = inv; + } + + A16BaseRelation ( String label ) { + relation = label; + } + + public void write( PrintWriter writer ) { + writer.print( relation ); + } + +}