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.algorithms.lstargeneric.mealy;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import net.automatalib.automata.concepts.SuffixOutput;
023import net.automatalib.automata.transout.MealyMachine;
024import net.automatalib.automata.transout.impl.compact.CompactMealy;
025import net.automatalib.automata.transout.impl.compact.CompactMealyTransition;
026import net.automatalib.words.Alphabet;
027import net.automatalib.words.Word;
028import de.learnlib.algorithms.lstargeneric.ExtensibleAutomatonLStar;
029import de.learnlib.algorithms.lstargeneric.ce.ObservationTableCEXHandler;
030import de.learnlib.algorithms.lstargeneric.closing.ClosingStrategy;
031import de.learnlib.algorithms.lstargeneric.table.Row;
032import de.learnlib.api.LearningAlgorithm.MealyLearner;
033import de.learnlib.api.MembershipOracle;
034import de.learnlib.oracles.DefaultQuery;
035
036public class ExtensibleLStarMealy<I, O> extends
037                ExtensibleAutomatonLStar<MealyMachine<?,I,?,O>, I, Word<O>, Integer, CompactMealyTransition<O>, Void, O, CompactMealy<I,O>>
038                implements MealyLearner<I,O> {
039        
040        private final List<O> outputTable
041                = new ArrayList<O>();
042        
043
044        public ExtensibleLStarMealy(Alphabet<I> alphabet,
045                        MembershipOracle<I, Word<O>> oracle,
046                        List<Word<I>> initialSuffixes,
047                        ObservationTableCEXHandler<? super I, ? super Word<O>> cexHandler,
048                        ClosingStrategy<? super I, ? super Word<O>> closingStrategy) {
049                super(alphabet, oracle, new CompactMealy<I,O>(alphabet),
050                                LStarMealyUtil.ensureSuffixCompliancy(initialSuffixes, alphabet, cexHandler.needsConsistencyCheck()),
051                                cexHandler,
052                                closingStrategy);
053        }
054
055        @Override
056        protected Void stateProperty(Row<I> stateRow) {
057                return null;
058        }
059
060        @Override
061        protected O transitionProperty(Row<I> stateRow, int inputIdx) {
062                updateOutputs();
063                Row<I> transRow = stateRow.getSuccessor(inputIdx);
064                return outputTable.get(transRow.getRowId() - 1);
065        }
066
067        @Override
068        protected List<Word<I>> initialSuffixes() {
069                return initialSuffixes;
070        }
071        
072        protected void updateOutputs() {
073                int numOutputs = outputTable.size();
074                int numTransRows = table.numTotalRows() - 1;
075                
076                int newOutputs = numTransRows - numOutputs;
077                if(newOutputs == 0)
078                        return;
079                
080                List<DefaultQuery<I,Word<O>>> outputQueries
081                        = new ArrayList<DefaultQuery<I,Word<O>>>(numOutputs);
082                
083                for(int i = numOutputs+1; i <= numTransRows; i++) {
084                        Row<I> row = table.getRow(i);
085                        Word<I> rowPrefix = row.getPrefix();
086                        int prefixLen = rowPrefix.size();
087                        outputQueries.add(new DefaultQuery<I,Word<O>>(rowPrefix.prefix(prefixLen - 1),
088                                        rowPrefix.suffix(1)));
089                }
090                
091                oracle.processQueries(outputQueries);
092                
093                for(int i = 0; i < newOutputs; i++) {
094                        DefaultQuery<I,Word<O>> query = outputQueries.get(i);
095                        O outSym = query.getOutput().getSymbol(0);
096                        outputTable.add(outSym);
097                }
098        }
099
100        @Override
101        protected MealyMachine<?, I, ?, O> exposeInternalHypothesis() {
102                return internalHyp;
103        }
104        
105        @Override
106        protected SuffixOutput<I,Word<O>> hypothesisOutput() {
107                return internalHyp;
108        }
109
110}