Added exercise code from BB
authorpimjager <pim@pimjager.nl>
Wed, 20 Jan 2016 10:04:52 +0000 (11:04 +0100)
committerpimjager <pim@pimjager.nl>
Wed, 20 Jan 2016 10:04:52 +0000 (11:04 +0100)
a4/code/src/CandyLearner.java [new file with mode: 0755]
a4/code/src/SutSocketWrapper.java [new file with mode: 0755]
a4/code/sut/CandyMachine.jar [new file with mode: 0755]
a4/code/sut/learnlib_dot2jtorx_aut.py [new file with mode: 0755]

diff --git a/a4/code/src/CandyLearner.java b/a4/code/src/CandyLearner.java
new file mode 100755 (executable)
index 0000000..7b08a7a
--- /dev/null
@@ -0,0 +1,213 @@
+package nl.ru.cs.TT1415.assignment3;
+
+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 CandyLearner {
+       
+       public static int  sutInterface_portNumber=7892;
+       
+       /*
+     * The Adapter: needed in order to let LearnLib and the sut to communicate 
+     * 
+     */
+    public static class SULAdapter implements SUL<String, String> {
+
+        // 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<String> inputs = new SimpleAlphabet<>();
+               inputs.add("IREFUND");
+               inputs.add("IBUTTONMARS");
+               inputs.add("IBUTTONSNICKERS");
+               inputs.add("IBUTTONBOUNTY");
+               inputs.add("ICOIN10");
+               inputs.add("ICOIN5");
+               
+               // Instantiate the sut
+               SUL<String,String> sul = new SULAdapter();
+               
+               // oracle for counting queries wraps sul
+               StatisticSUL<String, String> statisticSul = new ResetCounterSUL<>("membership queries", sul);
+               
+               SUL<String,String> effectiveSul = statisticSul;
+               // use caching in order to avoid duplicate queries
+               effectiveSul = Caches.createSULCache(inputs, effectiveSul);
+               
+               SULOracle<String, String> mqOracle = new SULOracle<>(effectiveSul);
+
+               // create initial set of suffixes
+               List<Word<String>> suffixes = new ArrayList<>();
+               suffixes.add(Word.fromSymbols("IREFUND"));
+               suffixes.add(Word.fromSymbols("IBUTTONMARS"));
+               suffixes.add(Word.fromSymbols("IBUTTONSNICKERS"));
+               suffixes.add(Word.fromSymbols("IBUTTONBOUNTY"));
+               suffixes.add(Word.fromSymbols("ICOIN10"));
+               suffixes.add(Word.fromSymbols("ICOIN5"));
+              
+               // construct L* instance (almost classic Mealy version)
+               // almost: we use words (Word<String>) in cells of the table 
+               // instead of single outputs.
+               MealyLearner<String,String> lstar =
+                       new ExtensibleLStarMealy<>(
+                       inputs, // input alphabet
+                       mqOracle, // mq oracle
+                       suffixes, // initial suffixes
+                       ObservationTableCEXHandlers.FIND_LINEAR_ALLSUFFIXES, // handling of counterexamples
+                       ClosingStrategies.CLOSE_SHORTEST // choose row for closing the table
+                       );
+
+               // create random words equivalence test
+              RandomWordsEQOracle<String, Word<String>, MealyMachine<?,String,?,String>> randomWords =
+                               new RandomWordsEQOracle<String, Word<String>, MealyMachine<?,String,?,String>>(
+                                               mqOracle, 
+                                               3, // int minLength
+                                               8,  // int maxLength
+                                               1000,  // int maxTests
+                                               new Random(46346293) // make results reproducible
+                                               );
+               
+               // create complete exploration equivalence test
+               CompleteExplorationEQOracle<String, Word<String>> completeOracle =
+                               new CompleteExplorationEQOracle<>(
+                                               mqOracle, // a membership oracle
+                                               5, // int minDepth
+                                               7  // int maxDepth
+                                               ); 
+               
+            // create equivalence oracle based on the W method
+               MealyWMethodEQOracle<String, String> 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<String,String> experiment =
+                       new MealyExperiment<>(
+                                       lstar, 
+                                       randomWords, // 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<?, String, ?, String> 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 = "/path/to/yourfolder/CandyMachine.dot";
+               PrintStream writer = new PrintStream(
+                    new FileOutputStream(filename)); 
+               GraphDOT.write(result, inputs, writer); // may throw IOException!
+               
+               System.out.println(executeCommand("dot -Tpdf /path/to/yourfolder/CandyMachine.dot -o /path/to/yourfolder/CandyMachine.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/a4/code/src/SutSocketWrapper.java b/a4/code/src/SutSocketWrapper.java
new file mode 100755 (executable)
index 0000000..04ffd46
--- /dev/null
@@ -0,0 +1,93 @@
+package nl.ru.cs.TT1415.assignment3;
+
+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"));
+                       
+                       
+                       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
+                       sockout.println(inputStr);
+                       sockout.flush();
+                       
+                       // Receive output from SUT
+                       String outputStr=sockin.readLine();
+                       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()  {
+        
+               // send reset to SUT
+               sockout.println("reset");
+               sockout.flush();
+
+               run=run+1;
+       }
+       
+       
+
+       
+       public void close() {
+               /*
+               try {
+                       sockin.close();
+                       sockout.close();
+                       sock.close();
+               } catch (IOException ex) {
+                       
+               }
+               */
+       }
+
+       
+       
+}
diff --git a/a4/code/sut/CandyMachine.jar b/a4/code/sut/CandyMachine.jar
new file mode 100755 (executable)
index 0000000..e78003b
Binary files /dev/null and b/a4/code/sut/CandyMachine.jar differ
diff --git a/a4/code/sut/learnlib_dot2jtorx_aut.py b/a4/code/sut/learnlib_dot2jtorx_aut.py
new file mode 100755 (executable)
index 0000000..d9bae6d
--- /dev/null
@@ -0,0 +1,181 @@
+#!/usr/bin/env python\r
+"""\r
+generates aut for jtorx from dot file learned with learnlib\r
+  '?COIN_1_1'\r
+  '!TEA_0_1'\r
+\r
+note: dot file uses I for input instead of ? and O for output instead of !\r
+"""\r
+# Author: Harco Kuppens\r
+\r
+\r
+import sys, re, pprint  # modules from standard lib (python 2.6 and later)\r
+\r
+\r
+\r
+def get_lts_from_dotfile(dot_file):\r
+    """ Get labeled transition system from graphviz dot file\r
+\r
+        The dot file:\r
+           - describes a digraph with labels\r
+           - encodes the start state with the color='red' attribute\r
+             note: this corresponds with the highlighted state in learnlib API\r
+\r
+        Returns: [start_state,transions]\r
+        Where :\r
+           - start_state: start state label\r
+           - transitions: list of transitions\r
+\r
+    """\r
+\r
+    start_state='unknown'\r
+    f=file(dot_file)\r
+    lines=f.readlines()\r
+    \r
+    \r
+\r
+    # find start state          \r
+    #  line in dot: __start0 -> s0;\r
+    for line in lines:\r
+        if line.find('->') != -1:\r
+            if line.find('__start') != -1:\r
+               start_state=line[line.find('->')+2:].strip(" ;\t\n")\r
+               break\r
+\r
+\r
+    # get transitions\r
+    #   line in dot:  s5 -> s5 [label="ARTREG 20013226 / 531"];\r
+    transitions=[]\r
+    for line in lines:\r
+        if line.find('__start') != -1:\r
+            continue\r
+        if line.find('->') != -1:\r
+            transitions.append(line)\r
+\r
+    # throw away transitions with the keywords : quiescence or inconsistency or undefined\r
+    #transitions = [ t for t in transitions if ( 'quiescence' not in t ) and ( 'inconsistency' not in t  )  and ( 'undefined' not in t  )]\r
+\r
+    trans_out=[]\r
+    regexpr_transition=re.compile(r'\s*(\w*)\s*-\>\s*(\w*)\s*\[label=\"(.*)\"\]')\r
+    regexpr_tag=re.compile(r'<[^>]+>')\r
+    for transition in transitions:\r
+        match=regexpr_transition.match(transition)\r
+        if match:\r
+            match=match.groups()\r
+            label=regexpr_tag.sub('',match[2])\r
+            trans_out.append({\r
+              'source' : match[0],\r
+              'target' : match[1],\r
+              'label': label\r
+            })\r
+\r
+    states=set()\r
+    for t in trans_out:\r
+        states.add(t['source'])\r
+        states.add(t['target'])\r
+\r
+\r
+    return [start_state,states,trans_out]\r
+\r
+\r
+def parse_labels_of_mealy_lts(transitions):\r
+    """Parse labels of labeled transition system\r
+    """\r
+    trans_out=[]\r
+    for t in transitions:\r
+        label=t['label']\r
+        [inputstr,outputstr]=label.split('/')\r
+        trans_out.append({\r
+          'source' : t['source'],\r
+          'target' : t['target'],\r
+          'input':  inputstr,\r
+          'output':  outputstr,\r
+        })\r
+    return trans_out\r
+\r
+def split_io_transitions_in_separate_input_and_output_transition(io_transitions,nr_states):\r
+    """Split transitions with both an input and output event into two transitions\r
+\r
+       Makes two sequential transitions with a dummy state in between:\r
+        - dummy state <midstate> is labeled :\r
+             m_<counter>\r
+        - first transition :\r
+             <source> -> <midstate>  for  <input>\r
+        - second transition :\r
+             <midstate> -> <target>  for <output>\r
+    """\r
+    trans_out=[]\r
+    id=nr_states\r
+    for t in io_transitions:\r
+        midstate= 'm' + str(id)\r
+        trans_out.append({\r
+            'source': t['source'],\r
+            'target': midstate,\r
+            'label' : "?" + t['input'].strip(),\r
+        })\r
+        trans_out.append({\r
+            'source': midstate,\r
+            'target': t['target'],\r
+            'label' : "!" + t['output'].strip(),\r
+        })\r
+        id=id+1\r
+\r
+    states=set()\r
+    for t in trans_out:\r
+        states.add(t['source'])\r
+        states.add(t['target'])\r
+\r
+    return [states,trans_out]\r
+\r
+\r
+def transitions2aut(transitions,first_state,nr_of_states):\r
+    nr_of_transitions=len(transitions)\r
+    strings=[ "des(" + first_state[1:] + ","  + str(nr_of_transitions) + "," + str(nr_of_states) +")"]\r
+    for t in transitions:\r
+       #aut_edge ::= "(" start_state "," label "," end_state ")"\r
+       strings.append("("+t['source'][1:] + "," + '"' + t['label'] + '"' + "," + t['target'][1:] + ")" )\r
+\r
+    return "\n".join(strings)\r
+\r
+\r
+def dot2aut(dot_filename_in):\r
+    """\r
+       from mealy machine in a .dot file written by DotUtil.write of learnlib\r
+       we create an .aut file containing an lts where input and output each\r
+       have its own labeled transition. An input transition has a\r
+       label starting with '?' and an output transition has a label\r
+       starting with '!'\r
+\r
+    """\r
+\r
+    if  dot_filename_in[-4:].lower() != '.dot':\r
+       print "Problem: file '"+ dot_filename_in + "' is not a dot file!!"\r
+       print "Exit!"\r
+       sys.exit(1)\r
+\r
+\r
+    [start_state,states,transitions]=get_lts_from_dotfile(dot_filename_in)\r
+    \r
+\r
+    \r
+    io_transitions=parse_labels_of_mealy_lts(transitions) # each transition has input and output\r
+    [states,transitions]=split_io_transitions_in_separate_input_and_output_transition(io_transitions,len(states)) # each transition only has label again\r
+\r
+    #pprint.pprint(start_state)\r
+    #pprint.pprint(states)\r
+    #pprint.pprint(transitions)\r
+\r
+    result=transitions2aut(transitions,start_state,len(states))\r
+\r
+    aut_filename=dot_filename_in[:-4] + ".aut"\r
+\r
+    f=open(aut_filename ,'w')\r
+    f.write(result)\r
+    f.close()\r
+\r
+    print "written file : " +  aut_filename\r
+\r
+\r
+if __name__ == "__main__":\r
+    dot2aut(*sys.argv[1:])\r
+\r