added truth table generation

This commit is contained in:
hneemann 2018-11-22 12:44:28 +01:00
parent a0c134b01d
commit ec1511258d
4 changed files with 172 additions and 26 deletions

View File

@ -5,11 +5,15 @@
*/
package de.neemann.digital.fsm;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.draw.graphics.Graphic;
import de.neemann.digital.draw.graphics.VectorFloat;
import de.neemann.digital.lang.Lang;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.TreeSet;
/**
* A simple finite state machine
@ -165,4 +169,122 @@ public class FSM {
for (Transition t : transitions)
t.initPos();
}
/**
* Creates the truth table which is defined by this finite state machine
*
* @return the truth table
* @throws ExpressionException ExpressionException
* @throws FinitStateMachineException FinitStateMachineException
*/
public TruthTable createTruthTable() throws ExpressionException, FinitStateMachineException {
int stateBits = getStateVarBits();
// create state variables
ArrayList<Variable> vars = new ArrayList<>();
for (int i = stateBits - 1; i >= 0; i--)
vars.add(new Variable("Q^" + i + "_n"));
TruthTable truthTable = new TruthTable(vars);
// create the next state result variables
for (int i = stateBits - 1; i >= 0; i--)
truthTable.addResult("Q^" + i + "_n+1");
// add the output variables
TreeSet<String> results = new TreeSet<>();
for (State s : states)
results.addAll(s.getValues().keySet());
for (String name : results)
truthTable.addResult(name);
// set all to dc
truthTable.setAllTo(2);
// set output variables
for (State s : states) {
int row = s.getNumber();
int col = stateBits * 2;
for (String name : results) {
Long val = s.getValues().get(name);
long v = val == null ? 0 : val;
truthTable.setValue(row, col, (int) v);
col++;
}
}
// set all next state variables to "stay is state"
for (State s : states) {
int c = stateBits * 2;
int row = s.getNumber();
int m = row;
for (int j = 0; j < stateBits; j++) {
c--;
truthTable.setValue(row, c, m & 1);
m >>= 1;
}
}
// add the additional input variables
VariableVisitor vv = new VariableVisitor();
for (Transition t : transitions)
if (t.getCondition() != null)
t.getCondition().traverse(vv);
ArrayList<Variable> inVars = new ArrayList<>(vv.getVariables());
for (Variable v : inVars)
truthTable.addVariable(v);
int rowsPerState = 1 << inVars.size();
// fill in the transitions
for (Transition t : transitions) {
int startState = t.getStartState().getNumber();
int startRow = startState * rowsPerState;
ContextMap c = new ContextMap();
for (int r = 0; r < rowsPerState; r++) {
int m = 1 << (inVars.size() - 1);
for (Variable v : inVars) {
c.set(v, (r & m) != 0);
m >>= 1;
}
if (t.getCondition() == null || t.getCondition().calculate(c)) {
int col = stateBits * 2 + inVars.size();
int row = startRow + r;
int mask = t.getTargetState().getNumber();
for (int j = 0; j < stateBits; j++) {
col--;
truthTable.setValue(row, col, mask & 1);
mask >>= 1;
}
}
}
}
return truthTable;
}
private int getStateVarBits() throws FinitStateMachineException {
HashSet<Integer> numbers = new HashSet<>();
int maxNumber = 0;
for (State s : states) {
final int n = s.getNumber();
if (n > maxNumber)
maxNumber = n;
if (numbers.contains(n))
throw new FinitStateMachineException(Lang.get("err_fsmNumberUsedTwice_N", n));
numbers.add(n);
}
if (!numbers.contains(0))
throw new FinitStateMachineException(Lang.get("err_fsmNoInitialState"));
int n = 1;
while ((1 << n) <= maxNumber) n++;
return n;
}
}

View File

@ -124,4 +124,11 @@ public class State extends Movable {
public int getNumber() {
return number;
}
/**
* @return the state value map
*/
public TreeMap<String, Long> getValues() {
return values;
}
}

View File

