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