From: pimjager Date: Wed, 20 Jan 2016 10:04:52 +0000 (+0100) Subject: Added exercise code from BB X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=2abd99c70b29f717c49c1b08419f5ebc1480a040;p=tt2015.git Added exercise code from BB --- diff --git a/a4/code/src/CandyLearner.java b/a4/code/src/CandyLearner.java new file mode 100755 index 0000000..7b08a7a --- /dev/null +++ b/a4/code/src/CandyLearner.java @@ -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 { + + // 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("IREFUND"); + inputs.add("IBUTTONMARS"); + inputs.add("IBUTTONSNICKERS"); + inputs.add("IBUTTONBOUNTY"); + inputs.add("ICOIN10"); + inputs.add("ICOIN5"); + + // 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("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) in cells of the table + // instead of single outputs. + MealyLearner 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, 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 + 5, // int minDepth + 7 // 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, + 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 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 index 0000000..04ffd46 --- /dev/null +++ b/a4/code/src/SutSocketWrapper.java @@ -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 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 index 0000000..d9bae6d --- /dev/null +++ b/a4/code/sut/learnlib_dot2jtorx_aut.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +""" +generates aut for jtorx from dot file learned with learnlib + '?COIN_1_1' + '!TEA_0_1' + +note: dot file uses I for input instead of ? and O for output instead of ! +""" +# Author: Harco Kuppens + + +import sys, re, pprint # modules from standard lib (python 2.6 and later) + + + +def get_lts_from_dotfile(dot_file): + """ Get labeled transition system from graphviz dot file + + The dot file: + - describes a digraph with labels + - encodes the start state with the color='red' attribute + note: this corresponds with the highlighted state in learnlib API + + Returns: [start_state,transions] + Where : + - start_state: start state label + - transitions: list of transitions + + """ + + start_state='unknown' + f=file(dot_file) + lines=f.readlines() + + + + # find start state + # line in dot: __start0 -> s0; + for line in lines: + if line.find('->') != -1: + if line.find('__start') != -1: + start_state=line[line.find('->')+2:].strip(" ;\t\n") + break + + + # get transitions + # line in dot: s5 -> s5 [label="ARTREG 20013226 / 531"]; + transitions=[] + for line in lines: + if line.find('__start') != -1: + continue + if line.find('->') != -1: + transitions.append(line) + + # throw away transitions with the keywords : quiescence or inconsistency or undefined + #transitions = [ t for t in transitions if ( 'quiescence' not in t ) and ( 'inconsistency' not in t ) and ( 'undefined' not in t )] + + trans_out=[] + regexpr_transition=re.compile(r'\s*(\w*)\s*-\>\s*(\w*)\s*\[label=\"(.*)\"\]') + regexpr_tag=re.compile(r'<[^>]+>') + for transition in transitions: + match=regexpr_transition.match(transition) + if match: + match=match.groups() + label=regexpr_tag.sub('',match[2]) + trans_out.append({ + 'source' : match[0], + 'target' : match[1], + 'label': label + }) + + states=set() + for t in trans_out: + states.add(t['source']) + states.add(t['target']) + + + return [start_state,states,trans_out] + + +def parse_labels_of_mealy_lts(transitions): + """Parse labels of labeled transition system + """ + trans_out=[] + for t in transitions: + label=t['label'] + [inputstr,outputstr]=label.split('/') + trans_out.append({ + 'source' : t['source'], + 'target' : t['target'], + 'input': inputstr, + 'output': outputstr, + }) + return trans_out + +def split_io_transitions_in_separate_input_and_output_transition(io_transitions,nr_states): + """Split transitions with both an input and output event into two transitions + + Makes two sequential transitions with a dummy state in between: + - dummy state is labeled : + m_ + - first transition : + -> for + - second transition : + -> for + """ + trans_out=[] + id=nr_states + for t in io_transitions: + midstate= 'm' + str(id) + trans_out.append({ + 'source': t['source'], + 'target': midstate, + 'label' : "?" + t['input'].strip(), + }) + trans_out.append({ + 'source': midstate, + 'target': t['target'], + 'label' : "!" + t['output'].strip(), + }) + id=id+1 + + states=set() + for t in trans_out: + states.add(t['source']) + states.add(t['target']) + + return [states,trans_out] + + +def transitions2aut(transitions,first_state,nr_of_states): + nr_of_transitions=len(transitions) + strings=[ "des(" + first_state[1:] + "," + str(nr_of_transitions) + "," + str(nr_of_states) +")"] + for t in transitions: + #aut_edge ::= "(" start_state "," label "," end_state ")" + strings.append("("+t['source'][1:] + "," + '"' + t['label'] + '"' + "," + t['target'][1:] + ")" ) + + return "\n".join(strings) + + +def dot2aut(dot_filename_in): + """ + from mealy machine in a .dot file written by DotUtil.write of learnlib + we create an .aut file containing an lts where input and output each + have its own labeled transition. An input transition has a + label starting with '?' and an output transition has a label + starting with '!' + + """ + + if dot_filename_in[-4:].lower() != '.dot': + print "Problem: file '"+ dot_filename_in + "' is not a dot file!!" + print "Exit!" + sys.exit(1) + + + [start_state,states,transitions]=get_lts_from_dotfile(dot_filename_in) + + + + io_transitions=parse_labels_of_mealy_lts(transitions) # each transition has input and output + [states,transitions]=split_io_transitions_in_separate_input_and_output_transition(io_transitions,len(states)) # each transition only has label again + + #pprint.pprint(start_state) + #pprint.pprint(states) + #pprint.pprint(transitions) + + result=transitions2aut(transitions,start_state,len(states)) + + aut_filename=dot_filename_in[:-4] + ".aut" + + f=open(aut_filename ,'w') + f.write(result) + f.close() + + print "written file : " + aut_filename + + +if __name__ == "__main__": + dot2aut(*sys.argv[1:]) +