@ -121,4 +121,25 @@ public class Transition extends Movable {
setPos(fromState.getPos().add(toState.getPos()).mul(0.5f)
.add(new VectorFloat((float) Math.random() - 0.5f, (float) Math.random() - 0.5f).mul(30)));
}
/**
* @return the condition
*/
public Expression getCondition() {
return condition;
}
/**
* @return the starting state
*/
public State getStartState() {
return fromState;
}
/**
* @return the target state
*/
public State getTargetState() {
return toState;
}
}

View File

@ -8,8 +8,11 @@ package de.neemann.digital.fsm.gui;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.parser.ParseException;
import de.neemann.digital.analyse.parser.Parser;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.fsm.FSM;
import de.neemann.digital.fsm.State;
import de.neemann.digital.gui.components.table.TableDialog;
import javax.swing.*;
import java.awt.*;
@ -38,7 +41,6 @@ public class FSMDialog extends JDialog {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.fsm = fsm;
fsmComponent = new FSMComponent(fsm);
getContentPane().add(fsmComponent);
pack();
@ -72,49 +74,43 @@ public class FSMDialog extends JDialog {
* @throws Exception Exception
*/
public static void main(String[] args) throws Exception {
/*
FSM fsm = new FSM()
.add(new State("initial").val("Y", 0))
.add(new State("1 match").val("Y", 0))
.add(new State("2 matches").val("Y", 0))
.add(new State("found").val("Y", 1))
.transition(0, 1, new Parser("!E").parse().get(0))
.transition(1, 2, new Parser("!E").parse().get(0))
.transition(2, 3, new Parser("E").parse().get(0))
.transition(1, 0, new Parser("E").parse().get(0))
.transition(3, 0, new Parser("E").parse().get(0))
.transition(3, 1, new Parser("!E").parse().get(0));*/
State top = new State("top");
State topSet = new State("topSet").val("Y", 1);
State topSetLeft = new State("topSetLeft").val("L", 1);
State topSetRight = new State("topSetRight").val("R", 1);
State leftA = new State("leftA");
State leftB = new State("leftB");
State bottom = new State("bottom");
State bottomSet = new State("bottomSet").val("Y", 1);
State bottomSetLeft = new State("bottomSetRight").val("R", 1);
State bottomSetRight = new State("bottomSetLeft").val("L", 1);
State rightA = new State("rightA");
State rightB = new State("rightB");
FSM fsm = new FSM(top, topSet, leftA, leftB, bottom, bottomSet, rightA, rightB)
FSM fsm = new FSM(top, topSetLeft, leftA, leftB, bottomSetLeft, bottom, bottomSetRight, rightB, rightA, topSetRight)
.transition(top, leftA, e("A & !B"))
.transition(top, rightA, e("!A & B"))
.transition(topSet, top, null)
.transition(topSetLeft, top, null)
.transition(topSetRight, top, null)
.transition(rightA, top, e("!A & !B"))
.transition(rightB, topSet, e("!A & !B"))
.transition(rightB, topSetRight, e("!A & !B"))
.transition(leftA, top, e("!A & !B"))
.transition(leftB, topSet, e("!A & !B"))
.transition(leftB, topSetLeft, e("!A & !B"))
.transition(bottom, leftB, e("A & !B"))
.transition(bottom, rightB, e("!A & B"))
.transition(bottomSet, bottom, null)
.transition(bottomSetLeft, bottom, null)
.transition(bottomSetRight, bottom, null)
.transition(rightB, bottom, e("A & B"))
.transition(rightA, bottomSet, e("A & B"))
.transition(rightA, bottomSetRight, e("A & B"))
.transition(leftB, bottom, e("A & B"))
.transition(leftA, bottomSet, e("A & B"));
.transition(leftA, bottomSetLeft, e("A & B"));
new FSMDialog(null, fsm).setVisible(true);
ElementLibrary lib = new ElementLibrary();
ShapeFactory shapeFactory = new ShapeFactory(lib);
new TableDialog(null, fsm.createTruthTable(), lib, shapeFactory, null).setVisible(true);
//new FSMDialog(null, fsm).setVisible(true);
}