diff --git a/ExperimentsBlackBox.java b/ExperimentsBlackBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..1be6602eaaaedcbf8aa959169ea6a211d13ea406
--- /dev/null
+++ b/ExperimentsBlackBox.java
@@ -0,0 +1,347 @@
+import de.learnlib.acex.AcexAnalyzer;
+import de.learnlib.algorithm.kv.dfa.KearnsVaziraniDFA;
+import de.learnlib.algorithm.kv.dfa.KearnsVaziraniDFABuilder;
+import de.learnlib.algorithm.lstar.dfa.ClassicLStarDFABuilder;
+import de.learnlib.algorithm.observationpack.dfa.OPLearnerDFA;
+import de.learnlib.algorithm.observationpack.dfa.OPLearnerDFABuilder;
+import de.learnlib.algorithm.rivestschapire.RivestSchapireDFA;
+import de.learnlib.algorithm.ttt.base.AbstractTTTLearner;
+import de.learnlib.algorithm.ttt.dfa.TTTLearnerDFA;
+import de.learnlib.algorithm.ttt.dfa.TTTLearnerDFABuilder;
+import de.learnlib.filter.statistic.oracle.DFACounterOracle;
+import de.learnlib.oracle.EquivalenceOracle;
+import de.learnlib.oracle.MembershipOracle;
+import de.learnlib.oracle.equivalence.DFASimulatorEQOracle;
+import de.learnlib.oracle.equivalence.DFAWMethodEQOracle;
+import de.learnlib.oracle.equivalence.WMethodEQOracle;
+import de.learnlib.oracle.membership.DFASimulatorOracle;
+import de.learnlib.query.DefaultQuery;
+import net.automatalib.alphabet.Alphabet;
+import net.automatalib.alphabet.Alphabets;
+import net.automatalib.automaton.fsa.DFA;
+import de.learnlib.algorithm.lstar.dfa.ClassicLStarDFA;
+import de.learnlib.algorithm.rivestschapire.RivestSchapireDFABuilder;
+import net.automatalib.word.Word;
+import org.knowm.xchart.QuickChart;
+import org.knowm.xchart.SwingWrapper;
+import org.knowm.xchart.XYChart;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class ExperimentsBlackBox {
+
+ public static void main(String[] args) {
+ // Define configurations
+ int[] yValues = { 3 };
+ int[] zValues = { 35 };
+ double[] xValues = { 1,2,3,4};
+
+ // Declare arrays to store the average membership queries and average equivalence queries
+ double[] avgMemQueriesLstar = new double[xValues.length];
+ double[] avgMemQueriesRS = new double[xValues.length];
+ double[] avgMemQueriesKV = new double[xValues.length];
+ double[] avgMemQueriesOP = new double[xValues.length];
+ double[] avgMemQueriesTTT = new double[xValues.length];
+
+ double[] avgMemQueriesLstarLearn = new double[xValues.length];
+ double[] avgMemQueriesRSLearn = new double[xValues.length];
+ double[] avgMemQueriesKVLearn = new double[xValues.length];
+ double[] avgMemQueriesOPLearn = new double[xValues.length];
+ double[] avgMemQueriesTTTLearn = new double[xValues.length];
+
+ double[] avgEqQueriesLstar = new double[xValues.length];
+ double[] avgEqQueriesRS = new double[xValues.length];
+ double[] avgEqQueriesKV = new double[xValues.length];
+ double[] avgEqQueriesOP = new double[xValues.length];
+ double[] avgEqQueriesTTT = new double[xValues.length];
+
+ double[] accuracyLstar = new double[xValues.length];
+ double[] accuracyRS = new double[xValues.length];
+ double[] accuracyKV = new double[xValues.length];
+ double[] accuracyOP = new double[xValues.length];
+ double[] accuracyTTT = new double[xValues.length];
+
+
+
+
+
+ // Iterate over each configuration: y denotes the size of the alphabet of the target DFA, z denotes the size of the target DFA, x denotes the acceptance ratio of the target DFA
+ for(int y:yValues) {
+ for (int z : zValues) {
+ int k=0;
+ for (double x : xValues) {
+ // Create the alphabet
+ Alphabet<Integer> alphabet = Alphabets.integers(0, y - 1);
+
+ int memCounterLstar = 0;
+ int memCounterRS = 0;
+ int memCounterKV = 0;
+ int memCounterOP = 0;
+ int memCounterTTT = 0;
+
+ int memCounterLstarLearn = 0;
+ int memCounterRSLearn = 0;
+ int memCounterKVLearn = 0;
+ int memCounterOPLearn = 0;
+ int memCounterTTTLearn = 0;
+
+ int eqCounterLstar = 0;
+ int eqCounterRS = 0;
+ int eqCounterKV = 0;
+ int eqCounterOP = 0;
+ int eqCounterTTT = 0;
+
+ int controleLstar = 0;
+ int controleRS = 0;
+ int controleKV = 0;
+ int controleOP = 0;
+ int controleTTT = 0;
+
+ // Generate 100 random DFAs for each configuration
+ for (int i = 0; i < 5; i++) {
+ System.out.println("Generating random DFA " + i + " for configuration (x,y,z):" + 0.01 + "," + y + "," + z + "lookahead:" + x);
+ Random rand = new Random();
+ ExampleRandomDFA example = new ExampleRandomDFA(rand, y, z, 0.01, alphabet);
+ DFA<?, Integer> dfa = example.getReferenceAutomaton();
+
+ // Initialize the Query Counters and the Oracles - we used the white-box oracles
+
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle = new DFASimulatorEQOracle<>(dfa); // for controle
+
+ MembershipOracle.DFAMembershipOracle<Integer> memOraclePlainLstar = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleLstarLearn = new DFACounterOracle<>(memOraclePlainLstar);
+ MembershipOracle.DFAMembershipOracle<Integer> memOracleLstar = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleLstar = new DFACounterOracle<>(memOracleLstar);
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleLstar = new DFAWMethodEQOracle<>(memCounterOracleLstar,(int)x);
+ EQCounterOracle<DFA<?, Integer>, Integer, Boolean> eqCounterOracleLstar = new EQCounterOracle<>(eqOracleLstar);
+
+
+
+ MembershipOracle.DFAMembershipOracle<Integer> memOraclePlainRS = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleRSLearn = new DFACounterOracle<>(memOraclePlainRS);
+ MembershipOracle.DFAMembershipOracle<Integer> memOracleRS = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleRS = new DFACounterOracle<>(memOracleRS);
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleRS = new DFAWMethodEQOracle<>(memCounterOracleRS,(int)x);
+ EQCounterOracle<DFA<?, Integer>, Integer, Boolean> eqCounterOracleRS = new EQCounterOracle<>(eqOracleRS);
+
+ MembershipOracle.DFAMembershipOracle<Integer> memOraclePlainKV = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleKVLearn = new DFACounterOracle<>(memOraclePlainKV);
+ MembershipOracle.DFAMembershipOracle<Integer> memOracleKV = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleKV = new DFACounterOracle<>(memOracleKV);
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleKV = new DFAWMethodEQOracle<>(memCounterOracleKV,(int)x);
+ EQCounterOracle<DFA<?, Integer>, Integer, Boolean> eqCounterOracleKV = new EQCounterOracle<>(eqOracleKV);
+
+ MembershipOracle.DFAMembershipOracle<Integer> memOraclePlainOP = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleOPLearn = new DFACounterOracle<>(memOraclePlainOP);
+ MembershipOracle.DFAMembershipOracle<Integer> memOracleOP = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleOP = new DFACounterOracle<>(memOracleOP);
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleOP = new DFAWMethodEQOracle<>(memCounterOracleOP,(int)x);
+ EQCounterOracle<DFA<?, Integer>, Integer, Boolean> eqCounterOracleOP = new EQCounterOracle<>(eqOracleOP);
+
+ MembershipOracle.DFAMembershipOracle<Integer> memOraclePlainTTT = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleTTTLearn = new DFACounterOracle<>(memOraclePlainTTT);
+ MembershipOracle.DFAMembershipOracle<Integer> memOracleTTT = new DFASimulatorOracle<>(dfa);
+ DFACounterOracle<Integer> memCounterOracleTTT = new DFACounterOracle<>(memOracleTTT);
+ EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleTTT = new DFAWMethodEQOracle<>(memCounterOracleTTT,(int)x);
+ EQCounterOracle<DFA<?, Integer>, Integer, Boolean> eqCounterOracleTTT = new EQCounterOracle<>(eqOracleTTT);
+
+
+ // Learn the DFA using each learning algorithm
+ if(learnWithClassicLStarDFA(dfa, alphabet, eqCounterOracleLstar, memCounterOracleLstarLearn, controle)==1){controleLstar++;};
+ if(learnWithRivestShapireDFA(dfa, alphabet, eqCounterOracleRS, memCounterOracleRSLearn, controle)==1){controleRS++;};
+ if((learnWithKearnsVauiraniDFA(dfa, alphabet, eqCounterOracleKV, memCounterOracleKVLearn, controle)==1)){controleKV++;};
+ if(learnWithOPLearnerDFA(dfa, alphabet, eqCounterOracleOP, memCounterOracleOPLearn, controle)==1){controleOP++;};
+ if(learnWithTTTLearnerDFA(dfa, alphabet, eqCounterOracleTTT, memCounterOracleTTTLearn, controle)==1){controleTTT++;};
+
+ // Update the counters
+ memCounterLstar += memCounterOracleLstar.getQueryCounter().getCount();
+ memCounterRS += memCounterOracleRS.getQueryCounter().getCount();
+ memCounterKV += memCounterOracleKV.getQueryCounter().getCount();
+ memCounterOP += memCounterOracleOP.getQueryCounter().getCount();
+ memCounterTTT += memCounterOracleTTT.getQueryCounter().getCount();
+
+ memCounterLstarLearn += memCounterOracleLstarLearn.getQueryCounter().getCount();
+ memCounterRSLearn += memCounterOracleRSLearn.getQueryCounter().getCount();
+ memCounterKVLearn += memCounterOracleKVLearn.getQueryCounter().getCount();
+ memCounterOPLearn += memCounterOracleOPLearn.getQueryCounter().getCount();
+ memCounterTTTLearn += memCounterOracleTTTLearn.getQueryCounter().getCount();
+
+ eqCounterLstar += eqCounterOracleLstar.getCounter();
+ eqCounterRS += eqCounterOracleRS.getCounter();
+ eqCounterKV += eqCounterOracleKV.getCounter();
+ eqCounterOP += eqCounterOracleOP.getCounter();
+ eqCounterTTT += eqCounterOracleTTT.getCounter();
+ }
+ //Calculate average for configuration (x,y,z) for the counters
+ System.out.println("For configuration (x,y,z):" + x + "," + y + "," + z + " :");
+ System.out.println("Average memCounterLstar: " + memCounterLstar/5);
+ System.out.println("Average memCounterRS: " + memCounterRS/5);
+ System.out.println("Average memCounterKV: " + memCounterKV/5);
+ System.out.println("Average memCounterOP: " + memCounterOP/5);
+ System.out.println("Average memCounterTTT: " + memCounterTTT/5);
+
+ System.out.println("Average eqCounterLstar: " + eqCounterLstar/5);
+ System.out.println("Average eqCounterRS: " + eqCounterRS/5);
+ System.out.println("Average eqCounterKV: " + eqCounterKV/5);
+ System.out.println("Average eqCounterOP: " + eqCounterOP/5);
+ System.out.println("Average eqCounterTTT: " + eqCounterTTT/5);
+
+ // Calculate the averages and store them in the arrays
+
+ avgMemQueriesLstar[k] = memCounterLstar / 5;
+ avgMemQueriesRS[k] = memCounterRS / 5;
+ avgMemQueriesKV[k] = memCounterKV / 5;
+ avgMemQueriesOP[k] = memCounterOP / 5;
+ avgMemQueriesTTT[k] = memCounterTTT / 5;
+
+ avgEqQueriesLstar[k] = eqCounterLstar / 5.0;
+ avgEqQueriesRS[k] = eqCounterRS / 5.0;
+ avgEqQueriesKV[k] = eqCounterKV / 5.0;
+ avgEqQueriesOP[k] = eqCounterOP / 5.0;
+ avgEqQueriesTTT[k] = eqCounterTTT / 5.0;
+
+ avgMemQueriesLstarLearn[k] = memCounterLstarLearn / 5;
+ avgMemQueriesRSLearn[k] = memCounterRSLearn / 5;
+ avgMemQueriesKVLearn[k] = memCounterKVLearn / 5;
+ avgMemQueriesOPLearn[k] = memCounterOPLearn / 5;
+ avgMemQueriesTTTLearn[k] = memCounterTTTLearn / 5;
+
+ accuracyLstar[k] = (double)controleLstar/5;
+ accuracyRS[k] = (double)controleRS/5;
+ accuracyKV[k] = (double)controleKV/5;
+ accuracyOP[k] = (double)controleOP/5;
+ accuracyTTT[k] = (double)controleTTT/5;
+ k++;
+ }
+ }
+ }
+ String[] seriesNames = {"LStar","RS","KV", "OP", "TTT"};
+
+// Create the first XY chart (membership queries)
+ XYChart chart1 = QuickChart.getChart("Average Additional Membership Queries", "Lookahead", "Queries", seriesNames, xValues, new double[][]{avgMemQueriesLstar,avgMemQueriesRS, avgMemQueriesKV, avgMemQueriesOP, avgMemQueriesTTT});
+ new SwingWrapper(chart1).displayChart();
+
+ // Create the second XY chart (membership queries)
+ XYChart chart3 = QuickChart.getChart("Average Membership Queries", "Lookahead", "Queries", seriesNames, xValues, new double[][]{avgMemQueriesLstarLearn,avgMemQueriesRSLearn, avgMemQueriesKVLearn, avgMemQueriesOPLearn, avgMemQueriesTTTLearn});
+ new SwingWrapper(chart3).displayChart();
+
+ double[] avgMemQueriesLstarRatio = new double[xValues.length];
+ double[] avgMemQueriesRSRatio = new double[xValues.length];
+ double[] avgMemQueriesKVRatio = new double[xValues.length];
+ double[] avgMemQueriesOPRatio = new double[xValues.length];
+ double[] avgMemQueriesTTTRatio = new double[xValues.length];
+
+ for (int i = 0; i < xValues.length; i++) {
+ avgMemQueriesLstarRatio[i] = avgMemQueriesLstar[i] / avgMemQueriesLstarLearn[i];
+ avgMemQueriesRSRatio[i] = avgMemQueriesRS[i] / avgMemQueriesRSLearn[i];
+ avgMemQueriesKVRatio[i] = avgMemQueriesKV[i] / avgMemQueriesKVLearn[i];
+ avgMemQueriesOPRatio[i] = avgMemQueriesOP[i] / avgMemQueriesOPLearn[i];
+ avgMemQueriesTTTRatio[i] = avgMemQueriesTTT[i] / avgMemQueriesTTTLearn[i];
+ }
+
+ // Create the third XY chart (membership queries)
+ XYChart chart4 = QuickChart.getChart("Average Membership Queries Ratio", "Lookahead", "Factor (Additional/Base)", seriesNames, xValues, new double[][]{avgMemQueriesLstarRatio, avgMemQueriesRSRatio, avgMemQueriesKVRatio, avgMemQueriesOPRatio, avgMemQueriesTTTRatio});
+ new SwingWrapper(chart4).displayChart();
+
+
+// Create the fourth XY chart (equivalence queries)
+ XYChart chart2 = QuickChart.getChart("Average Equivalence Queries", "Lookahead", "Queries", seriesNames, xValues, new double[][]{avgEqQueriesLstar, avgEqQueriesRS,avgEqQueriesKV, avgEqQueriesOP, avgEqQueriesTTT});
+ new SwingWrapper(chart2).displayChart();
+
+ // Create the fifth XY chart (accuracy)
+ XYChart chart5 = QuickChart.getChart("Accuracy", "Lookahead", "Queries", seriesNames, xValues, new double[][]{accuracyLstar, accuracyRS, accuracyKV, accuracyOP, accuracyTTT});
+ new SwingWrapper(chart5).displayChart();
+ }
+
+ // Define the learning methods
+ public static int learnWithClassicLStarDFA(DFA<?, Integer> dfa, Alphabet<Integer> alphabet, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleLstar, MembershipOracle.DFAMembershipOracle<Integer> memOracleLstar, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle){
+ // Create an instance of the ClassicLStar algorithm
+ ClassicLStarDFA<Integer> learner =
+ new ClassicLStarDFABuilder<Integer>().withAlphabet(alphabet) // input alphabet
+ .withOracle(memOracleLstar) // membership oracle
+ .create();
+
+ // Start the learning process
+ learner.startLearning();
+ // Perform equivalence queries until no counterexample is found
+ DefaultQuery<Integer, Boolean> counterexample;
+ while ((counterexample = eqOracleLstar.findCounterExample(learner.getHypothesisModel(), alphabet)) != null) {
+ learner.refineHypothesis(counterexample);
+ }
+ if((counterexample = controle.findCounterExample(learner.getHypothesisModel(), alphabet)) == null){return 1;}
+ return 0;
+ }
+
+ public static int learnWithRivestShapireDFA(DFA<?, Integer> dfa, Alphabet<Integer> alphabet, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleRS, MembershipOracle.DFAMembershipOracle<Integer> memOracleRS, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle) {
+ // Implement learning with RivestShapireDFA
+ RivestSchapireDFABuilder<Integer> rsBuilder = new RivestSchapireDFABuilder<>();
+ rsBuilder.withAlphabet(alphabet); // input alphabet
+ rsBuilder.withOracle(memOracleRS); // membership oracle
+ RivestSchapireDFA<Integer> learner = rsBuilder.create();
+ learner.startLearning();
+ DefaultQuery<Integer, Boolean> counterexample;
+
+ while ((counterexample = eqOracleRS.findCounterExample(learner.getHypothesisModel(), alphabet)) != null) {
+ learner.refineHypothesis(counterexample);
+ }
+ if((counterexample = controle.findCounterExample(learner.getHypothesisModel(), alphabet)) == null){return 1;}
+ return 0;
+ }
+
+ public static int learnWithKearnsVauiraniDFA(DFA<?, Integer> dfa, Alphabet<Integer> alphabet, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleKV, MembershipOracle.DFAMembershipOracle<Integer> memOracleKV, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle) {
+ KearnsVaziraniDFABuilder<Integer> kol= new KearnsVaziraniDFABuilder<Integer>();
+ kol.withAlphabet(alphabet);
+ kol.withOracle(memOracleKV);
+ kol.withRepeatedCounterexampleEvaluation(true);
+ KearnsVaziraniDFA<Integer> learner = kol.create();
+ learner.startLearning();
+ DefaultQuery<Integer, Boolean> counterexample;
+
+ while ((counterexample = eqOracleKV.findCounterExample(learner.getHypothesisModel(), alphabet)) != null) {
+ learner.refineHypothesis(counterexample);
+ }
+ if((counterexample = controle.findCounterExample(learner.getHypothesisModel(), alphabet)) == null){return 1;}
+ return 0;
+ }
+
+ public static int learnWithOPLearnerDFA(DFA<?, Integer> dfa, Alphabet<Integer> alphabet, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> eqOracleOP, MembershipOracle.DFAMembershipOracle<Integer> memOracleOP, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle) {
+
+ OPLearnerDFABuilder<Integer> opBuilder = new OPLearnerDFABuilder<>();
+ opBuilder.withAlphabet(alphabet);
+ opBuilder.withOracle(memOracleOP);
+ opBuilder.setRepeatedCounterexampleEvaluation(true);
+ OPLearnerDFA<Integer> learner = opBuilder.create();
+
+
+ // Perform equivalence queries until no counterexample is found
+ DefaultQuery<Integer, Boolean> counterexample;
+ learner.startLearning();
+ while ((counterexample = eqOracleOP.findCounterExample(learner.getHypothesisModel(), alphabet)) != null) {
+ learner.refineHypothesis(counterexample);
+ }
+ if((counterexample = controle.findCounterExample(learner.getHypothesisModel(), alphabet)) == null){return 1;}
+ return 0;
+ }
+
+ public static int learnWithTTTLearnerDFA(DFA<?, Integer> dfa, Alphabet<Integer> alphabet, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> oracle, MembershipOracle.DFAMembershipOracle<Integer> mem, EquivalenceOracle<DFA<?, Integer>, Integer, Boolean> controle) {
+ TTTLearnerDFA<Integer> learner =
+ new TTTLearnerDFABuilder<Integer>().withAlphabet(alphabet)
+ .withOracle(mem)
+ .create();
+
+ learner.startLearning();
+
+
+ // Perform equivalence queries until no counterexample is found
+ DefaultQuery counterexample;
+
+ while ((counterexample = oracle.findCounterExample(learner.getHypothesisModel(), alphabet)) != null) {
+ learner.refineHypothesis(counterexample);
+ }
+ if((counterexample = controle.findCounterExample(learner.getHypothesisModel(), alphabet)) == null){return 1;}
+ return 0;
+ }
+
+}