From c83abc16b3708e04164075f5e6f7585e34594e25 Mon Sep 17 00:00:00 2001
From: Ludovic Apvrille <ludovic.apvrille@telecom-paristech.fr>
Date: Fri, 28 Sep 2018 11:32:27 +0200
Subject: [PATCH] Adding jautomata-core and new minimiztion algorithm in TTool

---
 .idea/libraries/libs.xml                      |    2 +-
 extra/jautomata-core/Makefile                 |    7 +
 extra/jautomata-core/rationals/Acceptor.java  |   56 +
 extra/jautomata-core/rationals/Automaton.java | 1017 +++++++++++++++++
 .../rationals/AutomatonRunListener.java       |   51 +
 .../rationals/AutomatonRunner.java            |   50 +
 extra/jautomata-core/rationals/Builder.java   |   79 ++
 extra/jautomata-core/rationals/Couple.java    |   63 +
 .../rationals/DefaultStateFactory.java        |  181 +++
 .../rationals/DefaultSynchronization.java     |   77 ++
 extra/jautomata-core/rationals/MixPlay.java   |  347 ++++++
 .../rationals/NoSuchStateException.java       |   56 +
 .../rationals/RandomAutomaton.java            |  168 +++
 extra/jautomata-core/rationals/Rational.java  |  214 ++++
 extra/jautomata-core/rationals/State.java     |   56 +
 .../rationals/StateFactory.java               |   86 ++
 .../jautomata-core/rationals/StateLabels.java |   77 ++
 .../rationals/StateMachine.java               |  155 +++
 .../jautomata-core/rationals/StatesTuple.java |   78 ++
 .../rationals/Synchronization.java            |   83 ++
 .../jautomata-core/rationals/Transition.java  |  170 +++
 .../rationals/TransitionBuilder.java          |  127 ++
 .../rationals/algebra/Matrix.java             |  226 ++++
 .../rationals/algebra/RationalMatrix.java     |  145 +++
 .../rationals/algebra/SemiRing.java           |   70 ++
 .../converters/ConverterException.java        |   24 +
 .../rationals/converters/Expression.java      |   29 +
 .../rationals/converters/FromString.java      |   26 +
 .../rationals/converters/ToRExpression.java   |  144 +++
 .../rationals/converters/ToString.java        |   25 +
 .../converters/analyzers/DefaultLexer.class   |  Bin 0 -> 2567 bytes
 .../converters/analyzers/DefaultLexer.java    |  178 +++
 .../converters/analyzers/Lexer.class          |  Bin 0 -> 849 bytes
 .../rationals/converters/analyzers/Lexer.java |  102 ++
 .../converters/analyzers/Parser.class         |  Bin 0 -> 4800 bytes
 .../converters/analyzers/Parser.java          |  301 +++++
 .../rationals/converters/toAscii.java         |   45 +
 .../rationals/expr/BinaryExpr.java            |   64 ++
 .../rationals/expr/Iteration.java             |   52 +
 .../jautomata-core/rationals/expr/Letter.java |   93 ++
 extra/jautomata-core/rationals/expr/Plus.java |   41 +
 .../rationals/expr/Product.java               |   43 +
 .../rationals/expr/RationalExpr.java          |   86 ++
 .../rationals/properties/AreEquivalent.java   |   78 ++
 .../rationals/properties/AreIsomorph.java     |   46 +
 .../rationals/properties/BinaryTest.java      |   54 +
 .../rationals/properties/Bisimilar.java       |   34 +
 .../rationals/properties/Bisimulation.java    |  139 +++
 .../rationals/properties/ContainsEpsilon.java |   52 +
 .../rationals/properties/IsDeterministic.java |   64 ++
 .../rationals/properties/ModelCheck.java      |   76 ++
 .../rationals/properties/Relation.java        |   77 ++
 .../rationals/properties/Similar.java         |   34 +
 .../rationals/properties/Simulation.java      |  144 +++
 .../properties/TraceEquivalence.java          |  161 +++
 .../rationals/properties/TraceEquivalent.java |   34 +
 .../rationals/properties/UnaryTest.java       |   25 +
 .../properties/WeakBisimulation.java          |   70 ++
 .../rationals/properties/WeaklyBisimilar.java |   35 +
 .../rationals/properties/isEmpty.java         |   37 +
 .../rationals/properties/isNormalized.java    |   45 +
 .../rationals/transformations/Accessible.java |   97 ++
 .../transformations/BinaryTransformation.java |   30 +
 .../rationals/transformations/Complement.java |   93 ++
 .../transformations/CompleteNop.java          |   91 ++
 .../transformations/Concatenation.java        |  118 ++
 .../EpsilonTransitionRemover.java             |  110 ++
 .../rationals/transformations/HashValue.java  |   64 ++
 .../rationals/transformations/Identity.java   |   37 +
 .../transformations/InverseMorphism.java      |  131 +++
 .../rationals/transformations/Mix.java        |  194 ++++
 .../rationals/transformations/Morphism.java   |   83 ++
 .../rationals/transformations/Normalizer.java |  104 ++
 .../transformations/PartialCommutation.java   |   34 +
 .../transformations/PrefixClosure.java        |   77 ++
 .../rationals/transformations/Projection.java |   84 ++
 .../rationals/transformations/Pruner.java     |   57 +
 .../transformations/RandomWalk.java.old       |   89 ++
 .../rationals/transformations/Reducer.java    |  140 +++
 .../rationals/transformations/Reverser.java   |   62 +
 .../rationals/transformations/Shuffle.java    |   71 ++
 .../transformations/SinkComplete.java         |   89 ++
 .../rationals/transformations/Star.java       |   75 ++
 .../transformations/StatesCouple.java         |   66 ++
 .../transformations/Substitution.java         |  133 +++
 .../rationals/transformations/ToC.java        |  104 ++
 .../transformations/ToCanonicalRFSA.java      |   31 +
 .../rationals/transformations/ToDFA.java      |  121 ++
 .../transformations/Transformations.java      |   39 +
 .../TransformationsToolBox.java               |  124 ++
 .../transformations/UnaryTransformation.java  |   25 +
 .../rationals/transformations/Union.java      |   61 +
 src/main/java/graph/AUTGraph.java             |   35 +-
 src/main/java/ui/window/JFrameMinimize.java   |    2 +-
 ttool/build.gradle                            |    1 +
 95 files changed, 8756 insertions(+), 15 deletions(-)
 create mode 100644 extra/jautomata-core/Makefile
 create mode 100755 extra/jautomata-core/rationals/Acceptor.java
 create mode 100755 extra/jautomata-core/rationals/Automaton.java
 create mode 100755 extra/jautomata-core/rationals/AutomatonRunListener.java
 create mode 100755 extra/jautomata-core/rationals/AutomatonRunner.java
 create mode 100755 extra/jautomata-core/rationals/Builder.java
 create mode 100755 extra/jautomata-core/rationals/Couple.java
 create mode 100755 extra/jautomata-core/rationals/DefaultStateFactory.java
 create mode 100755 extra/jautomata-core/rationals/DefaultSynchronization.java
 create mode 100755 extra/jautomata-core/rationals/MixPlay.java
 create mode 100755 extra/jautomata-core/rationals/NoSuchStateException.java
 create mode 100755 extra/jautomata-core/rationals/RandomAutomaton.java
 create mode 100755 extra/jautomata-core/rationals/Rational.java
 create mode 100755 extra/jautomata-core/rationals/State.java
 create mode 100755 extra/jautomata-core/rationals/StateFactory.java
 create mode 100755 extra/jautomata-core/rationals/StateLabels.java
 create mode 100755 extra/jautomata-core/rationals/StateMachine.java
 create mode 100755 extra/jautomata-core/rationals/StatesTuple.java
 create mode 100755 extra/jautomata-core/rationals/Synchronization.java
 create mode 100755 extra/jautomata-core/rationals/Transition.java
 create mode 100755 extra/jautomata-core/rationals/TransitionBuilder.java
 create mode 100755 extra/jautomata-core/rationals/algebra/Matrix.java
 create mode 100755 extra/jautomata-core/rationals/algebra/RationalMatrix.java
 create mode 100755 extra/jautomata-core/rationals/algebra/SemiRing.java
 create mode 100755 extra/jautomata-core/rationals/converters/ConverterException.java
 create mode 100755 extra/jautomata-core/rationals/converters/Expression.java
 create mode 100755 extra/jautomata-core/rationals/converters/FromString.java
 create mode 100755 extra/jautomata-core/rationals/converters/ToRExpression.java
 create mode 100755 extra/jautomata-core/rationals/converters/ToString.java
 create mode 100644 extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.class
 create mode 100755 extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.java
 create mode 100644 extra/jautomata-core/rationals/converters/analyzers/Lexer.class
 create mode 100755 extra/jautomata-core/rationals/converters/analyzers/Lexer.java
 create mode 100644 extra/jautomata-core/rationals/converters/analyzers/Parser.class
 create mode 100755 extra/jautomata-core/rationals/converters/analyzers/Parser.java
 create mode 100755 extra/jautomata-core/rationals/converters/toAscii.java
 create mode 100755 extra/jautomata-core/rationals/expr/BinaryExpr.java
 create mode 100755 extra/jautomata-core/rationals/expr/Iteration.java
 create mode 100755 extra/jautomata-core/rationals/expr/Letter.java
 create mode 100755 extra/jautomata-core/rationals/expr/Plus.java
 create mode 100755 extra/jautomata-core/rationals/expr/Product.java
 create mode 100755 extra/jautomata-core/rationals/expr/RationalExpr.java
 create mode 100755 extra/jautomata-core/rationals/properties/AreEquivalent.java
 create mode 100755 extra/jautomata-core/rationals/properties/AreIsomorph.java
 create mode 100755 extra/jautomata-core/rationals/properties/BinaryTest.java
 create mode 100755 extra/jautomata-core/rationals/properties/Bisimilar.java
 create mode 100755 extra/jautomata-core/rationals/properties/Bisimulation.java
 create mode 100755 extra/jautomata-core/rationals/properties/ContainsEpsilon.java
 create mode 100755 extra/jautomata-core/rationals/properties/IsDeterministic.java
 create mode 100755 extra/jautomata-core/rationals/properties/ModelCheck.java
 create mode 100755 extra/jautomata-core/rationals/properties/Relation.java
 create mode 100755 extra/jautomata-core/rationals/properties/Similar.java
 create mode 100755 extra/jautomata-core/rationals/properties/Simulation.java
 create mode 100755 extra/jautomata-core/rationals/properties/TraceEquivalence.java
 create mode 100755 extra/jautomata-core/rationals/properties/TraceEquivalent.java
 create mode 100755 extra/jautomata-core/rationals/properties/UnaryTest.java
 create mode 100755 extra/jautomata-core/rationals/properties/WeakBisimulation.java
 create mode 100755 extra/jautomata-core/rationals/properties/WeaklyBisimilar.java
 create mode 100755 extra/jautomata-core/rationals/properties/isEmpty.java
 create mode 100755 extra/jautomata-core/rationals/properties/isNormalized.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Accessible.java
 create mode 100755 extra/jautomata-core/rationals/transformations/BinaryTransformation.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Complement.java
 create mode 100755 extra/jautomata-core/rationals/transformations/CompleteNop.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Concatenation.java
 create mode 100755 extra/jautomata-core/rationals/transformations/EpsilonTransitionRemover.java
 create mode 100755 extra/jautomata-core/rationals/transformations/HashValue.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Identity.java
 create mode 100755 extra/jautomata-core/rationals/transformations/InverseMorphism.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Mix.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Morphism.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Normalizer.java
 create mode 100755 extra/jautomata-core/rationals/transformations/PartialCommutation.java
 create mode 100755 extra/jautomata-core/rationals/transformations/PrefixClosure.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Projection.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Pruner.java
 create mode 100755 extra/jautomata-core/rationals/transformations/RandomWalk.java.old
 create mode 100755 extra/jautomata-core/rationals/transformations/Reducer.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Reverser.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Shuffle.java
 create mode 100755 extra/jautomata-core/rationals/transformations/SinkComplete.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Star.java
 create mode 100755 extra/jautomata-core/rationals/transformations/StatesCouple.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Substitution.java
 create mode 100755 extra/jautomata-core/rationals/transformations/ToC.java
 create mode 100755 extra/jautomata-core/rationals/transformations/ToCanonicalRFSA.java
 create mode 100755 extra/jautomata-core/rationals/transformations/ToDFA.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Transformations.java
 create mode 100755 extra/jautomata-core/rationals/transformations/TransformationsToolBox.java
 create mode 100755 extra/jautomata-core/rationals/transformations/UnaryTransformation.java
 create mode 100755 extra/jautomata-core/rationals/transformations/Union.java

diff --git a/.idea/libraries/libs.xml b/.idea/libraries/libs.xml
index f6f184a7f6..19404ec0f4 100644
--- a/.idea/libraries/libs.xml
+++ b/.idea/libraries/libs.xml
@@ -6,7 +6,6 @@
       <root url="jar://$PROJECT_DIR$/libs/commons-io-2.5.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/gs-core-1.3.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/jaxen-1.1.6.jar!/" />
-      <root url="jar://$PROJECT_DIR$/libs/commons-io-2.4-javadoc.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/jsoup-1.8.1.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/commons-io-2.5-javadoc.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/gs-ui-1.3.jar!/" />
@@ -25,6 +24,7 @@
       <root url="jar://$PROJECT_DIR$/libs/batik-svggen.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/batik-util.jar!/" />
       <root url="jar://$PROJECT_DIR$/libs/batik-xml.jar!/" />
+      <root url="jar://$PROJECT_DIR$/libs/jautomata-core.jar!/" />
     </CLASSES>
     <JAVADOC>
       <root url="jar://$PROJECT_DIR$/libs/commons-io-2.5-javadoc.jar!/" />
