/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package automata.mealy;
import java.util.*;
import automata.*;
/**
* The Mealy machine step by state simulator simulates the behavior
* of a Mealy machine. It takes a MealyMachine
object
* and runs an input string on the object.
*
*
It simulates the machine's behavior by stepping through one state
* at a time. Output of the machine can be accessed through
* {@link MealyConfiguration#getOutput()} and is printed out on the
* tape in the simulation window. This does not deal with lambda
* transitions.
*
* @author Jinghui Lim
* @see automata.mealy.MealyConfiguration
*
*/
public class MealyStepByStateSimulator extends AutomatonSimulator
{
/**
* Creates a Mealy machine step by state simulator for the given
* automaton.
*
* @param automaton the machine to simulate
*/
public MealyStepByStateSimulator(Automaton automaton)
{
super(automaton);
}
/**
* Returns a MealyConfiguration
that represents the
* initial configuration of the Mealy machine, before any input
* has been processed. This returns an array of length one.
*
* @param input the input string to simulate
*/
public Configuration[] getInitialConfigurations(String input)
{
Configuration[] configs = new Configuration[1];
configs[0] = new MealyConfiguration(myAutomaton.getInitialState(),
null, input, input, "");
return configs;
}
/**
* Simulates one step for a particular configuration, adding all
* possible configurations reachable in one step to a list of
* possible configurations.
*
* @param configuration the configuration simulate one step on
*/
public ArrayList stepConfiguration(Configuration configuration)
{
ArrayList list = new ArrayList();
MealyConfiguration config = (MealyConfiguration) configuration;
String unprocessedInput = config.getUnprocessedInput();
String totalInput = config.getInput();
State currentState = config.getCurrentState();
Transition[] transitions = myAutomaton.getTransitionsFromState(currentState);
for(int i = 0; i < transitions.length; i++)
{
MealyTransition trans = (MealyTransition) transitions[i];
String transLabel = trans.getLabel();
if(unprocessedInput.startsWith(transLabel))
{
String input = "";
if(transLabel.length() < unprocessedInput.length())
input = unprocessedInput.substring(transLabel.length());
State toState = trans.getToState();
String output = config.getOutput() + trans.getOutput();
MealyConfiguration configToAdd =
new MealyConfiguration(toState, config, totalInput, input, output);
list.add(configToAdd);
}
}
return list;
}
/**
* Returns true
if all the input has been processed and output
* generated. This calls the {@link MealyConfiguration#isAccept()}. It
* returns false
otherwise.
*
* @return true
if all input has been processed, false
*
otherwise
*/
public boolean isAccepted()
{
Iterator it = myConfigurations.iterator();
while(it.hasNext())
{
MealyConfiguration config = (MealyConfiguration) it.next();
if(config.isAccept())
return true;
}
return false;
}
/**
* Simulated the input in the machine.
*
* @param input the input string to run on the machine
* @return true
once the entire input string has been
* processed.
* @see #isAccepted()
*/
public boolean simulateInput(String input)
{
myConfigurations.clear();
Configuration[] initialConfigs = getInitialConfigurations(input);
myConfigurations.addAll(Arrays.asList(initialConfigs));
while(!myConfigurations.isEmpty())
{
if(isAccepted())
return true;
ArrayList configurationsToAdd = new ArrayList();
Iterator it = myConfigurations.iterator();
while(it.hasNext())
{
MealyConfiguration config = (MealyConfiguration) it.next();
configurationsToAdd.addAll(stepConfiguration(config));
it.remove();
}
myConfigurations.addAll(configurationsToAdd);
}
return false;
}
}