Commit 06e5418d authored by Frédéric Bapst's avatar Frédéric Bapst
Browse files

add s03

parent c5b72546
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>tp-formals</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
package s03;
public class DiagSynt {
//========================================================================
static class ParseException extends Exception {
public ParseException() { super(); }
public ParseException(String msg) { super(msg); }
}
//========================================================================
private static String theWord;
private static int crtIndex;
// ----------------------------------------------------------------------
private static void initSymbolStream(String w) {
theWord = w; crtIndex=0;
}
private static void goToNextSymbol() {
crtIndex++;
}
private static boolean isEndOfSymbolStream() {
return crtIndex >= theWord.length();
}
private static char crtSymbol() {
if (isEndOfSymbolStream())
return '\0';
return theWord.charAt(crtIndex);
}
// ----------------------------------------------------------------------
private static void parse_S() throws ParseException {
// TODO - A COMPLETER
}
private static void parse_A() throws ParseException {
// TODO - A COMPLETER
}
private static void parse_B() throws ParseException {
// TODO - A COMPLETER
}
private static void parse_C() throws ParseException {
// TODO - A COMPLETER
}
public static boolean isAccepted(String w) {
initSymbolStream(w);
try {
parse_S();
} catch (ParseException e) {
return false;
}
return (isEndOfSymbolStream());
}
// ----------------------------------------------------------------------
public static void main(String [] args) {
if (args.length != 1) {
System.out.println("Usage: java DiagSynt word");
System.exit(-1);
}
System.out.println(isAccepted(args[0]));
}
}
package s03;
import java.util.HashSet;
import java.util.Set;
public class FSM {
private int[][] transition; // copy of the transition table
// TODO - A COMPLETER
public FSM(int[][] transitions, // also gives n and m
Set<Integer> acceptingStates) {
int nStates = transitions.length;
int nSymbols = transitions[0].length;
// TODO - A COMPLETER
}
public boolean accepts(int[] word) {
// ------ Simulation pseudo-code :
// crtState = 0;
// for each symbol s in word
// apply transition with s
// return true if crtState is accepting
return false; // TODO - A COMPLETER
}
public int nStates() {
return transition.length;
}
public int nSymbols() {
return transition[0].length;
}
// -----------------------------------------------------------
public static void main(String [] args) {
if (args.length==0)
args = new String[] {"abbab", "baab", "bbabbb"};
int [][] transitions = {
{1, 0}, // <-- from state 0, with symbol a,b,c...
{2, 1}, // <-- from state 1, with symbol a,b,c...
{2, 2}
};
Set<Integer> acceptingStates = new HashSet<>();
acceptingStates.add(1);
FSM autom = new FSM(transitions, acceptingStates);
for (int i=0; i<args.length; i++) {
String letters = args[i];
int [] word = new int [letters.length()];
for (int j=0; j<letters.length(); j++)
word[j] = letters.charAt(j) - 'a';
boolean res = autom.accepts(word);
System.out.println(letters +" : "+res);
}
}
}
package s03;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
public class FsmMinimization {
static public class EquivalenceRelation {
/** internally we only use [i][j] cells where i<j*/
private final boolean[][] equiv;
/** Initially all elements are equivalent */
public EquivalenceRelation(int size) {
this.equiv=new boolean[size][size];
for(int i=0; i<size; i++)
for(int j=i+1; j<size; j++)
equiv[i][j]=true;
}
public int size() {
return equiv.length;
}
public boolean areEquivalent(int i, int j) {
if(i==j) return true;
return equiv[Math.min(i, j)][Math.max(i, j)];
}
public void markAsEquivalent(int i, int j) {
equiv[Math.min(i, j)][Math.max(i, j)]=true;
}
public void markAsNonEquivalent(int i, int j) {
if(i==j)
throw new RuntimeException(i+" is necessarily equivalent to itself...");
equiv[Math.min(i, j)][Math.max(i, j)]=false;
}
public int smallestEquivalent(int i) {
for(int j=0; j<i; j++)
if(areEquivalent(j,i)) return j;
return i;
}
public void removeAllEquivalences() {
for(int i=0; i<size(); i++)
for(int j=i+1; j<size(); j++)
equiv[i][j]=false;
}
public boolean isValid() {
for(int i=0; i<size(); i++) {
Set<Integer> eqClass=new HashSet<>();
for(int j=0; j<size(); j++)
if(areEquivalent(i, j)) {
for(int a:eqClass)
if(!areEquivalent(a, j)) return false;
eqClass.add(i);
}
}
return true;
}
}
//============================================================
public static EquivalenceRelation equivalences(int[][] transitions,
Set<Integer> acceptingStates) {
int nStates = transitions.length;
int nSymbols = transitions[0].length;
// first consider (x,y) as equivalent unless one only is an accepting state
// TODO: A COMPLETER...
return null;
}
public static FSM minimized(int[][] transitions, Set<Integer> acceptingStates) {
int nStates = transitions.length;
int nSymbols = transitions[0].length;
EquivalenceRelation r=equivalences(transitions, acceptingStates);
if (!r.isValid()) throw new RuntimeException("Oups: not an equivalence relation");
// renumber equivalence class representatives as 0,1,2...; old->new
Map<Integer,Integer> renumber=new HashMap<>();
int nStatesMin=0;
for(int i=0; i<nStates; i++) {
int k=r.smallestEquivalent(i);
int remapped;
if(renumber.containsKey(k)) remapped=renumber.get(k);
else remapped=nStatesMin++;
renumber.put(i, remapped);
}
// rebuild transition function
int[][] transitionsMin=new int[nStatesMin][nSymbols];
for(int i=0; i<nStates; i++)
for(int s=0; s<nSymbols; s++)
transitionsMin[renumber.get(i)][s]=renumber.get(transitions[i][s]);
// rebuild set of accepting states
Set<Integer> acceptingStatesMin=new HashSet<>();
for(int i:acceptingStates)
acceptingStatesMin.add(renumber.get(i));
return new FSM(transitionsMin, acceptingStatesMin);
}
//---------------------------------------------------------
public static int[][] rndTransitions(int nStates, int nSymbols, Random rnd) {
int[][] t=new int[nStates][nSymbols];
for(int i=0; i<nStates; i++)
for(int s=0; s<nSymbols; s++)
t[i][s]=rnd.nextInt(nStates);
return t;
}
public static Set<Integer> rndAcceptingStates(int nStates, Random rnd) {
Set<Integer> a=new HashSet<>();
int k=rnd.nextInt(nStates+1);
while(a.size()<k)
a.add(rnd.nextInt(nStates));
return a;
}
public static int[] rndWord(int nSymbols, int maxLength, Random rnd) {
int len=rnd.nextInt(maxLength+1);
int[] w=new int[len];
for(int i=0; i<len; i++)
w[i]=rnd.nextInt(nSymbols);
return w;
}
public static boolean seemEquivalent(FSM a, FSM b) {
if(a.nSymbols()!=b.nSymbols()) {
return false; // not the same alphabet...
}
Random rnd=new Random();
int nWords=10_000;
int maxWordLen=50;
while(nWords-- >0) {
int[] word=rndWord(a.nSymbols(), maxWordLen, rnd);
if(a.accepts(word) != b.accepts(word)) {
return false;
}
}
return true;
}
public static void testOneExampleOfMinimization(Random rnd) {
int nStates=100, nSymbols=2;
int[][] transitions=new int[nStates][nSymbols];
for(int i=0; i<nStates; i++) {
transitions[i][0]=rnd.nextInt(nStates/2);
transitions[i][1]=rnd.nextInt(nStates/2)+nStates/2;
}
Set<Integer> acceptingStates=new HashSet<>();
for(int i=0; i<nStates/2; i++)
acceptingStates.add(i);
FSM f1=new FSM(transitions, acceptingStates);
FSM f2=minimized(transitions, acceptingStates);
if (f2.nStates()>2) {
System.out.println("Oups... Some equivalent states remain undetected");
System.exit(-1);
}
if(!seemEquivalent(f1, f2)) {
System.out.println("Oups... Minimized FSM differs from original");
System.exit(0);
}
}
public static void testRndMinimization(int nStates, int nSymbols, Random rnd) {
int nFSM=100;
long nStatesMin=0;
for(int i=0; i<nFSM; i++) {
int[][] transitions=rndTransitions(nStates, nSymbols, rnd);
Set<Integer> acceptingStates=rndAcceptingStates(nStates, rnd);
FSM a=new FSM(transitions, acceptingStates);
FSM b=minimized(transitions, acceptingStates);
nStatesMin+=b.nStates();
if(!seemEquivalent(a,b)) {
System.out.println("Oups... Minimized FSM differs from original");
System.exit(0);
}
}
System.out.print("avg nb of states before/after minimization: "+nStates);
System.out.println(" / "+nStatesMin/(double)nFSM);
}
public static void main(String... args) {
Random rnd=new Random();
testOneExampleOfMinimization(rnd);
testRndMinimization(3, 2, rnd);
testRndMinimization(5, 2, rnd);
testRndMinimization(10, 3, rnd);
System.out.println("Test passed successfully");
}
}
package s03;
/**
* <p>Description: Tests the DiagSynt class </p>
* @author Stotzer
* @version 1.0
*/
import java.util.Random;
public class MyDiagSyntTest {
public static String generateCorrectWord(Random r, int maxNbr) {
String word = "";
int n1 = r.nextInt(maxNbr) + 1;
int n2 = r.nextInt(maxNbr) + 1;
for (int i = 0; i < n1; i++)
word += 'i';
word += '+';
for (int i = 0; i < n2; i++)
word += 'i';
word += '=';
for (int i = 0; i < n1 + n2; i++)
word += 'i';
return word;
}
public static boolean testWord(String word, boolean expectedResult) {
boolean res = DiagSynt.isAccepted(word);
if (expectedResult != res)
if (expectedResult)
System.out.println("'" + word + "' should be accepted");
else
System.out.println("'" + word + "' should be refused");
return res;
}
public static boolean testCorrectWords(Random r, int maxNbr, int nbrOfTest) {
boolean res = true;
String word;
// Following words should be accepted
for (int i = 0; i < nbrOfTest; i++){
word= generateCorrectWord(r, maxNbr);
res = testWord(word, true) && res;
}
return res;
}
public static boolean testWrongWords(Random r, int maxNbr, int nbrOfTest) {
boolean res = true;
res = !testWord("", false) && res;
res = !testWord("=", false) && res;
res = !testWord("i=i", false) && res;
String word;
// Following words should be refused
for (int i = 0; i < nbrOfTest; i++) {
word = generateCorrectWord(r, maxNbr);
if (r.nextBoolean())
word = word.substring(1+r.nextInt(word.length()));
else
word = word.substring(0, 1 + r.nextInt(word.length() - 1));
res = !testWord(word, false) && res;
}
return res;
}
public static void main(String[] args) {
boolean res = true;
int maxNbr = 10;
int nbrOfTest = 100;
Random r = new Random();
res = testWrongWords(r, maxNbr, nbrOfTest);
res = testCorrectWords(r, maxNbr, nbrOfTest) && res;
if (res)
System.out.println("\nTest passed successfully");
else
System.out.println("\nTest failed; there is a bug");
}
}
package s03;
/**
* <p>Description: tests the FSM class</p>
* @author Stotzer, HEIA-FR
* @version 1.0
*/
import java.util.*;
import java.util.Set;
public class MyFSMTest {
public static String generateWrongWord(int nbOfStates, Random r) {
if (r.nextBoolean())
return generateCorrectWord(nbOfStates, r) + 'c';
else
return generateCorrectWord(nbOfStates, r) + 'b';
}
public static String generateCorrectWord(int nbOfStates, Random r) {
String letters = "";
//int maxWordSize = r.nextInt(20);
int nextStep;
for (int i = 0; i < nbOfStates - 1; i++) {
while (r.nextBoolean() || r.nextBoolean()) {
nextStep = r.nextInt(2);
switch (nextStep) {
case 0:
letters += 'a';
break;
case 1:
letters += "bc";
break;
case 2:
letters += "cb";
break;
}
}
letters += 'b';
}
return letters;
}
public static boolean testWord(FSM autom, String letters,
boolean expectedResult) {
int[] word = new int[letters.length()];
for (int j = 0; j < letters.length(); j++)
word[j] = letters.charAt(j) - 'a';
boolean res = autom.accepts(word);
if (expectedResult != res)
if (expectedResult)
System.out.println("'" + letters + "' should be accepted");
else
System.out.println("'" + letters + "' should be refused");
return res;
}
public static boolean testCorrectWords(FSM autom, Random r, int nStates,
int nWords) {
// Following words should be accepted
boolean res = true;
String letters = "";
res = testWord(autom, "c", true) && res;
for (int i = 0; i < nStates - 1; i++)
letters += 'b';
res = testWord(autom, letters, true) && res;
for (int i = 0; i < nWords; i++) {
letters = generateCorrectWord(nStates, r);
res = testWord(autom, letters, true) && res;
}
return res;
}
public static boolean testWrongWords(FSM autom, Random r, int nStates,
int nWords) {
// Following words should be refused
boolean res = true;
String letters = "";
res = !testWord(autom, "", false) && res;
res = !testWord(autom, "a", false) && res;
for (int i = 0; i < nWords; i++) {
letters = generateWrongWord(nStates, r);
res = !testWord(autom, letters, false) && res;
}
return res;
}
public static int[][] createTransitions(int nStates) {
// creates a circular graph with following transitions
// a: stay in current state
// b: go to next state
// c: go to previous state
// the last state is the accepting state
int[][] transitions = new int[nStates][3];
for (int i = 0; i < nStates; i++) {
transitions[i][0] = i;
transitions[i][1] = (i + 1) % nStates;
transitions[i][2] = (nStates + i - 1) % nStates;
}
return transitions;
}
public static void main(String[] args) {
System.out.println("Testing FSM");
Random r = new Random();
int nStates = 3; // Nbr of States in the graph
int nWordsToTest = 100;
boolean res = true;
// create graph
int[][] transitions = createTransitions(nStates);
Set<Integer> acceptingStates = new HashSet<>();
acceptingStates.add(nStates - 1);
FSM autom = new FSM(transitions, acceptingStates);
// test a few words
res = testWrongWords(autom, r, nStates, nWordsToTest);
res = testCorrectWords(autom, r, nStates, nWordsToTest) && res;
if (res)
System.out.println("\nTest passed successfully");
else
System.out.println("\nTest failed; there is a bug");
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment