diff --git a/examples/tictactoe/completetesting.py b/examples/tictactoe/completetesting.py index c96db2bb2f6b2114919baa3d8155c52a7048fd83..7bccb598729d8ee76043bd3797c8dc119f4bd162 100644 --- a/examples/tictactoe/completetesting.py +++ b/examples/tictactoe/completetesting.py @@ -30,7 +30,8 @@ class CompleteTicTacToeTester(AbstractTester): self._teacher = teacher # upper bound: 9! (possible plays, also invalid ones) # according to wikipedia - self._all_games = set(itertools.permutations(['0','1','2','3','4','5','6','7','8'])) + # Reduced to games of length 5 (maximum number of X in a bard) + self._all_games = set(itertools.permutations(['0','1','2','3','4','5','6','7','8'],5)) self._logger = logger or logging.getLogger(__name__) # Search a counterexample to teacher ioco model diff --git a/examples/tictactoe/learnLib/README.md b/examples/tictactoe/learnLib/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3f66be051549d56c050c4f565898e7b68695220d --- /dev/null +++ b/examples/tictactoe/learnLib/README.md @@ -0,0 +1,11 @@ +This is the code used for comparing my tool with learnLib version 0.9.1. + +I use this version because of some errors introduced in learnLib by newer versions. + +LearnLib code, readme, license and other relevent information can be found at https://github.com/LearnLib/learnlib + +How to setup this example: +In your favorite IDE create a project including the content of the src folder and adding to the path +the LearnLib library (the content of the lib folder). Everything has been tested in Eclipse Lunawith JavaSE-1.7. +Adapt the paths to your specific case (around line 178 of TicTacToeLearner.java) and run it to +learn the SUT. You might need to install Graphviz for the dot program. diff --git a/examples/tictactoe/learnLib/version0.9.1/lib/learnlib-0.9.1-dependencies-bundle.jar b/examples/tictactoe/learnLib/version0.9.1/lib/learnlib-0.9.1-dependencies-bundle.jar new file mode 100644 index 0000000000000000000000000000000000000000..56351bb322b8521ef576cb581280d640fc39cbbb Binary files /dev/null and b/examples/tictactoe/learnLib/version0.9.1/lib/learnlib-0.9.1-dependencies-bundle.jar differ diff --git a/examples/tictactoe/learnLib/version0.9.1/src/SutSocketWrapper.java b/examples/tictactoe/learnLib/version0.9.1/src/SutSocketWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3515b6a8c38064bbfcc7c26b2937bf8c31cc6e44 --- /dev/null +++ b/examples/tictactoe/learnLib/version0.9.1/src/SutSocketWrapper.java @@ -0,0 +1,108 @@ +package nl.ru.cs.mvolpato.tictaclearnlib; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.Socket; + + +public class SutSocketWrapper { + private Socket sock; + private PrintWriter sockout; + private BufferedReader sockin; + private int run; + + public SutSocketWrapper(int portNumber) { + + try { + sock = new Socket("localhost", portNumber); + + /* Call setTcpNoDelay to improve communication performance : */ + + sock.setTcpNoDelay(true); // remove unnecessary delay in socket communication! + + + // make char writer from byte writer which automatically encodes chars using UTF-8 and + // automatically flushes the buffer on each println call. + sockout = new PrintWriter(new OutputStreamWriter(sock.getOutputStream(), "UTF-8"),true); + // make char reader from byte reader which automatically decodes bytes to chars using UTF-8 + sockin = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8")); + + // consume an output + String outputStr=sockin.readLine(); + System.out.println("Consuming output in connection: "+outputStr); + + + run=1; + } catch (IOException e) { + // e.printStackTrace(); + System.err.println(""); + System.err.println("\n\nPROBLEM: problem connecting with SUT:\n\n " + e.getMessage() +"\n\n"); + System.exit(1); + } + } + + + + public String sendInput(String inputStr) { + try { + + // Send input to SUT + //System.out.println("Input: "+inputStr); + sockout.println(inputStr); + sockout.flush(); + + // Receive output from SUT + String outputStr=sockin.readLine(); + //System.out.println("Output: "+outputStr); + if (outputStr==null) { + System.err.println(""); + System.err.println("\n\nPROBLEM: problem reading output from SUT: SUT closed connection\n\n " ); + System.exit(1); + } + + return outputStr; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public void sendReset() { + try { + // send reset to SUT + //System.out.println("Resetting"); + sockout.println("9"); + sockout.flush(); + + // consume an output + String outputStr=sockin.readLine(); + //System.out.println("Consuming output: "+outputStr); + } catch (IOException e) { + e.printStackTrace(); + } + run=run+1; + } + + + + + public void close() { + + //try { + sockout.println("EXIT"); + sockout.flush(); + /*sockin.close(); + sockout.close(); + sock.close();*/ + //} catch (IOException ex) { + + //} + + } + + + +} diff --git a/examples/tictactoe/learnLib/version0.9.1/src/TicTacToeLearner.java b/examples/tictactoe/learnLib/version0.9.1/src/TicTacToeLearner.java new file mode 100644 index 0000000000000000000000000000000000000000..94c4740339bf77ff98eed23d52441a8705055b0a --- /dev/null +++ b/examples/tictactoe/learnLib/version0.9.1/src/TicTacToeLearner.java @@ -0,0 +1,211 @@ +package nl.ru.cs.mvolpato.tictaclearnlib; + +import java.io.BufferedReader; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import net.automatalib.automata.transout.MealyMachine; +import net.automatalib.util.graphs.dot.GraphDOT; +import net.automatalib.words.Alphabet; +import net.automatalib.words.Word; +import net.automatalib.words.impl.SimpleAlphabet; +import de.learnlib.algorithms.lstargeneric.ce.ObservationTableCEXHandlers; +import de.learnlib.algorithms.lstargeneric.closing.ClosingStrategies; +import de.learnlib.algorithms.lstargeneric.mealy.ExtensibleLStarMealy; +import de.learnlib.api.LearningAlgorithm.MealyLearner; +import de.learnlib.api.SUL; +import de.learnlib.cache.Caches; +import de.learnlib.eqtests.basic.CompleteExplorationEQOracle; +import de.learnlib.eqtests.basic.RandomWordsEQOracle; +import de.learnlib.eqtests.basic.WMethodEQOracle.MealyWMethodEQOracle; +import de.learnlib.experiments.Experiment.MealyExperiment; +import de.learnlib.oracles.ResetCounterSUL; +import de.learnlib.oracles.SULOracle; +import de.learnlib.statistics.SimpleProfiler; +import de.learnlib.statistics.StatisticSUL; + + +public class TicTacToeLearner { + + public static int sutInterface_portNumber=29000; + + /* + * The Adapter: needed in order to let LearnLib and the sut to communicate + * + */ + public static class SULAdapter implements SUL { + + // system under learning + private SutSocketWrapper sul = new SutSocketWrapper(sutInterface_portNumber); + + // reset the SUL + @Override + public void reset() { + sul.sendReset(); + } + + // execute one input on the SUL + @Override + public String step(String in) { + String output = sul.sendInput(in); + //System.out.println(in + ":" + output); + return output; + } + } + + public static void main(String[] args) throws NoSuchMethodException, IOException { + + // create alphabet + Alphabet inputs = new SimpleAlphabet<>(); + inputs.add("0"); + inputs.add("1"); + inputs.add("2"); + inputs.add("3"); + inputs.add("4"); + inputs.add("5"); + inputs.add("6"); + inputs.add("7"); + inputs.add("8"); + + // Instantiate the sut + SUL sul = new SULAdapter(); + + // oracle for counting queries wraps sul + StatisticSUL statisticSul = new ResetCounterSUL<>("membership queries", sul); + + SUL effectiveSul = statisticSul; + // use caching in order to avoid duplicate queries + effectiveSul = Caches.createSULCache(inputs, effectiveSul); + + SULOracle mqOracle = new SULOracle<>(effectiveSul); + + // create initial set of suffixes + List> suffixes = new ArrayList<>(); + //suffixes.add(Word.fromSymbols("0")); + + // construct L* instance (almost classic Mealy version) + // almost: we use words (Word) in cells of the table + // instead of single outputs. + MealyLearner lstar = + new ExtensibleLStarMealy<>( + inputs, // input alphabet + mqOracle, // mq oracle + suffixes, // initial suffixes + ObservationTableCEXHandlers.RIVEST_SCHAPIRE_ALLSUFFIXES, // handling of counterexamples + ClosingStrategies.CLOSE_FIRST // choose row for closing the table + ); + + // create random words equivalence test + RandomWordsEQOracle, MealyMachine> randomWords = + new RandomWordsEQOracle, MealyMachine>( + mqOracle, + 3, // int minLength + 8, // int maxLength + 1000, // int maxTests + new Random(46346293) // make results reproducible + ); + + // create complete exploration equivalence test + CompleteExplorationEQOracle> completeOracle = + new CompleteExplorationEQOracle<>( + mqOracle, // a membership oracle + 3, // int minDepth + 6 // int maxDepth + ); + + // create equivalence oracle based on the W method + MealyWMethodEQOracle wOracle= + new MealyWMethodEQOracle<>( + 5, //int maxDepth + mqOracle // a membership oracle + ); + + + // construct a learning experiment from + // the learning algorithm and one of the equivalence oracles. + // The experiment will execute the main loop of + // active learning + MealyExperiment experiment = + new MealyExperiment<>( + lstar, + completeOracle, // equivalence oracle, choose among [randomWords | completeOracle | wOracle] **remember to change their settings** + inputs // input alphabet + ); + + // turn off time profiling + experiment.setProfile(true); + + // enable logging of models + experiment.setLogModels(true); + + // run experiment + experiment.run(); + + // get learned model + MealyMachine result = experiment.getFinalHypothesis(); + + // report results + System.out.println("-------------------------------------------------------"); + + // profiling + System.out.println(SimpleProfiler.getResults()); + + // learning statistics + System.out.println(experiment.getRounds().getSummary()); + System.out.println(statisticSul.getStatisticalData().getSummary()); + + // model statistics + System.out.println("States: " + result.size()); + System.out.println("Sigma: " + inputs.size()); + + // show model + System.out.println(); + System.out.println("Model: "); + + GraphDOT.write(result, inputs, System.out); // may throw IOException! +// Writer w = DOT.createDotWriter(true); +// GraphDOT.write(result, inputs, w); +// w.close(); + + String filename = "/home/mic/repo/learnLTS/examples/tictactoe/learnLib/TicTacToe.dot"; + PrintStream writer = new PrintStream( + new FileOutputStream(filename)); + GraphDOT.write(result, inputs, writer); // may throw IOException! + + System.out.println(executeCommand("dot -Tpdf /home/mic/repo/learnLTS/examples/tictactoe/learnLib/TicTacToe.dot -o /home/mic/repo/learnLTS/examples/tictactoe/learnLib/TicTacToe.pdf")); + + + System.out.println("-------------------------------------------------------"); + + } + + // execute command, for translation from dot to pdf + public static String executeCommand(String command) { + + StringBuffer output = new StringBuffer(); + + Process p; + try { + p = Runtime.getRuntime().exec(command); + p.waitFor(); + BufferedReader reader = + new BufferedReader(new InputStreamReader(p.getInputStream())); + + String line = ""; + while ((line = reader.readLine())!= null) { + output.append(line + "\n"); + } + + } catch (Exception e) { + e.printStackTrace(); + } + + return output.toString(); + + } +} diff --git a/examples/tictactoe/tictacteacher.py b/examples/tictactoe/tictacteacher.py index ca38f0ec6e2a58c6a25f516bf51e207b5b69647a..5f0653415688a0e98355f489d060dbf1cf6b50ba 100644 --- a/examples/tictactoe/tictacteacher.py +++ b/examples/tictactoe/tictacteacher.py @@ -80,7 +80,7 @@ class TicTacToeTeacher(AbstractTeacher): # reset SUL self._socket.sendall(bytes("9", 'UTF-8')) grid = self._socket.recv(1024).decode("utf-8") - if grid == "012345678": + if grid == "_________": return True return False diff --git a/examples/tictactoe/tictactoe.py b/examples/tictactoe/tictactoe.py index ec9a3464ce9147aeef0f2a6ffef0c2abfd0dece8..28b877a1ab5cad5d4ea499656912517f3a980e23 100644 --- a/examples/tictactoe/tictactoe.py +++ b/examples/tictactoe/tictactoe.py @@ -395,10 +395,14 @@ if __name__ == "__main__": #Receiving from client data = conn.recv(1024) - if not data or str(data.decode("utf-8")) == "EXIT\r\n": - break - - move1 = int(data.decode("utf-8")) + move1 = data + if not isinstance(data,int): + if (not data or "EXIT" in str(data.decode("utf-8"))): + break + if isinstance(data.decode("utf-8")[0],int): + move1 = data.decode("utf-8")[0] + else: + move1 = int(data.decode("utf-8")[0]) logger.debug("Received: " + str(move1)) @@ -423,12 +427,12 @@ if __name__ == "__main__": if winner != 0: logger.debug("We have a winner!") - board = board + " END" - conn.sendall(bytes(board, 'UTF-8')) + #board = board + "END" + conn.sendall(bytes(board+"\n", 'UTF-8')) newGame() else: logger.debug("Sending: " + board) - conn.sendall(bytes(board, 'UTF-8')) + conn.sendall(bytes(board+"\n", 'UTF-8'))