001/* Copyright (C) 2013 TU Dortmund 002 * This file is part of LearnLib, http://www.learnlib.de/. 003 * 004 * LearnLib is free software; you can redistribute it and/or 005 * modify it under the terms of the GNU Lesser General Public 006 * License version 3.0 as published by the Free Software Foundation. 007 * 008 * LearnLib is distributed in the hope that it will be useful, 009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 011 * Lesser General Public License for more details. 012 * 013 * You should have received a copy of the GNU Lesser General Public 014 * License along with LearnLib; if not, see 015 * <http://www.gnu.de/documents/lgpl.en.html>. 016 */ 017package de.learnlib.experiments; 018 019import net.automatalib.automata.fsa.DFA; 020import net.automatalib.automata.transout.MealyMachine; 021import net.automatalib.words.Alphabet; 022import net.automatalib.words.Word; 023import de.learnlib.api.EquivalenceOracle; 024import de.learnlib.api.LearningAlgorithm; 025import de.learnlib.logging.LearnLogger; 026import de.learnlib.oracles.DefaultQuery; 027import de.learnlib.statistics.Counter; 028import de.learnlib.statistics.SimpleProfiler; 029 030/** 031 * runs a learning experiment. 032 * 033 * @author falkhowar 034 * @param <A> 035 * @param <I> 036 * @param <O> 037 */ 038public class Experiment<A> { 039 040 public static class DFAExperiment<I> extends Experiment<DFA<?,I>> { 041 public DFAExperiment( 042 LearningAlgorithm<? extends DFA<?, I>, I, Boolean> learningAlgorithm, 043 EquivalenceOracle<? super DFA<?, I>, I, Boolean> equivalenceAlgorithm, 044 Alphabet<I> inputs) { 045 super(learningAlgorithm, equivalenceAlgorithm, inputs); 046 } 047 } 048 049 public static class MealyExperiment<I,O> extends Experiment<MealyMachine<?,I,?,O>> { 050 public MealyExperiment( 051 LearningAlgorithm<? extends MealyMachine<?, I, ?, O>, I, Word<O>> learningAlgorithm, 052 EquivalenceOracle<? super MealyMachine<?, I, ?, O>, I, Word<O>> equivalenceAlgorithm, 053 Alphabet<I> inputs) { 054 super(learningAlgorithm, equivalenceAlgorithm, inputs); 055 } 056 057 } 058 059 private final class ExperimentImpl<I,O> { 060 private final LearningAlgorithm<? extends A, I, O> learningAlgorithm; 061 private final EquivalenceOracle<? super A, I, O> equivalenceAlgorithm; 062 private final Alphabet<I> inputs; 063 064 public ExperimentImpl(LearningAlgorithm<? extends A, I, O> learningAlgorithm, EquivalenceOracle<? super A, I, O> equivalenceAlgorithm, Alphabet<I> inputs) { 065 this.learningAlgorithm = learningAlgorithm; 066 this.equivalenceAlgorithm = equivalenceAlgorithm; 067 this.inputs = inputs; 068 } 069 070 public A run() { 071 rounds.increment(); 072 logger.logPhase("Starting round " + rounds.getCount()); 073 logger.logPhase("Learning"); 074 profileStart("Learning"); 075 learningAlgorithm.startLearning(); 076 profileStop("Learning"); 077 078 boolean done = false; 079 A hyp = null; 080 while (!done) { 081 hyp = learningAlgorithm.getHypothesisModel(); 082 if (logModels) { 083 logger.logModel(hyp); 084 } 085 086 logger.logPhase("Searching for counterexample"); 087 profileStart("Searching for counterexample"); 088 DefaultQuery<I, O> ce = equivalenceAlgorithm.findCounterExample(hyp, inputs); 089 if (ce == null) { 090 done = true; 091 continue; 092 } 093 profileStop("Searching for counterexample"); 094 095 logger.logCounterexample(ce.getInput().toString()); 096 097 // next round ... 098 rounds.increment(); 099 logger.logPhase("Starting round " + rounds.getCount()); 100 logger.logPhase("Learning"); 101 profileStart("Learning"); 102 learningAlgorithm.refineHypothesis(ce); 103 profileStop("Learning"); 104 } 105 106 return hyp; 107 } 108 } 109 110 private static LearnLogger logger = LearnLogger.getLogger(Experiment.class); 111 112 private boolean logModels = false; 113 private boolean profile = false; 114 private Counter rounds = new Counter("rounds", "#"); 115 private A finalHypothesis = null; 116 private final ExperimentImpl<?,?> impl; 117 118 public <I,O> Experiment(LearningAlgorithm<? extends A, I, O> learningAlgorithm, EquivalenceOracle<? super A, I, O> equivalenceAlgorithm, Alphabet<I> inputs) { 119 this.impl = new ExperimentImpl<>(learningAlgorithm, equivalenceAlgorithm, inputs); 120 } 121 122 123 124 /** 125 * 126 */ 127 public A run() { 128 finalHypothesis = impl.run(); 129 return finalHypothesis; 130 } 131 132 public A getFinalHypothesis() { 133 return finalHypothesis; 134 } 135 136 137 138 private void profileStart(String taskname) { 139 if (profile) { 140 SimpleProfiler.start(taskname); 141 } 142 } 143 144 private void profileStop(String taskname) { 145 if (profile) { 146 SimpleProfiler.stop(taskname); 147 } 148 } 149 150 /** 151 * @param logModels the logModels to set 152 */ 153 public void setLogModels(boolean logModels) { 154 this.logModels = logModels; 155 } 156 157 /** 158 * @param profile the profile to set 159 */ 160 public void setProfile(boolean profile) { 161 this.profile = profile; 162 } 163 164 /** 165 * @return the rounds 166 */ 167 public Counter getRounds() { 168 return rounds; 169 } 170}