diff --git a/extra/jautomata-core/Makefile b/extra/jautomata-core/Makefile
new file mode 100644
index 0000000000..769ac920bb
--- /dev/null
+++ b/extra/jautomata-core/Makefile
@@ -0,0 +1,7 @@
+all: clean
+	mkdir build/
+	javac -d build/ rationals/*.java rationals/*/*.java
+	cd build;jar -cf jautomata-core.jar rationals/*.class rationals/*/*.class
+
+clean:
+	rm -rf build/
diff --git a/extra/jautomata-core/rationals/Acceptor.java b/extra/jautomata-core/rationals/Acceptor.java
new file mode 100755
index 0000000000..ee519c61d7
--- /dev/null
+++ b/extra/jautomata-core/rationals/Acceptor.java
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author nono
+ * @version $Id: Acceptor.java 10 2007-05-30 17:25:00Z oqube $
+ */
+public interface Acceptor<L> {
+    /**
+     * Checks this automaton accepts the given "word".
+     * A word is a list of objects. This method checks that reading <code>word</code>
+     * starting from initials state leads to at least one terminal state.
+     * 
+     * @param word
+     * @return
+     */
+    boolean accept(List<L> word);
+
+    /**
+     * Return a trace of states reading word from start state. 
+     * If start state is null, assume reading from
+     * initials().
+     * This method returns a List of Set objects showing all the states 
+     * reached by this run while reading <code>word</code> starting from <code>start</code>.
+     * 
+     * @param word a List of objects in this automaton's alphabet
+     * @param start a starting State. Maybe null
+     * @return a List of Set of State objects
+     */
+    List<Set<State>> traceStates(List<L> word, State start);
+    
+    /*
+     *  (non-Javadoc)
+     * @see rationals.Acceptor#steps(java.util.List)
+     */
+    Set<State> steps(List<L> word);
+
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/Automaton.java b/extra/jautomata-core/rationals/Automaton.java
new file mode 100755
index 0000000000..02b6d2e8d8
--- /dev/null
+++ b/extra/jautomata-core/rationals/Automaton.java
@@ -0,0 +1,1017 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import rationals.transformations.TransformationsToolBox;
+
+import java.util.*;
+
+/**
+ * A class defining Automaton objects
+ * 
+ * This class defines the notion of automaton. Following notations are used to
+ * describe this class.
+ * <p>
+ * An automaton is a 5-uple <em>A = (X , Q , I , T , D)</em> where
+ * <ul>
+ * <li><em>X</em> is a finite set of labels named alphabet ,
+ * <li><em>Q</em> is a finite set of states,
+ * <li><em>I</em>, included in <em>Q</em>, is the set of initial states,
+ * <li><em>T</em>, included in <em>Q</em>, is the set of terminal states
+ * <li>and <em>D</em> is the set of transitions, which is included in
+ * <em>Q times X times Q</em> (transitions are triples <em>(q , l , q')</em> where <em>q, q'</em>
+ * are states and <em>l</em> a label).
+ * </ul>
+ * The empty word, usually denoted by <em>epsilon</em> will be denoted here by
+ * the symbol <em>@</em>.
+ * <p>
+ * In this implementation of automaton, any object may be a label, states are
+ * instance of class <tt>State</tt> and transitions are intances of class
+ * <tt>Transition</tt>. Only automata should create instances of states through
+ * <tt>Automaton</tt> method <tt>newState</tt>.
+ * 
+ * @author yroos@lifl.fr
+ * @author bailly@lifl.fr
+ * @version $Id: Automaton.java 10 2007-05-30 17:25:00Z oqube $
+ * @see Transition State
+ */
+public class Automaton<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>>
+		implements Acceptor<L>, StateMachine<L>, Rational<L>, Cloneable {
+	/* the identification of this automaton */
+	private Object id;
+
+	protected Builder<L, Tr, T> builder;
+
+	/**
+	 * @return Returns the id.
+	 */
+	public Object getId() {
+		return id;
+	}
+
+	/**
+	 * @param id
+	 *            The id to set.
+	 */
+	public void setId(Object id) {
+		this.id = id;
+	}
+
+	// The set of all objects which are labels of
+	// transitions of this automaton.
+	protected Set<L> alphabet;
+
+	// The set of all states of this automaton.
+	private Set<State> states;
+
+	// the set of initial states
+	private Set<State> initials;
+
+	// the set of terminal states
+	private Set<State> terminals;
+
+	// Allows access to transitions of this automaton
+	// starting from a given state and labelled by
+	// a given object. The keys of this map are instances
+	// of class Key and
+	// values are sets of transitions.
+	private Map<Key, Set<Transition<L>>> transitions;
+
+	// Allows access to transitions of this automaton
+	// arriving to a given state and labelled by
+	// a given object. The keys of this map are instances
+	// of class Key and
+	// values are sets of transitions.
+	private Map<Key, Set<Transition<L>>> reverse;
+
+	// bonte
+	private StateFactory stateFactory = new DefaultStateFactory(this);
+
+    private StateLabels stateLabels = new StateLabels();
+    
+	/**
+	 * @return
+	 */
+	public StateFactory getStateFactory() {
+		return this.stateFactory;
+	}
+
+	/**
+	 * @param factory
+	 */
+	public void setStateFactory(StateFactory factory) {
+		this.stateFactory = factory;
+		factory.setAutomaton(this);
+	}
+
+	/**
+	 * Returns an automaton which recognizes the regular language associated
+	 * with the regular expression <em>@</em>, where <em>@</em> denotes the
+	 * empty word.
+	 * 
+	 * @return an automaton which recognizes <em>@</em>
+	 */
+	public static <L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> Automaton<L, Tr, T> epsilonAutomaton() {
+		Automaton<L, Tr, T> v = new Automaton<>();
+		v.addState(true, true);
+		return v;
+	}
+
+	/**
+	 * Returns an automaton which recognizes the regular language associated
+	 * with the regular expression <em>l</em>, where <em>l</em> is a given
+	 * label.
+	 * 
+	 * @param label
+	 *            any object that will be used as a label.
+	 * @return an automaton which recognizes <em>label</em>
+	 */
+	public static <L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> Automaton<L, Tr, T> labelAutomaton(L label) {
+		Automaton<L, Tr, T> v = new Automaton<>();
+		State start = v.addState(true, false);
+		State end = v.addState(false, true);
+		try {
+			v.addTransition(new Transition<L>(start, label, end));
+		} catch (NoSuchStateException x) {
+		}
+		return v;
+	}
+
+	/**
+	 * Returns an automaton which recognizes the regular language associated
+	 * with the regular expression <em>u</em>, where <em>u</em> is a given word.
+	 * 
+	 * @param word
+	 *            a List of Object interpreted as a word
+	 * @return an automaton which recognizes <em>label</em>
+	 */
+	public static <L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> Automaton<L, Tr, T>  labelAutomaton(List<L> word) {
+		Automaton<L, Tr, T> v = new Automaton<>();
+		State start = null;
+		if (word.isEmpty()) {
+			v.addState(true, true);
+			return v;
+		} else
+			start = v.addState(true, false);
+		State end = null;
+		try {
+			for (Iterator<L> i = word.iterator(); i.hasNext();) {
+				L o = i.next();
+				end = v.addState(false, !i.hasNext());
+				v.addTransition(new Transition<L>(start, o, end));
+				start = end;
+			}
+		} catch (NoSuchStateException x) {
+		}
+		return v;
+	}
+
+	/**
+	 * Creates a new empty automaton which contains no state and no transition.
+	 * An empty automaton recognizes the empty language.
+	 */
+	public Automaton() {
+		this(null);
+	}
+
+	/**
+	 * Create a new empty automaton with given state factory.
+	 * 
+	 * @param sf
+	 *            the StateFactory object to use for creating new states. May be
+	 *            null.
+	 */
+	public Automaton(StateFactory sf) {
+		this.stateFactory = sf == null ? new DefaultStateFactory(this) : sf;
+		alphabet = new HashSet<>();
+		states = stateFactory.stateSet();
+		initials = stateFactory.stateSet();
+		terminals = stateFactory.stateSet();
+		transitions = new HashMap<>();
+		reverse = new HashMap<>();
+	}
+
+	/**
+	 * Returns a new instance of state which will be initial and terminal or not
+	 * depending of parameters.
+	 * 
+	 * @param initial
+	 *            if true, the new state will be initial; otherwise this state
+	 *            will be non initial.
+	 * @param terminal
+	 *            if true, the new state will be terminal; otherwise this state
+	 *            will be non terminal.
+	 * @return a new state, associated with this automaton. This new state
+	 *         should be used only with this automaton in order to create a new
+	 *         transition for this automaton.
+	 * @see Transition
+	 */
+	public State addState(boolean initial, boolean terminal) {
+
+		State state = stateFactory.create(initial, terminal);
+		if (initial)
+			initials.add(state);
+		if (terminal)
+			terminals.add(state);
+		states.add(state);
+		return state;
+	}
+
+	/**
+	 * Returns the alphabet <em>X</em> associated with this automaton.
+	 * 
+	 * @return the alphabet <em>X</em> associated with this automaton.
+	 */
+	@Override
+	public Set<L> alphabet() {
+		return alphabet;
+	}
+
+	/**
+	 * Returns the set of states <em>Q</em> associated with this automaton.
+	 * 
+	 * @return the set of states <em>Q</em> associated with this automaton.
+	 *         Objects which are contained in this set are instances of class
+	 *         <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> states() {
+		return states;
+	}
+
+	/**
+	 * Returns the set of initial states <em>I</em> associated with this
+	 * automaton.
+	 * 
+	 * @return the set of initial states <em>I</em> associated with this
+	 *         automaton. Objects which are contained in this set are instances
+	 *         of class <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> initials() {
+		return initials;
+	}
+
+	/**
+	 * Returns the set of terminal states <em>T</em> associated with this
+	 * automaton.
+	 * 
+	 * @return set of terminal states <em>T</em> associated with this automaton.
+	 *         Objects which are contained in this set are instances of class
+	 *         <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> terminals() {
+		return terminals;
+	}
+
+	// Computes and return the set of all accessible states, starting
+	// from a given set of states and using transitions
+	// contained in a given Map
+	protected Set<State> access(Set<State> start, Map<Key, Set<Transition<L>>> map) {
+		Set<State> current = start;
+		Set<State> old;
+		do {
+			old = current;
+			current = stateFactory.stateSet();
+			Iterator<State> i = old.iterator();
+			while (i.hasNext()) {
+				State e = i.next();
+				current.add(e);
+				Iterator<L> j = alphabet.iterator();
+				while (j.hasNext()) {
+					Iterator<Transition<L>> k = find(map, e, j.next()).iterator();
+					while (k.hasNext()) {
+						current.add(k.next().end());
+					}
+				}
+			}
+		} while (current.size() != old.size());
+		return current;
+	}
+
+	/**
+	 * Returns the set of all accessible states in this automaton.
+	 * 
+	 * @return the set of all accessible states in this automaton. A state
+	 *         <em>s</em> is accessible if there exists a path from an initial
+	 *         state to <em>s</em>. Objects which are contained in this set are
+	 *         instances of class <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> accessibleStates() {
+		return access(initials, transitions);
+	}
+
+	/**
+	 * Returns the set of states that can be accessed in this automaton starting
+	 * from given set of states
+	 * 
+	 * @param states
+	 *            a non null set of starting states
+	 * @return a - possibly empty - set of accessible states
+	 */
+	public Set<State> accessibleStates(Set<State> states) {
+		return access(states, transitions);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see rationals.Rational#accessibleStates(rationals.State)
+	 */
+	public Set<State> accessibleStates(State state) {
+		Set<State> s = stateFactory.stateSet();
+		s.add(state);
+		return access(s, transitions);
+	}
+
+	/**
+	 * Returns the set of co-accesible states for a given set of states, that is
+	 * the set of states from this automaton from which there exists a path to a
+	 * state in <code>states</code>.
+	 * 
+	 * @param states
+	 *            a non null set of ending states
+	 * @return a - possibly empty - set of coaccessible states
+	 */
+	public Set<State> coAccessibleStates(Set<State> states) {
+		return access(states, reverse);
+	}
+
+	/**
+	 * Returns the set of all co-accessible states in this automaton.
+	 * 
+	 * @return the set of all co-accessible states in this automaton. A state
+	 *         <em>s</em> is co-accessible if there exists a path from this
+	 *         state <em>s</em> to a terminal state. Objects which are contained
+	 *         in this set are instances of class <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> coAccessibleStates() {
+		return access(terminals, reverse);
+	}
+
+	/**
+	 * Returns the set of all states which are co-accessible and accessible in
+	 * this automaton.
+	 * 
+	 * @return the set of all states which are co-accessible and accessible in
+	 *         this automaton. A state <em>s</em> is accessible if there exists
+	 *         a path from an initial state to <em>s</em>. A state <em>s</em> is
+	 *         co-accessible if there exists a path from this state <em>s</em>
+	 *         to a terminal state. Objects which are contained in this set are
+	 *         instances of class <tt>State</tt>.
+	 * @see State
+	 */
+	public Set<State> accessibleAndCoAccessibleStates() {
+		Set<State> ac = accessibleStates();
+		ac.retainAll(coAccessibleStates());
+		return ac;
+	}
+
+	// Computes and return the set of all transitions, starting
+	// from a given state and labelled by a given label
+	// contained in a given Map
+	protected Set<Transition<L>> find(Map<Key, Set<Transition<L>>> m, State e, L l) {
+		Key n = new Key(e, l);
+		if (!m.containsKey(n))
+			return new HashSet<Transition<L>>();
+		return m.get(n);
+	}
+
+	// add a given transition in a given Map
+	protected void add(Map<Key, Set<Transition<L>>> m, Transition<L> t) {
+		Key n = new Key(t.start(), t.label());
+		Set<Transition<L>> s;
+		if (!m.containsKey(n)) {
+			s = new HashSet<>();
+			m.put(n, s);
+		} else
+			s = m.get(n);
+		s.add(t);
+	}
+
+	/**
+	 * Returns the set of all transitions of this automaton
+	 * 
+	 * @return the set of all transitions of this automaton Objects which are
+	 *         contained in this set are instances of class <tt>Transition</tt>.
+	 * @see Transition
+	 */
+	public Set<Transition<L>> delta() {
+		Set<Transition<L>> s = new HashSet<>();
+		for (Set<Transition<L>> tr : transitions.values())
+			s.addAll(tr);
+		return s;
+	}
+
+	/**
+	 * Returns the set of all transitions of this automaton starting from a
+	 * given state and labelled b a given label.
+	 * 
+	 * @param state
+	 *            a state of this automaton.
+	 * @param label
+	 *            a label used in this automaton.
+	 * @return the set of all transitions of this automaton starting from state
+	 *         <tt>state</tt> and labelled by <tt>label</tt>. Objects which are
+	 *         contained in this set are instances of class <tt>Transition</tt>.
+	 * @see Transition
+	 */
+	public Set<Transition<L>> delta(State state, L label) {
+		return find(transitions, state, label);
+	}
+
+	/**
+	 * Returns the set of all transitions from state <code>from</code> to state
+	 * <code>to</code>.
+	 * 
+	 * @param from
+	 *            starting state
+	 * @param to
+	 *            ending state
+	 * @return a Set of Transition objects
+	 */
+	@Override
+	public Set<Transition<L>> deltaFrom(State from, State to) {
+		Set<Transition<L>> t = delta(from);
+		for (Iterator<Transition<L>> i = t.iterator(); i.hasNext();) {
+			Transition<L> tr = i.next();
+			if (!to.equals(tr.end()))
+				i.remove();
+		}
+		return t;
+	}
+
+	/**
+	 * Return all transitions from a State
+	 * 
+	 * @param state
+	 *            start state
+	 * @return a new Set of transitions (maybe empty)
+	 */
+	public Set<Transition<L>> delta(State state) {
+		Set<Transition<L>> s = new HashSet<>();
+		for (L lt : alphabet)
+			s.addAll(delta(state, lt));
+		return s;
+	}
+
+	/**
+	 * Returns all transitions from a given set of states.
+	 * 
+	 * @param s
+	 *            a Set of State objects
+	 * @return a Set of Transition objects
+	 */
+	public Set<Transition<L>> delta(Set<State> s) {
+		Set<Transition<L>> ds = new HashSet<>();
+		for (State st : s)
+			ds.addAll(delta(st));
+		return ds;
+	}
+
+	/**
+	 * Return a mapping from couples (q,q') of states to all (q,l,q')
+	 * transitions from q to q'
+	 * 
+	 * @return a Map
+	 */
+	public Map<Couple, Set<Transition<L>>> couples() {
+		// loop on transition map keys
+		Iterator<Map.Entry<Key, Set<Transition<L>>>> it = transitions.entrySet().iterator();
+		Map<Couple, Set<Transition<L>>> ret = new HashMap<>();
+		while (it.hasNext()) {
+			Map.Entry<Key, Set<Transition<L>>> e = it.next();
+			// get start and end state
+			State st = e.getKey().s;
+			Iterator<Transition<L>> trans = e.getValue().iterator();
+			while (trans.hasNext()) {
+				Transition<L> tr = trans.next();
+				State nd = tr.end();
+				Couple cpl = new Couple(st, nd);
+				Set<Transition<L>> s = ret.get(cpl);
+				if (s == null)
+					s = new HashSet<>();
+				s.add(tr);
+				ret.put(cpl, s);
+			}
+		}
+		return ret;
+	}
+
+	/**
+	 * Returns the set of all transitions of the reverse of this automaton
+	 * 
+	 * @return the set of all transitions of the reverse of this automaton. A
+	 *         reverse of an automaton <em>A = (X , Q , I , T , D)</em> is the
+	 *         automaton <em>A' = (X , Q , T , I , D')</em> where <em>D'</em> is the set <em>{ (q , l , q') | (q' , l , q) in D}</em>. Objects
+	 *         which are contained in this set are instances of class
+	 *         <tt>Transition</tt>.
+	 * @see Transition
+	 */
+	@Override
+	public Set<Transition<L>> deltaMinusOne(State state, L label) {
+		return find(reverse, state, label);
+	}
+
+	/**
+	 * Adds a new transition in this automaton if it is a new transition for
+	 * this automaton. The parameter is considered as a new transition if there
+	 * is no transition in this automaton which is equal to the parameter in the
+	 * sense of method <tt>equals</tt> of class <tt>Transition</tt>.
+	 * 
+	 * @param transition
+	 *            the transition to add.
+	 * @throws NoSuchStateException
+	 *             if <tt>transition</tt> is <tt>null</<tt>
+	 * or if <tt>transition</tt> = <em>(q , l , q')</em> and <em>q</em> or <em>q'</em> does
+	 *             not belong to <em>Q</em> the set of the states of this
+	 *             automaton.
+	 */
+	public void addTransition(Transition<L> transition) throws NoSuchStateException {
+		if (!states.contains(transition.start())
+				|| !states.contains(transition.end()))
+			throw new NoSuchStateException();
+		if (!alphabet.contains(transition.label())) {
+			alphabet.add(transition.label());
+		}
+		add(transitions, transition);
+		add(reverse, new Transition<>(transition.end(), transition.label(), transition.start()));
+	}
+
+	/**
+	 * the project method keeps from the Automaton only the transitions labelled
+	 * with the letters contained in the set alph, effectively computing a
+	 * projection on this alphabet.
+	 * 
+	 * @param alph
+	 *            the alphabet to project on
+	 */
+	public void projectOn(Set<?> alph) {
+		// remove unwanted transitions from ret
+		Iterator<Map.Entry<Key, Set<Transition<L>>>> trans = transitions.entrySet().iterator();
+		Set<Transition<L>> newtrans = new HashSet<>();
+		while (trans.hasNext()) {
+			Map.Entry<Key, Set<Transition<L>>> entry = trans.next();
+			Key k = entry.getKey();
+			Iterator<Transition<L>> tit = entry.getValue().iterator();
+			while (tit.hasNext()) {
+				Transition<?> tr = tit.next();
+				if (!alph.contains(k.l)) {
+					// create epsilon transition
+					newtrans.add(new Transition<L>(k.s, null, tr.end()));
+					// remove transition
+					tit.remove();
+				}
+			}
+		}
+		// add newly created transitions
+		if (!newtrans.isEmpty()) {
+			for (Transition<L> tr : newtrans) {
+				add(transitions, tr);
+				add(reverse, new Transition<>(tr.end(), tr.label(), tr.start()));
+			}
+		}
+		// remove alphabet
+		alphabet.retainAll(alph);
+	}
+
+	/**
+	 * returns a textual representation of this automaton.
+	 * 
+	 * @return a textual representation of this automaton based on the converter
+	 *         <tt>toAscii</tt>.
+	 * @see rationals.converters.toAscii
+	 */
+	public String toString() {
+		return new rationals.converters.toAscii().toString(this);
+	}
+
+	/**
+	 * returns a copy of this automaton.
+	 * 
+	 * @return a copy of this automaton with new instances of states and
+	 *         transitions.
+	 */
+	@Override
+	public Automaton<L, Tr, T> clone() {
+		Automaton<L, Tr, T> b = new Automaton<L, Tr, T>();
+		Map<State, State> map = new HashMap<>();
+		for (State e : states)
+			map.put(e, b.addState(e.isInitial(), e.isTerminal()));
+		for (Transition<L> t : delta()) {
+			try {
+				b.addTransition(new Transition<>(map.get(t.start()), t.label(), map.get(t.end())));
+			} catch (NoSuchStateException x) {
+			}
+		}
+		return b;
+	}
+
+    /**
+     * 
+     * @return the set of labels matching initial states.
+     */
+    public Set<Object> labelledInitials() {
+        return stateLabels.labels(initials());
+    }
+
+    /**
+     * 
+     * @return the set of labels for terminal states.
+     */
+    public Set<Object> labelledTerminals() {
+        return stateLabels.labels(terminals());
+    }
+
+    /**
+     * 
+     * @return labels for states of this automaton.
+     */
+    public Set<Object> labelledStates() {
+        return stateLabels.labels(states);
+    }
+
+    private class Key {
+		private State s;
+
+		private L l;
+
+		protected Key(State s, L l) {
+			this.s = s;
+			this.l = l;
+		}
+
+		public boolean equals(Object o) {
+			if (o == null || !(o instanceof Automaton.Key))
+				return false;
+			Key t = (Key) o;
+			boolean ret = (l == null ? t.l == null : l.equals(t.l))	&& (s == null ? t.s == null : s.equals(t.s));
+			return ret;
+		}
+
+		public int hashCode() {
+			int x, y;
+			if (s == null)
+				x = 0;
+			else
+				x = s.hashCode();
+			if (l == null)
+				y = 0;
+			else
+				y = l.hashCode();
+			return y << 16 | x;
+		}
+	}
+
+	/**
+	 * Returns true if this automaton accepts given word -- ie. sequence of
+	 * letters. Note that this method accepts words with letters not in this
+	 * automaton's alphabet, effectively recognizing all words from any alphabet
+	 * projected to this alphabet.
+	 * <p>
+	 * If you need standard recognition, use
+	 * 
+	 * @see{accept(java.util.List) .
+	 * @param word
+	 * @return
+	 */
+	public boolean prefixProjection(List<L> word) {
+		Set<?> s = stepsProject(word);
+		return !s.isEmpty();
+	}
+
+	/**
+	 * Return the set of steps this automaton will be in after reading word.
+	 * Note this method skips letters not in alphabet instead of rejecting them.
+	 * 
+	 * @param l
+	 * @return
+	 */
+	public Set<State> stepsProject(List<L> word) {
+		Set<State> s = initials();
+		Iterator<L> it = word.iterator();
+		while (it.hasNext()) {
+			L o = it.next();
+			if (!alphabet.contains(o))
+				continue;
+			s = step(s, o);
+			if (s.isEmpty())
+				return s;
+		}
+		return s;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see rationals.Acceptor#accept(java.util.List)
+	 */
+	@Override
+	public boolean accept(List<L> word) {
+		Set<State> s = TransformationsToolBox.epsilonClosure(steps(word), this);
+		s.retainAll(terminals());
+		return !s.isEmpty();
+	}
+
+	/**
+	 * Return true if this automaton can accept the given word starting from
+	 * given set. <em>Note</em> The ending state(s) need not be terminal for
+	 * this method to return true.
+	 * 
+	 * @param state
+	 *            a starting state
+	 * @param word
+	 *            a List of objects in this automaton's alphabet
+	 * @return true if there exists a path labelled by word from s to at least
+	 *         one other state in this automaton.
+	 */
+	public boolean accept(State state, List<L> word) {
+		Set<State> s = stateFactory.stateSet();
+		s.add(state);
+		return !steps(s, word).isEmpty();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see rationals.Acceptor#steps(java.util.List)
+	 */
+	@Override
+	public Set<State> steps(List<L> word) {
+		Set<State> s = TransformationsToolBox.epsilonClosure(initials(), this);
+		return steps(s, word);
+	}
+
+	/**
+	 * Return the set of states this automaton will be in after reading the word
+	 * from start states s.
+	 * 
+	 * @param s
+	 *            the set of starting states
+	 * @param word
+	 *            the word to read.
+	 * @return the set of reached states.
+	 */
+	@Override
+	public Set<State> steps(Set<State> s, List<L> word) {
+		Iterator<L> it = word.iterator();
+		while (it.hasNext()) {
+			L o = it.next();
+			s = step(s, o);
+			if (s.isEmpty())
+				return s;
+		}
+		return s;
+	}
+
+	/**
+	 * Return the set of states this automaton will be in after reading the word
+	 * from single start state s.
+	 * 
+	 * @param st
+	 *            the starting state
+	 * @param word
+	 *            the word to read.
+	 * @return the set of reached states.
+	 */
+	@Override
+	public Set<State> steps(State st, List<L> word) {
+		Set<State> s = stateFactory.stateSet();
+		s.add(st);
+		Iterator<L> it = word.iterator();
+		while (it.hasNext()) {
+			L o = it.next();
+			s = step(s, o);
+			if (s.isEmpty())
+				return s;
+		}
+		return s;
+	}
+
+	/**
+	 * Return the list of set of states this automaton will be in after reading
+	 * word from start state. Is start state is null, assume reading from
+	 * initials().
+	 * 
+	 * @param word
+	 * @param start
+	 */
+	@Override
+	public List<Set<State>> traceStates(List<L> word, State start) {
+		List<Set<State>> ret = new ArrayList<Set<State>>();
+		Set<State> s = null;
+		if (start != null) {
+			s = stateFactory.stateSet();
+			s.add(start);
+		} else {
+			s = initials();
+		}
+		Iterator<L> it = word.iterator();
+		while (it.hasNext()) {
+			L o = it.next();
+			if (!alphabet.contains(o))
+				continue;
+			s = step(s, o);
+			ret.add(s);
+			if (s.isEmpty())
+				return null;
+		}
+		return ret;
+	}
+
+	/**
+	 * Returns the size of the longest word recognized by this automaton where
+	 * letters not belonging to its alphabet are ignored.
+	 * 
+	 * 
+	 * @param word
+	 * @return
+	 */
+	public int longestPrefixWithProjection(List<L> word) {
+		int lret = 0;
+		Set<State> s = initials();
+		Iterator<L> it = word.iterator();
+		while (it.hasNext()) {
+			L o = it.next();
+			if ((o == null) || !alphabet.contains(o)) {
+				lret++;
+				continue;
+			}
+			s = step(s, o);
+			if (s.isEmpty())
+				break;
+			lret++;
+		}
+		return lret;
+	}
+
+	/**
+	 * Return the set of states accessible in one transition from given set of
+	 * states s and letter o.
+	 * 
+	 * @param s
+	 * @param o
+	 * @return
+	 */
+	public Set<State> step(Set<State> s, L o) {
+		Set<State> ns = stateFactory.stateSet();
+		Set<State> ec = TransformationsToolBox.epsilonClosure(s, this);
+		Iterator<State> it = ec.iterator();
+		while (it.hasNext()) {
+			State st = it.next();
+			Iterator<?> it2 = delta(st).iterator();
+			while (it2.hasNext()) {
+				Transition<?> tr = (Transition<?>) it2.next();
+				if (tr.label() != null && tr.label().equals(o))
+					ns.add(tr.end());
+			}
+		}
+		return ns;
+	}
+
+	/**
+	 * @param tr
+	 * @param msg
+	 */
+	public void updateTransitionWith(Transition<L> tr, L msg) {
+		L lbl = tr.label();
+		alphabet.remove(lbl);
+		alphabet.add(msg);
+		/* update transition map */
+		Key k = new Key(tr.start(), lbl);
+		Set<Transition<L>> s = transitions.remove(k);
+		if (s != null)
+			transitions.put(new Key(tr.start(), msg), s);
+		/* update reverse map */
+		k = new Key(tr.end(), lbl);
+		s = reverse.remove(k);
+		if (s != null)
+			reverse.put(new Key(tr.end(), msg), s);
+		tr.setLabel(msg);
+	}
+
+	/**
+	 * @param st
+	 * @return
+	 */
+	@Override
+	public Set<Transition<L>> deltaMinusOne(State st) {
+		Set<Transition<L>> s = new HashSet<>();
+		Iterator<L> alphit = alphabet().iterator();
+		while (alphit.hasNext()) {
+			s.addAll(deltaMinusOne(st, alphit.next()));
+		}
+		return s;
+	}
+
+	/**
+	 * Enumerate all prefix of words of length lower or equal than i in this
+	 * automaton. This method takes exponential time and space to execute: <em>
+   * use with care !</em>
+	 * .
+	 * 
+	 * @param i
+	 *            maximal length of words.
+	 * @return a Set of List of Object
+	 */
+	public Set<List<L>> enumerate(int ln) {
+		Set<List<L>> ret = new HashSet<>();
+		class EnumState {
+			/**
+			 * @param s
+			 * @param list
+			 */
+			public EnumState(State s, List<L> list) {
+				st = s;
+				word = new ArrayList<L>(list);
+			}
+
+			State st;
+
+			List<L> word;
+		}
+		;
+		LinkedList<EnumState> ll = new LinkedList<EnumState>();
+		List<L> cur = new ArrayList<>();
+		for (Iterator<State> i = initials.iterator(); i.hasNext();) {
+			State s = i.next();
+			if (s.isTerminal())
+				ret.add(new ArrayList<L>());
+			ll.add(new EnumState(s, cur));
+		}
+
+		do {
+			EnumState st = ll.removeFirst();
+			Set<Transition<L>> trs = delta(st.st);
+			List<L> word = st.word;
+			for (Iterator<Transition<L>> k = trs.iterator(); k.hasNext();) {
+				Transition<L> tr = k.next();
+				word.add(tr.label());
+				if (word.size() <= ln) {
+					EnumState en = new EnumState(tr.end(), word);
+					ll.add(en);
+					ret.add(en.word);
+				}
+				word.remove(word.size() - 1);
+			}
+		} while (!ll.isEmpty());
+		return ret;
+	}
+
+	/**
+	 * Create a new state with given label. The state is created with as neither
+	 * initial nor terminal.
+	 * 
+	 * @param label
+	 *            the state's label. May not be null.
+	 * @return the newly created state.
+	 */
+	public State state(L label) {
+		State s = stateLabels.state(label);
+		if (s == null) {
+			s = stateFactory.create(false, false, label);
+			states.add(s);
+			stateLabels.bind(s, label);
+		}
+		return s;
+	}
+
+	/**
+	 * Starts creation of a new transition from the given state. Note that the
+	 * state is created with given label if it does not exists.
+	 * 
+	 * @param o
+	 *            the label of state to create transition from. may not be null.
+	 * @return a TransitionBuilder that can be used to create a new transition.
+	 */
+	public T from(L o) {
+		return builder.build(state(o), this);
+	}
+
+	public void setBuilder(Builder<L, Tr, T> t) {
+		this.builder = t;
+		this.builder.setAutomaton(this);
+	}
+
+	public void build(State from, L l, State to)
+			throws NoSuchStateException {
+		addTransition(this.builder.build(from, l, to));
+	}
+}
diff --git a/extra/jautomata-core/rationals/AutomatonRunListener.java b/extra/jautomata-core/rationals/AutomatonRunListener.java
new file mode 100755
index 0000000000..7dd2643814
--- /dev/null
+++ b/extra/jautomata-core/rationals/AutomatonRunListener.java
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2003 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Set;
+
+/**
+ * An interface to communicate run events.
+ * <p>
+ * This interface should be implemented by objects interested in being notified
+ * of run events, that is the firing of transitions during a run of an automaton.
+ * 
+ * @version $Id: AutomatonRunListener.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface AutomatonRunListener {
+
+    /**
+     * Callback method for notification of fire events occuring during the 
+     * run of an automaton.
+     * 
+     * @param automatonutomaton where the event took place
+     * @param transitions the set of transitions which have been fired
+     * @param o the object effectively "read" for firing transitions 
+     */
+    public void fire(Automaton automaton,Set transitions,Object o);
+
+}
+
+/* 
+ * $Log: AutomatonRunListener.java,v $
+ * Revision 1.2  2004/07/23 14:36:34  bailly
+ * ajout setTag
+ *
+ * Revision 1.1  2004/07/23 11:59:17  bailly
+ * added listener interfaces
+ *
+*/
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/AutomatonRunner.java b/extra/jautomata-core/rationals/AutomatonRunner.java
new file mode 100755
index 0000000000..53bd4202f0
--- /dev/null
+++ b/extra/jautomata-core/rationals/AutomatonRunner.java
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2003 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+/**
+ * An interface for objects running automatons
+ * <p>
+ * This interface essentially provide a way to communicate with {@link AutomatonRunListener}
+ * objects for notifying run events
+ * 
+ * @author nono
+ * @version $Id: AutomatonRunner.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface AutomatonRunner {
+
+    /**
+     * Adds a listener to this runner
+     * 
+     * @param l the listener to add - may no be null
+     */
+    public void addRunListener(AutomatonRunListener l);
+    
+    /**
+     * Remove a listener from this runner
+     * 
+     * @param l the listener to remove
+     */
+    public void removeRunListener(AutomatonRunListener l);
+}
+
+/* 
+ * $Log: AutomatonRunner.java,v $
+ * Revision 1.1  2004/07/23 11:59:17  bailly
+ * added listener interfaces
+ *
+*/
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/Builder.java b/extra/jautomata-core/rationals/Builder.java
new file mode 100755
index 0000000000..3c5d84d899
--- /dev/null
+++ b/extra/jautomata-core/rationals/Builder.java
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+/**
+ * An interface for easier creation of automata.
+ */
+public interface Builder<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+
+	/**
+	 * Factory method.
+	 * 
+	 * @param label
+	 * @param auto
+	 * @return
+	 */
+	T build(State label, Automaton<L, Tr, T> auto);
+
+	/**
+	 * Sets the label of the transition.
+	 * 
+	 * @param label
+	 * @return this transition builder.
+	 */
+	T on(L label);
+
+	/**
+	 * Sets the end state and terminates transition construction. This method
+	 * effectively adds the transition to the automaton.
+	 * 
+	 * @param o
+	 *            the label of the end state.
+	 */
+	T go(L o);
+
+	/**
+	 * Adds a new transition in the automaton that loops on current label and
+	 * from state.
+	 * 
+	 * @return
+	 */
+	T loop();
+
+	/**
+	 * Resets this builder to another starting state. Note that the state is
+	 * created if needed.
+	 * 
+	 * @param label
+	 *            the state to start from.
+	 * @return this builder.
+	 */
+	T from(L label);
+
+	/**
+	 * Build a transition according to the specific logic of this builder.
+	 * 
+	 * @param from
+	 * @param lable
+	 * @param to
+	 * @return
+	 */
+	Tr build(State from, L label, State to);
+
+	void setAutomaton(Automaton<L, Tr, T> a);
+}
diff --git a/extra/jautomata-core/rationals/Couple.java b/extra/jautomata-core/rationals/Couple.java
new file mode 100755
index 0000000000..f78c5c8b5d
--- /dev/null
+++ b/extra/jautomata-core/rationals/Couple.java
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+public class Couple {
+
+    private final int hash;
+    
+  public final State from;
+
+  public final State to;
+
+  public Couple(State from, State to) {
+    this.from = from;
+    this.to = to;
+    this.hash = (from.hashCode() << 16) ^ to.hashCode();
+  }
+
+  public State getFrom() {
+    return from;
+  }
+
+  public State getTo() {
+    return to;
+  }
+
+  public boolean equals(Object o) {
+    if ((o != null) && (o instanceof Couple)) {
+      Couple c = (Couple) o;
+      return from.equals(c.from) && to.equals(c.to);
+    }
+    return false;
+  }
+
+  public int hashCode() {
+    return hash;
+  }
+}
+
+/*
+ * $Log: Couple.java,v $
+ * Revision 1.2  2004/09/21 11:50:28  bailly
+ * added interface BinaryTest
+ * added class for testing automaton equivalence (isomorphism of normalized automata)
+ * added computation of RE from Automaton
+ * Revision 1.1 2004/07/19 06:39:02 bailly made Automaton,
+ * State and Transition subclasses of Graph API modified StateFactory API
+ *  
+ */
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/DefaultStateFactory.java b/extra/jautomata-core/rationals/DefaultStateFactory.java
new file mode 100755
index 0000000000..4247b24cda
--- /dev/null
+++ b/extra/jautomata-core/rationals/DefaultStateFactory.java
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class is used by Automaton objects to create new states on A user can
+ * implement its own version of StateFactory by providing an implementation for
+ * createState
+ *
+ * @author Arnaud.Bailly - bailly@lifl.fr
+ */
+public class DefaultStateFactory<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements StateFactory<L, Tr, T>, Cloneable {
+
+    private int id = 0;
+
+    private Automaton<L, Tr, T> automaton;
+	
+    public class DefaultState implements State {
+
+        public final int i;
+
+        boolean initial;
+
+        boolean terminal;
+
+        Automaton<L, Tr, T> a;
+
+        private Object label = null;
+
+        DefaultState(int i, boolean initial, boolean terminal) {
+            this.i = i;
+            this.a = automaton;
+            this.initial = initial;
+            this.terminal = terminal;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see rationals.State#setInitial(boolean)
+         */
+        public State setInitial(boolean initial) {
+            this.initial = initial;
+            if (initial)
+                a.initials().add(this);
+            else
+                a.initials().remove(this);
+            return this;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see rationals.State#setTerminal(boolean)
+         */
+        public State setTerminal(boolean terminal) {
+            this.terminal = terminal;
+            if (terminal)
+                a.terminals().add(this);
+            else
+                a.terminals().remove(this);
+            return this;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see rationals.State#isInitial()
+         */
+        public boolean isInitial() {
+            return this.initial;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see rationals.State#isTerminal()
+         */
+        public boolean isTerminal() {
+            return this.terminal;
+        }
+
+        @Override
+        public String toString() {
+            return label == null ? Integer.toString(i) : label.toString();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof DefaultStateFactory.DefaultState)) return false;
+            @SuppressWarnings("unchecked")
+			DefaultState ds = (DefaultState) o;
+            return (ds.i == i) && (a == ds.a);
+        }
+
+        @Override
+        public int hashCode() {
+            return i;
+        }
+    }
+    
+    DefaultStateFactory(Automaton<L, Tr, T> a) {
+        this.automaton = a;
+    }
+
+    /**
+     * Creates a new state which is initial and terminal or not, depending on the
+     * value of parameters.
+     *
+     * @param initial  if true, this state will be initial; otherwise this state will be non initial.
+     * @param terminal if true, this state will be terminal; otherwise this state will be non terminal.
+     */
+    public State create(boolean initial, boolean terminal) {
+        return new DefaultState(id++, initial, terminal);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.StateFactory#stateSet()
+     */
+    public Set<State> stateSet() {
+    	return new HashSet<State>();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.StateFactory#stateSet(java.util.Set)
+     */
+    @Override
+    public Set<State> stateSet(Set<State> s) {
+    	Set<State> result = new HashSet<>();
+    	result.addAll(s);
+        return s;
+    }
+
+    public DefaultStateFactory<L, Tr, T> clone() {
+        try {
+        	@SuppressWarnings("unchecked")
+			DefaultStateFactory<L, Tr, T> cl = (DefaultStateFactory<L, Tr, T>) super.clone();
+            cl.id = 0;
+            return cl;
+        } catch (CloneNotSupportedException ex) {
+            throw new Error(ex);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.StateFactory#setAutomaton(rationals.Automaton)
+     */
+    public void setAutomaton(Automaton<L, Tr, T> automaton) {
+        this.automaton = automaton;
+    }
+
+    @Override
+    public State create(boolean initial, boolean terminal, Object label) {
+        DefaultState defaultState = new DefaultState(id++, initial, terminal);
+        defaultState.label = label;
+        return defaultState;
+    }
+}
diff --git a/extra/jautomata-core/rationals/DefaultSynchronization.java b/extra/jautomata-core/rationals/DefaultSynchronization.java
new file mode 100755
index 0000000000..376adb9f74
--- /dev/null
+++ b/extra/jautomata-core/rationals/DefaultSynchronization.java
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Default synchronization scheme for standard automaton. This class
+ * synchronizes the labels of two transitions if they are equal as returned by
+ * {@see java.lang.Object#equals(java.lang.Object)}.
+ * 
+ * @author nono
+ * @version $Id: DefaultSynchronization.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class DefaultSynchronization implements Synchronization {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.Synchronization#synchronize(rationals.Transition,
+     *      rationals.Transition)
+     */
+    public Object synchronize(Object t1, Object t2) {
+        return t1 == null ? null : (t1.equals(t2) ? t1 : null);
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.Synchronization#synchronizing(java.util.Set, java.util.Set)
+     */
+    public Set synchronizable(Set a, Set b) {
+        Set r = new HashSet(a);
+        r.retainAll(b);
+        return r;
+    }
+
+    /*
+     * TO VERIFY (non-Javadoc)
+     * @see rationals.Synchronization#synchronizing(java.util.Collection)
+     */
+    public Set synchronizing(Collection alphabets) {
+        Set niou = new HashSet();
+        /*
+         * synchronization set is the union of pairwise 
+         * intersection of the sets in alphl
+         */
+        for(Iterator i = alphabets.iterator();i.hasNext();) {
+            Set s = (Set)i.next();
+            for(Iterator j = alphabets.iterator();j.hasNext();) {
+                Set b = (Set)j.next();
+                niou.addAll(synchronizable(s,b));
+            }
+        }
+        return niou;
+    }
+
+    public boolean synchronizeWith(Object object, Set alph) {
+        return alph.contains(object);
+    }
+
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/MixPlay.java b/extra/jautomata-core/rationals/MixPlay.java
new file mode 100755
index 0000000000..bd6eb1f271
--- /dev/null
+++ b/extra/jautomata-core/rationals/MixPlay.java
@@ -0,0 +1,347 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * This class implements an algorithm for finding a synchronizing
+ * word given a target letter.
+ * 
+ * @author bailly
+ * @version $Id: MixPlay.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class MixPlay implements AutomatonRunner {
+
+    class MixException extends Exception {
+
+        List word;
+
+        List states;
+
+        MixException(List w, List st) {
+            this.word = w;
+            this.states = st;
+        }
+    }
+
+    private Set explored;
+
+    private final static Random random = new Random();
+
+    private final static Transition[] trmodel = new Transition[0];
+
+    private int upperBound = 1;
+
+    private Object target;
+
+    private List autos;
+
+    private Synchronization sync;
+
+    private Set syncAlphabet;
+
+    private Set listeners = new HashSet();
+
+    /*
+     * current set of states
+     */
+    private StatesTuple current;
+
+    /**
+     * Construct a mix with the given list of automata.
+     * 
+     * @param autos a List of automaton objects
+     */
+    public MixPlay(List autos) {
+        this.autos = autos;
+        this.sync = new DefaultSynchronization();
+    }
+
+    /**
+     * Construct an empty mix.
+     *
+     */
+    public MixPlay() {
+        this.autos = new ArrayList();
+        this.sync = new DefaultSynchronization();
+    }
+
+    /**
+     * Adds a new automaton to this mix.
+     * 
+     * @param a
+     */
+    public void addAutomaton(Automaton a) {
+        this.autos.add(a);
+    }
+
+    /**
+     * Reset the state of this mix.
+     * The current state is set to the start states of the 
+     * mixed automata.
+     */
+    public void reset() {
+        this.explored = new HashSet();
+        this.target = null;
+        Set[] states = new Set[autos.size()];
+        int i = 0;
+        Set synalph = new HashSet();
+        List alphl = new ArrayList();
+        for (Iterator it = autos.iterator(); it.hasNext();) {
+            Automaton a = (Automaton) it.next();
+            upperBound *= a.states().size();
+            states[i++] = a.initials();
+            Set alph = a.alphabet();
+            alphl.add(alph);
+        }
+        /* make synalph */
+        this.syncAlphabet = sync.synchronizing(alphl);
+        this.current = new StatesTuple(states);
+    }
+
+    /**
+     * Try to play for given target with given start states in each automaton.
+     * 
+     * @param target
+     *            the targeted letter
+     * @return a list of letters ending in <code>target</code>
+     */
+    public List play(Object target) throws Exception {
+        this.target = target;
+        List word = new ArrayList();
+        List tuples = new ArrayList();
+        /* initial states */
+        try {
+            doPlay(word, tuples, current);
+        } catch (MixException mex) {
+            /* notify listeners of synchronization */
+            notify(mex.word, mex.states);
+            return mex.word;
+        }
+        return new ArrayList();
+    }
+
+    /**
+     * Notify each listener of the fired transitions when a word is found.
+     * 
+     * @param word
+     * @param states
+     */
+    private void notify(List word, List states) {
+        if (listeners.isEmpty() || word.isEmpty() || states.isEmpty())
+            return;
+        Iterator wit = word.iterator();
+        Iterator sit = states.iterator();
+        for (; sit.hasNext();) {
+            StatesTuple tup = (StatesTuple) sit.next();
+            Object lt = wit.next();
+            int ln = tup.sets.length;
+            /* fire event */
+            for (int i = 0; i < ln; i++) {
+                Automaton a = (Automaton) autos.get(i);
+                Set trans = new HashSet();
+                for (Iterator stit = tup.sets[i].iterator(); stit.hasNext();)
+                    trans.addAll(a.delta((State) stit.next(), lt));
+                for (Iterator lit = listeners.iterator(); lit.hasNext();)
+                    ((AutomatonRunListener) lit.next()).fire(a, trans, lt);
+            }
+        }
+    }
+
+    /**
+     * Recursive play function
+     * 
+     * @param word current accumulated word
+     * @param tuples current accumulated list of states tuples
+     * @param states current states tuple
+     */
+    private void doPlay(List word, List tuples, StatesTuple states)
+            throws MixException {
+        /* set current states*/
+        System.err.println("in states "+ states);
+        current = states;
+        if (!word.isEmpty() && word.get(word.size() - 1).equals(target))
+            throw new MixException(word, tuples);
+        /* stop exploring on loop */
+        if (explored.contains(states))
+            return;
+        else
+            explored.add(states);
+        /* contains already tested transitions */
+        Set s = new HashSet();
+        /* list of transitions */
+        for (int i = 0; i < states.sets.length; i++) {
+            Transition[] trs = (Transition[]) ((Automaton) autos.get(i)).delta(
+                    states.sets[i]).toArray(trmodel);
+            int ln = trs.length;
+            int k = random.nextInt(ln);
+            for (int j = 0; j < ln; j++) {
+                Transition tr = trs[(k + j) % ln];
+                System.err.println("trying random transition "+ tr);
+                if (s.contains(tr))
+                    continue;
+                s.add(tr);
+                /* check synchronization */
+                if (!checkSynchronizableWith(tr.label(), states))
+                    continue;
+                /* check early rejection */
+                if (!checkAccessibleWith(tr.label(), states))
+                    continue;
+                /* ok - try this transition */
+                StatesTuple tup = advanceWith(tr.label(), states);
+                /* recurse - an exception is thrown if a match is found */
+                word.add(tr.label());
+                tuples.add(states);
+                System.err.println("Trying " + word);
+                doPlay(word, tuples, tup);
+                System.err.println("No way for " + word);
+                word.remove(word.size() - 1);
+                tuples.remove(tuples.size() - 1);
+            }
+        }
+    }
+
+    /**
+     * Checks synchronization of automaton on this letter
+     * 
+     * @param object
+     * @param states
+     * @return
+     */
+    private boolean checkSynchronizableWith(Object object, StatesTuple states) {
+        if (!syncAlphabet.contains(object))
+            return true;
+        for (int i = 0; i < states.sets.length; i++) {
+            Automaton auto = (Automaton) autos.get(i);
+            if (!sync.synchronizeWith(object, auto.alphabet()))
+                continue;
+            /*
+             * compute synchronizing transitions
+             */
+            Set s = auto.delta(states.sets[i]);
+            Set adv = auto.getStateFactory().stateSet();
+            for (Iterator j = s.iterator(); j.hasNext();) {
+                Transition tr = (Transition) j.next();
+                Object lbl = tr.label();
+                if (sync.synchronize(lbl, object) != null)
+                    adv.add(tr.end());
+            }
+            if (adv.isEmpty())
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks that, if object is in the alphabet of an automaton, firing of
+     * transation does not preclude access of target
+     * 
+     * @param object
+     * @param states
+     * @return
+     */
+    private boolean checkAccessibleWith(Object object, StatesTuple states) {
+        return true;
+    }
+
+    /**
+     * @param object
+     * @param states
+     * @return
+     */
+    private StatesTuple advanceWith(Object object, StatesTuple states) {
+        Set[] nstates = new Set[autos.size()];
+        for (int i = 0; i < states.sets.length; i++) {
+            Automaton auto = (Automaton) autos.get(i);
+            /*
+             * compute synchronizing transitions
+             */
+            Set s = auto.delta(states.sets[i]);
+            Set adv = auto.getStateFactory().stateSet();
+            for (Iterator j = s.iterator(); j.hasNext();) {
+                Transition tr = (Transition) j.next();
+                Object lbl = tr.label();
+                if (sync.synchronize(lbl, object) != null)
+                    adv.add(tr.end());
+            }
+            nstates[i] = adv.isEmpty() ? states.sets[i] : adv;
+        }
+        return new StatesTuple(nstates);
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see rationals.AutomatonRunner#addRunListener(rationals.AutomatonRunListener)
+     */
+    public void addRunListener(AutomatonRunListener l) {
+        listeners.add(l);
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see rationals.AutomatonRunner#removeRunListener(rationals.AutomatonRunListener)
+     */
+    public void removeRunListener(AutomatonRunListener l) {
+        listeners.remove(l);
+    }
+
+    /**
+     * 
+     * @return
+     */
+    public Synchronization getSynchronization() {
+        return sync;
+    }
+
+    /**
+     * 
+     * @param sync
+     */
+    public void setSynchronization(Synchronization sync) {
+        this.sync = sync;
+    }
+}
+/*
+ * Created on Apr 9, 2004
+ * 
+ * $Log: MixPlay.java,v $ Revision 1.7 2004/08/31 14:16:22 bailly *** empty log
+ * message ***
+ * 
+ * Revision 1.6 2004/04/15 11:51:00 bailly added randomization of MixPlay TODO:
+ * check accessibility of synchronization letter
+ * 
+ * Revision 1.5 2004/04/14 10:02:14 bailly *** empty log message ***
+ * 
+ * Revision 1.4 2004/04/14 07:33:43 bailly correct version of synchronization on
+ * the fly
+ * 
+ * Revision 1.3 2004/04/13 07:08:38 bailly *** empty log message ***
+ * 
+ * Revision 1.2 2004/04/12 16:37:59 bailly worked on synchronization algorithm :
+ * begins to work but there are still problems with proper implementation of
+ * backtracking
+ * 
+ * Revision 1.1 2004/04/09 15:51:50 bailly Added algorithm for computing a mixed
+ * word from several automata (to be verified)
+ *  
+ */
diff --git a/extra/jautomata-core/rationals/NoSuchStateException.java b/extra/jautomata-core/rationals/NoSuchStateException.java
new file mode 100755
index 0000000000..6a7acd36f2
--- /dev/null
+++ b/extra/jautomata-core/rationals/NoSuchStateException.java
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+/** Instances of this class are thrown by the method
+ * <tt>addTransition</tt> in class <tt>Automaton</tt>
+ * when an attempt is made to use a state which does
+ * not belong to the correct automaton.
+ * @author yroos@lifl.fr
+ * @version 1.0
+ * @see Automaton
+ */
+public class NoSuchStateException extends Exception {
+
+	private static final long serialVersionUID = 1L;
+
+	public NoSuchStateException() {
+		super();
+	}
+
+	/**
+	 * @param message
+	 */
+	public NoSuchStateException(String message) {
+		super(message);
+	}
+
+	/**
+	 * @param message
+	 * @param cause
+	 */
+	public NoSuchStateException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+	/**
+	 * @param cause
+	 */
+	public NoSuchStateException(Throwable cause) {
+		super(cause);
+	}
+}
diff --git a/extra/jautomata-core/rationals/RandomAutomaton.java b/extra/jautomata-core/rationals/RandomAutomaton.java
new file mode 100755
index 0000000000..02c42f279e
--- /dev/null
+++ b/extra/jautomata-core/rationals/RandomAutomaton.java
@@ -0,0 +1,168 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Instances of this class are random automata. A RandomAutomaton is generated
+ * according to following parameters :
+ * <ul>
+ * <li>The number of states in the automaton</li>
+ * <li>The number of terminal states</li>
+ * <li>The alphabet : if the alphabet contains a <code>null</code> element,
+ * it will be used and the resulting automaton will contain epsilon-transitions
+ * </li>
+ * <li>The mean transition density which is the number of transitions in the
+ * automaton divided by the square of the number of states times the size of the
+ * alphabet</li>
+ * <li>The standard deviation of the transition density</li>
+ * <li>A flag indicating if the automaton should be deterministic or not. Note
+ * that if the alphabet contains epsilon, then the resulting automaton will most
+ * probably be non-deterministic even if this flag is set.</li>
+ * </ul>
+ * The result is an - non reduced - automaton with a single start state and
+ * random transitions following a normal distribution according to preceding
+ * parameters over the alphabet.
+ * 
+ * @version $Id: RandomAutomaton.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class RandomAutomaton<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> extends Automaton<L, Tr, T> {
+
+    private static final Random rand = new Random();
+
+    private int nstate;
+
+    private int fstate;
+
+    private L[] alph;
+
+    private double density;
+
+    private double deviation;
+
+    /**
+     * Construct a RandomAutomaton according to the given parameters.
+     * 
+     * @param nstate
+     *            number of total states
+     * @param fstate
+     *            number of final states
+     * @param alphabet
+     *            alphabet
+     * @param density
+     *            mean transition density
+     * @param deviation
+     *            transition density standard deviation
+     * @param det
+     *            is the result deterministic
+     */
+    public RandomAutomaton(int nstate, int fstate, L[] alph, double density, double deviation, boolean det) {
+        this.nstate = nstate;
+        this.fstate = fstate;
+        this.alph = alph;
+        this.density = density;
+        this.deviation = deviation;
+        if (det)
+            makeDFA();
+        else
+            makeNFA();
+    }
+
+    /**
+     *  
+     */
+    private void makeNFA() {
+        /* create initial state and other states */
+    	addState(true, false);
+        for (int i = 0; i < fstate; i++)
+            addState(false, true);
+        for (int i = fstate; i < nstate; i++)
+            addState(false, false);
+        State[] sts = states().toArray(new State[nstate + 1]);
+        /* create transitions */
+        Iterator<State> it = states().iterator();
+        while (it.hasNext()) {
+            State from = it.next();
+            int c = alph.length * sts.length * sts.length;
+            /* number of transitions from this state to other state */
+            int nt = (int) (c * (deviation * rand.nextGaussian() + density));
+            for (int i = 0; i < nt; i++) {
+                State to = sts[rand.nextInt(sts.length)];
+                L lbl = alph[rand.nextInt(alph.length)];
+                try {
+                    /* create transition */
+                    addTransition(new Transition<L>(from, lbl, to));
+                } catch (NoSuchStateException e1) {
+                }
+            }
+        }
+    }
+
+    /**
+     *  
+     */
+    private void makeDFA() {
+        /* create initial state and other states */
+        State init = addState(true, false);
+        List<State> todo = new ArrayList<>();
+        List<State> done = new ArrayList<>();
+        int fs = fstate;
+        int ns = nstate;
+        todo.add(init);
+        while (ns > 0) {
+            /* pop state */
+            State from = (State) todo.remove(0);
+            done.add(from);
+            /* list for alph */
+            List<L> l = new ArrayList<>(Arrays.asList(alph));
+            /* number of transitions from this state to other state */
+            int nt = (int) (deviation * rand.nextGaussian() + density);
+            for (int i = 0; i < nt && !l.isEmpty(); i++) {
+                /*
+                 * select a state : this an already visited state with
+                 * probability (done.size() / nstate)
+                 */
+                State to = null;
+                double r = rand.nextDouble() * (nstate - 1);
+                if ((int) r < done.size()) {
+                    to = done.get((int) r);
+                } else {
+                    /*
+                     * state is final with probability fs / ns
+                     */
+                    r = rand.nextDouble() * ns;
+                    to = addState(false, r < fs);
+                    todo.add(to);
+                    ns--;
+                    if (r < fs)
+                        fs--;
+                }
+                L lbl = l.remove(rand.nextInt(l.size()));
+                try {
+                    /* create transition */
+                    addTransition(new Transition<>(from, lbl, to));
+                } catch (NoSuchStateException e1) {
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/Rational.java b/extra/jautomata-core/rationals/Rational.java
new file mode 100755
index 0000000000..8e0cbcd1e7
--- /dev/null
+++ b/extra/jautomata-core/rationals/Rational.java
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Set;
+
+/**
+ * @version $Id: Rational.java 10 2007-05-30 17:25:00Z oqube $
+ */
+public interface Rational<L> {
+  /**
+   * Returns a new instance of state which will be initial and terminal or not
+   * depending of parameters.
+   * 
+   * @param initial
+   *          if true, the new state will be initial; otherwise this state will
+   *          be non initial.
+   * @param terminal
+   *          if true, the new state will be terminal; otherwise this state will
+   *          be non terminal.
+   * @return a new state, associated with this automaton. This new state should
+   *         be used only with this automaton in order to create a new
+   *         transition for this automaton.
+   * @see Transition
+   */
+  State addState(boolean initial, boolean terminal);
+
+  /**
+   * Returns the alphabet <em>X</em> associated with this automaton.
+   * 
+   * @return the alphabet <em>X</em> associated with this automaton.
+   */
+  Set<L> alphabet();
+
+  /**
+   * Returns the set of states <em>Q</em> associated with this automaton.
+   * 
+   * @return the set of states <em>Q</em> associated with this automaton.
+   *         Objects which are contained in this set are instances of class
+   *         <tt>State</tt>.
+   * @see State
+   */
+  Set<State> states();
+
+  /**
+   * Returns the set of initial states <em>I</em> associated with this
+   * automaton.
+   * 
+   * @return the set of initial states <em>I</em> associated with this
+   *         automaton. Objects which are contained in this set are instances of
+   *         class <tt>State</tt>.
+   * @see State
+   */
+  Set<State> initials();
+
+  /**
+   * Returns the set of terminal states <em>T</em> associated with this
+   * automaton.
+   * 
+   * @return set of terminal states <em>T</em> associated with this automaton.
+   *         Objects which are contained in this set are instances of class
+   *         <tt>State</tt>.
+   * @see State
+   */
+  Set<State> terminals();
+
+  /**
+   * Returns the set of all accessible states in this automaton.
+   * 
+   * @return the set of all accessible states in this automaton. A state
+   *         <em>s</em> is accessible if there exists a path from an initial
+   *         state to <em>s</em>. Objects which are contained in this set are
+   *         instances of class <tt>State</tt>.
+   * @see State
+   */
+  Set<State> accessibleStates();
+
+  /**
+   * Returns the set of states that can be accessed in this automaton starting
+   * from given set of states
+   * 
+   * @param states
+   *          a non null set of starting states
+   * @return a - possibly empty - set of accessible states
+   */
+  Set<State> accessibleStates(Set<State> states);
+
+  /**
+   * Returns the set of co-accesible states for a given set of states, that is
+   * the set of states from this automaton from which there exists a path to a
+   * state in <code>states</code>.
+   * 
+   * @param states
+   *          a non null set of ending states
+   * @return a - possibly empty - set of coaccessible states
+   */
+  Set<State> coAccessibleStates(Set<State> states);
+
+  /**
+   * Returns the set of all co-accessible states in this automaton.
+   * 
+   * @return the set of all co-accessible states in this automaton. A state
+   *         <em>s</em> is co-accessible if there exists a path from this
+   *         state <em>s</em> to a terminal state. Objects which are contained
+   *         in this set are instances of class <tt>State</tt>.
+   * @see State
+   */
+  Set<State> coAccessibleStates();
+
+  /**
+   * Returns the set of all states which are co-accessible and accessible in
+   * this automaton.
+   * 
+   * @return the set of all states which are co-accessible and accessible in
+   *         this automaton. A state <em>s</em> is accessible if there exists
+   *         a path from an initial state to <em>s</em>. A state <em>s</em>
+   *         is co-accessible if there exists a path from this state <em>s</em>
+   *         to a terminal state. Objects which are contained in this set are
+   *         instances of class <tt>State</tt>.
+   * @see State
+   */
+  Set<State> accessibleAndCoAccessibleStates();
+
+  /**
+   * Returns the set of all transitions of this automaton
+   * 
+   * @return the set of all transitions of this automaton Objects which are
+   *         contained in this set are instances of class <tt>Transition</tt>.
+   * @see Transition
+   */
+  Set<Transition<L>> delta();
+
+  /**
+   * Returns the set of all transitions of this automaton starting from a given
+   * state and labelled b a given label.
+   * 
+   * @param state
+   *          a state of this automaton.
+   * @param label
+   *          a label used in this automaton.
+   * @return the set of all transitions of this automaton starting from state
+   *         <tt>state</tt> and labelled by <tt>label</tt>. Objects which
+   *         are contained in this set are instances of class
+   *         <tt>Transition</tt>.
+   * @see Transition
+   */
+  Set<Transition<L>> delta(State state, L label);
+
+  /**
+   * Return all transitions from a State
+   * 
+   * @param state
+   *          start state
+   * @return a new Set of transitions (maybe empty)
+   */
+  Set<Transition<L>> delta(State state);
+
+  Set<Transition<L>> deltaFrom(State from, State to);
+
+  /**
+   * Returns the set of all transitions of the reverse of this automaton
+   * 
+   * @return the set of all transitions of the reverse of this automaton. A
+   *         reverse of an automaton <em>A = (X , Q , I , T , D)</em> is the
+   *         automaton <em>A' = (X , Q , T , I , D')</em> where <em>D'</em>
+   *         is the set <em>{ (q , l , q') | (q' , l , q) in D}</em>. Objects
+   *         which are contained in this set are instances of class
+   *         <tt>Transition</tt>.
+   * @see Transition
+   */
+  Set<Transition<L>> deltaMinusOne(State state, L label);
+
+  /**
+   * Adds a new transition in this automaton if it is a new transition for this
+   * automaton. The parameter is considered as a new transition if there is no
+   * transition in this automaton which is equal to the parameter in the sense
+   * of method <tt>equals</tt> of class <tt>Transition</tt>.
+   * 
+   * @param transition
+   *          the transition to add.
+   * @throws NoSuchStateException
+   *           if <tt>transition</tt> is <tt>null</<tt>
+   * or if <tt>transition</tt> = <em>(q , l , q')</em> and <em>q</em> or
+   * <em>q'</em> does not belong to <em>Q</em> the set of the states
+   * of this automaton.
+   */
+  void addTransition(Transition<L> transition) throws NoSuchStateException;
+
+  /**
+   * @param st
+   * @return
+   */
+  Set<Transition<L>> deltaMinusOne(State st);
+
+  /**
+   * @param st
+   * @return
+   */
+  Set<State> accessibleStates(State st);
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/State.java b/extra/jautomata-core/rationals/State.java
new file mode 100755
index 0000000000..f83a98192f
--- /dev/null
+++ b/extra/jautomata-core/rationals/State.java
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+
+/** 
+ * Interface for State objects
+ * 
+ * This class defines the notion of state of an automaton. 
+ * @author yroos@lifl.fr
+ * @version 1.0
+ * @see Automaton
+ * @see StateFactory
+*/
+public interface State {
+
+
+    /** Determines if this state is initial.
+     *  @return true iff this state is initial.
+     */
+    public boolean isInitial();
+    
+    /** Determines if this state is terminal.
+     *  @return true iff this state is terminal.
+     */
+    public boolean isTerminal();
+    
+    /** returns a textual representation of this state.
+     *  @return a textual representation of this state.
+     */
+    public String toString();
+
+    /**
+     * Sets the initial status of this state.
+     * 
+     * @param initial
+     * @return
+     */
+    public State setInitial(boolean initial);
+
+    public State setTerminal(boolean terminal);
+}
diff --git a/extra/jautomata-core/rationals/StateFactory.java b/extra/jautomata-core/rationals/StateFactory.java
new file mode 100755
index 0000000000..667b59c76d
--- /dev/null
+++ b/extra/jautomata-core/rationals/StateFactory.java
@@ -0,0 +1,86 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Set;
+
+/**
+ * This class is used by Automaton objects to create new states on A user can
+ * implement its own version of StateFactory by providing an implementation for
+ * createState
+ *
+ * @author Arnaud.Bailly - bailly@lifl.fr
+ * @version $Id: StateFactory.java 10 2007-05-30 17:25:00Z oqube $
+ */
+public interface StateFactory<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+
+    /**
+     * @param initial
+     * @param terminal
+     * @return
+     */
+    State create(boolean initial, boolean terminal);
+
+    /**
+     * Return a new empty set that can contains State instances created by this
+     * factory. This method is provided for optimisation purposes so that more
+     * efficient implementations than plain sets can be used for handling sets of
+     * states.
+     *
+     * @return an - opaque - implementation of Set.
+     */
+    Set<State> stateSet();
+
+    /**
+     * Returns a new Set which is a copy of <code>s</code>. The given set s
+     * must have been created through <strong>this</strong> StateFactory object
+     * to ensure consistent behavior.
+     *
+     * @param s a Set
+     * @return a shallow copy of <code>s</code>
+     */
+    Set<State> stateSet(Set<State> s);
+
+    /**
+     * Returns a new StateFactory object which is the same as this StateFactory.
+     *
+     * @return an initialized StateFactory.
+     */
+    Object clone();
+
+    /**
+     * @param automaton
+     */
+    void setAutomaton(Automaton<L, Tr, T> automaton);
+
+    State create(boolean initial, boolean terminal, Object label);
+}
+// /*
+// * $Log: StateFactory.java,v $
+// * Revision 1.3 2004/07/20 13:21:25 bonte
+// * *** empty log message ***
+// *
+// */=======
+// /*
+// * $Log: StateFactory.java,v $
+// * Revision 1.3 2004/07/20 13:21:25 bonte
+// * *** empty log message ***
+// *
+// * Revision 1.2 2004/07/19 06:39:02 bailly
+// * made Automaton, State and Transition subclasses of Graph API
+// * modified StateFactory API
+// *
diff --git a/extra/jautomata-core/rationals/StateLabels.java b/extra/jautomata-core/rationals/StateLabels.java
new file mode 100755
index 0000000000..b60abcc1c8
--- /dev/null
+++ b/extra/jautomata-core/rationals/StateLabels.java
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Maintain mapping between labels and abstract {@link State} objects.
+ * <p>
+ *     This is a disguised bi-directional {@link Map} between {@link State} instances 
+ *     and arbitrary {@link Object} instances as labels.
+ * </p>
+ */
+class StateLabels {
+    
+    private Map<State, Object> stateToLabels = new HashMap<State, Object>(); 
+    private Map<Object, State> labelToStates = new HashMap<Object, State>();
+
+
+    public State state(Object label) {
+        return labelToStates.get(label);
+    }
+
+    public Set<Object> labels(Set<State> states) {
+        Set<Object> ret = new HashSet<Object>();
+        for (State state : states) {
+            Object label = stateToLabels.get(state);
+            if(label != null)
+                ret.add(label);
+            else
+                ret.add(state);
+        }
+        return ret;
+    }
+
+    /**
+     * Register a unique binding betwee a {@link State} object and an arbitrary label.
+     * <p>
+     *     Both must be unique within their respective collection.
+     * </p>
+     * 
+     * @param state a state. Must not exist in this set.
+     * @param label a lable. Must not exist in this set.
+     * @return this object for chaining purpose.
+     */
+    public StateLabels bind(State state, Object label) {
+        if(state == null) {
+            throw new NullPointerException("cannot bind a null state");
+        }
+        
+        if(label == null) {
+            label = state;
+        }
+        
+        stateToLabels.put(state,label);
+        labelToStates.put(label,state);
+        
+        return this;
+    }
+}
diff --git a/extra/jautomata-core/rationals/StateMachine.java b/extra/jautomata-core/rationals/StateMachine.java
new file mode 100755
index 0000000000..e44433c788
--- /dev/null
+++ b/extra/jautomata-core/rationals/StateMachine.java
@@ -0,0 +1,155 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An interface for abstract state machines.
+ * <p>
+ * A state machine - or labelled transition system - is defined by
+ * a tuple <code>(Q,S,q0,d)</code> where:
+ * <ul>
+ * <li><code>Q</code> is a set of states ;</li>
+ * <li><code>S</code> is a finite set of labels ;</li>
+ * <li><code>q0</code> is the initial state of the machine ;</li>
+ * <li><code>d</code> is a transition relation in <code>Q x S x Q</code>.
+ * </ul>
+ * This definition is slightly modified for this interface as the initials 
+ * is defined as a {@see java.util.Set} instead of a single state. <code>null</code>
+ * may be used to denote <em>silent transitions</em>, that is unobservable 
+ * internal behaviour of the machine, which can lead to non determinism.
+ * <p>
+ * The {@see rationals.Automaton} is the main implementation for this interface.
+ * 
+ * @version $Id: StateMachine.java 10 2007-05-30 17:25:00Z oqube $
+ */
+public interface StateMachine<L> {
+    
+    /**
+     * Returns the alphabet - <code>S</code> - of this state machine.
+     * 
+     * @return a Set of Object.
+     */
+    Set<L> alphabet();
+    
+    /**
+     * @return Returns the id.
+     */
+    Object getId();
+
+    /**
+     * @param id
+     *            The id to set.
+     */
+    void setId(Object id);
+
+    /**
+     * Retrieves the state factory associated to this SM.
+     * 
+     * @return a StateFactory instance
+     */
+    StateFactory getStateFactory();
+
+    /**
+     * Defines the state factory to use for this SM.
+     * 
+     * @param factory a StateFactory instance.
+     */
+    void setStateFactory(StateFactory factory);
+
+    /**
+     * Returns the set of all transitions of this machine starting from a
+     * given state and labelled 
+     * with  a given label.
+     * 
+     * @param state
+     *            a state of this SM.
+     * @param label
+     *            a label used in this SM.
+     * @return the set of all transitions of this automaton starting from state
+     *         <tt>state</tt> and labelled by <tt>label</tt>. Objects which
+     *         are contained in this set are instances of class
+     *         <tt>Transition</tt>.
+     * @see Transition
+     */
+    Set<Transition<L>> delta(State state, L label);
+
+    /**
+     * Return all transitions from a State.
+     * 
+     * @param state
+     *            start state
+     * @return a new Set of transitions (maybe empty)
+     */
+    Set<Transition<L>> delta(State state);
+
+    /**
+     * Returns all transitions from a given set of states.
+     * 
+     * @param s a Set of State objects
+     * @return a Set of Transition objects 
+     */
+    Set<Transition<L>> delta(Set<State> s);
+
+    /**
+     * Return the set of states this SM will be in
+     * after reading the word from start states <code>s</code>.
+     * 
+     * @param s the set of starting states
+     * @param word the word to read.
+     * @return the set of reached states. Maybe empty or <code>null</code>.
+     */
+    Set<State> steps(Set<State> s, List<L> word);
+
+    /**
+     * Return the set of states this SM will be in
+     * after reading the word from single start state s.
+     * 
+     * @param st the starting state
+     * @param word the word to read.
+     * @return the set of reached states. Maybe empty or <code>null</code>
+     */
+    Set<State> steps(State st, List<L> word);
+
+    /**
+     * Return the set of states accessible in one transition from given set of
+     * states s and letter o.
+     * 
+     * @param s the starting states
+     * @param o the letter 
+     * @return a set of reachable states. Maybe empty or <code>null</code>.
+     */
+    Set<State> step(Set<State> s, L o);
+
+    /**
+     * Returns the set of initial states for this machine.
+     * 
+     * @return a Set of State objects.
+     */
+    Set<State> initials();
+    
+    /**
+     * Returns the set of states that can access the given states' set <code>st</code>.
+     * This is the inverse relation of <code>d</code>
+     * 
+     * @param st end states
+     * @return a set of states that can reach <code>st</code>. May be empty or null.
+     */
+    Set<Transition<L>> deltaMinusOne(State st);
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/StatesTuple.java b/extra/jautomata-core/rationals/StatesTuple.java
new file mode 100755
index 0000000000..6c18ad4119
--- /dev/null
+++ b/extra/jautomata-core/rationals/StatesTuple.java
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Set;
+
+public class StatesTuple {
+    public final Set<State>[] sets;
+
+    final int hash;
+
+    @SuppressWarnings("unchecked")
+	public StatesTuple(Set<State>[] sets) {
+        this.sets = new Set[sets.length];
+        System.arraycopy(sets,0,this.sets,0,sets.length);
+        int h = 0;
+        for (int i = 0; i < sets.length; i++)
+            h ^= sets[i].hashCode() << i;
+        this.hash = h;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+    	if (!(obj instanceof StatesTuple)) return false;
+        StatesTuple sc = (StatesTuple) obj;
+        for (int i = 0; i < sc.sets.length; i++)
+            if (!sets[i].equals(sc.sets[i]))
+                return false;
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+    	StringBuilder sb = new StringBuilder();
+        sb.append("( ");
+        for(int i = 0; i < sets.length; i++){
+            sb.append(sets[i]);
+            if(i != sets.length - 1)
+                sb.append(",");
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/Synchronization.java b/extra/jautomata-core/rationals/Synchronization.java
new file mode 100755
index 0000000000..4b995b9eea
--- /dev/null
+++ b/extra/jautomata-core/rationals/Synchronization.java
@@ -0,0 +1,83 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * An interface for defining various synchronization schemes.
+ * This interface is used in {@see rationals.transformations.Synchronize} for
+ * and allows various strategies of synchronization between transitions
+ * of two automata.
+ * 
+ * @author nono
+ * @version $Id: Synchronization.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface Synchronization<L> {
+
+    /**
+     * Synchronize two transitions.
+     * This method should return a letter denoting the result of synchronizing 
+     * the two transitions' labels. If the result is <code>null</code>, then no synchronization
+     * occurs.
+     * 
+     * @param t1 first label to synchronize
+     * @param t2 second label to synchronize
+     * @return a non null Object if the two transitions can be synchronized.
+     */
+    L synchronize(L t1, L t2);
+    
+    /**
+     * Compute the synchronizing letters from two alphabets.
+     * This method returns the set of letters from a and b that can be synchronized.
+     * In the default case, this method simply computes the intersection of the two
+     * sets. More precisely, the resultant set will contain the result of all 
+     * possible synchronizations between both input sets.
+     * 
+     * @param a an alphabet 
+     * @param b another alphabet
+     * @return a new Set of letters (may be empty) from a and b that can be synchronized.
+     */
+    Set<L> synchronizable(Set<L> a, Set<L> b);
+
+    /**
+     * Construct the synchronization alphabet from a collection of
+     * alphabets.
+     * 
+     * <p>This is an extension to more than 2 alphabets of {@link #synchronizable(Set, Set)}.</p>
+     * 
+     * @param alphabets a collection of alphabets (sets) on which to compute synchronizing letters. 
+     * @return a Set implementation containing all letters of all alphabets 
+     * in <code>alphabets</code> that could be synchronized.
+     */
+    Set<L> synchronizing(Collection<Set<L>> alphabets);
+
+    /**
+     * Checks whether or not the given letter is synchronizing in the
+     * given automaton's alphabet.
+     * This method checks in a synchronization dependant way that the 
+     * given letter pertains to the synchronization set.
+     *  
+     * @param object the letter to check
+     * @param alph the alphabet
+     * @return true if object is synchronizing with some letter in <code>alph</code>, 
+     * false otherwise.
+     */
+    boolean synchronizeWith(L object, Set<L> alph);
+    
+}
diff --git a/extra/jautomata-core/rationals/Transition.java b/extra/jautomata-core/rationals/Transition.java
new file mode 100755
index 0000000000..bafe9aebe2
--- /dev/null
+++ b/extra/jautomata-core/rationals/Transition.java
@@ -0,0 +1,170 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+/**
+ * Defines a Transition (an edge from a state to a state) in an Automaton
+ * 
+ * This class defines the notion of transition of an automaton. a transition is
+ * a triple <em>(q , l , q')</em> where <em>q, q'</em> are states and
+ * <em>l</em> a label. States <em>q</em> and <em>q'</em> must belong to
+ * the same automaton <em>A</em> and the transition may only be used with this
+ * automaton <em>A</em>.
+ * 
+ * @author yroos@lifl.fr
+ * @version 1.0
+ * @see Automaton
+ */
+public class Transition<L> {
+
+  private int hashCodeCache = Integer.MIN_VALUE;
+
+  private State start;
+
+  private L label;
+
+  private State end;
+
+  /**
+   * Creates a new transition <em>(q , l , q')</em>.
+   * 
+   * @param start
+   *          the state <em>q</em> for this transition <em>(q , l , q')</em>.
+   * @param label
+   *          the label <em>l</em>
+   * @param end
+   *          the state <em>q'</em> for this transition <em>(q , l , q')</em>.
+   */
+  public Transition(State start, L label, State end) {
+    this.start = start;
+    this.label = label;
+    this.end = end;
+  }
+
+  /**
+   * Creates a new (invalid) transition. This transition is meant to be updated
+   * internally by an automaton.
+   * 
+   * @param start
+   *          the starting state.
+   */
+  Transition(State start) {
+    this.start = start;
+  }
+
+  /**
+   * Returns the starting state of this transition.
+   * 
+   * @return the starting state of this transition, that is the state <em>q</em>
+   *         for this transition <em>(q , l , q')</em>.
+   */
+  public State start() {
+    return start;
+  }
+
+  /**
+   * Returns the label this transition.
+   * 
+   * @return the label state of this transition, that is the object <em>l</em>
+   *         for this transition <em>(q , l , q')</em>.
+   */
+  public L label() {
+    return label;
+  }
+
+  /**
+   * Returns the ending state of this transition.
+   * 
+   * @return the ending state of this transition, that is the state <em>q'</em>
+   *         for this transition <em>(q , l , q')</em>.
+   */
+  public State end() {
+    return end;
+  }
+
+  /**
+   * returns a textual representation of this transition.
+   * 
+   * @return a textual representation of this transition based
+   */
+  @Override
+  public String toString() {
+    if (label == null) {
+      return "(" + start + " , epsilon , " + end + ")";
+    } else {
+      return "(" + start + " , " + label + " , " + end + ")";
+    }
+  }
+
+  /**
+   * Determines if this transition is equal to the parameter.
+   * 
+   * @param o
+   *          any object.
+   * @return true iff this transition is equal to the parameter. That is if
+   *         <tt>o</tt> is a transition which is composed same states and
+   *         label (in the sense of method <tt>equals</tt>).
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (!(o instanceof Transition)) return false;
+    @SuppressWarnings("unchecked")
+	Transition<L> t = (Transition<L>) o;
+    if (label != t.label) {
+      if (label == null || t.label == null)
+        return false;
+      if (!t.label.equals(label))
+        return false;
+    }
+    return (start == t.start()) && (end == t.end());
+  }
+
+  /**
+   * Returns a hashcode value for this transition.
+   * 
+   * @return a hashcode value for this transition.
+   */
+  @Override
+  public int hashCode() {
+    /* store computed value */
+    if (hashCodeCache != Integer.MIN_VALUE)
+      return hashCodeCache;
+    int x = start == null ? 0 : start.hashCode();
+    int y = end == null ? 0 : end.hashCode();  
+    int z = label == null ? 0 : label.hashCode();  
+    int hash = 17;
+    hash = hash * 31 + x;
+    hash = hash * 31 + y;
+    hash = hash * 31 + z;
+    hashCodeCache = hash;
+    return hash;
+  }
+
+  /**
+   * Replaces the label for this transition
+   * <p>
+   * WARNING: this method is extremely dangerous as it does not update the
+   * alphabet of the automaton this transition is part of. Be sure you know what
+   * you are doing or else everything could break down
+   * 
+   * @param msg
+   */
+  void setLabel(L obj) {
+    this.label = obj;
+  }
+
+}
diff --git a/extra/jautomata-core/rationals/TransitionBuilder.java b/extra/jautomata-core/rationals/TransitionBuilder.java
new file mode 100755
index 0000000000..3cfe9b66f4
--- /dev/null
+++ b/extra/jautomata-core/rationals/TransitionBuilder.java
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals;
+
+/**
+ * A class for step-by-step creation of transitions. A TransitionBuilder can be
+ * used to add expesiveness to transition creation withing automaton.
+ */
+public class TransitionBuilder<L> implements
+		Builder<L, Transition<L>, TransitionBuilder<L>> {
+
+	private State start;
+
+	private Automaton<L, Transition<L>, TransitionBuilder<L>> automaton;
+
+	protected L label;
+
+	/**
+	 * Creates a transition builder for given automaton.
+	 * 
+	 * @param state
+	 *            the starting state of transition.
+	 * @param automaton
+	 *            the automaton where transition will be added.
+	 */
+	public TransitionBuilder(State state, Automaton<L, Transition<L>, TransitionBuilder<L>> automaton) {
+		this.start = state;
+		this.automaton = automaton;
+	}
+
+	public TransitionBuilder() {
+	}
+
+	/**
+	 * Sets the label of the transition.
+	 * 
+	 * @param label
+	 * @return this transition builder.
+	 */
+	@Override
+	public TransitionBuilder<L> on(L label) {
+		this.label = label;
+		return this;
+	}
+
+	/**
+	 * Sets the end state and terminates transition construction. This method
+	 * effectively adds the transition to the automaton.
+	 * 
+	 * @param o
+	 *            the label of the end state.
+	 */
+	@Override
+	public TransitionBuilder<L> go(L o) {
+		State s = automaton.state(o);
+		try {
+			automaton.addTransition(new Transition<L>(start, label, s));
+		} catch (NoSuchStateException e) {
+			assert false;
+		}
+		return this;
+	}
+
+	/**
+	 * Adds a new transition in the automaton that loops on current label and
+	 * from state.
+	 * 
+	 * @return
+	 */
+	public TransitionBuilder<L> loop() {
+		try {
+			automaton.addTransition(new Transition<L>(start, label, start));
+		} catch (NoSuchStateException e) {
+			assert false;
+		}
+		return this;
+	}
+
+	/**
+	 * Resets this builder to another starting state. Note that the state is
+	 * created if needed.
+	 * 
+	 * @param label
+	 *            the state to start from.
+	 * @return this builder.
+	 */
+	public TransitionBuilder<L> from(L label) {
+		this.start = automaton.state(label);
+		this.label = null;
+		return this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see rationals.Builder#build(java.lang.Object, rationals.Automaton)
+	 */
+	public TransitionBuilder<L> build(State state, Automaton<L, Transition<L>, TransitionBuilder<L>> auto) {
+		this.start = state;
+		this.label = null;
+		this.automaton = auto;
+		return this;
+	}
+
+	public Transition<L> build(State from, L label, State to) {
+		return new Transition<L>(from, label, to);
+	}
+
+	public void setAutomaton(Automaton<L, Transition<L>, TransitionBuilder<L>> a) {
+		this.automaton = a;
+	}
+
+}
diff --git a/extra/jautomata-core/rationals/algebra/Matrix.java b/extra/jautomata-core/rationals/algebra/Matrix.java
new file mode 100755
index 0000000000..8d7e05fd2b
--- /dev/null
+++ b/extra/jautomata-core/rationals/algebra/Matrix.java
@@ -0,0 +1,226 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.algebra;
+
+import java.util.Arrays;
+
+/**
+ * Matrix representation of an automaton.
+ * <p>
+ * The elements of a the matrix are {@see SemiRing}objects.
+ * 
+ * @author nono
+ * @version $Id: Matrix.java 6 2006-08-30 08:56:44Z oqube $
+ */
+public final class Matrix implements SemiRing {
+
+    /* matrices for transitions, initial and terminal states */
+    protected final SemiRing[][] matrix;
+
+    private int line;
+    
+    private int col;
+    
+
+    public Matrix(int ns) {
+        this.line = this.col = ns;
+        this.matrix = new SemiRing[ns][ns];
+    }
+
+    /**
+     * @param matrix
+     */
+    public Matrix(Matrix matrix) {
+        this(matrix.line);
+        for (int i = 0; i < line; i++) 
+            for (int j = 0; j < col; j++) 
+                this.matrix[i][j] = matrix.matrix[i][j];
+        
+    }
+
+    /**
+     * @param l
+     * @param c
+     */
+    public Matrix(int l, int c) {
+        this.line = l;
+        this.col = c;
+        matrix = new SemiRing[l][c];
+    }
+
+    /**
+     * Returns the n <sup>th </sup> power of this matrix.
+     * 
+     * @param n
+     *            the power. Must be positive or null.
+     * @param res
+     *            matrix where the result should be stored. Must be same size as
+     *            this matrix with all elements initialized with null.
+     * @return the result Matrix object with transition matrix equals the n
+     *         <sup>th </sup> power of this matrix's transition.
+     */
+    public Matrix power(int n, Matrix res) {
+        int l = line;
+        if(line != col)
+            throw new IllegalStateException("Cannot compute power of a non square matrix");
+        SemiRing[][] tmp = new SemiRing[l][l];
+        for (int i = 0; i < l; i++)
+            Arrays.fill(tmp[i], matrix[0][0].zero());
+        for (int k = 0; k <n; k++) {
+            for (int i = 0; i < l; i++) {
+                for (int j = 0; j < l; j++) {
+                    for (int m = 0; m < l; m++) {
+                        if (k==0)
+                            tmp[i][j] = tmp[i][j].plus(matrix[i][m]
+                                    .mult(matrix[m][j]));
+                        else
+                            tmp[i][j] = tmp[i][j].plus(res.matrix[i][m]
+                                    .mult(matrix[m][j]));
+                    }
+                }
+            }
+            /* copy to res */
+            for (int i = 0; i < l; i++)
+                System.arraycopy(tmp[i],0,res.matrix[i],0,l);
+        }
+        return res;
+    }
+
+
+    /**
+     * Returns the star of this matrix.
+     * 
+     * @return
+     */
+    public Matrix star() {
+        return null;
+    }
+
+    public int getLine() {
+        return line;
+    }
+    
+    public String toString() {
+        final String ln = System.getProperty("line.separator");
+        StringBuffer sb = new StringBuffer();
+        int n = matrix.length;
+        for (int i = 0; i < line; i++) {
+            sb.append("[ ");
+            for (int j = 0; j < col; j++) {
+                String s = matrix[i][j].toString();
+                sb.append(s).append(' ');
+            }
+            sb.append("]").append(ln);
+        }
+        return sb.toString();
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.algebra.SemiRing#plus(rationals.algebra.SemiRing)
+     */
+    public SemiRing plus(SemiRing s2) {
+        if(s2 == null)
+            throw new IllegalArgumentException("Null argument");
+        Matrix o = (Matrix)s2; // maybe ClassCastException
+        if(col != o.col || line != o.line)
+            throw new IllegalArgumentException("Incompatible matrices dimensions : cannot add non square matrices");
+        int l = line;
+        int c = col;
+        Matrix res = Matrix.zero(l,c,matrix[0][0]);
+        for(int i=0;i<l;i++) 
+            for(int j=0;j<c;j++)
+                res.matrix[i][j] = matrix[i][j].plus(o.matrix[i][j]);
+        return res;               
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.algebra.SemiRing#mult(rationals.algebra.SemiRing)
+     */
+    public SemiRing mult(SemiRing s2) {
+        if(s2 == null)
+            throw new IllegalArgumentException("Null argument");
+        Matrix o = (Matrix)s2; // maybe ClassCastException
+        if(col != o.line)
+            throw new IllegalArgumentException("Incompatible matrices dimensions");
+        int l = line; // lines
+        int c = o.col;  // cols
+        int m = col;
+        Matrix res = Matrix.zero(l,c,matrix[0][0]);
+        for(int i=0;i<l;i++) {
+            for(int j=0;j<c;j++)
+                for(int k=0;k<m;k++){
+                   if(k ==0)
+                       res.matrix[i][j] = matrix[i][k].mult(o.matrix[k][j]);
+                   else
+                       res.matrix[i][j] = res.matrix[i][j].plus(matrix[i][k].mult(o.matrix[k][j]));
+                }
+        }
+        return res;
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.algebra.SemiRing#one()
+     */
+    public SemiRing one() {
+        if(line != col)
+            throw new IllegalStateException("Cannot get unit matrix on non-square matrices");
+        return one(line,matrix[0][0]);
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.algebra.SemiRing#zero()
+     */
+    public SemiRing zero() {
+        return zero(line,col,matrix[0][0]);
+    }
+    
+    public int getCol() {
+        return col;
+    }
+    
+    /**
+     * Factory method for creating Matrix instances with coefficients
+     * in a certain SemiRing.
+     * 
+     * @param sr a SemiRing instance. Used to get one and zero.
+     * @return a new zero matrix.
+     */
+    public static Matrix zero(int line,int col,SemiRing sr) {
+        Matrix m = new Matrix(line,col);
+        for(int i=0;i<line;i++)
+            for(int j=0;j<col;j++)
+                m.matrix[i][j] = sr.zero();
+        return m;
+    }
+    
+    /**
+     * Factory method for creating unit Matrix instances with coefficients
+     * in a certain SemiRing.
+     * 
+     * @param sr a SemiRing instance. Used to get one and zero.
+     * @return a new unit square matrix.
+     */
+    public static Matrix one(int dim,SemiRing sr) {
+        Matrix m = new Matrix(dim);
+        for(int i=0;i<dim;i++)
+            for(int j=0;j<dim;j++)
+                m.matrix[i][j] = (i == j) ? sr.one() : sr.zero();
+        return m;
+    }
+    
+    
+}
diff --git a/extra/jautomata-core/rationals/algebra/RationalMatrix.java b/extra/jautomata-core/rationals/algebra/RationalMatrix.java
new file mode 100755
index 0000000000..7a7ffbaf61
--- /dev/null
+++ b/extra/jautomata-core/rationals/algebra/RationalMatrix.java
@@ -0,0 +1,145 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.algebra;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import rationals.Rational;
+import rationals.State;
+import rationals.Transition;
+import rationals.expr.Letter;
+import rationals.expr.Plus;
+import rationals.expr.RationalExpr;
+
+/**
+ * A matrix for representing regular languages.
+ * <p>
+ * The cell of the matrix are rational expressions made from concatenation,
+ * epsilon, letters and union.
+ * 
+ * @author nono
+ * @version $Id: RationalMatrix.java 2 2006-08-24 14:41:48Z oqube $
+ * @see rationals.expr
+ */
+public class RationalMatrix  {
+
+    private Matrix init;
+    private Matrix fini;
+    private Matrix transitions;
+    
+    /**
+	 * @return Returns the fini.
+	 */
+	public Matrix getFini() {
+		return fini;
+	}
+
+	/**
+	 * @param fini The fini to set.
+	 */
+	public void setFini(Matrix fini) {
+		this.fini = fini;
+	}
+
+	/**
+	 * @return Returns the init.
+	 */
+	public Matrix getInit() {
+		return init;
+	}
+
+	/**
+	 * @param init The init to set.
+	 */
+	public void setInit(Matrix init) {
+		this.init = init;
+	}
+
+	/**
+	 * @return Returns the transitions.
+	 */
+	public Matrix getTransitions() {
+		return transitions;
+	}
+
+	/**
+	 * @param transitions The transitions to set.
+	 */
+	public void setTransitions(Matrix transitions) {
+		this.transitions = transitions;
+	}
+
+	/**
+     * Construct the matrix of a rational language.
+     * 
+     * @param rat
+     *            a Rational language.
+     */
+    public RationalMatrix(Rational rat) {
+        Set st = rat.states();
+        int n = st.size();
+        init = Matrix.zero(1,n,RationalExpr.zero);
+        fini = Matrix.zero(n,1,RationalExpr.zero);
+        transitions = Matrix.zero(n,n,RationalExpr.zero);
+        State[] sta = (State[]) rat.states().toArray(new State[n]);
+        /* fill matrices */
+        for (int i = 0; i < sta.length; i++) {
+            if (sta[i].isInitial())
+                init.matrix[0][i] = Letter.epsilon;
+            else 
+                init.matrix[0][i] = RationalExpr.zero;
+            if (sta[i].isTerminal())
+                fini.matrix[i][0] = Letter.epsilon;
+            else 
+                fini.matrix[i][0] = RationalExpr.zero;
+            /* transitions */
+            for (int j = 0; j < n; j++) {
+                Set trs = rat.deltaFrom(sta[i], (State) sta[j]);
+                RationalExpr re = null;
+                for (Iterator it = trs.iterator(); it.hasNext();) {
+                    Transition tr = (Transition) it.next();
+                    Object o = tr.label();
+                    Letter l = (o == null) ? Letter.epsilon : new Letter(o);
+                    if (re == null)
+                        re = l;
+                    else
+                        re = new Plus(re, l);
+                }
+                transitions.matrix[i][j] = re == null ? RationalExpr.zero : re;
+            }
+        }
+    }
+
+    /**
+     * Compute words from this rational whose length is 
+     * n.
+     * 
+     * @param n
+     * @return
+     */
+    public Matrix nwords(int n) {
+        Matrix res = transitions.power(n,Matrix.zero(transitions.getLine(),transitions.getLine(),RationalExpr.zero));
+        /* compute product for init and fini */
+        Matrix in = (Matrix)init.mult(res);
+        return (Matrix)in.mult(fini);
+    }
+
+    public String toString() {
+        return init.toString() + '\n'+ transitions.toString() + '\n'+fini.toString();
+    }
+}
diff --git a/extra/jautomata-core/rationals/algebra/SemiRing.java b/extra/jautomata-core/rationals/algebra/SemiRing.java
new file mode 100755
index 0000000000..62c2229a79
--- /dev/null
+++ b/extra/jautomata-core/rationals/algebra/SemiRing.java
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.algebra;
+
+/**
+ * An interface implemented by objects that can be coefficients of a 
+ * Matrix.
+ * <p>
+ * A semi-ring is a structure <code>(R,+,*,0,1)</code> such that:
+ * <ol>
+ * <li><code>(R,+,0)</code> is a commutative monoid </li>
+ * <li><code>(R,*,1)</code> is a monoid </li>
+ * <li><code>x*(y+z) = x*y + x*z</code> and <code>(y+z)*x = y*x + z*x</code> : multiplication
+ * is distributive with respect to addition </li>
+ * <li><code>x*0 = 0*x = 0</code>: 0 is an absorbing element for *</li>
+ * </ol>
+ * 
+ * @author nono
+ * @version $Id: SemiRing.java 2 2006-08-24 14:41:48Z oqube $
+ * @see Matrix
+ */
+public interface SemiRing {
+
+    /**
+     * Addition of a Semi-ring element with another element.
+     * 
+     * @param s1
+     * @param s2
+     * @return
+     */
+    public SemiRing plus(SemiRing s2);
+    
+    /**
+     * Multiplication of semiring element with another element.
+     * 
+     * @param s1
+     * @param s2
+     * @return
+     */
+    public SemiRing mult(SemiRing s2);
+    
+    /**
+     * Neutral element for multiplication.
+     * 
+     * @return
+     */
+    public SemiRing one();
+    
+    /**
+     * Neutral element for addition.
+     * 
+     * @return
+     */
+    public SemiRing zero();
+    
+}
diff --git a/extra/jautomata-core/rationals/converters/ConverterException.java b/extra/jautomata-core/rationals/converters/ConverterException.java
new file mode 100755
index 0000000000..046b833c71
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/ConverterException.java
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters;
+
+
+public class ConverterException extends Exception {
+	private static final long serialVersionUID = 1L;
+
+    public ConverterException(String message) {super(message) ;}
+}
diff --git a/extra/jautomata-core/rationals/converters/Expression.java b/extra/jautomata-core/rationals/converters/Expression.java
new file mode 100755
index 0000000000..e34ba3dee5
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/Expression.java
@@ -0,0 +1,29 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters;
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+import rationals.converters.analyzers.Parser;
+
+public class Expression<Tr extends Transition<String>, T extends Builder<String, Tr, T>> implements FromString<Tr, T> {
+  public Automaton<String, Tr, T> fromString(String s) throws ConverterException {
+    return new Parser<String, Tr, T>(s).analyze() ;
+  }
+    
+}
+
diff --git a/extra/jautomata-core/rationals/converters/FromString.java b/extra/jautomata-core/rationals/converters/FromString.java
new file mode 100755
index 0000000000..e02ee06633
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/FromString.java
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+
+public interface FromString<Tr extends Transition<String>, T extends Builder<String, Tr, T>> {
+  public Automaton<String, Tr, T> fromString(String s) throws ConverterException ;
+}
diff --git a/extra/jautomata-core/rationals/converters/ToRExpression.java b/extra/jautomata-core/rationals/converters/ToRExpression.java
new file mode 100755
index 0000000000..0e5a5f3556
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/ToRExpression.java
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters;
+
+import rationals.*;
+import rationals.properties.isNormalized;
+import rationals.transformations.Normalizer;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This Converter takes an Automaton and generates an equivalent Regular
+ * expression.
+ * <p>
+ * This conversion applies classical conversion algorithm based on state
+ * removal. 
+ * cf. Algorithm BMC (Brozowski et  al.) from J.sakarovitch "El&eacute;ments de th&eacute;orie
+ * des automates", sec. 2
+ * 
+ * @version $Id: ToRExpression.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class ToRExpression<Tr extends Transition<String>, T extends Builder<String, Tr, T>> implements ToString<String, Tr, T> {
+
+    private Map<Couple, String> keys = new HashMap<>();
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.converters.ToString#toString(rationals.Automaton)
+     */
+    public String toString(Automaton<String, Tr, T> a) {
+        if(a == null) return "0";
+        Automaton<String, Tr, T> ret = a.clone();
+        if (!new isNormalized().test(a))
+            ret = new Normalizer<String, Tr, T>().transform(a);
+        /* special case for empty automaton */
+        if (ret.initials().isEmpty())
+            return "0";        
+        /* add all transitions from start to end state */
+        State init = ret.initials().iterator().next();
+        State fini = ret.terminals().iterator().next();
+        String re = "";
+        for(Iterator<Transition<String>> i = ret.deltaFrom(init,fini).iterator();i.hasNext();) {
+        	Transition<String> tr = i.next();
+            if("".equals(re)) {
+                re = (tr.label() == null) ? "1" : tr.label().toString();
+            }else
+                re += "+" + ((tr.label() == null) ? "1" : tr.label().toString());
+        }
+        if(!"".equals(re))
+            keys.put(new Couple(init,fini), re);
+        Iterator<State> it = ret.states().iterator();
+        while (it.hasNext()) {
+            State st = it.next();
+            if (st.isInitial() || st.isTerminal())
+                continue;
+          
+            re = "";
+            /* first handle self transitions */
+            Iterator<Transition<String>> it2 = ret.delta(st).iterator();
+            while (it2.hasNext()) {
+            	Transition<String> t1 = it2.next();
+                if (!t1.end().equals(st))
+                    continue;
+                re += "+" + t1.label();
+            }
+            /* clean first '+' */
+            if (!"".equals(re)) {
+                re = re.substring(1);
+                if (re.length() > 1)
+                    re = "(" + re + ")*";
+                else
+                    re = re + "*";
+            }
+            Set<Transition<String>> to = ret.delta(st); /* outgoing */
+            Set<Transition<String>> from = ret.deltaMinusOne(st); /* incoming */
+            it2 = from.iterator();
+            while (it2.hasNext()) {
+                /* beware : this is reverse transition */
+            	Transition<String> t1 = it2.next();
+                if (t1.end().equals(st)) /* skip self transitions */
+                    continue;
+                Iterator<Transition<String>> it3 = to.iterator();
+                while (it3.hasNext()) {
+                	Transition<String> t2 = it3.next();
+                    if (t2.end().equals(st))
+                        continue;
+                    /* find completed expression from start to end */
+                    State s2 = t2.end();
+                    State s1 = t1.end();
+                    Couple k = new Couple(s1, s2);
+                    String oldre = (String) keys.get(k);
+                    String nre = t1.label() + "" + re + t2.label();
+                    if (oldre == null) {
+                        oldre = nre;
+                    } else {
+                        oldre += "+" + nre;
+                    }
+                    try {
+                        keys.put(k, oldre);
+                        ret.addTransition(new Transition<String>(s1, oldre, s2));
+                    } catch (NoSuchStateException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+        /* returns the transition from stat to end */
+        re = (String) keys.get(new Couple(init,fini));
+        return re;
+    }
+
+}
+
+/*
+ * $Log: ToRExpression.java,v $ Revision 1.3 2005/03/23 07:22:42 bailly created
+ * transductions package corrected EpsilonRemover added some tests removed
+ * DirectedGRaph Interface from Automaton
+ * 
+ * Revision 1.2 2005/02/02 14:21:10 bailly corrected bad import
+ * 
+ * Revision 1.1 2004/09/21 11:50:28 bailly added interface BinaryTest added
+ * class for testing automaton equivalence (isomorphism of normalized automata)
+ * added computation of RE from Automaton
+ *  
+ */
diff --git a/extra/jautomata-core/rationals/converters/ToString.java b/extra/jautomata-core/rationals/converters/ToString.java
new file mode 100755
index 0000000000..606a6daba4
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/ToString.java
@@ -0,0 +1,25 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters ;
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+
+public interface ToString<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+  public String toString(Automaton<L, Tr, T> a) ;
+}
diff --git a/extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.class b/extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..89d2dcd099c23a2f4d0417ca39cef7734ae05274
GIT binary patch
literal 2567
zcmZ`)`%_a_5dID%xyj`M0a0GsVznAVdDyDeg3tI0f`}j%-<NQKKuF@v4G-Vdscol@
zojQH$)S-hNf6$qh8Av*1+RpUH{t5k8Y&-qVO@Kf#GrOC!XLrxHdv?$L^WR^71F#);
z6$BI<Qjv$lDg=(G*n*=fw&IwF|AJE2D%o+#+9Ye2?1W?;lAV-xoeEA#*(EjI3QjBN
zapR1NG8~rr_uc4~@~nsZ=Tw}>1r--@Nx@|Wx{B9uOtL-&Ar%|ZFBgVn12W*Cf*}QA
z0gn|MF{0tChAB|lHmr~7jp0~hmt`9IX!pWavp~KP?H3Sd1)Skgeb5jn%~(hD=%BO@
zM+a%<9MdC7Zi=9Q5=xq;5w!$dE#YX`+AFZu_kX9_9sx%n)=#hEws6!qksR$a%x=9e
zLd}}212LU4^nSx^mgei1v@4O?(FmSk^L=tr*k$RVk#;?9N3`pBSwKBJ5i;UdI2KKC
z5m`Le_9Av?MDH^q0%gA19K;=c!$!zrnrc@pX@-m=VTrNikTIYqBUYO+VVDiFgaYNS
zs3ari?678;tTb%H+mh{&Y^P+qH26@fVOahfK}5r-WKqdth-<h4Q$s>BKk5WFo4QO#
zk0csHvFMm#T85cu)Tx-{<t7?!bQ+q_sKEm7V$A}OV8>!H1h%dkCa@4O$Fl5n)R>5~
z9!7snXh=78{v((MGzvh&Td3ENM7@GB4da+lFsb1xt}PsF_f1Z?OvQ4#>0mM(;e~6s
zjvLFI0!xQ&!%ew=OT%q^py7_pt8Uc{mI{%3TLNCY3ih#?+Z8A<jf7!!O-3z!f(Aw`
z5=?Z32czMEa7dT!?C_nnJ1Y_!H_U*ZFxu_zElou9#88)Hf!OFMJD<Jfxsr@ohJ-Br
zg3`}39y9x;hTBeG(AE`?4}~ow5!XYut#o8{Eqem#nBZ6~!<rd5PL{0v0UJ}WHo#t7
zN+%e#j6pfp?l_M!xO~O@vE5yIJZ=wo{b~c6GXa@%vsc4GaQFf;rDbl}Dajq2m2Pe;
zwvfT{3Cn01*d=E&8sp2gg)b*_hm#K~CxUNmp6qyAvdL`8rn4oxo6=2t&J+1NTs6T(
z51`CH579f1yxzJr^3!mn;hdpf@XZF~a}C<B;Yxb%$a>epVeb^$-t=6}Z4di>ukE%o
z>vkXcwp*J&4VS-e4vK#kN(yc%@>B3+r7EQ(g#szPZ=|5vf113zQz*1;yfrBl`Sa&c
zyacuZ1q6GP(2l`_AdAzA3LHlb+E}7?!aso)bl?b1Qrk&P?_wA6upD`hS;%~5J;vz8
z-$M0!J##3Tk!Ph)+VTuV?ei$>EnS<&y5FnwrcmW~@NkKs++SKThsvx+wfCPXSbpg^
ziz=y~MI}?K_BMTw&c(&<X&hQG`Wfq&qRgWF5%YHO^k=A`eYs<bYp1<-%R@_M+WlVD
zMrWT+MxYrCQc?Y!Rd_)1kT#J<NIsHDl8rJ+@{`VxWW#ilE@tT(<!#b+Qa|Yi=_9|}
zKEf+O&G?nfq97x*jL0gphJ_hrku4-Xw#jR~X}n%qkwVQpHuhFOOoR8jDTU3f(F|{)
z2<uSEMjOF2o?-(vvH}0XPV#Q>3xz`T(CQrRF4FQms&E0Dafvxy=KHGi9{aExA?zda
z{TSdq4>GqQMjU3&Be;bK?(uu^fM1HQ5XTc%WSX!3Q$EN)U<}XsAiv;aJcDaUu>xt_
z#IN-F1GhyP?ubg<6;=39)Zm`jh>yh<d?L2uQ&Ermq5%)Yc6=sw;B(Q8hoS{vh=cf2
z1n{*8;v3P5N8%(Ni%xtedhkRfF-5HMe#(kk6}<O1R8jpB?ZuA$3Yr!5CC)otPM7^-
z(}GRSk0fc2JyLRlYq;V!B{MuJy!nFvGgIrb_0#10ScuHLZ=jUcPT7J#tuTGYt%k+G
bxu)eSqduo;)2gN=D@}i-=>eXUhlBqCs4FYP

literal 0
HcmV?d00001

diff --git a/extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.java b/extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.java
new file mode 100755
index 0000000000..e3d97a9111
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/analyzers/DefaultLexer.java
@@ -0,0 +1,178 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters.analyzers;
+
+import rationals.converters.ConverterException;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+
+/**
+ * Default lexical analyser for regular expressions.
+ * This lexer parse a regular expression and treats each letter 
+ * as a label.
+ * 
+ * @author yroos
+ * @version $Id: DefaultLexer.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class DefaultLexer implements Lexer {
+    private StreamTokenizer tokenizer;
+
+    private boolean end;
+
+    private String image;
+
+    private int value;
+
+    private int current;
+
+    /**
+     * Construct a lexical analyzer to parse given string.
+     * 
+     * @param in the String to parse.
+     */
+    public DefaultLexer(String in) {
+        this(new StreamTokenizer(new StringReader(in)));
+    }
+
+    /**
+     * construct a lexical analyzer to parse the characters from given
+     * Reader object.
+     * 
+     * @param rd the character stream to parse.
+     */
+    public DefaultLexer(Reader rd) {
+      this(new StreamTokenizer(rd));  
+    }
+    
+    /**
+     * Construct  a lexical analyzer that uses given StreamTokenizer object
+     * to get data from.
+     * Note that the tokenizer is reset and given new attributes.
+     * 
+     * @param st
+     */
+    public DefaultLexer(StreamTokenizer st) {
+        tokenizer = st;
+        tokenizer.resetSyntax();
+        tokenizer.eolIsSignificant(false);
+        tokenizer.lowerCaseMode(false);
+        tokenizer.slashSlashComments(true);
+        tokenizer.quoteChar('\"');
+        tokenizer.wordChars('0', '9');
+        tokenizer.whitespaceChars(0, 32);        
+        end = false;
+    }
+    
+    public void read() throws ConverterException {
+        if (end) {
+            current = END;
+            return;
+        }
+        ;
+        int tk;
+        try {
+            tk = tokenizer.nextToken();
+        } catch (IOException e) {
+            throw new ConverterException("Unexpected character");
+        }
+        if (tk == StreamTokenizer.TT_EOF) {
+            end = true;
+            value = 0;
+            image = "";
+            current = END;
+            return;
+        }
+        if (tk == StreamTokenizer.TT_WORD) {
+            image = tokenizer.sval;
+            if (image.charAt(0) >= '0' && image.charAt(0) <= '9') {
+                try {
+                    value = Integer.parseInt(tokenizer.sval);
+                    image = "";
+                    if (value == 0)
+                        current = EMPTY;
+                    else {
+                        if (value == 1)
+                            current = EPSILON;
+                        else
+                            current = INT;
+                    }
+                    return;
+                } catch (Exception e) {
+                    current = UNKNOWN;
+                    return;
+                }
+            }
+            value = 0;
+            current = LABEL;
+            return;
+        }
+        image = "";
+        value = 0;
+        switch (tk) {
+        case '+':
+            current = UNION;
+            return;
+        case '*':
+            current = STAR;
+            return;
+        case '^':
+            current = ITERATION;
+            return;
+        case '|':
+            current = SHUFFLE;
+            return;
+        case '#':
+            current = MIX;
+            return;
+        case '(':
+            current = OPEN;
+            return;
+        case ')':
+            current = CLOSE;
+            return;
+        case '{':
+            current = OBRACE;
+            return;
+        case '}':
+            current = CBRACE;
+            return;
+        default:
+            current = LABEL;
+            image = "" + new Character((char) tk);
+        }
+    }
+
+    public int lineNumber() {
+        return tokenizer.lineno();
+    }
+
+    public Object label() {
+        return image;
+    }
+
+    public int value() {
+        return value;
+    }
+
+    public int current() {
+        return current;
+    }
+}
+
diff --git a/extra/jautomata-core/rationals/converters/analyzers/Lexer.class b/extra/jautomata-core/rationals/converters/analyzers/Lexer.class
new file mode 100644
index 0000000000000000000000000000000000000000..c175185f4eb1d3a357b62bb62980e9f1b82fd033
GIT binary patch
literal 849
zcmZwF*>2N76b9fkNgOw6)0Va@WnT()SZbDX0|+S%j<A^8QS20YIdMl-D&wGu9Tgsp
z3m$-nLj2=Y)rfMH`Of^aoN<2t`T2{8cImZEFKv3o$l{$nk27LEqgHp4O>>du2O=$G
z6+vQD^@CUs86(^4M?Mb&%?g%!`~CP(qspk^$KIe5`}5fvW{1HUEJn2`?hJIYj&a!c
z$}Mb!x;%_LJ+Xk3yx@Z#HgM7~_!NYn%UBbPJ`Q_5UIrHt-1ooe;1Z*HxHsr@%ZV1$
zJ=Zc0Qc@ft?X(XVHNDeBe#^(`(578D9cMBqzK*0SBWT}B#Ym=%Hk>v;5i{YYB0F}&
z(TPm*x9Bh$A7>&jltk2N#~d|lre6vdObVrBmNRnR@i!M&zrR?*6{1O@64@K4*rCbg
zsZ=}qTt-_;=$ndk>L!zHCRHxg)D<Xv|Di`^meK0Jw`8>a-<9~T^G(hl0pEd91#h@Q
zn^dJ5WI+|G!?xiCxM8>nFB)EgTZWh66~n9WCBtj*y5SA@vf(T6Rm0cdO~cor8-{Pf
zw+!Eg?-;%d-!pulEc`hi&=xv=h>msVk5Jhr2Vm5u$EZ9h-{L9!?5w_{fAK!^8JC`y
Gdhr*(=7Qb;

literal 0
HcmV?d00001

diff --git a/extra/jautomata-core/rationals/converters/analyzers/Lexer.java b/extra/jautomata-core/rationals/converters/analyzers/Lexer.java
new file mode 100755
index 0000000000..d743ee76a7
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/analyzers/Lexer.java
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters.analyzers;
+
+import rationals.converters.ConverterException;
+
+/**
+ * Interface lifting lexical analysis.
+ * This interface allows customization of parsing of RE, in particular to
+ * override the definition of what is a labeL. 
+ * Instances of Lexer are used by instances of Parser to retrieve tokens.
+ * @author nono
+ * @version $Id: Lexer.java 2 2006-08-24 14:41:48Z oqube $
+ * @see DefaultLexer
+ * @see Parser
+ */
+public interface Lexer<L> {
+    public static final int LABEL = 0;
+
+    public static final int INT = 1;
+
+    public static final int EPSILON = 2;
+
+    public static final int EMPTY = 3;
+
+    public static final int ITERATION = 4;
+
+    public static final int UNION = 5;
+
+    public static final int STAR = 6;
+
+    public static final int OPEN = 7;
+
+    public static final int CLOSE = 8;
+
+    public static final int END = 9;
+
+    public static final int UNKNOWN = 10;
+
+    // AB
+    public static final int SHUFFLE = 11;
+
+    public static final int MIX = 12;
+
+    public static final int OBRACE = 13;
+
+    public static final int CBRACE = 14;
+
+    /**
+     * Read more data from the underying input.
+     * 
+     * @throws ConverterException if some characters cannot be converted
+     */
+    public abstract void read() throws ConverterException;
+
+    /**
+     * Return the current line number in the underlying character
+     * stream.
+     * Line separation is platform dependent.
+     * 
+     * @return number of current line, starting from 1
+     */
+    public abstract int lineNumber();
+
+    /**
+     * Return the image of current token.
+     * This method is used by Parser to create atomic Automaton objects
+     * so any Object can be used.
+     * 
+     * @return an Object which is a label for a transition.
+     */
+    public abstract L label();
+
+    /**
+     * Return the value of a number.
+     * 
+     * @return value of a number.
+     */
+    public abstract int value();
+
+    /**
+     * Returns the current token value.
+     * This value must be one of the constants defined in interface Lexer.
+     * 
+     * @return a constant denoting the kind of token.
+     */
+    public abstract int current();
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/converters/analyzers/Parser.class b/extra/jautomata-core/rationals/converters/analyzers/Parser.class
new file mode 100644
index 0000000000000000000000000000000000000000..03676571000bffa59bc33c11a0550350912164ce
GIT binary patch
literal 4800
zcmcInZE#dq8Gg=Yvv;#xLf96N2s9*+Cc8i={Sfn|1cK5oDJ2Vtt(BY2O|r1rP4Die
z3--fmtF~4utw>uxDCqc6W*lH@QjMeIA9b9OAC9Ac?2P~X<ES(0jHOKL^WKl$&F04N
zr#ExYJ?Gu?zUO`3=RNN^`R%(u{W*ZU@ZAXdaZG~|K>#BS=tD}ws0K5F5RQd0Cg1U8
zScM7crNcNbgA+2ygfS`KYy|Zf5pga;15?s_M1vJZUd9D!iqcGLcr=1$S+5kqIvkVc
zq)1MM@tH6l)9`o%ts?Kk6Vg1X;j<C6i=-VV!+1)5{+x!-M-UfbT-5vUv^39X_(BBR
zMZDb+e^JC=3gg)@o)g6{Yj{3_oibx5PKlde3FEYe7c_iTA(Syo=~PakJz*JzbS`UT
z@?EK1cG|QGrj_q9C^&gadI_^+T0II4!|Cy?Q7BrbLj0zbdXtHserkq#)7f;PUtv{8
z;<zzwbY+a}c-L^jN@vG=Iu9!ZcjrcFbwwhbHHV6mBc_!!MlzIicHGoLwvlZ&H`j4W
zR;@QJD`(k@EcB{s-Ce~(Zqg{^vV;;DETzmTiC13XZa+AFin3-hY4Nq=p}E0TSkuwz
zH=heFA1)ZF6Z?%RI}%J4g*N}mHOAGTLSXQKf=aTJ9A<}aASsf)d<Qrf;9yI2xGE4A
z^JkCm^m%Lhs?M9CFwvXnuF8S?M~<7RLQm4_t_nlaGP3!!#8{O3dy?JNzYY}BnNic4
zXSaW$Nm4bOD_SXYZ(0&**#X1Ko7OfVTE}jjVGb{m_j}ASqnIh!=`SjKbbJIKRk+<(
zZ@0H~$_YYtYtzd0ovD{$rnl&L5ijZZ8qP}Z>k4%(TPQq-mu38ljJr9072nYDO`Oqj
z5JNh?g|iBqe4VJ-v<l5;cC;lo)?${XEHj^HNTth=o1;4R;a(j{F*%GOg^d-H1z}(;
zXEEy~)4L9uqs5fTt#aGqa}H%WRmZn+UYZ9LZt+=Ep|L3Q%3g3<#bh}PbsQGA4lUu<
z@I-NJOxRt`!j&=#Cd*T`aUHLTh4qycYJu%fmvnqW);c0HtEjD=Nq#FU=r}4mpA?uY
z#*9=UXH_AJbd(1=F5sfVhQ&SLHn((qM>xIpP}U=-B{gAKv@0>+Tv7I|&rW75G*z<A
z*;dS-4ykh?V`_?dps>}qURBhbitHw-6g$aMrykq3_9?9E*w<OL*=jZFGscLSArzLX
zid}b?*Erxxt0&f)3m0;ZsMew*rHet!G>A+~6)nrm7I;dPiBs6+TeEtqN=-TAdVGr)
z7ico4^65-2Tb{`jwn0`2cuFk*yO_QDX(LlKv5{wWKkp<g#!^-I-NjJ=16a;Jiw)aB
zO71|AQeb6l7AiJ}z|r_D>VAyi6<c{P+eXx}-NA`>qKTIrQU4f~L_Nl@s7Gw|xQ|{B
z^?D&!A;*D_b3O|LZHoROclo|K)E}Kg=;$o8Xm|z<u{RL>2_gzJSQgdGg5@G;jIN*{
z&UXe)vsn2H8d4BfL;Qkh?_(QezusLm!Tx>>xr-igo!;y$5>=r0w<Mg=t)!&kJOM>l
z&tlDy_+^?3*v6wY2?nl#o;Om`#wgrRNf_z|+B6(ku<QfWWJz_G{Q>nQl7;d@uX6;9
z+AW~-yW1Vh*Xzsg^45-RIX(YCg3a3fb7*GtJ~)SU{H%{}nZbq`+;%w@Z6S^diq#AX
z=xKufKES`j^l%an*+@bNyn{rGFAkP)7soXh$MZEf9;01(JRCCia7h0kUr%-~`|`@z
zeq+&%;^rJ$>3!SfYG#(gXDiZ<!%{2x01V<YdF+hiL8KYI<7`hLiwvGY-eoOFtRbz_
z7cEb%_nEa#!rJBvYwg5+yRg==IBO-MdYqg+LDrrmYtJsp8c#R}hpKm3yIRBAMMg^=
zk2M*4tVv&3@?;)sG9KbvibXqxwKox)$Ji3s?5*wWy4sm>Mq!IYVXG4b+dNltxZPoU
zd74ppk=&l;nR*V#@G_Zxg$%!nr+6`V4(IU#UgM?b0xscuc7z&GFI?Ak`jgGO!23-0
zHX*yKLiTpTyhC8_Se)!jgn5}{Um@97N%qf{B%4<Z7snNs>{1Qc6AYz19@#SX$d<m8
z6i?=r9Zx<=2>&04od!-u(2he{Gix&NOJeyIvHY4?enTwR@Cbfy<IzwjC8y4J7xLod
z0y<4|0UCO^29RW-JRTq!dw`_xy(07a<!_9L?wrM4i8!m|-SeuXQ|tdkxBtvD>Mds4
zU#r3&@%5HhHpg4l?s_{{<LxDSA&+?b5?>jMXHprZ@4aSK-;-TpbloG0TPN;S%4(6b
z+QQ>3Y#(R$2*C0bLbkUd57amDp?OwnLNUNYANU(X@pm2>|KQE^pDe2XLJI$8IsFfd
z>VNSl-ewuUjx%_N+wcbenRpLB<WYQ8DZHVU*`ZsB5Sea_-asqQ%Ik=%@r@$yylxZ+
zc~Z$)^;S(3e@B@-9_Odo_g?Ru9Hh+41Nn-MJ@#-jO63D{CwJqAd7bFCH=|db%0D}s
zbq-b2oNa5*<Q1;39942ORCiBsRdC%!w9GfKl?#a4(9=Qn{rCQ|l_}RdFXg&<seo!i
zLapJy3TtshHDgk($F$mjbE*{=R2yDboA4vG8M92WYyAE}b>NRGX2*9mG{#qL=zJGz
h6(g*!qxEgxd+sCj>buZGOit%2_9;Bf-vapb{{WD~E3N<l

literal 0
HcmV?d00001

diff --git a/extra/jautomata-core/rationals/converters/analyzers/Parser.java b/extra/jautomata-core/rationals/converters/analyzers/Parser.java
new file mode 100755
index 0000000000..51f42d2bc9
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/analyzers/Parser.java
@@ -0,0 +1,301 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters.analyzers;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+import rationals.converters.ConverterException;
+import rationals.transformations.Concatenation;
+import rationals.transformations.Mix;
+import rationals.transformations.Reducer;
+import rationals.transformations.Shuffle;
+import rationals.transformations.Star;
+import rationals.transformations.Union;
+// Grammar :
+// E -> T E'
+// E' -> + T E' | '/' '{' L '}' | eps
+// T -> S T"
+// T" -> '|' S T" | '#' S T" | eps
+// S -> F T'
+// T' -> F T' | eps
+// F -> B B'
+// B' -> * | int | ^ | eps
+// B -> letter | 1 | 0 | ( E )
+public class Parser<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+    
+  private Lexer<L> lexico ;
+  
+  /**
+   * Parse given string using standard grammar and lexical analyzer.
+   * 
+   * @param expression the expression to parse
+   * @see Lexer
+   * @see DefaultLexer
+   */
+  public Parser(String expression) {
+    lexico = new DefaultLexer(expression) ;
+  }
+
+  /**
+   * Parse using the given lexer. 
+   * 
+   * @param lexer the lexer to use for parsing.
+   */
+  public Parser(Lexer<L> lexer) {
+      this.lexico = lexer;
+  }
+  
+  private Automaton<L, Tr, T> error(String message) throws ConverterException {
+    throw new ConverterException("line " + lexico.lineNumber() + " , " + lexico.label() + " : " + message);
+  }
+  
+  public Automaton<L, Tr, T> analyze() throws ConverterException {
+    lexico.read() ;
+    Automaton<L, Tr, T> r = E() ;
+    if (lexico.current() != Lexer.END) error("end of expression expected") ;
+    return r ; 
+  }
+  
+  private Automaton<L, Tr, T> E() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL : {
+        Automaton<L, Tr, T> a = T() ;
+        Automaton<L, Tr, T> b = EP() ;
+        return new Reducer<L, Tr, T>().transform(new Union<L, Tr, T>().transform(a , b)) ;
+      }       
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.UNION :
+      case Lexer.SHUFFLE :
+	  case Lexer.MIX : 
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("expression expected") ;
+    }
+  }
+
+  private Automaton<L, Tr, T> EP() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL : return error("union expected") ; 
+      case Lexer.CLOSE :
+      case Lexer.END : return new Automaton<L, Tr, T>() ;
+      case Lexer.UNION : {
+        lexico.read() ;
+        Automaton<L, Tr, T> a = T() ;
+        Automaton<L, Tr, T> b = EP() ;
+        return new Reducer<L, Tr, T>().transform(new Union().transform(a , b)) ;
+      }
+      case Lexer.SHUFFLE :
+	  case Lexer.MIX : 
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("union expected") ; 
+    }
+  }
+
+  private Automaton<L, Tr, T> T() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL : {
+        Automaton<L, Tr, T> a = S() ;
+        Automaton<L, Tr, T> b = TS() ;
+        return new Reducer<L, Tr, T>().transform(new Shuffle().transform(a , b)) ;
+      }       
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.UNION :
+      case Lexer.SHUFFLE :
+	  case Lexer.MIX : 
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("expression expected") ;
+    }
+  }
+
+  private Automaton<L, Tr, T> TS() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL :return error("concatenation expected") ;
+      case Lexer.CLOSE :
+      case Lexer.END : 
+      case Lexer.UNION : return Automaton.epsilonAutomaton() ;
+	  case Lexer.SHUFFLE : {
+		lexico.read() ;
+		Automaton<L, Tr, T> a = S() ;
+		Automaton<L, Tr, T> b = TS() ;
+		return new Reducer<L, Tr, T>().transform(new Shuffle<L, Tr, T>().transform(a , b)) ;
+	  }
+	  case Lexer.MIX : 
+	  	{
+		lexico.read() ;
+		Automaton<L, Tr, T> a = S() ;
+		Automaton<L, Tr, T> b = TS() ;
+		return new Reducer<L, Tr, T>().transform(new Mix().transform(a , b)) ;
+	  }
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("concatenation expected") ; 
+    }
+  }
+
+  private Automaton<L, Tr, T> S() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL : {
+        Automaton<L, Tr, T> a = F() ;
+        Automaton<L, Tr, T> b = TP() ;
+        return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(a , b)) ;
+      }       
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.UNION :
+      case Lexer.SHUFFLE :
+	  case Lexer.MIX : 
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("expression expected") ;
+    }
+  }
+
+  private Automaton<L, Tr, T> TP() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL :{
+        Automaton<L, Tr, T> a = F() ;
+        Automaton<L, Tr, T> b = TP() ;
+        return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(a , b)) ;
+      }
+      case Lexer.CLOSE :
+      case Lexer.END : 
+      case Lexer.UNION : 
+	  case Lexer.MIX : 
+      case Lexer.SHUFFLE :return Automaton.epsilonAutomaton() ;
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("concatenation expected") ; 
+    }
+  }
+
+  private Automaton<L, Tr, T> F() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.OPEN :
+      case Lexer.LABEL : {
+        Automaton<L, Tr, T> a = BP(B()) ; 
+        return a ;
+      }       
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.UNION :
+	  case Lexer.MIX : 
+      case Lexer.SHUFFLE :
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("factor expected") ;
+    }
+  }
+
+  private Automaton<L, Tr, T> B() throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.EPSILON : {
+        Automaton<L, Tr, T> a = Automaton.epsilonAutomaton() ;
+        lexico.read() ;
+        return a ;
+      }
+      case Lexer.EMPTY : {
+        Automaton<L, Tr, T> a = new Automaton<>() ;
+        lexico.read() ;
+        return a ;
+      }
+      case Lexer.OPEN : {
+        lexico.read() ;
+        Automaton<L, Tr, T> a = E() ;
+        if (lexico.current() != Lexer.CLOSE) return error("( expected") ;
+        lexico.read() ;
+        return a ;
+      }
+      case Lexer.LABEL : {
+        Automaton<L, Tr, T> a = Automaton.labelAutomaton(lexico.label()) ;
+        lexico.read() ;
+        return a ;
+      }      
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.SHUFFLE :
+	  case Lexer.MIX : 
+      case Lexer.UNION :
+      case Lexer.STAR :
+      case Lexer.ITERATION :
+      case Lexer.INT :
+      default : return error("factor expected") ;
+    }
+  }
+
+  private Automaton<L, Tr, T> BP(Automaton<L, Tr, T> a) throws ConverterException {
+    switch(lexico.current()) {
+      case Lexer.OPEN :
+      case Lexer.LABEL :
+      case Lexer.CLOSE :
+      case Lexer.END :
+      case Lexer.UNION : 
+	  case Lexer.MIX : 
+      case Lexer.SHUFFLE :return a ;
+      case Lexer.STAR : {
+        lexico.read() ; 
+        return new Reducer<L, Tr, T>().transform(new Star().transform(a)) ;
+      }
+      case Lexer.ITERATION :
+        lexico.read() ; 
+        return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(a, new Star().transform(a))) ;
+      case Lexer.EPSILON :
+      case Lexer.EMPTY :
+      case Lexer.INT : {
+        int value = lexico.value() ;
+        lexico.read() ;
+        Automaton<L, Tr, T> b = Automaton.epsilonAutomaton();
+        for (int i = 0 ; i < value ; i++) {
+          b = new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(b , a)) ;
+        }
+        return b ;
+      }
+      default : return error("Unexpected character") ;
+    }
+  }
+}
diff --git a/extra/jautomata-core/rationals/converters/toAscii.java b/extra/jautomata-core/rationals/converters/toAscii.java
new file mode 100755
index 0000000000..db3088b711
--- /dev/null
+++ b/extra/jautomata-core/rationals/converters/toAscii.java
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.converters;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class toAscii<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements ToString<L, Tr, T> {
+    public String toString(Automaton<L, Tr, T> a) {
+    	StringBuilder sb = new StringBuilder();
+        sb.append("A = ").append(a.alphabet().toString()).append("\n");
+        sb.append("Q = ").append(a.states().toString()).append("\n");
+        sb.append("I = ").append(a.initials().toString()).append("\n");
+        sb.append("T = ").append(a.terminals().toString()).append("\n");
+        sb.append("delta = [\n");
+        List<String> list = new ArrayList<>();
+        Iterator<Transition<L>> i = a.delta().iterator();
+        while (i.hasNext())
+        	list.add(i.next().toString());
+        java.util.Collections.sort(list);
+        for (String s : list)
+        	sb.append(s).append("\n");
+        sb.append("]\n");
+        return sb.toString();
+    }
+}
diff --git a/extra/jautomata-core/rationals/expr/BinaryExpr.java b/extra/jautomata-core/rationals/expr/BinaryExpr.java
new file mode 100755
index 0000000000..a9b2cbec55
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/BinaryExpr.java
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+/**
+ * @author nono
+ * @version $Id: BinaryExpr.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public abstract class BinaryExpr extends RationalExpr {
+    
+    private RationalExpr left;
+    private RationalExpr right;
+
+    /**
+     * Construct a binary expression from two sub-expressions.
+     * 
+     * @param e
+     * @param f
+     */
+    public BinaryExpr(RationalExpr e,RationalExpr f) {
+        this.left = e ;
+        this.right = f;
+    }
+    
+    /**
+     * @return Returns the left.
+     */
+    public RationalExpr getLeft() {
+        return left;
+    }
+    /**
+     * @param left The left to set.
+     */
+    public void setLeft(RationalExpr left) {
+        this.left = left;
+    }
+    /**
+     * @return Returns the right.
+     */
+    public RationalExpr getRight() {
+        return right;
+    }
+    /**
+     * @param right The right to set.
+     */
+    public void setRight(RationalExpr right) {
+        this.right = right;
+    }
+    
+}
diff --git a/extra/jautomata-core/rationals/expr/Iteration.java b/extra/jautomata-core/rationals/expr/Iteration.java
new file mode 100755
index 0000000000..61b2b0f82c
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/Iteration.java
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+/**
+ * @author nono
+ * @version $Id: Iteration.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Iteration extends RationalExpr{
+
+    
+    private RationalExpr expr;
+
+    public Iteration(RationalExpr expr) {
+        this.expr = expr;
+    }
+    
+    /**
+     * @return Returns the expr.
+     */
+    public RationalExpr getExpr() {
+        return expr;
+    }
+    
+    /**
+     * @param expr The expr to set.
+     */
+    public void setExpr(RationalExpr expr) {
+        this.expr = expr;
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+       return expr.toString() + "*";
+    }
+}
diff --git a/extra/jautomata-core/rationals/expr/Letter.java b/extra/jautomata-core/rationals/expr/Letter.java
new file mode 100755
index 0000000000..415a00df14
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/Letter.java
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+import rationals.algebra.SemiRing;
+
+/**
+ * A letter expression is simply a wrapper over any object. 
+ * Note that the semantics of equals and hashcode must be properly
+ * implemented by the wrapped object as this may be used in 
+ * Collections, for example as keys in hashtables.
+ * 
+ * @author nono
+ * @version $Id: Letter.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Letter extends RationalExpr {
+
+    private Object label;
+
+    public static final Letter epsilon = new Letter(null) {
+
+        public boolean equals(Object o) {
+            return o == epsilon;
+        }
+        
+
+        public SemiRing mult(SemiRing s2) {
+            return s2;
+        }
+        
+        public String toString() {
+            return "1";
+        }
+
+        public int hashCode() {
+            return 0;
+        }
+    };
+
+    /**
+     * Construct a new letter expression.
+     * 
+     * @param o
+     *            label of the letter. May not be null. (use epsilon constant).
+     */
+    public Letter(Object o) {
+        this.label = o;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        Letter lt = (Letter) obj;
+        if (lt == null)
+            return false;
+        return lt.label == null ? this.label == null : lt.label.equals(label);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return label.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return label.toString();
+    }
+}
diff --git a/extra/jautomata-core/rationals/expr/Plus.java b/extra/jautomata-core/rationals/expr/Plus.java
new file mode 100755
index 0000000000..95999114c0
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/Plus.java
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+/**
+ * A plus expression.
+ * 
+ * @author nono
+ * @version $Id: Plus.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Plus extends BinaryExpr {
+
+    /**
+     * @param e
+     * @param f
+     */
+    public Plus(RationalExpr e, RationalExpr f) {
+        super(e, f);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return getLeft() + "+"+getRight();
+    }
+}
diff --git a/extra/jautomata-core/rationals/expr/Product.java b/extra/jautomata-core/rationals/expr/Product.java
new file mode 100755
index 0000000000..8e1cc98bb5
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/Product.java
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+
+/**
+ * A product expression.
+ * 
+ * @author nono
+ * @version $Id: Product.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Product extends BinaryExpr {
+
+    /**
+     * @param e
+     * @param f
+     */
+    public Product(RationalExpr e, RationalExpr f) {
+        super(e, f);
+    }
+    
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return getLeft() + "" +getRight();
+    }
+}
diff --git a/extra/jautomata-core/rationals/expr/RationalExpr.java b/extra/jautomata-core/rationals/expr/RationalExpr.java
new file mode 100755
index 0000000000..18584c59f6
--- /dev/null
+++ b/extra/jautomata-core/rationals/expr/RationalExpr.java
@@ -0,0 +1,86 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.expr;
+
+import rationals.algebra.SemiRing;
+
+/**
+ * @author nono
+ * @version $Id: RationalExpr.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public abstract class RationalExpr implements SemiRing {
+
+    
+    public static final RationalExpr zero = new RationalExpr() {
+        
+        public SemiRing mult(SemiRing s1) {
+            return zero;
+        }
+
+        public SemiRing plus(SemiRing s1) {
+            return s1;
+        }
+        
+        @Override
+        public boolean equals(Object o) {
+            return this == o;
+        }
+        
+        @Override
+        public int hashCode() {
+            return -1;
+        }
+        
+        @Override
+        public String toString() {
+            return "0";
+        }
+    };
+    
+    public static final RationalExpr one = Letter.epsilon;
+    
+    /* (non-Javadoc)
+     * @see rationals.SemiRing#one()
+     */
+    public final SemiRing one() {
+        return one;
+    }
+    
+    /* (non-Javadoc)
+     * @see rationals.SemiRing#zero()
+     */
+    public final SemiRing zero() {
+        return zero;
+    }
+    
+    
+    public SemiRing mult(SemiRing s2) {
+        if(s2 == zero)
+            return zero;
+        if(s2 == Letter.epsilon)
+            return this;
+        RationalExpr re = (RationalExpr)s2;
+        return new Product(this,re);
+    }
+    
+    public SemiRing plus(SemiRing s2) {
+        if(s2 == zero)
+            return this;
+        return new Plus(this,(RationalExpr)s2);
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/AreEquivalent.java b/extra/jautomata-core/rationals/properties/AreEquivalent.java
new file mode 100755
index 0000000000..681b3e5eb7
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/AreEquivalent.java
@@ -0,0 +1,78 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * Tests that two automata are equivalent according to some equivalence relation
+ * between states.
+ * <p>
+ * Instances of this class are parameterized by an instance of {@link TransducerRelation}.
+ * Given any such instance R, and two automata A1=(Q1,q01,T1,S1,d1) and
+ * A2=(Q2,q02,T2,S2,d2), we say that <code>A1 R A2</code> iff
+ * <code>q01 R q02</code>.
+ * 
+ * @version $Id: AreEquivalent.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class AreEquivalent<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTest<L, Tr, T> {
+
+    private Relation<L, Tr, T> relation;
+
+    public AreEquivalent(Relation<L, Tr, T> r) {
+        this.setRelation(r);
+    }
+
+    /**
+     * Defines the relation to be used for computing equivalence.
+     * 
+     * @param r
+     */
+    public void setRelation(Relation<L, Tr, T> r) {
+        this.relation = r;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.BinaryTest#test(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public boolean test(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+        relation.setAutomata(a, b);
+        return relation.equivalence(a.initials(), b.initials());
+    }
+
+}
+
+/*
+ * $Log: AreEquivalent.java,v $ Revision 1.1 2005/03/23 07:22:42 bailly created
+ * transductions package corrected EpsilonRemover added some tests removed
+ * DirectedGRaph Interface from Automaton
+ * 
+ * Revision 1.3 2005/02/20 21:14:19 bailly added API for computing equivalence
+ * relations on automata
+ * 
+ * Revision 1.2 2004/11/15 12:45:33 bailly changed equivalence algorithm
+ * 
+ * Revision 1.1 2004/09/21 11:50:28 bailly added interface BinaryTest added
+ * class for testing automaton equivalence (isomorphism of normalized automata)
+ * added computation of RE from Automaton
+ *  
+ */
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/AreIsomorph.java b/extra/jautomata-core/rationals/properties/AreIsomorph.java
new file mode 100755
index 0000000000..08f43e3417
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/AreIsomorph.java
@@ -0,0 +1,46 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+//import rationals.Automaton;
+//import java.util.HashMap;
+//import java.util.Map;
+
+/**
+ * Test if two automaton are isomorphic.
+ * Two automata are isomorphic iff there exists a bijection
+ * between states of each automata that preserve the initial states, the 
+ * terminal states and the transition relation.
+ *  
+ * @author nono
+ * @version $Id: AreIsomorph.java 2 2006-08-24 14:41:48Z oqube $
+ */
+//public class AreIsomorph implements BinaryTest {
+//
+//    /* (non-Javadoc)
+//     * @see rationals.properties.BinaryTest#test(rationals.Automaton, rationals.Automaton)
+//     */
+//    public boolean test(Automaton a, Automaton b) {
+//        /* basic test */
+//        if(a.states().size() != b.states().size() || a.initials().size() != b.initials().size() || a.terminals().size() != b.terminals().size())
+//            return false;
+//        Map /* < State , State > */ atob = new HashMap();
+//        // TODO        
+//        return false;
+//    }
+//
+//}
diff --git a/extra/jautomata-core/rationals/properties/BinaryTest.java b/extra/jautomata-core/rationals/properties/BinaryTest.java
new file mode 100755
index 0000000000..c75db1c069
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/BinaryTest.java
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * Interface describing binary tests (ie. tests between two automata).
+ * 
+ * @version $Id: BinaryTest.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface BinaryTest<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+
+  /**
+   * Tests that some predicate is true for two given automata.
+   * 
+   * @param a
+   * @param b
+   * @return
+   */
+  public boolean test(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b);
+  
+}
+
+/* 
+ * $Log: BinaryTest.java,v $
+ * Revision 1.1  2005/03/23 07:22:42  bailly
+ * created transductions package
+ * corrected EpsilonRemover
+ * added some tests
+ * removed DirectedGRaph Interface from Automaton
+ *
+ * Revision 1.1  2004/09/21 11:50:28  bailly
+ * added interface BinaryTest
+ * added class for testing automaton equivalence (isomorphism of normalized automata)
+ * added computation of RE from Automaton
+ *
+*/
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/Bisimilar.java b/extra/jautomata-core/rationals/properties/Bisimilar.java
new file mode 100755
index 0000000000..6c2bcb0a3a
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/Bisimilar.java
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * @version $Id: Bisimilar.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Bisimilar<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> extends AreEquivalent<L, Tr, T> {
+
+    /**
+     * @param r
+     */
+    public Bisimilar() {
+        super(new Bisimulation<L, Tr, T>());
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/Bisimulation.java b/extra/jautomata-core/rationals/properties/Bisimulation.java
new file mode 100755
index 0000000000..53081ee767
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/Bisimulation.java
@@ -0,0 +1,139 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Couple;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * This method computes the (strong) bisimulation relation between two states.
+ * 
+ * @version $Id: Bisimulation.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Bisimulation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements Relation<L, Tr, T> {
+
+    private Automaton<L, Tr, T> a1;
+
+    private Automaton<L, Tr, T> a2;
+
+    private Set<Couple> exp;
+
+    /**
+     * Constructor with two automaton.
+     * This constructor effectively calls {@link setAutomata(Automaton,Automaton)}.
+     * 
+     * @param automaton
+     * @param automaton2
+     */
+    public Bisimulation(Automaton<L, Tr, T> automaton, Automaton<L, Tr, T> automaton2) {
+        setAutomata(automaton,automaton2);
+    }
+
+    /**
+     * Argument-less constructor.
+     * Note that this implies the method {@link setAutomata(Automaton,Automaton)} 
+     * <strong>must</strong> be called before using this relation.
+     */
+    public Bisimulation() {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#setAutomata(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public void setAutomata(Automaton<L, Tr, T> a1, Automaton<L, Tr, T> a2) {
+        this.a1 = a1;
+        this.a2 = a2;
+        this.exp = new HashSet<>();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#equivalence(rationals.State,
+     *      rationals.State)
+     */
+    public boolean equivalence(State q0a, State q0b) {
+        Couple cpl = new Couple(q0a, q0b);
+        /* check states are unknown */
+        if (exp.contains(cpl))
+            return true;
+        exp.add(cpl);
+        /* iterate over all transitions */
+        Set<Transition<L>> tas = a1.delta(q0a);
+        Set<Transition<L>> tbs = a2.delta(q0b);
+        Iterator<Transition<L>> it = tas.iterator();
+        while (it.hasNext()) {
+            Transition<L> tr = it.next();
+            State ea = tr.end();
+            /* check transition exists in b */
+            Set<Transition<L>> tbsl = a2.delta(q0b, tr.label());
+            if (tbsl.isEmpty())
+                return false;
+            Iterator<Transition<L>> trb = tbsl.iterator();
+            while (trb.hasNext()) {
+                Transition<L> tb = trb.next();
+                /* mark transition as visited */
+                tbs.remove(tb);
+                State eb = tb.end();
+                if (!equivalence(ea, eb) && !trb.hasNext())
+                    return false;
+            }
+        }
+        /* checks all transitions from b has been visited */
+        if (!tbs.isEmpty()) {
+            exp.remove(cpl);
+            return false;
+        }
+        /* OK */
+        return true;
+    }
+
+    /**
+     * Checks that all combination of states from nsa and nsb
+     * are bisimilar.
+     * 
+     */
+    public boolean equivalence(Set<State> nsa, Set<State> nsb) {
+       for(Iterator<State> i = nsa.iterator();i.hasNext();) {
+           State sa = i.next();
+           for(Iterator<State> j = nsb.iterator();j.hasNext();) {
+               State sb = j.next();
+               if(!equivalence(sa,sb))
+                   return false;
+           }
+       }
+       return true;
+    }
+    
+    /* (non-Javadoc)
+     * @see rationals.properties.Relation#getErrorTrace()
+     */
+    public List<L> getErrorTrace() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/ContainsEpsilon.java b/extra/jautomata-core/rationals/properties/ContainsEpsilon.java
new file mode 100755
index 0000000000..b15e1cf044
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/ContainsEpsilon.java
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+import rationals.transformations.TransformationsToolBox;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Checks whether an automaton recognizes the empty word. This test assumes that
+ * the tested automaton does not contain epsilon (ie. <code>null</code>)
+ * transitions.
+ * 
+ * @version $Id: ContainsEpsilon.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class ContainsEpsilon<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTest<L, Tr, T> {
+
+    public boolean test(Automaton<L, Tr, T> a) {
+        Iterator<State> i = a.initials().iterator();
+        Set<State> s = a.getStateFactory().stateSet();
+        while (i.hasNext()) {
+            State st = i.next();
+            if (st.isTerminal())
+                return true;
+            s.add(st);
+            /* compute epsilon closure */
+            Set<State> cl = TransformationsToolBox.epsilonClosure(s,a);
+            if(TransformationsToolBox.containsATerminalState(cl))
+                return true;
+        }
+        return false;
+    }
+}
diff --git a/extra/jautomata-core/rationals/properties/IsDeterministic.java b/extra/jautomata-core/rationals/properties/IsDeterministic.java
new file mode 100755
index 0000000000..785d3ffc0f
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/IsDeterministic.java
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * A property that checks a given automaton is deterministic. 
+ * <p>
+ * An automaton <code>(X,Q,I,T,D)</code> is deterministic iff :
+ * <ul>
+ * <li><code>|I| = 1</code></li>
+ * <li><code>D is a function from (Q x X) -> Q</code>
+ * <li><code>X</code> does not contains the symbol <code>epsilon</code></li>
+ * </ul>
+ * 
+ * @version $Id: IsDeterministic.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class IsDeterministic<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTest<L, Tr, T> {
+
+    /* (non-Javadoc)
+     * @see rationals.properties.UnaryTest#test(rationals.Automaton)
+     */
+    public boolean test(Automaton<L, Tr, T> a) {
+        if(a.alphabet().contains(null))
+            return false;
+        if(a.initials().size() > 1)
+            return false;
+        for(Iterator<State> it = a.states().iterator();it.hasNext();) {
+            State s = it.next();
+            Set<L> tra = new HashSet<>();
+            for(Iterator<Transition<L>> it2 = a.delta(s).iterator();it2.hasNext();) {
+                Transition<L> tr = it2.next();
+                if(tra.contains(tr.label()))
+                    return false;
+                else
+                    tra.add(tr.label());
+            }
+        }
+        return true;
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/ModelCheck.java b/extra/jautomata-core/rationals/properties/ModelCheck.java
new file mode 100755
index 0000000000..ddb4e82286
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/ModelCheck.java
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+import rationals.transformations.Complement;
+import rationals.transformations.Mix;
+import rationals.transformations.Pruner;
+import rationals.transformations.ToDFA;
+
+/**
+ * This class implements a basic model-checking algorithm.
+ * <p>
+ * The first automata is first complemented on its alphabet using the operation
+ * {@see rationals.transformations.Complement}. It is then synchronized with
+ * the second automaton using the {@see rationals.transformations.Mix}
+ * operation.
+ * <p>
+ * If the language produced is empty, then the test returns true which means that
+ * automaton <code>b</code> contains the language of <code>a</code>. Else,
+ * the language produced represents counterexamples of the property modelled by
+ * <code>a</code> in <code>b</code>: the test returns false.
+ * <p>
+ * The resulting automaton can be retrieved using the method
+ * {@see #counterExamples()}.
+ * 
+ * @version $Id: ModelCheck.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class ModelCheck<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTest<L, Tr, T> {
+
+    private Automaton<L, Tr, T> cex;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.properties.BinaryTest#test(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public boolean test(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+    	Automaton<L, Tr, T> aDFA = new ToDFA<L, Tr, T>().transform(a);
+    	Automaton<L, Tr, T> bDFA = new ToDFA<L, Tr, T>().transform(b);
+        Automaton<L, Tr, T> caDFA = new Complement<L, Tr, T>().transform(aDFA);
+        cex = new Pruner<L, Tr, T>().transform(new Mix<L, Tr, T>().transform(caDFA, bDFA));
+        if (new isEmpty<L, Tr, T>().test(cex))
+            return true;
+        else
+            return false;
+    }
+
+    /**
+     * Return the automaton resulting from this test.
+     * 
+     * @return an Automaton or null if
+     *         {@see #test(rationals.Automaton,rationals.Automaton)}has not
+     *         been called yet.
+     */
+    public Automaton<L, Tr, T> counterExamples() {
+        return cex;
+    }
+}
diff --git a/extra/jautomata-core/rationals/properties/Relation.java b/extra/jautomata-core/rationals/properties/Relation.java
new file mode 100755
index 0000000000..e657e6674e
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/Relation.java
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import java.util.List;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * An interface for computing equivalences between automata.
+ * 
+ * This interface allows definition of various relation between 
+ * states.
+ * 
+ * @version $Id: Relation.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface Relation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+
+    /**
+     * Sets the context for computing the relation.
+     * This method must be called before {@link equivalent(State,State)}.
+     * 
+     * @param a1
+     * @param a2
+     */
+    void setAutomata(Automaton<L, Tr, T> a1, Automaton<L, Tr, T> a2);
+    
+    /**
+     * Assert the equivalence between two states.
+     * This method returns true if and only if the two states
+     * are in relation.
+     * 
+     * @param s1
+     * @param s2
+     * @return true is s1 ~ s2, false otherwise 
+     */
+    boolean equivalence(State s1, State s2);
+
+    /**
+     * Asset the equivalence between two set of states.
+     * This method returns true if and only if the two states set 
+     * are equivalent.
+     * 
+     * @param nsa a Set of State objects from a
+     * @param nsb a Set of State objects from b
+     * @return true if nsa is equivalent to nsb
+     */
+    public boolean equivalence(Set<State> nsa, Set<State> nsb);
+    
+    /**
+     * Returns the trace of labels that lead to an error.
+     * 
+     * This is an optional operation, and subclasses may throw {@link UnsupportedOperationException}/
+     * 
+     * @return a List of objects or null.
+     */
+    public List<L> getErrorTrace() throws UnsupportedOperationException;
+
+}
diff --git a/extra/jautomata-core/rationals/properties/Similar.java b/extra/jautomata-core/rationals/properties/Similar.java
new file mode 100755
index 0000000000..e36756de34
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/Similar.java
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * @version $Id: Similar.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Similar<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> extends AreEquivalent<L, Tr, T> {
+
+    /**
+     * @param r
+     */
+    public Similar() {
+        super(new Simulation<L, Tr, T>());
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/Simulation.java b/extra/jautomata-core/rationals/properties/Simulation.java
new file mode 100755
index 0000000000..567141fcfd
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/Simulation.java
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Couple;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class implements (strong) simulation equivalence between 
+ * two automata.
+ * <p />
+ * Given two automata <code>A=(Qa,q0a,Ta,Sa,deltaA)</code> and <code>B=(Qb,q0b,Tb,Sb,deltaB)</code>,
+ * a simulation S of A by B is a relation in <code>Qa x Qb</code> 
+ * s.t., whenever <code>(qa,qb) \in S</code>,
+ * <ul>
+ * <li>for each <code>(qa,a,qa') \in deltaA</code>, exists <code>(qb,a,qb')\in deltaB</code>
+ * and <code>(qa',qb') \in S</code>,</li>
+ * </ul>
+ * B is a simulation of A iff <code>q0b ~ q0a</code>.
+ * <p />
+ * Note that in general, a simulation is not symetric. A symmetric 
+ * simulation is of course a bisimulation.
+ * 
+ * @version $Id: Simulation.java 2 2006-08-24 14:41:48Z oqube $
+ * @see rationals.properties.Bisimulation
+ */
+public class Simulation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements Relation<L, Tr, T> {
+    
+    private Automaton<L, Tr, T> a1;
+
+    private Automaton<L, Tr, T> a2;
+
+    private Set<Couple> exp;
+
+    /**
+     * Constructor with two automataon.
+     * This constructor effectively calls {@link #setAutomata(Automaton,Automaton)}.
+     * 
+     * @param automaton
+     * @param automaton2
+     */
+    public Simulation(Automaton<L, Tr, T> automaton, Automaton<L, Tr, T> automaton2) {
+        setAutomata(automaton,automaton2);
+    }
+    
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#setAutomata(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public void setAutomata(Automaton<L, Tr, T> a1, Automaton<L, Tr, T> a2) {
+        this.a1 = a1;
+        this.a2 = a2;
+        this.exp = new HashSet<>();
+    }
+
+    public Simulation() {}
+    
+    /**
+     * Checks that all combination of states from nsa and nsb
+     * are bisimilar.
+     * 
+     */
+    public boolean equivalence(Set<State> nsa, Set<State> nsb) {
+       for(Iterator<State> i = nsa.iterator();i.hasNext();) {
+           State sa = i.next();
+           for(Iterator<State> j = nsb.iterator();j.hasNext();) {
+               State sb = j.next();
+               if(!equivalence(sa,sb))
+                   return false;
+           }
+       }
+       return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#equivalence(rationals.State,
+     *      rationals.State)
+     */
+    public boolean equivalence(State q0a, State q0b) {
+        Couple cpl = new Couple(q0a, q0b);
+        /* check states are unknown */
+        if (exp.contains(cpl))
+            return true;
+        exp.add(cpl);
+        /* iterate over all transitions */
+        Set<Transition<L>> tas = a1.delta(q0a);
+        Set<Transition<L>> tbs = a2.delta(q0b);
+        Iterator<Transition<L>> it = tas.iterator();
+        while (it.hasNext()) {
+            Transition<L> tr = it.next();
+            State ea = tr.end();
+            /* check transition exists in b */
+            Set<Transition<L>> tbsl = a2.delta(q0b, tr.label());
+            if (tbsl.isEmpty())
+                return false;
+            Iterator<Transition<L>> trb = tbsl.iterator();
+            while (trb.hasNext()) {
+                Transition<L> tb = trb.next();
+                /* mark transition as visited */
+                tbs.remove(tb);
+                State eb = tb.end();
+                if (!equivalence(ea, eb) && !trb.hasNext())
+                    return false;
+            }
+        }
+        /* OK */
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see rationals.properties.Relation#getErrorTrace()
+     */
+    public List<L> getErrorTrace() {
+    	throw new UnsupportedOperationException();
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/TraceEquivalence.java b/extra/jautomata-core/rationals/properties/TraceEquivalence.java
new file mode 100755
index 0000000000..65b3e4ee3e
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/TraceEquivalence.java
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+import rationals.transformations.StatesCouple;
+import rationals.transformations.TransformationsToolBox;
+
+import java.util.*;
+
+/**
+ * A class that compute trace equivalence relation between two states. This
+ * class checks whether two states from two automata are trace equivalent, which
+ * simply means they recognize the same prefix of languages.
+ * <p>
+ * This class effectively computes the deterministic form of the two given
+ * automata.
+ * 
+ * @version $Id: TraceEquivalence.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class TraceEquivalence<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements Relation<L, Tr, T> {
+
+    private Automaton<L, Tr, T> a1;
+
+    private Automaton<L, Tr, T> a2;
+
+    private List<L> errorTrace;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#setAutomata(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public void setAutomata(Automaton<L, Tr, T> a1, Automaton<L, Tr, T> a2) {
+        this.a1 = a1;
+        this.a2 = a2;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#equivalence(rationals.State,
+     *      rationals.State)
+     */
+    public boolean equivalence(State q0a, State q0b) {
+        /* compute epsilon closures on states */
+        Set<State> nsa = a1.getStateFactory().stateSet();
+        Set<State> nsb = a2.getStateFactory().stateSet();
+        nsa.add(q0a);
+        nsb.add(q0b);
+        /* check equivalence on sets */
+        return equivalence(nsa, nsb);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.properties.Relation#equivalence(java.util.Set,
+     *      java.util.Set)
+     */
+    public boolean equivalence(Set<State> nsa, Set<State> nsb) {
+        /* sets of explored states */
+        Stack<StatesCouple> todo = new Stack<>();
+        /* current traces for failure */
+        Stack<L> labels = new Stack<>();
+        Stack<L> trace = new Stack<>();
+        Set<StatesCouple> done = new HashSet<>();
+        todo.push(new StatesCouple(nsa, nsb));
+        labels.push(null); // Needed to avoid empty stack
+        do {
+            StatesCouple cpl = todo.pop();
+            L lbl = labels.pop();
+            Set<State> sa = TransformationsToolBox.epsilonClosure(cpl.sa, a1);
+            Set<State> sb = TransformationsToolBox.epsilonClosure(cpl.sb, a2);
+            if (done.contains(cpl)) {
+            	L top = trace.peek();
+            	// Bug fix: two different transitions to the same state can cause the trace to become empty
+                if (top == null ? lbl == null : top.equals(lbl)) trace.pop();
+                continue;
+            } else {
+            	trace.push(lbl);
+            }
+            done.add(cpl);
+            /* compute set of transitions */
+            List<Transition<L>> tas = new ArrayList<>(a1.delta(sa));
+            List<Transition<L>> tbs = new ArrayList<>(a2.delta(sb));
+            /* map from letters to set of states */
+            Map<L, Set<State>> am = new HashMap<>();
+            Map<L, Set<State>> bm = new HashMap<>();
+            /* compute set of states reached for each letter */
+            mapAlphabet(tas, am, a1);
+            mapAlphabet(tbs, bm, a2);
+            Iterator<Map.Entry<L, Set<State>>> it2 = am.entrySet().iterator();
+            while (it2.hasNext()) {
+            	Map.Entry<L, Set<State>> me = it2.next();
+                L l = me.getKey();
+                Set<State> as = me.getValue();
+                Set<State> bs = bm.remove(l);
+                if (bs == null) {
+                    this.errorTrace = trace;
+                    this.errorTrace.add(l);
+                    return false;
+                }
+                StatesCouple sc = new StatesCouple(as, bs);
+                todo.push(sc);
+                labels.push(l);
+            }
+            if (!bm.isEmpty()) {
+                this.errorTrace = trace;
+                this.errorTrace.addAll(bm.keySet());
+                return false;
+            }
+        } while (!todo.isEmpty());
+        return true;
+    }
+
+    /**
+     * @param tas
+     * @param am
+     */
+    public void mapAlphabet(List<Transition<L>> tas, Map<L, Set<State>> am, Automaton<L, Tr, T> a) {
+        /* compute set of states for each letter */
+        while (!tas.isEmpty()) {
+            Transition<L> tr = tas.remove(0);
+            L l = tr.label();
+            if (l == null)
+                continue;
+            Set<State> as = am.get(l);
+            if (as == null) {
+                as = a.getStateFactory().stateSet();
+                am.put(l, as);
+            }
+            as.add(tr.end());
+        }
+    }
+
+    /**
+     * @return Returns the errorTrace.
+     */
+    public List<L> getErrorTrace() {
+        return errorTrace;
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/TraceEquivalent.java b/extra/jautomata-core/rationals/properties/TraceEquivalent.java
new file mode 100755
index 0000000000..f4bbc10eb8
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/TraceEquivalent.java
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * @version $Id: TraceEquivalent.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class TraceEquivalent<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> extends AreEquivalent<L, Tr, T> {
+
+    /**
+     * @param r
+     */
+    public TraceEquivalent() {
+        super(new TraceEquivalence<L, Tr, T>());
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/UnaryTest.java b/extra/jautomata-core/rationals/properties/UnaryTest.java
new file mode 100755
index 0000000000..0c4083bf04
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/UnaryTest.java
@@ -0,0 +1,25 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+public interface UnaryTest<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+  public boolean test(Automaton<L, Tr, T> a) ;
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/WeakBisimulation.java b/extra/jautomata-core/rationals/properties/WeakBisimulation.java
new file mode 100755
index 0000000000..9e4837b021
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/WeakBisimulation.java
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+import rationals.transformations.EpsilonTransitionRemover;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This method computes the weak bisimulation relation between two states.
+ * The weak bisimulation is computed as (strong) bisimulation between the two 
+ * given automata where all epsilon transitions have been removed.
+ * 
+ * @version $Id: WeakBisimulation.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class WeakBisimulation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements Relation<L, Tr, T> {
+
+    private Bisimulation<L, Tr, T> bisim;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#setAutomata(rationals.Automaton,
+     *      rationals.Automaton)
+     */
+    public void setAutomata(Automaton<L, Tr, T> a1, Automaton<L, Tr, T> a2) {
+        EpsilonTransitionRemover<L, Tr, T> er = new EpsilonTransitionRemover<>();
+        this.bisim = new Bisimulation<>(er.transform(a1), er.transform(a2));
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.tests.Relation#equivalence(rationals.State,
+     *      rationals.State)
+     */
+    public boolean equivalence(State q0a, State q0b) {
+        return bisim.equivalence(q0a, q0b);
+    }
+
+    public boolean equivalence(Set<State> nsa, Set<State> nsb) {
+        return bisim.equivalence(nsa, nsb);
+    }
+    
+    /* (non-Javadoc)
+     * @see rationals.properties.Relation#getErrorTrace()
+     */
+    public List<L> getErrorTrace() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/properties/WeaklyBisimilar.java b/extra/jautomata-core/rationals/properties/WeaklyBisimilar.java
new file mode 100755
index 0000000000..abdbbaa428
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/WeaklyBisimilar.java
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * @author nono
+ * @version $Id: WeaklyBisimilar.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class WeaklyBisimilar<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> extends AreEquivalent<L, Tr, T> {
+
+    /**
+     * @param r
+     */
+    public WeaklyBisimilar() {
+        super(new WeakBisimulation<L, Tr, T>());
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/properties/isEmpty.java b/extra/jautomata-core/rationals/properties/isEmpty.java
new file mode 100755
index 0000000000..772ed06797
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/isEmpty.java
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.Iterator;
+
+
+public class isEmpty<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTest<L, Tr, T> {
+	
+  public boolean test(Automaton<L, Tr, T> a) {
+    Iterator<State> i = a.accessibleStates().iterator() ;
+    while (i.hasNext()) {
+      if (i.next().isTerminal()) return false ;
+    }
+    return true ;
+  }
+  
+}
diff --git a/extra/jautomata-core/rationals/properties/isNormalized.java b/extra/jautomata-core/rationals/properties/isNormalized.java
new file mode 100755
index 0000000000..4eff572f0d
--- /dev/null
+++ b/extra/jautomata-core/rationals/properties/isNormalized.java
@@ -0,0 +1,45 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.properties;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * Tests if an automaton is normalized.
+ * 
+ * @see rationals.transformations.Normalizer
+ * @author nono
+ * @version $Id: isNormalized.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class isNormalized<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTest<L, Tr, T> {
+    public boolean test(Automaton<L, Tr, T> a) {
+        if (a.initials().size() != 1)
+            return false;
+        if (a.terminals().size() != 1)
+            return false;
+        State e = a.initials().iterator().next();
+        if (a.deltaMinusOne(e).size() > 0)
+            return false;
+        e = a.terminals().iterator().next();
+        if (a.delta(e).size() > 0)
+            return false;
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Accessible.java b/extra/jautomata-core/rationals/transformations/Accessible.java
new file mode 100755
index 0000000000..2f32a626f5
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Accessible.java
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * Compute the automaton accessible from a given state
+ * @author bailly
+ * @version $Id: Accessible.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Accessible<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+	private State state;
+
+	/**
+	 * The state we must start exploration from
+	 * 
+	 */
+	public Accessible(State s) {
+		this.state = s;
+	}
+
+	/* (non-Javadoc)
+	 * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+	 */
+	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+		Set<Transition<L>> trs = a.delta();
+		Automaton<L, Tr, T> b = new Automaton<>();
+		Map<State, State> stmap = new HashMap<>();
+		/* initial state = state */
+		State ns = b.addState(true, state.isTerminal());
+		stmap.put(state, ns);
+		explore(state, stmap, a, b);
+		/* explore a and remove transitions from trs */
+		Iterator<Transition<L>> it = trs.iterator();
+		while(it.hasNext()) {
+			Transition<L> tr = it.next();
+			State nstart = stmap.get(tr.start());
+			State nend = stmap.get(tr.end());
+			if(nstart != null && nend != null)
+				try {
+					b.addTransition(new Transition<>(nstart,tr.label(),nend));
+				} catch (NoSuchStateException e) {
+					System.err.println(e.getMessage());
+					return null;
+				}
+		}
+		return b;
+	}
+
+	/**
+	 * Recursive function to explore transitions from a state
+	 * @param state
+	 * @param stmap
+	 * @param b
+	 */
+	private void explore(State curstate, Map<State, State> stmap, Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+		Iterator<Transition<L>> it = a.delta(curstate).iterator();
+		while(it.hasNext()) {
+			Transition<L> tr = it.next();
+			State e = tr.end();
+			State ne = stmap.get(e);
+			if(ne != null)
+				continue;
+			else {
+				ne = b.addState(e.isInitial(),e.isTerminal());
+				stmap.put(e,ne);
+				explore(e,stmap,a,b);
+			}
+		}
+	}
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/BinaryTransformation.java b/extra/jautomata-core/rationals/transformations/BinaryTransformation.java
new file mode 100755
index 0000000000..a7439d3750
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/BinaryTransformation.java
@@ -0,0 +1,30 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * A generic interface for binary operations between two automata.
+ * 
+ * @version $Id: BinaryTransformation.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public interface BinaryTransformation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a , Automaton<L, Tr, T> b) ;
+}
diff --git a/extra/jautomata-core/rationals/transformations/Complement.java b/extra/jautomata-core/rationals/transformations/Complement.java
new file mode 100755
index 0000000000..67c6c4945c
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Complement.java
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * A transformation that computes the complement of an automaton.
+ * <p>
+ * This transformation computes the complement of an automaton: Terminal states
+ * are inverted and missing transitions are added.
+ * 
+ * @author nono
+ * @version $Id: Complement.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Complement<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton<L, Tr, T> ret = new Automaton<>();
+        List<State> todo = new ArrayList<>();
+        Map<State, State> sm = new HashMap<>();
+        Set<State> done = new HashSet<>();
+        Set<State> s = a.initials();
+        todo.addAll(s);
+        while (!todo.isEmpty()) {
+            State st = todo.remove(0);
+            State ns = sm.get(st);
+            if (ns == null) {
+                ns = ret.addState(st.isInitial(), !st.isTerminal());
+                sm.put(st, ns);
+            }
+            done.add(st);
+            for (Iterator<L> it = a.alphabet().iterator(); it.hasNext();) {
+                L l = it.next();
+                Set<Transition<L>> ends = a.delta(st, l);
+                if (ends.isEmpty())
+                    try {
+                        ret.addTransition(new Transition<>(ns, l, ns));
+                    } catch (NoSuchStateException e) {
+                    }
+                else {
+                    for (Iterator<Transition<L>> i = ends.iterator(); i.hasNext();) {
+                        State end = i.next().end();
+                        State ne = sm.get(end);
+                        if (ne == null) {
+                            ne = ret.addState(end.isInitial(), !end.isTerminal());
+                            sm.put(end, ne);
+                            todo.add(end);
+                        }
+                        try {
+                            ret.addTransition(new Transition<>(ns, l, ne));
+                        } catch (NoSuchStateException e) {
+                        }
+                    }
+                }
+
+            }
+        }
+        return ret;
+    }
+
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/CompleteNop.java b/extra/jautomata-core/rationals/transformations/CompleteNop.java
new file mode 100755
index 0000000000..4105186a6a
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/CompleteNop.java
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * This methods completes the transitions in an Automaton w.r.t. to an
+ * arbitrary alphabet.
+ * <p>
+ * That is, for each state <code>q</code> and for each letter <code>l</code>
+ * in <code>ioa</code>'s alphabet, if there is no transition labelled with
+ * <code>l</code> starting from <code>q</code>, it adds a transition
+ * <code>(q,l,q)</code> to this automaton.
+ * <p>
+ * The semantic of this completion scheme should be compared with
+ * {@link rationals.transformations.CompleteSink}which completes an automaton
+ * by adding a sink state.
+ * <p>
+ * 
+ * @version $Id: CompleteNop.java 6 2006-08-30 08:56:44Z oqube $
+ */
+public class CompleteNop<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    private Set<L> alphabet;
+
+    public CompleteNop(Set<L> alphabet) {
+        this.alphabet = alphabet;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton<L, Tr, T> b = new Automaton<>();
+        Map<State, State> qm = new HashMap<>();
+        for (Iterator<State> i = a.states().iterator(); i.hasNext();) {
+            State q = i.next();
+            State p = b.addState(q.isInitial(), q.isTerminal());
+            qm.put(q, p);
+        }
+        Set<L> alph = new HashSet<>();
+        for (Iterator<State> it = a.states().iterator(); it.hasNext();) {
+            State q = it.next();
+            alph.addAll(alphabet);
+            for (Iterator<Transition<L>> i2 = a.delta(q).iterator(); i2.hasNext();) {
+                Transition<L> tr = i2.next();
+                try {
+                    b.addTransition(new Transition<>(qm.get(tr.start()), tr.label(), qm.get(tr.end())));
+                } catch (NoSuchStateException e) {
+                }
+                alph.remove(tr.label());
+            }
+            for (Iterator<L> i2 = alph.iterator(); i2.hasNext();) {
+                try {
+                    b.addTransition(new Transition<L>(q, i2.next(), q));
+                } catch (NoSuchStateException e) {
+                }
+            }
+            alph.clear();
+        }
+        return b;
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/Concatenation.java b/extra/jautomata-core/rationals/transformations/Concatenation.java
new file mode 100755
index 0000000000..86ef5cf5c3
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Concatenation.java
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+import rationals.properties.ContainsEpsilon;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Compute the concatenation of two automata.
+ * <ul>
+ * <li>C = A . B</li>
+ * <li>S(C) = S(A) U S(B)</li>
+ * <li>S0(C) =
+ * <ul>
+ * <li>S0(A), if not A contains epsilon,</li>
+ * <li>S0(A) U SO(B), otherwise</li>
+ * </ul>
+ * </li>
+ * <li>T(C) =
+ * <ul>
+ * <li>T(B), if not B contains epsilon,</li>
+ * <li>T(A) U T(B), otherwise</li>
+ * </ul>
+ * </li>
+ * <li>D(C) = D(A) U D(B) U { (s1,a,s2) | (s,a,s2) in D(B), s in S0(B),s1 in
+ * T(A) } - {(s,a,s2) in D(B), s in S0(B) }</li>
+ * </ul>
+ * 
+ * @version $Id: Concatenation.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Concatenation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTransformation<L, Tr, T> {
+
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+        Automaton<L, Tr, T> ap = new Normalizer<L, Tr, T>().transform(a);
+        Automaton<L, Tr, T> bp = new Normalizer<L, Tr, T>().transform(b);
+        ContainsEpsilon<L, Tr, T> ce = new ContainsEpsilon<L, Tr, T>();
+        boolean ace = ce.test(a);
+        boolean bce = ce.test(b);
+        if (ap.states().size() == 0 && ace)
+            return b;
+        if (bp.states().size() == 0 && bce)
+            return a;
+        State junc = null; /* junction state */
+        Automaton<L, Tr, T> c = new Automaton<>();
+        Map<State, State> map = new HashMap<>();
+        /* add all states from ap */
+        Iterator<State> i1 = ap.states().iterator();
+        while (i1.hasNext()) {
+            State e = i1.next();
+            State n;
+            if (e.isInitial()) {
+                n = c.addState(true, ace && bce);
+            } else if(!e.isTerminal())
+                n = c.addState(false, e.isTerminal() && bce);
+            else
+                continue;
+            map.put(e, n);
+        }
+        /* add states from bp */
+        Iterator<State> i2 = bp.states().iterator();
+        while (i2.hasNext()) {
+            State e = i2.next();
+            State n;
+            if (!e.isInitial())  {
+                n = c.addState(false, e.isTerminal());
+                map.put(e, n);
+            }
+        }
+        /* create junction state */
+        junc = c.addState(ace,bce);
+        Iterator<Transition<L>> i3 = ap.delta().iterator();
+        while (i3.hasNext()) {
+        	Transition<L> t = i3.next();
+            try {
+                if (t.end().isTerminal())
+                    c.addTransition(new Transition<>(map.get(t.start()), t.label(), junc));
+                else
+                    c.addTransition(new Transition<>(map.get(t.start()), t.label(), map.get(t.end())));
+            } catch (NoSuchStateException x) {
+            }
+
+        }
+        Iterator<Transition<L>> i4 = bp.delta().iterator();
+        while (i4.hasNext()) {
+            Transition<L> t = i4.next();
+            try {
+                if (t.start().isInitial())
+                    c.addTransition(new Transition<>(junc, t.label(), map.get(t.end())));
+                else
+                    c.addTransition(new Transition<>(map.get(t.start()), t.label(), map.get(t.end())));
+            } catch (NoSuchStateException x) {
+            }
+        }
+        return c;
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/EpsilonTransitionRemover.java b/extra/jautomata-core/rationals/transformations/EpsilonTransitionRemover.java
new file mode 100755
index 0000000000..1526fb319c
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/EpsilonTransitionRemover.java
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2002 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.*;
+
+/**
+ * This class allows to remove epsilon transitions in an automaton. Epsilon
+ * transition are transitions (q , l , q') where l is null.
+ * 
+ * @author Yves Roos
+ * @version 22032002
+ */
+public class EpsilonTransitionRemover<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton<L, Tr, T> ret = new Automaton<>(); /* resulting automaton */
+        Map<HashValue<State>, State> sm = new HashMap<>();
+        Set<HashValue<State>> done = new HashSet<>();
+        List<HashValue<State>> todo = new ArrayList<>(); /* set of states to explore */
+        Set<State> cur = TransformationsToolBox.epsilonClosure(a.initials(), a);
+        /* add cur as initial state of ret */
+        State is = ret.addState(true,TransformationsToolBox.containsATerminalState(cur));
+        HashValue<State> hv = new HashValue<>(cur);
+        sm.put(hv,is);
+        todo.add(hv);
+        do {
+            HashValue<State> s = todo.remove(0);
+            State ns =  sm.get(s);
+            if(ns == null) {
+                ns = ret.addState(false,TransformationsToolBox.containsATerminalState(s.s));
+                sm.put(s,ns);
+            }
+            /* set s as explored */
+            done.add(s);
+            /* look for all transitions in s */
+            Map<L, Set<State>> trm = instructions(a.delta(s.s),a);
+            Iterator<Map.Entry<L, Set<State>>> it = trm.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry<L, Set<State>> e = it.next();
+                L o = e.getKey();
+                Set<State> ar = e.getValue();
+                /* compute closure of arrival set */
+                ar = TransformationsToolBox.epsilonClosure(ar, a);
+                hv = new HashValue<>(ar);
+                /* retrieve state in new automaton from hashvalue */
+                State ne = sm.get(hv);
+                if(ne == null) {
+                    ne = ret.addState(false,TransformationsToolBox.containsATerminalState(ar));
+                    sm.put(hv,ne);
+                }
+                try {
+                    /* create transition */
+                    ret.addTransition(new Transition<L>(ns,o,ne));
+                } catch (NoSuchStateException e1) {
+                }
+                /* explore new state */
+                if(!done.contains(hv))
+                    todo.add(hv);
+            }
+        } while (!todo.isEmpty());
+        return ret;
+    }
+
+    private Map<L, Set<State>> instructions(Set<Transition<L>> s, Automaton<L, Tr, T> a) {
+        Map<L, Set<State>> m = new HashMap<L, Set<State>>();
+        Iterator<Transition<L>> it = s.iterator();
+        while (it.hasNext()) {
+            Transition<L> tr = it.next();
+            L l = tr.label();
+            if (l != null) {
+                Set<State> st = m.get(l);
+                if (st == null) {
+                    st = a.getStateFactory().stateSet();
+                    m.put(l,st);
+                }
+                /* add arrival state */
+                st.add(tr.end());
+            }
+        }
+        return m;
+    }
+
+}
+
diff --git a/extra/jautomata-core/rationals/transformations/HashValue.java b/extra/jautomata-core/rationals/transformations/HashValue.java
new file mode 100755
index 0000000000..9fd2185449
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/HashValue.java
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.Set;
+
+/**
+ * A simple class for encapsulating sets s.t. they can be used
+ * efficiently in Set or HashMap.
+ * 
+ * @author nono
+ * @version $Id: HashValue.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class HashValue<T> {
+    
+    public final int hash;
+
+    public final Set<T> s;
+
+    public HashValue(Set<T> s) {
+        this.s = s;
+        this.hash = s.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+    	if (!(obj instanceof HashValue)) return false;
+        return ((HashValue<?>) obj).hash == hash;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return hash;
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return s.toString();
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Identity.java b/extra/jautomata-core/rationals/transformations/Identity.java
new file mode 100755
index 0000000000..fe03048455
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Identity.java
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+/**
+ * A transformation that simply returns a clone of its argument.
+ * 
+ * @version $Id: Identity.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Identity<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    /* (non-Javadoc)
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        return a.clone();
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/InverseMorphism.java b/extra/jautomata-core/rationals/transformations/InverseMorphism.java
new file mode 100755
index 0000000000..e89364350a
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/InverseMorphism.java
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import rationals.Automaton;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * A general  class for applying inverse morphism on rational sets.
+ * <p>
+ * A morphism is constructed from a {@see java.util.Map} from letters to
+ * letters (ie. from Object to Object). An inverse morphism is then computed 
+ * by inversing the given map. A morphism is usually surjective, which is
+ * not the case of an inverse morphism, unless of course it is also 
+ * injective. This means that the image of a single letter may be a
+ * set of letters. 
+ * </p>
+ * <p>
+ * 
+ * </p>
+ *  
+ * @author nono
+ * @version $Id: InverseMorphism.java 2 2006-08-24 14:41:48Z oqube $
+ * @see rationals.transformations.Morphism
+ */
+public class InverseMorphism implements UnaryTransformation {
+
+    private Map morph;
+
+    public InverseMorphism(Map m) {
+        this.morph = inverse(m);
+    }
+    
+    /*
+     * create inverse mapping from given map.
+     * The key are letters (Object) and the values 
+     * are sets of letters (Set).
+     */
+    private Map inverse(Map m) {
+    	Map inv = new HashMap();
+    	for(Iterator i = m.entrySet().iterator();i.hasNext();) {
+    		Map.Entry e  = (Map.Entry)i.next();
+    		Object v = e.getValue();
+    		Object k = e.getKey();
+    		Set s = (Set)inv.get(v);
+    		if(s == null) {
+    			s = new HashSet();
+    			inv.put(v,s);
+    		}
+    		s.add(k);
+    	}
+    	return inv;
+	}
+
+	/* (non-Javadoc)
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton transform(Automaton a) {
+        Automaton b = new Automaton();
+        /* state map */
+        Map stm = new HashMap();
+        for(Iterator i = a.delta().iterator();i.hasNext();) {
+            Transition tr = (Transition)i.next();
+            State ns = tr.start();
+            State nss = (State)stm.get(ns);
+            if(nss == null) {
+                nss = b.addState(ns.isInitial(),ns.isTerminal());
+                stm.put(ns,nss);
+            }
+            State ne = tr.end();
+            State nse = (State)stm.get(ne);
+            if(nse == null) {
+                nse = b.addState(ne.isInitial(),ne.isTerminal());
+                stm.put(ne,nse);
+            }
+            Object lbl = tr.label();
+            Set s = (Set)morph.get(lbl);
+            if(s == null)
+                try {
+                    b.addTransition(new Transition(nss,lbl,nse));
+                } catch (NoSuchStateException e) {
+                }
+            else
+                try {
+                	for(Iterator j = s.iterator();j.hasNext();)
+                		b.addTransition(new Transition(nss,j.next(),nse));
+                } catch (NoSuchStateException e1) {
+                }
+        }
+        // handle epsilon's image
+        Set s = (Set)morph.get(null);
+        if(s != null) {
+        	// append auto transition to each state
+        	for(Iterator i = b.states().iterator();i.hasNext();){
+        		State st = (State)i.next();
+        		for(Iterator j = s.iterator();j.hasNext();) {
+        			Object o = j.next();
+        			try {
+						if(o != null)
+							b.addTransition(new Transition(st,o,st));
+					} catch (NoSuchStateException e) {
+					}
+        		}
+        	}
+        }
+        return b;
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/Mix.java b/extra/jautomata-core/rationals/transformations/Mix.java
new file mode 100755
index 0000000000..a86fea3332
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Mix.java
@@ -0,0 +1,194 @@
+/*
+ * (C) Copyright 2002 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.*;
+
+import java.util.*;
+
+/**
+ * This class implements the mix - ie: synchronization product - operator
+ * between two automatas.
+ * <ul>
+ * <li>C = A mix B</li>
+ * <li>S(C) = { (a,b) | a in S(A) and b in S(B) }</li>
+ * <li>S0(C) = (S0(A),SO(B))</li>
+ * <li>T(C) = { (a,b) | a in T(A) and b in T(B) }</li>
+ * <li>D(C) = { ((s1a,s1b),a,(s2a,s2b)) | exists (s1a,a,s2a) in D(A) and exists
+ * (s1b,a,s2b) in D(b) } U { ((s1a,s1b),a,(s1a,s2b)) | a not in S(A) and exists
+ * (s1b,a,s2b) in D(b) } U { ((s1a,s1b),a,(s2a,s1b)) | a not in S(B) and exists
+ * (s1a,a,s2a) in D(a) }</li>
+ * </ul>
+ * 
+ * @author Arnaud Bailly
+ * @version 22032002
+ */
+public class Mix<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTransformation<L, Tr, T> {
+
+	private Synchronization<L> synchronization;
+
+	/**
+	 * Compute mix of two automata using default synchronization scheme which is
+	 * the equality of labels.
+	 * 
+	 * @see rationals.DefaultSynchronization
+	 * @see rationals.Synchronization
+	 */
+	public Mix() {
+		this.synchronization = new DefaultSynchronization();
+	}
+
+	/**
+	 * Compute mix of two automata using given synchronization scheme.
+	 * 
+	 * @param synch
+	 *            a Synchronization object. Must not be null.
+	 */
+	public Mix(Synchronization synch) {
+		this.synchronization = synch;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * rationals.transformations.BinaryTransformation#transform(rationals.Automaton
+	 * , rationals.Automaton)
+	 */
+	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+		Automaton<L, Tr, T> ret = (Automaton<L, Tr, T>) new Automaton();
+		// FIXME: Potentially unsafe cast, but adding generics reveals an inconsistency in the APIs 
+		ret.setBuilder((T) new TransitionBuilder<L>());
+		return transformTo(a, b, ret);
+	}
+
+	/**
+	 * Compute transformation and stores the result in the given automaton.
+	 * 
+	 * @param a
+	 * @param b
+	 * @param ret
+	 * @return the automaton {@code ret} containing the result of the
+	 *         transformation.
+	 */
+	public Automaton<L, Tr, T> transformTo(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b, Automaton<L, Tr, T> ret) {
+		Set alph = synchronization.synchronizable(a.alphabet(), b.alphabet());
+		/* check alphabets */
+		Map<StatesCouple, State> amap = (Map<StatesCouple, State> )(new HashMap());
+		//Map<StatesCouple, State> bmap = (Map<StatesCouple, State>)new HashMap();
+		List<StatesCouple> todo = (List<StatesCouple>)new ArrayList();
+		Set<StatesCouple> done = (Set<StatesCouple>)(new HashSet());
+		Set<State> as = TransformationsToolBox.epsilonClosure(a.initials(), a);
+		Set<State> bs = TransformationsToolBox.epsilonClosure(b.initials(), b);
+		State from = ret.addState(true, TransformationsToolBox
+				.containsATerminalState(as)
+				&& TransformationsToolBox.containsATerminalState(bs));
+		StatesCouple sc = new StatesCouple(as, bs);
+		amap.put(sc, from);
+		todo.add(sc);
+		do {
+			StatesCouple couple = todo.remove(0);
+			from = amap.get(couple);
+			if (done.contains(couple))
+				continue;
+			done.add(couple);
+			/* get transition sets */
+			Map<L, Set<State>> tam = TransformationsToolBox.mapAlphabet(a.delta(couple.sa), a);
+			Map<L, Set<State>> tbm = TransformationsToolBox.mapAlphabet(b.delta(couple.sb), b);
+			/* create label map for synchronized trans */
+			Map<L, StatesCouple> tcm = new HashMap();
+			/* unsynchronizable transitions in A */
+			for (Iterator<Map.Entry<L, Set<State>>> i = tam.entrySet().iterator(); i.hasNext();) {
+				Map.Entry<L, Set<State>> me = i.next();
+				L l = me.getKey();
+				as = me.getValue();
+				if (!alph.contains(l)) {
+					Set<State> asc = TransformationsToolBox.epsilonClosure(as, a);
+					tcm.put(l, sc = new StatesCouple(asc, couple.sb));
+					State to =  amap.get(sc);
+					makeNewState(ret, amap, sc, to);
+					todo.add(sc);
+					i.remove();
+				}
+			}
+			/* unsynchronizable transition(s) in B */
+			for (Iterator<Map.Entry<L, Set<State>>> i = tbm.entrySet().iterator(); i.hasNext();) {
+				Map.Entry<L, Set<State>> me =  i.next();
+				L l = me.getKey();
+				bs = me.getValue();
+				if (!alph.contains(l)) {
+					Set<State> bsc = TransformationsToolBox.epsilonClosure(bs, b);
+					tcm.put(l, sc = new StatesCouple(couple.sa, bsc));
+					State to = amap.get(sc);
+					makeNewState(ret, amap, sc, to);
+					todo.add(sc);
+					i.remove();
+				}
+			}
+			/*
+			 * there remains in tam and tbm only possibly synchronizing
+			 * transitions
+			 */
+			for (Iterator<Map.Entry<L, Set<State>>> i = tam.entrySet().iterator(); i.hasNext();) {
+				Map.Entry<L, Set<State>> me = i.next();
+				L l = me.getKey();
+				as = me.getValue();
+				for (Iterator<Map.Entry<L, Set<State>>> j = tbm.entrySet().iterator(); j.hasNext();) {
+					Map.Entry<L, Set<State>> mbe = j.next();
+					L k = mbe.getKey();
+					bs = mbe.getValue();
+					L sy = synchronization.synchronize(l, k);
+					if (sy != null) {
+						Set<State> asc = TransformationsToolBox.epsilonClosure(as, a);
+						Set<State> bsc = TransformationsToolBox.epsilonClosure(bs, b);
+						tcm.put(sy, sc = new StatesCouple(asc, bsc));
+						State to = amap.get(sc);
+						makeNewState(ret, amap, sc, to);
+						todo.add(sc);
+					}
+				}
+			}
+			/*
+			 * 
+			 * create new transitions in return automaton, update maps
+			 */
+			for (Iterator<Map.Entry<L, StatesCouple>> i = tcm.entrySet().iterator(); i.hasNext();) {
+				Map.Entry<L, StatesCouple> me =  i.next();
+				L l = me.getKey();
+				sc = me.getValue();
+				State to = amap.get(sc);
+				makeNewState(ret, amap, sc, to);
+				try {
+					ret.build(from, l, to);
+				} catch (NoSuchStateException e) {
+				}
+				// ret.from(from).on(l).go(to);
+			}
+		} while (!todo.isEmpty());
+		return ret;
+	}
+
+	private void makeNewState(Automaton ret, Map amap, StatesCouple sc, State to) {
+		if (to == null) {
+			to = ret.addState(false, TransformationsToolBox
+					.containsATerminalState(sc.sa)
+					&& TransformationsToolBox.containsATerminalState(sc.sb));
+			amap.put(sc, to);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Morphism.java b/extra/jautomata-core/rationals/transformations/Morphism.java
new file mode 100755
index 0000000000..35da2eb14f
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Morphism.java
@@ -0,0 +1,83 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import rationals.Automaton;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * A general  class for alphabetic morphism over automaton.
+ * <p>
+ * A morphism is constructed from a {@see java.util.Map} from letters to
+ * letters (ie. from Object to Object). To distinguish between explicit 
+ * mapping to <code>null</code> and implicit identity, if a letter is mapped 
+ * as is, then it should not be included as a key.
+ *  
+ * @author nono
+ * @version $Id: Morphism.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Morphism implements UnaryTransformation {
+
+    private Map morph;
+
+    public Morphism(Map m) {
+        this.morph = m;
+    }
+    
+    /* (non-Javadoc)
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton transform(Automaton a) {
+        Automaton b = new Automaton();
+        /* state map */
+        Map stm = new HashMap();
+        for(Iterator i = a.delta().iterator();i.hasNext();) {
+            Transition tr = (Transition)i.next();
+            State ns = tr.start();
+            State nss = (State)stm.get(ns);
+            if(nss == null) {
+                nss = b.addState(ns.isInitial(),ns.isTerminal());
+                stm.put(ns,nss);
+            }
+            State ne = tr.end();
+            State nse = (State)stm.get(ne);
+            if(nse == null) {
+                nse = b.addState(ne.isInitial(),ne.isTerminal());
+                stm.put(ne,nse);
+            }
+            Object lbl = tr.label();
+            if(!morph.containsKey(lbl))
+                try {
+                    b.addTransition(new Transition(nss,lbl,nse));
+                } catch (NoSuchStateException e) {
+                }
+            else
+                try {
+                    b.addTransition(new Transition(nss,morph.get(lbl),nse));
+                } catch (NoSuchStateException e1) {
+                }
+        }
+        return b;
+    }
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/Normalizer.java b/extra/jautomata-core/rationals/transformations/Normalizer.java
new file mode 100755
index 0000000000..392a41cadf
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Normalizer.java
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+import rationals.properties.ContainsEpsilon;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A transformation that normalizes a given Automaton.
+ * <p>
+ * This transformation produces a new Automaton with the following features :
+ * <ol>
+ * <li>it has <em>one</em> start state and <em>one</em> end state,</li>
+ * <li>there is no incoming (resp. outgoing) transitions to (resp. from) the
+ * start (resp. end) state,</li>
+ * <li>the resultant automaton is then pruned ({@link Pruner}) to remove
+ * inaccessible states.</li>
+ * </ol>
+ * 
+ * @author yroos
+ * @version $Id: Normalizer.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Normalizer<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton<L, Tr, T> b = new Automaton<>();
+        State ni = b.addState(true, false);
+        State nt = b.addState(false, true);
+        Map<State, State> map = new HashMap<State, State>();
+        Iterator<State> i1 = a.states().iterator();
+        while (i1.hasNext()) {
+            State st = i1.next();
+            map.put(st, b.addState(false, false));
+        }
+        /* add epsilon transition if contains epsilon */
+        if (new ContainsEpsilon<L, Tr, T>().test(a))
+            try {
+                b.addTransition(new Transition<L>(ni, null, nt));
+            } catch (NoSuchStateException e) {
+            }
+        Iterator<Transition<L>> i2 = a.delta().iterator();
+        while (i2.hasNext()) {
+            Transition<L> t =  i2.next();
+            if (t.start().isInitial() && t.end().isTerminal()) {
+                try {
+                    b.addTransition(new Transition<L>(ni, t.label(), nt));
+                } catch (NoSuchStateException x) {
+                }
+            }
+            if (t.start().isInitial()) {
+                try {
+                    b.addTransition(new Transition<L>(ni, t.label(), map.get(t.end())));
+                } catch (NoSuchStateException x) {
+                }
+            }
+
+            if (t.end().isTerminal())
+                try {
+                    b.addTransition(new Transition<L>(map.get(t.start()), t.label(), nt));
+                } catch (NoSuchStateException x) {
+                }
+
+            try {
+                b.addTransition(new Transition<L>(map.get(t.start()), t.label(), map.get(t.end())));
+            } catch (NoSuchStateException x) {
+            }
+
+        }
+        b = new Pruner<L, Tr, T>().transform(b);
+        return b;
+    }
+}
+
+/*
+ * $Log: Normalizer.java,v $ Revision 1.4 2005/02/20 21:14:19 bailly added API
+ * for computing equivalence relations on automata
+ * 
+ * Revision 1.3 2004/09/21 11:50:28 bailly added interface BinaryTest added
+ * class for testing automaton equivalence (isomorphism of normalized automata)
+ * added computation of RE from Automaton
+ *  
+ */
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/PartialCommutation.java b/extra/jautomata-core/rationals/transformations/PartialCommutation.java
new file mode 100755
index 0000000000..4311b009f3
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/PartialCommutation.java
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2013 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+
+import java.util.Set;
+
+public class PartialCommutation implements UnaryTransformation{
+    private final Set commutingLetters;
+
+    public PartialCommutation(Set commutingLetters) {
+        this.commutingLetters = commutingLetters;
+    }
+
+    public Automaton transform(Automaton a) {
+        Automaton b = new Automaton();
+        return a;
+    };
+}
diff --git a/extra/jautomata-core/rationals/transformations/PrefixClosure.java b/extra/jautomata-core/rationals/transformations/PrefixClosure.java
new file mode 100755
index 0000000000..2becec3923
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/PrefixClosure.java
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2004 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import rationals.Automaton;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * Computes the prefix closure of given automaton.
+ * <p>
+ * The resulting automaton is simply the starting automaton with all states made
+ * terminal.
+ * <ul>
+ * <li>C = Pref(A)</li>
+ * <li>S(C) = S(A)</li>
+ * <li>S0(C) = S0(A)</li>
+ * <li>T(C) = S(A)</li>
+ * <li>D(C) = D(A)</li>
+ * </ul>
+ * 
+ * @author nono
+ * @version $Id: PrefixClosure.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class PrefixClosure implements UnaryTransformation {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton transform(Automaton a) {
+        Automaton ret = new Automaton();
+        Map sm = new HashMap();
+        for (Iterator it = a.states().iterator(); it.hasNext();) {
+            State st = (State) it.next();
+            State sr = ret.addState(st.isInitial(), true);
+            sm.put(st, sr);
+        }
+        /* add all transitions */
+        for (Iterator it = a.delta().iterator(); it.hasNext();) {
+            Transition tr = (Transition) it.next();
+            try {
+                ret.addTransition(new Transition((State) sm.get(tr.start()), tr
+                        .label(), (State) sm.get(tr.end())));
+            } catch (NoSuchStateException e) {
+            }
+        }
+        return ret;
+    }
+
+}
+
+/*
+ * $Log: PrefixClosure.java,v $ Revision 1.1 2004/11/15 12:39:14 bailly added
+ * PrefixClosure transformation
+ *  
+ */
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Projection.java b/extra/jautomata-core/rationals/transformations/Projection.java
new file mode 100755
index 0000000000..3af2bac34d
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Projection.java
@@ -0,0 +1,84 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class computes the projection of an Automaton on given alphabet. The
+ * projection alphabet is set by the class's constructor.
+ * <p />
+ * The algorithm is verys simple: All transitions which are not labelled
+ * with letters from the projection alphabet are transformed into 
+ * <code>null</code> transitions. The resulting automaton is obviously no 
+ * more deterministic if the automaton <code>a</code> was.
+ * 
+ * @author nono
+ * @version $Id: Projection.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Projection implements UnaryTransformation {
+
+    private Set alphabet;
+
+    public Projection(Set alphabet) {
+        this.alphabet = alphabet;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton transform(Automaton a) {
+        Automaton b = new Automaton();
+        Map smap = new HashMap();
+        Iterator it = a.delta().iterator();
+        while (it.hasNext()) {
+            Transition tr = (Transition) it.next();
+            State os = tr.start();
+            State oe = tr.end();
+            Object l = tr.label();
+            /* check states exist */
+            State ns = (State) smap.get(os);
+            State ne = (State) smap.get(oe);
+            if (ns == null)
+                smap.put(os, ns = b.addState(os.isInitial(), os.isTerminal()));
+            if (ne == null)
+                smap.put(oe, ne = b.addState(oe.isInitial(), oe.isTerminal()));
+            /* check label is in alphabet */
+            if (alphabet.contains(l))
+                try {
+                    b.addTransition(new Transition(ns, l, ne));
+                } catch (NoSuchStateException e) {
+                }
+            else
+                try {
+                    b.addTransition(new Transition(ns, null, ne));
+                } catch (NoSuchStateException e1) {
+                }
+        }
+        return b;
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Pruner.java b/extra/jautomata-core/rationals/transformations/Pruner.java
new file mode 100755
index 0000000000..182263dab7
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Pruner.java
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Removes states that neither accessible nor coaccessible.
+ * 
+ * @version $Id: Pruner.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Pruner<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+    Map<State, State> conversion = new HashMap<>() ;
+    Iterator<State> i1 = a.accessibleAndCoAccessibleStates().iterator();
+    Automaton<L, Tr, T> b = new Automaton<>() ;
+    while(i1.hasNext()) {
+      State e = i1.next() ;
+      conversion.put(e , b.addState(e.isInitial() , e.isTerminal())) ;
+    }
+    Iterator<Transition<L>> i2 = a.delta().iterator();
+    while(i2.hasNext()) {
+      Transition<L> t = i2.next() ;
+      State bs = conversion.get(t.start()) ;
+      State be = conversion.get(t.end()) ;
+      if(bs == null || be == null) continue;
+      try {
+        b.addTransition(new Transition<>(bs, t.label(), be));
+      } catch (NoSuchStateException x) {}
+    }
+    return b ;
+  }
+}
+  
diff --git a/extra/jautomata-core/rationals/transformations/RandomWalk.java.old b/extra/jautomata-core/rationals/transformations/RandomWalk.java.old
new file mode 100755
index 0000000000..da6707b885
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/RandomWalk.java.old
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2013 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import rationals.Automaton;
+import rationals.Transition;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+
+/**
+Randomly walk an {@link rationals.Automaton} until some condition is met.
+
+<p>A random walk start from the initial(s) state of the given automaton and repeatedly builds a word that, firing a
+transition, moving to given state, until the accumulated word matches some predicate. The condition is given as a
+parameter of the random walk.</p>
+ */
+public class RandomWalk {
+
+  private final Random random = new Random();
+
+  public List<Object> walk(Automaton a, Matcher<List<Object>> condition) {
+    Set states = a.initials();
+    List<Object> word = new ArrayList<Object>();
+
+    while (true) {
+      Object l = selectALetter(a, states);
+      word.add(l);
+      states = a.step(states, l);
+      if (condition.matches(word)) {
+        break;
+      }
+    }
+
+    return word;
+  }
+
+  private Object selectALetter(Automaton a, Set states) {
+    Set<Transition> delta = a.delta(states);
+
+    if (delta.isEmpty()) {
+      throw new IllegalStateException("cannot find a transition");
+    }
+
+    Object selected = null;
+    int ln = random.nextInt(delta.size());
+    for (Transition transition : delta) {
+      if (ln-- == 0) {
+        selected = transition.label();
+        break;
+      }
+    }
+    return selected;
+  }
+
+  public static Matcher<List<Object>> hasLength(final int length) {
+    return new TypeSafeMatcher<List<Object>>() {
+      @Override
+      protected boolean matchesSafely(List<Object> objects) {
+        return objects.size() == length;
+      }
+
+      @Override
+      public void describeTo(Description description) {
+        description.appendText("a word of length " + length);
+      }
+    };
+  }
+}
diff --git a/extra/jautomata-core/rationals/transformations/Reducer.java b/extra/jautomata-core/rationals/transformations/Reducer.java
new file mode 100755
index 0000000000..ba207bcfbf
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Reducer.java
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.*;
+
+/**
+ * Computes the minimal automaton from a deterministic automaton.
+ * <p />
+ * This class first determinizes the transformed automaton, then compute
+ * states equivalence classes to create new states and transitions.
+ * 
+ * @author nono
+ * @version $Id: Reducer.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Reducer<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    /*
+     * equivalence on DFA
+     */
+    private boolean same(State e1, State e2, Automaton<L, Tr, T> a, Map<State, Set<State>> m) {
+        if (!m.get(e1).equals(m.get(e2)))
+            return false;
+        /* iterate over all transitions */
+        Set<Transition<L>> tas = a.delta(e1);
+        Set<Transition<L>> tbs = a.delta(e2);
+        Iterator<Transition<L>> it = tas.iterator();
+        while (it.hasNext()) {
+            Transition<L> tr = it.next();
+            State ep1 = tr.end();
+            /* check transition exists in b */
+            Set<Transition<L>> tbsl = a.delta(e2, tr.label());
+            if (tbsl.isEmpty())
+                return false;
+            Iterator<Transition<L>> trb = tbsl.iterator();
+            while (trb.hasNext()) {
+                Transition<?> tb = trb.next();
+                /* mark transition as visited */
+                tbs.remove(tb);
+                State ep2 = tb.end();
+                if (!m.get(ep1).equals(m.get(ep2)))
+                    return false;
+            }
+        }
+        if (!tbs.isEmpty()) {
+            return false;
+        }
+        return true;
+    }
+
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton<L, Tr, T> b = new ToDFA<L, Tr, T>().transform(a);
+        Map<State, Set<State>> current = new HashMap<State, Set<State>>();
+        Set<State> s1 = b.getStateFactory().stateSet();
+        Set<State> s2 = b.getStateFactory().stateSet();
+        Iterator<State> i = b.states().iterator();
+        while (i.hasNext()) {
+            State e = i.next();
+            if (e.isTerminal()) {
+                s1.add(e);
+                current.put(e, s1);
+            } else {
+                s2.add(e);
+                current.put(e, s2);
+            }
+        }
+        Map<State, Set<State>> old;
+        do {
+            old = current;
+            current = new HashMap<State, Set<State>>();
+            i = old.keySet().iterator();
+            while (i.hasNext()) {
+                State e1 = i.next();
+                Set<State> s = b.getStateFactory().stateSet();
+                Iterator<State> j = current.keySet().iterator();
+                while (j.hasNext()) {
+                    State e2 = j.next();
+                    if (same(e1, e2, b, old)) {
+                        s = current.get(e2);
+                        break;
+                    }
+                }
+                s.add(e1);
+                current.put(e1, s);
+            }
+        } while (!new HashSet<Set<State>>(current.values())
+                .equals(new HashSet<Set<State>>(old.values())));
+        Automaton<L, Tr, T> c = new Automaton<L, Tr, T>();
+        Set<Set<State>> setSet = new HashSet<Set<State>>(current.values());
+        Iterator<Set<State>> sets = setSet.iterator();
+        Map<Set<State>, State> newStates = new HashMap<>();
+        while (sets.hasNext()) {
+            Set<State> set = sets.next();
+            boolean term = TransformationsToolBox.containsATerminalState(set);
+            boolean init = TransformationsToolBox.containsAnInitialState(set);
+            newStates.put(set, c.addState(init, term));
+        }
+        sets = setSet.iterator();
+        while (sets.hasNext()) {
+            Set<State> set = sets.next();
+            State r = set.iterator().next();
+            State rp = newStates.get(set);
+            Iterator<L> k = b.alphabet().iterator();
+            while (k.hasNext()) {
+                L l = k.next();
+                Set<Transition<L>> ds = b.delta(r, l);
+                if(ds.isEmpty())
+                    continue;
+                State f = ds.iterator().next().end();
+                State fp = newStates.get(current.get(f));
+                try {
+                    c.addTransition(new Transition<>(rp, l, fp));
+                } catch (NoSuchStateException x) {
+                }
+            }
+        }
+        return c;
+    }
+
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Reverser.java b/extra/jautomata-core/rationals/transformations/Reverser.java
new file mode 100755
index 0000000000..a9c9bb1a0c
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Reverser.java
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Computes the reversal of an Automaton.
+ * <p /> 
+ * <ul>
+ * <li>C = A-</li>
+ * <li>S(C) = S(A)</li>
+ * <li>S0(C) = T(A)</li>
+ * <li>T(C) = S0(A)</li>
+ * <li>D(C) = { (s1,a,s2) | exists (s2,a,s1) in D(A)  }</li>
+ * </ul>
+ *
+ * @version $Id: Reverser.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Reverser<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+    Automaton<L, Tr, T> b = new Automaton<>() ;
+    Map<State, State> map = new HashMap<>() ;
+    Iterator<State> i1 = a.states().iterator() ;
+    while(i1.hasNext()) {
+      State e = i1.next() ;
+      map.put(e , b.addState(e.isTerminal() , e.isInitial())) ;
+    }
+    Iterator<Transition<L>> i2 = a.delta().iterator() ;
+    while(i2.hasNext()) {
+      Transition<L> t = i2.next() ;
+      try {
+        b.addTransition(new Transition<L>(map.get(t.end()), t.label(), map.get(t.start())));
+      } catch(NoSuchStateException x) {}
+    }
+    return b;
+  }
+}
diff --git a/extra/jautomata-core/rationals/transformations/Shuffle.java b/extra/jautomata-core/rationals/transformations/Shuffle.java
new file mode 100755
index 0000000000..52fe8dff6d
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Shuffle.java
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Synchronization;
+import rationals.Transition;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class implements the shuffle operator between two automatas.
+ * <ul>
+ * <li>C = A shuffle B</li>
+ * <li>S(C) = { (a,b) | a in S(A) and b in S(B) }</li>
+ * <li>S0(C) = (S0(A),SO(B))</li>
+ * <li>T(C) = { (a,b) | a in T(A) and b in T(B) }</li>
+ * <li>D(C) = { ((s1a,s1b),a,(s2a,s2b)) | exists (s1a,a,s2a) in D(A) or exists
+ * (s1b,a,s2b) in D(b) }</li>
+ * </ul>
+ * This class uses the Mix operator with an empty alphabet to compute the
+ * Shuffle.
+ * 
+ * @author Arnaud Bailly
+ * @version $Id: Shuffle.java 2 2006-08-24 14:41:48Z oqube $
+ * @see Mix
+ */
+public class Shuffle<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTransformation<L, Tr, T> {
+
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a, Automaton<L, Tr, T> b) {
+
+        Mix mix = new Mix(new Synchronization() {
+            public Object synchronize(Object t1, Object t2) {
+                return null;
+            }
+
+            public Set synchronizable(Set a, Set b) {
+                return Collections.unmodifiableSet(new HashSet());
+            }
+
+            public Set synchronizing(Collection alphabets) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public boolean synchronizeWith(Object object, Set alph) {
+                // TODO Auto-generated method stub
+                return false;
+            }
+        });
+        return mix.transform(a, b);
+    }
+}
diff --git a/extra/jautomata-core/rationals/transformations/SinkComplete.java b/extra/jautomata-core/rationals/transformations/SinkComplete.java
new file mode 100755
index 0000000000..46239247e1
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/SinkComplete.java
@@ -0,0 +1,89 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Complete an Automaton by adding a sink state and needed transitions.
+ * <p />
+ * <ul>
+ * <li>C = complete(A)</li>
+ * <li>S(C) = S(A) U {sink}</li>
+ * <li>S0(C) = S0(A)</li>
+ * <li>T(C) = T(A)</li>
+ * <li>D(C) = D(A) U { (s1,a,sink)) | not exists (s1,a,s2) in D(A) }</li>
+ * </ul>
+ * 
+ * @author nono
+ * @version $Id: SinkComplete.java 6 2006-08-30 08:56:44Z oqube $
+ */
+public class SinkComplete implements UnaryTransformation {
+
+  private Set alphabet;
+
+  public SinkComplete(Set alphabet) {
+    this.alphabet = alphabet;
+  }
+
+  public SinkComplete() {
+  }
+
+    /*
+     *  (non-Javadoc)
+     * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+     */
+    public Automaton transform(Automaton a) {
+      Automaton b = (Automaton) a.clone();
+      Set alph = (alphabet == null) ? b.alphabet() : alphabet;
+      State hole = null;
+      Set states = b.getStateFactory().stateSet();
+      states.addAll(b.states());
+      Iterator i = states.iterator();
+      while (i.hasNext()) {
+	State e = (State) i.next();
+	Iterator j = alph.iterator();
+	while (j.hasNext()) {
+	  Object label = j.next();
+	  if (b.delta(e, label).isEmpty()) {
+	    if (hole == null)
+	      hole = b.addState(false, false);
+	    try {
+	      b.addTransition(new Transition(e, label, hole));
+	    } catch (NoSuchStateException x) {
+	    }
+	  }
+	}
+      }
+      if (!(hole == null)) {
+	Iterator j = alph.iterator();
+	while (j.hasNext()) {
+	  try {
+	    b.addTransition(new Transition(hole, j.next(), hole));
+	  } catch (NoSuchStateException x) {
+	  }
+	}
+      }
+      return b;
+    }
+}
diff --git a/extra/jautomata-core/rationals/transformations/Star.java b/extra/jautomata-core/rationals/transformations/Star.java
new file mode 100755
index 0000000000..743a0679b1
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Star.java
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Compute the kleene-star closure of an automaton.
+ * 
+ * @version $Id: Star.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Star<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        if (a.delta().size() == 0)
+            return Automaton.epsilonAutomaton();
+        Automaton<L, Tr, T> b = new Automaton<>();
+        State ni = b.addState(true, true);
+        State nt = b.addState(true, true);
+        Map<State, State> map = new HashMap<>();
+        Iterator<State> i1 = a.states().iterator();
+        while (i1.hasNext()) {
+            map.put(i1.next(), b.addState(false, false));
+        }
+        Iterator<Transition<L>> i2 = a.delta().iterator();
+        while (i2.hasNext()) {
+            Transition<L> t = i2.next();
+            try {
+                b.addTransition(new Transition<>(map.get(t.start()), t.label(), map.get(t.end())));
+            } catch (NoSuchStateException x) {
+            }
+            if (t.start().isInitial() && t.end().isTerminal()) {
+                try {
+                    b.addTransition(new Transition<>(ni, t.label(), nt));
+                    b.addTransition(new Transition<>(nt, t.label(), ni));
+                } catch (NoSuchStateException x) {
+                }
+            } else if (t.start().isInitial()) {
+                try {
+                    b.addTransition(new Transition<>(ni, t.label(), map.get(t.end())));
+                    b.addTransition(new Transition<>(nt, t.label(), map.get(t.end())));
+                } catch (NoSuchStateException x) {
+                }
+            } else if (t.end().isTerminal()) {
+                try {
+                    b.addTransition(new Transition<>(map.get(t.start()), t.label(), nt));
+                    b.addTransition(new Transition<>(map.get(t.start()), t.label(), ni));
+                } catch (NoSuchStateException x) {
+                }
+            }
+        }
+        return b;
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/StatesCouple.java b/extra/jautomata-core/rationals/transformations/StatesCouple.java
new file mode 100755
index 0000000000..ee8c3a1f1d
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/StatesCouple.java
@@ -0,0 +1,66 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.Set;
+
+import rationals.State;
+
+
+public final class StatesCouple {
+    public final Set<State> sa;
+    public final Set<State> sb;
+    private final int hash;
+
+    public StatesCouple(Set<State> sa, Set<State> sb) {
+        this.sa = sa;
+        this.sb = sb;
+        this.hash = sa.hashCode() + sb.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+    	if (!(obj instanceof StatesCouple)) return false;
+        StatesCouple sc = (StatesCouple) obj;
+        return sc.sa.equals(sa) && sc.sb.equals(sb);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return " < " + sa.toString() + "," + sb.toString() + " >";
+    }
+}
\ No newline at end of file
diff --git a/extra/jautomata-core/rationals/transformations/Substitution.java b/extra/jautomata-core/rationals/transformations/Substitution.java
new file mode 100755
index 0000000000..23ec063494
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Substitution.java
@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+/**
+ * A (rational) substitution is a  morphism that maps
+ * letters to languages.
+ * A rational substitution is constructed like a {@see rationals.transformations.Morphism}
+ * with an instance of {@see java.util.Map} that has Object as 
+ * keys and either Object or Automaton instances as values.
+ * If the value of a key is an object, then it is  considered a letter 
+ * and this class acts like a morphism. If the value of the key is an
+ * Automaton, then the complete transition is replaced by the language
+ * denoted by the automaton.
+ * 
+ * @author nono
+ * @see J.Berstel, "Transductions and context-free languages"
+ */
+public class Substitution<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+	private Map<?, ?> morph;
+
+	public Substitution(Map<?, ?> m) {
+		this.morph = m;
+	}
+
+	/* (non-Javadoc)
+	 * @see rationals.transformations.UnaryTransformation#transform(rationals.Automaton)
+	 */
+	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+		Automaton<L, Tr, T> b = new Automaton<>();
+		/* state map */
+		Map<State, State> stm = new HashMap<>();
+		for (Iterator<Transition<L>> i = a.delta().iterator(); i.hasNext();) {
+			Transition<L> tr = i.next();
+			State ns = tr.start();
+			State nss = stm.get(ns);
+			if (nss == null) {
+				nss = b.addState(ns.isInitial(), ns.isTerminal());
+				stm.put(ns, nss);
+			}
+			State ne = tr.end();
+			State nse = stm.get(ne);
+			if (nse == null) {
+				nse = b.addState(ne.isInitial(), ne.isTerminal());
+				stm.put(ne, nse);
+			}
+			L lbl = tr.label();
+			if (!morph.containsKey(lbl))
+				try {
+					b.addTransition(new Transition<L>(nss, lbl, nse));
+				} catch (NoSuchStateException e) {
+				}
+			else
+				try {
+					/* is value an automaton ? */
+					Object o = morph.get(lbl);
+					if (o instanceof Automaton)
+						insert(nss, nse, b, (Automaton<L, Tr, T>) o);
+					else
+						b.addTransition(new Transition<L>(nss, (L) morph.get(lbl), nse));
+				} catch (NoSuchStateException e1) {
+				}
+		}
+		return b;
+	}
+
+	/**
+	 * Insert <code>automaton</code> between states <code>nss</code> and
+	 * <code>nse</code> in automaton <code>b</code>.
+	 * This method add epsilon transitions from <code>nss</code> to each starting 
+	 * state of automaton and from each ending state to <code>nse</code>.
+	 * 
+	 * @param nss
+	 * @param nse
+	 * @param b
+	 * @param automaton
+	 */
+
+	private void insert(State nss, State nse, Automaton<L, Tr, T> b, Automaton<L, Tr, T> automaton) {
+		/* map states */
+		Map<State, State> map = new HashMap<State, State>();
+		for (Iterator<State> i = automaton.states().iterator(); i.hasNext();) {
+			State e = i.next();
+			State n = b.addState(false, false);
+			map.put(e, n);
+			if (e.isInitial())
+				try {
+					b.addTransition(new Transition<L>(nss, null, n));
+				} catch (NoSuchStateException e1) {
+				}
+			if (e.isTerminal())
+				try {
+					b.addTransition(new Transition<L>(n, null, nse));
+				} catch (NoSuchStateException e1) {
+				}
+
+		}
+		for (Iterator<Transition<L>> i = automaton.delta().iterator(); i.hasNext();) {
+			Transition<L> t = i.next();
+			try {
+				b.addTransition(new Transition<L>(map.get(t.start()), t.label(), map.get(t.end())));
+			} catch (NoSuchStateException x) {
+			}
+		}
+
+	}
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/ToC.java b/extra/jautomata-core/rationals/transformations/ToC.java
new file mode 100755
index 0000000000..cf530f47ba
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/ToC.java
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.*;
+
+public class ToC<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+    public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+        Automaton b = new EpsilonTransitionRemover().transform(a);
+        Set Ib = b.initials();
+        Set Tb = b.terminals();
+        Map /* < Set <State>, Set < State > > */ subsets = new HashMap();
+        Map /* < Set < State > , Map < Object, Set < State > > > */delta = new HashMap();
+        LinkedList l = new LinkedList();
+        Set /* < Set < State > > */ done = new HashSet();
+        l.add(Ib);
+        while (!l.isEmpty()) {
+            Set e1 = (Set) l.removeFirst();
+            Set sub = b.getStateFactory().stateSet();
+            subsets.put(e1, sub);
+            Iterator j = done.iterator();
+            while (j.hasNext()) {
+                Set x = (Set) j.next();
+                if (x.containsAll(e1) && !x.equals(e1))
+                    ((Set) subsets.get(x)).addAll(e1);
+                if (e1.containsAll(x) && !x.equals(e1))
+                    sub.addAll(x);
+            }
+            done.add(e1);
+            delta.put(e1, new HashMap());
+            j = b.alphabet().iterator();
+            while (j.hasNext()) {
+                Object label = j.next();
+                Iterator i = e1.iterator();
+                Set e2 = b.getStateFactory().stateSet();
+                while (i.hasNext()) {
+                    Iterator k = b.delta((State) i.next(), label).iterator();
+                    while (k.hasNext()) {
+                        e2.add(((Transition) k.next()).end());
+                    }
+                }
+                ((Map) delta.get(e1)).put(label, e2);
+                if (!done.contains(e2))
+                    l.add(e2);
+            }
+        }
+        Automaton c = new Automaton();
+        Map corr = new HashMap();
+        Iterator i = done.iterator();
+        while (i.hasNext()) {
+            Set x = (Set) i.next();
+            if (!x.isEmpty()) {
+                if (!((Set) subsets.get(x)).containsAll(x)) {
+                    boolean ini = Ib.containsAll(x);
+                    boolean term = TransformationsToolBox
+                            .containsATerminalState(x);
+                    corr.put(x, c.addState(ini, term));
+                }
+            }
+        }
+        i = corr.keySet().iterator();
+        while (i.hasNext()) {
+            Set e = (Set) i.next();
+            Iterator j = b.alphabet().iterator();
+            while (j.hasNext()) {
+                Object lab = j.next();
+                Set f = (Set) ((Map) delta.get(e)).get(lab);
+                Iterator k = corr.keySet().iterator();
+                while (k.hasNext()) {
+                    Set x = (Set) k.next();
+                    if (f.containsAll(x)) {
+                        try {
+                            c.addTransition(new Transition((State) corr.get(e),
+                                    lab, (State) corr.get(x)));
+                        } catch (NoSuchStateException z) {
+                        }
+                    }
+                }
+            }
+        }
+        return c;
+    }
+}
diff --git a/extra/jautomata-core/rationals/transformations/ToCanonicalRFSA.java b/extra/jautomata-core/rationals/transformations/ToCanonicalRFSA.java
new file mode 100755
index 0000000000..df4b01e6c3
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/ToCanonicalRFSA.java
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2005 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+public class ToCanonicalRFSA<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+    Reverser<L, Tr, T> r = new Reverser<>();
+    ToC<L, Tr, T> c = new ToC<>() ;
+    return c.transform(r.transform(c.transform(r.transform(a)))) ;
+  }
+}
diff --git a/extra/jautomata-core/rationals/transformations/ToDFA.java b/extra/jautomata-core/rationals/transformations/ToDFA.java
new file mode 100755
index 0000000000..2d906b11d5
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/ToDFA.java
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.*;
+
+/**
+ * Determinization of an automaton.
+ * 
+ * @author yroos
+ * @version $Id: ToDFA.java 7 2006-08-31 23:01:30Z oqube $
+ */
+public class ToDFA<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements UnaryTransformation<L, Tr, T> {
+  
+	public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) {
+		Automaton<L, Tr, T> ret = new Automaton<>();
+		Map<Set<State>, State> bmap = new HashMap<>();
+		List<Set<State>>todo = new ArrayList<>();
+		Set<Set<State>>done = new HashSet<>();
+		Set<State> as = TransformationsToolBox.epsilonClosure(a.initials(), a);
+		State from = ret.addState(true, TransformationsToolBox.containsATerminalState(as));
+		bmap.put(as, from);
+		todo.add(as);
+		do {
+			Set<State> sts = todo.remove(0);
+			from = bmap.get(sts);
+			if (done.contains(sts))
+				continue;
+			done.add(sts);
+			/* get transition sets */
+			Map<L, Set<State>> tam = TransformationsToolBox.mapAlphabet(a.delta(sts), a);
+			/* unsynchronizable transitions in A */
+			for (Iterator<Map.Entry<L, Set<State>>> i = tam.entrySet().iterator(); i.hasNext();) {
+				Map.Entry<L, Set<State>> me = i.next();
+				L l = me.getKey();
+				as = (Set<State>) me.getValue();
+				Set<State> asc = TransformationsToolBox.epsilonClosure(as, a);
+				State to = (State) bmap.get(asc);
+				if (to == null) {
+					to = ret.addState(false, TransformationsToolBox
+							.containsATerminalState(asc));
+					bmap.put(asc, to);
+				}
+				todo.add(asc);
+				try {
+					ret.addTransition(new Transition<L>(from, l, to));
+				} catch (NoSuchStateException e) {
+					assert false;
+				}
+			}
+		} while (!todo.isEmpty());
+		return ret;
+	}
+
+  /*
+    public Automaton transform(Automaton a) {
+        a = new EpsilonTransitionRemover().transform(a);
+        Automaton b = new Automaton();
+        Map map = new HashMap();
+        LinkedList l = new LinkedList();
+        Set done = new HashSet();
+        Set e = a.initials();
+        boolean t = TransformationsToolBox.containsATerminalState(e);
+        map.put(e, b.addState(true, t));
+        l.add(e);
+        while (!l.isEmpty()) {
+            Set e1 = (Set) l.removeFirst();
+            done.add(e1);
+            State ep1 = (State) map.get(e1);
+            Iterator j = a.alphabet().iterator();
+            Object label = null;
+            while (j.hasNext()) {
+                label = j.next();
+                Iterator i = e1.iterator();
+                Set e2 = a.getStateFactory().stateSet();
+                while (i.hasNext()) {
+                    Iterator k = a.delta((State) i.next(), label).iterator();
+                    while (k.hasNext()) {
+                        e2.add(((Transition) k.next()).end());
+                    }
+                }
+                State ep2;
+                if (!e2.isEmpty()) {
+                    if (!map.containsKey(e2)) {
+                        t = TransformationsToolBox.containsATerminalState(e2);
+                        map.put(e2, b.addState(false, t));
+                    }
+                    ep2 = (State) map.get(e2);
+                    try {
+                        b.addTransition(new Transition(ep1, label, ep2));
+                    } catch (NoSuchStateException x) {
+                    }
+                    if (!done.contains(e2))
+                        l.add(e2);
+                }
+            }
+        }
+        return b;
+    }
+  */
+}
diff --git a/extra/jautomata-core/rationals/transformations/Transformations.java b/extra/jautomata-core/rationals/transformations/Transformations.java
new file mode 100755
index 0000000000..420ec5be7c
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Transformations.java
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2013 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.Synchronization;
+
+
+/** Provides useful transformations as static methods for convenience. */
+public class Transformations {
+
+  /**
+   * Compute the <em>reduced synchronization product</em> of two automata under given {@link Synchronization} relation.
+   *
+   * @param  a               first automaton. Must not be null.
+   * @param  b               second automaton. Must not be null.
+   * @param  synchronization relation to synchronize letters on. may be null in which case it defaults to {@link
+   *                         rationals.DefaultSynchronization}.
+   *
+   * @return a new {@link Automaton} instance.
+   */
+  public static Automaton miniMix(Automaton a, Automaton b, Synchronization synchronization) {
+    return new Reducer().transform(new Mix(synchronization).transform(a, b));
+  }
+}
diff --git a/extra/jautomata-core/rationals/transformations/TransformationsToolBox.java b/extra/jautomata-core/rationals/transformations/TransformationsToolBox.java
new file mode 100755
index 0000000000..abb4b51e1c
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/TransformationsToolBox.java
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+
+import rationals.Automaton;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.*;
+
+/**
+ * A set of utility methods used in transformations of automaton.
+ * 
+ * @author nono
+ * @version $Id: TransformationsToolBox.java 10 2007-05-30 17:25:00Z oqube $
+ */
+public class TransformationsToolBox {
+
+  public static boolean containsATerminalState(Set<?> s) {
+    Iterator<?> i = s.iterator() ;
+    while(i.hasNext()) {
+      try {
+        State e = (State) i.next() ;
+        if (e.isTerminal()) return true ;
+      } catch(ClassCastException x) {}
+    }
+    return false ;
+  } 
+
+  public static boolean containsAnInitialState(Set<?> s) {
+    Iterator<?> i = s.iterator() ;
+    while(i.hasNext()) {
+      try {
+        State e = (State) i.next() ;
+        if (e.isInitial()) return true ;
+      } catch(ClassCastException x) {}
+    }
+    return false ;
+  } 
+  
+  /**
+   * Compute the set of states that are reachable ina given automanton
+   * from a set of states using epsilon moves.
+   * An epsilon transition is a transition which is labelled <code>null</code>.
+   * 
+   * @param s the set of starting states 
+   * @param a the automaton 
+   * @return a - possibly empty - set of states reachable from <code>s</code> through
+   * epsilon transitions. 
+   */
+  public static Set<State> epsilonClosure(Set<State> s, Automaton<?, ?, ?> a) {
+      Set<State> exp = a.getStateFactory().stateSet();
+      exp.addAll(s); /* set of states to visit */
+      Set<State> view = a.getStateFactory().stateSet(); /* set of states visited */
+      Set<State> arr = a.getStateFactory().stateSet(); /* the set of arrival states */
+      arr.addAll(s);
+      do {
+          Set<State> ns = a.getStateFactory().stateSet();
+          ns.addAll(exp); /* arrival states */
+          Iterator<State> it = ns.iterator();
+          while (it.hasNext()) {
+              State st = (State) it.next();
+              Iterator<?> it2 = a.delta(st).iterator();
+              while (it2.hasNext()) {
+                  Transition<?> tr = (Transition<?>) it2.next();
+                  if (tr.label() == null && !view.contains(tr.end())
+                          && !tr.end().equals(st)) {
+                      /* compute closure of epsilon transitions */
+                      exp.add(tr.end());
+                      arr.add(tr.end());
+                  }
+              }
+              exp.remove(st);
+              view.add(st);
+          }
+      } while (!exp.isEmpty());
+      return arr;
+  }
+
+  
+  /**
+   * Compute a map from letters to set of states given 
+   * a set of transitions.
+   * This method computes the arrival set of states for each letter
+   * occuring in a given set of transitions. epsilon transitions 
+   * are not taken into account.
+   *  
+   * @param ts a Set of Transition objects.
+   * @return a Map from Object - transition labels - to Set of State objects. 
+   */
+  public static <L> Map<L, Set<State>> mapAlphabet(Set<Transition<L>> ts, Automaton<L, ?, ?> a) {
+      Map<L, Set<State>> am = new HashMap<>();
+      List<Transition<L>> tas = new ArrayList<>(ts);
+      /* compute set of states for each letter */
+      while (!tas.isEmpty()) {
+          Transition<L> tr = tas.remove(0);
+          L l = tr.label();
+          if (l == null)
+              continue;
+          Set<State> as = (Set<State>) am.get(l);
+          if (as == null) {
+              as = a.getStateFactory().stateSet();
+              am.put(l, as);
+          }
+          as.add(tr.end());
+      }
+      return am;
+  }
+
+}
diff --git a/extra/jautomata-core/rationals/transformations/UnaryTransformation.java b/extra/jautomata-core/rationals/transformations/UnaryTransformation.java
new file mode 100755
index 0000000000..7d229f54a0
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/UnaryTransformation.java
@@ -0,0 +1,25 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations ;
+
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.Transition;
+
+public interface UnaryTransformation<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> {
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a) ;
+}
diff --git a/extra/jautomata-core/rationals/transformations/Union.java b/extra/jautomata-core/rationals/transformations/Union.java
new file mode 100755
index 0000000000..462a2c0523
--- /dev/null
+++ b/extra/jautomata-core/rationals/transformations/Union.java
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com),
+ *     Yves Roos (yroos@lifl.fr) and others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package rationals.transformations;
+import rationals.Automaton;
+import rationals.Builder;
+import rationals.NoSuchStateException;
+import rationals.State;
+import rationals.Transition;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Compute the union of two automaton.
+ * <ul>
+ * <li>C = A + B</li>
+ * <li>S(C) = S(A) U S(B)</li>
+ * <li>S0(C) = S0(A) U SO(B)</li>
+ * <li>T(C) = T(A) U T(B)</li>
+ * <li>D(C) = D(A) U D(B)</li>
+ * </ul>
+
+ * @author nono
+ * @version $Id: Union.java 2 2006-08-24 14:41:48Z oqube $
+ */
+public class Union<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> implements BinaryTransformation<L, Tr, T> {
+
+
+  public Automaton<L, Tr, T> transform(Automaton<L, Tr, T> a , Automaton<L, Tr, T> b) {
+    Automaton<L, Tr, T> ap = a.clone() ;
+    Map<State, State> map = new HashMap<State, State>() ;
+    Iterator<State> i1 = b.states().iterator() ;
+    while(i1.hasNext()) {
+      State e = i1.next() ;
+      map.put(e , ap.addState(e.isInitial() , e.isTerminal())) ;
+    }
+    Iterator<Transition<L>> i2 = b.delta().iterator() ;
+    while(i2.hasNext()) {
+      Transition<L> t = i2.next();
+      try {
+        ap.addTransition(new Transition<>(map.get(t.start()), t.label(), map.get(t.end()))) ;
+      } catch(NoSuchStateException x) {}
+    }
+    return ap ;
+  }      
+}
diff --git a/src/main/java/graph/AUTGraph.java b/src/main/java/graph/AUTGraph.java
index bab26ef529..e85ae7c51f 100755
--- a/src/main/java/graph/AUTGraph.java
+++ b/src/main/java/graph/AUTGraph.java
@@ -522,7 +522,7 @@ public class AUTGraph implements myutil.Graph {
     }
 
 
-    public void minimize(String[] tauTransitions, boolean tauOnly) {
+    public AUTGraph minimize(String[] tauTransitions, boolean tauOnly) {
         String s = "tau";
 
         // mark all transitions as non tau
@@ -540,8 +540,10 @@ public class AUTGraph implements myutil.Graph {
             }
         }
 
-        minimizeTau(tauOnly);
+        //minimizeTau(tauOnly);
+        //return this;
 
+        return reduceGraph();
     }
 
     public void minimizeTau(boolean tauOnly) {
@@ -1033,10 +1035,11 @@ public class AUTGraph implements myutil.Graph {
 
     public AUTGraph fromAutomaton(Automaton a) {
         AUTGraph graph = new AUTGraph();
-        Set<Transition<String>> trs = a.delta();
-        Set<State> sts = a.states();
+        Set<Transition<String>> trs = (Set<Transition<String>>)(a.delta());
+        //Set<?> trs = a.delta();
+        Set<State> sts = (Set<State>)(a.states());
 
-        HashMap<State, Integer> mapOfStates = new HashMap<>();
+        Map<State, Integer> mapOfStates = new HashMap<>();
         int cpt = 1;
         for(State st: sts) {
             if (st.isInitial()) {
@@ -1047,10 +1050,12 @@ public class AUTGraph implements myutil.Graph {
             }
         }
 
-        for(Transition tr: trs) {
+        graph.setNbOfStates(mapOfStates.size());
+
+        for(Transition<String> tr: trs) {
             State s1 = tr.start();
             State s2 = tr.end();
-            String label = (String)(tr.label());
+            String label = tr.label();
             Integer i1 = mapOfStates.get(s1);
             Integer i2 = mapOfStates.get(s2);
 
@@ -1060,7 +1065,7 @@ public class AUTGraph implements myutil.Graph {
             }
         }
 
-        computeStates();
+        graph.computeStates();
 
         return graph;
     }
@@ -1090,14 +1095,18 @@ public class AUTGraph implements myutil.Graph {
         return a;
     }
 
-    public void reduceGraph() {
+    public AUTGraph reduceGraph() {
         Automaton a = toAutomaton();
-        Automaton<String, Transition<String>, TransitionBuilder<String>> b =
+        //TraceManager.addDev("Initial AUT:" +  a.toString());
+        Automaton<String, Transition<String>, TransitionBuilder<String>> newA = (Automaton<String, Transition<String>, TransitionBuilder<String>>)(
                 new EpsilonTransitionRemover<String, Transition<String>,
-                        TransitionBuilder<String>>().transform(a);
+                        TransitionBuilder<String>>().transform(a));
+        //TraceManager.addDev("Aut with no tau / epsilon:" +  newA.toString());
 
-        b = new Reducer<String, Transition<String>, TransitionBuilder<String>>().transform(b);
-        TraceManager.addDev("Error in reduce graph:" +  b);
+        newA = new Reducer<String, Transition<String>, TransitionBuilder<String>>().transform(newA);
+        //TraceManager.addDev("Error in reduce graph:" +  newA);
+        //TraceManager.addDev("New Aut:" +  newA.toString());
+        return fromAutomaton(newA);
     }
 
 
diff --git a/src/main/java/ui/window/JFrameMinimize.java b/src/main/java/ui/window/JFrameMinimize.java
index a2f07000a7..fd1af9bdbe 100644
--- a/src/main/java/ui/window/JFrameMinimize.java
+++ b/src/main/java/ui/window/JFrameMinimize.java
@@ -581,7 +581,7 @@ public class JFrameMinimize extends javax.swing.JFrame implements ActionListener
 
             }
         }
-        newRG.graph.minimize(strarray, tauOnly.isSelected());
+        newRG.graph = newRG.graph.minimize(strarray, tauOnly.isSelected());
         newRG.nbOfStates = newRG.graph.getNbOfStates();
         newRG.nbOfTransitions = newRG.graph.getTransitions().size();
         mgui.addRG(newRG);
diff --git a/ttool/build.gradle b/ttool/build.gradle
index 8543ce1b9b..aeceeb9ea5 100644
--- a/ttool/build.gradle
+++ b/ttool/build.gradle
@@ -32,6 +32,7 @@ dependencies {
     compile name: 'batik-svggen'
     compile name: 'batik-dom'
     compile name: 'batik-awt-util'
+    compile name: 'jautomata-core'
 
     // Use JUnit test framework
     testCompile 'junit:junit:4.12'
-- 
GitLab