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.cache.dfa; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.List; 022 023import net.automatalib.incremental.dfa.Acceptance; 024import net.automatalib.incremental.dfa.IncrementalDFABuilder; 025import net.automatalib.words.Alphabet; 026import de.learnlib.api.MembershipOracle; 027import de.learnlib.api.Query; 028 029 030/** 031 * DFA cache. This cache is implemented as a membership oracle: upon construction, it is 032 * provided with a delegate oracle. Queries that can be answered from the cache are answered 033 * directly, others are forwarded to the delegate oracle. When the delegate oracle has finished 034 * processing these remaining queries, the results are incorporated into the cache. 035 * 036 * @author Malte Isberner <malte.isberner@gmail.com> 037 * 038 * @param <I> input symbol class 039 */ 040public class DFACacheOracle<I> implements MembershipOracle<I, Boolean> { 041 042 private final IncrementalDFABuilder<I> incDfa; 043 private final MembershipOracle<I,Boolean> delegate; 044 045 /** 046 * Constructor. 047 * @param alphabet the alphabet of the cache 048 * @param delegate the delegate oracle 049 */ 050 public DFACacheOracle(Alphabet<I> alphabet, MembershipOracle<I,Boolean> delegate) { 051 this.incDfa = new IncrementalDFABuilder<>(alphabet); 052 this.delegate = delegate; 053 } 054 055 public int getCacheSize() { 056 return incDfa.size(); 057 } 058 059 /** 060 * Creates an equivalence oracle that checks an hypothesis for consistency with the 061 * contents of this cache. Note that the returned oracle is backed by the cache data structure, 062 * i.e., it is sufficient to call this method once after creation of the cache. 063 * @return the cache consistency test backed by the contents of this cache. 064 */ 065 public DFACacheConsistencyTest<I> createCacheConsistencyTest() { 066 return new DFACacheConsistencyTest<>(incDfa); 067 } 068 069 /* 070 * (non-Javadoc) 071 * @see de.learnlib.api.MembershipOracle#processQueries(java.util.Collection) 072 */ 073 @Override 074 public void processQueries(Collection<? extends Query<I, Boolean>> queries) { 075 List<ProxyQuery<I>> unanswered = new ArrayList<>(); 076 077 for(Query<I,Boolean> q : queries) { 078 Acceptance acc = incDfa.lookup(q.getInput()); 079 if(acc != Acceptance.DONT_KNOW) 080 q.answer((acc == Acceptance.TRUE) ? true : false); 081 else 082 unanswered.add(new ProxyQuery<>(q)); 083 } 084 085 delegate.processQueries(unanswered); 086 087 for(ProxyQuery<I> q : unanswered) 088 incDfa.insert(q.getInput(), q.getAnswer()); 089 } 090 091}