/*
* (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;
}
}