All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.learnlib.eqtests.basic.RandomWordsEQOracle Maven / Gradle / Ivy

There is a newer version: 0.12.0
Show newest version
/* Copyright (C) 2014 TU Dortmund
 * This file is part of LearnLib, http://www.learnlib.de/.
 * 
 * LearnLib is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 3.0 as published by the Free Software Foundation.
 * 
 * LearnLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with LearnLib; if not, see
 * .
 */
package de.learnlib.eqtests.basic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.logging.Logger;

import net.automatalib.automata.concepts.OutputAutomaton;
import net.automatalib.automata.fsa.DFA;
import net.automatalib.automata.transout.MealyMachine;
import net.automatalib.words.Word;
import net.automatalib.words.WordBuilder;
import de.learnlib.api.EquivalenceOracle;
import de.learnlib.api.MembershipOracle;
import de.learnlib.oracles.DefaultQuery;

/**
 *
 * @author Maik Merten
 */
public class RandomWordsEQOracle> implements EquivalenceOracle {

	public static class DFARandomWordsEQOracle extends RandomWordsEQOracle>
			implements DFAEquivalenceOracle {
		public DFARandomWordsEQOracle(MembershipOracle mqOracle,
				int minLength, int maxLength, int maxTests, Random random) {
			super(mqOracle, minLength, maxLength, maxTests, random);
		}
		public DFARandomWordsEQOracle(MembershipOracle mqOracle,
				int minLength, int maxLength, int maxTests, Random random, int batchSize) {
			super(mqOracle, minLength, maxLength, maxTests, random, batchSize);
		}
	}
	
	public static class MealyRandomWordsEQOracle extends RandomWordsEQOracle,MealyMachine>
			implements MealyEquivalenceOracle {
		public MealyRandomWordsEQOracle(MembershipOracle> mqOracle,
				int minLength, int maxLength, int maxTests, Random random) {
			super(mqOracle, minLength, maxLength, maxTests, random);
		}
		public MealyRandomWordsEQOracle(MembershipOracle> mqOracle,
				int minLength, int maxLength, int maxTests, Random random, int batchSize) {
			super(mqOracle, minLength, maxLength, maxTests, random, batchSize);
		}
	}

	private static final Logger LOGGER = Logger.getLogger(RandomWordsEQOracle.class.getName());

	private MembershipOracle oracle;
	private int maxTests, minLength, maxLength;
	private final Random random;
	private final int batchSize;

	public RandomWordsEQOracle(MembershipOracle mqOracle, int minLength, int maxLength, int maxTests, Random random, int batchSize) {
		this.oracle = mqOracle;
		this.maxTests = maxTests;
		this.minLength = minLength;
		this.maxLength = maxLength;
		this.random = random;
		this.batchSize = batchSize;
	}

	public RandomWordsEQOracle(MembershipOracle mqOracle, int minLength, int maxLength, int maxTests, Random random) {
		this(mqOracle, minLength, maxLength, maxTests, random, 1);
	}

	@Override
	public DefaultQuery findCounterExample(A hypothesis, Collection inputs) {
		// Fail fast on empty inputs
		if(inputs.isEmpty()) {
			LOGGER.warning("Passed empty set of inputs to equivalence oracle; no counterexample can be found!");
			return null;
		}
		
		List symbolList;
		if (inputs instanceof List) {
			symbolList = (List) inputs;
		} else {
			symbolList = new ArrayList<>(inputs);
		}
		
		int numSyms = symbolList.size();

		final Collection> queryBatch = new ArrayList<>(batchSize);

		for (int i = 0; i < maxTests; ++i) {
			int length = minLength + random.nextInt((maxLength - minLength) + 1);

			WordBuilder testtrace = new WordBuilder<>(length);
			for (int j = 0; j < length; ++j) {
				int symidx = random.nextInt(numSyms);
				I sym = symbolList.get(symidx);
				testtrace.append(sym);
			}

			final DefaultQuery query = new DefaultQuery<>(testtrace.toWord());
			queryBatch.add(query);
			
			final boolean batchFilled = queryBatch.size() >= batchSize;
			final boolean maxTestsReached = i >= maxTests - 1;

			if(batchFilled || maxTestsReached) {
				// query oracle
				oracle.processQueries(queryBatch);

				for (final DefaultQuery ioQuery : queryBatch) {
					D oracleoutput = ioQuery.getOutput();

					// trace hypothesis
					D hypOutput = hypothesis.computeOutput(ioQuery.getInput());

					// compare output of hypothesis and oracle
					if (!Objects.equals(oracleoutput, hypOutput)) {
						return ioQuery;
					}
				}

				queryBatch.clear();
			}
		}

		// no counterexample found
		return null;
	}
}