if (tracesAlphabetMultiplier <= 0)
tracesAlphabetMultiplier = alphabetMultiplier;
final int alphabet = (int)(alphabetMultiplier*states);
final int tracesAlphabet = (int)(tracesAlphabetMultiplier*states);
LearnerGraph referenceGraph = null;
ThreadResult outcome = new ThreadResult();
MachineGenerator mg = new MachineGenerator(states, 400 , (int)Math.round((double)states/5));mg.setGenerateConnected(true);
referenceGraph = mg.nextMachine(alphabet,seed, config, converter).pathroutines.buildDeterministicGraph();// reference graph has no reject-states, because we assume that undefined transitions lead to reject states.
LearnerEvaluationConfiguration learnerEval = new LearnerEvaluationConfiguration(config);learnerEval.setLabelConverter(converter);
final Collection<List<Label>> testSet = PaperUAS.computeEvaluationSet(referenceGraph,states*3,makeEven(states*tracesAlphabet));
for(int attempt=0;attempt<2;++attempt)
{// try learning the same machine a few times
LearnerGraph pta = new LearnerGraph(config);
RandomPathGenerator generator = new RandomPathGenerator(referenceGraph,new Random(attempt),5,null);
final int tracesToGenerate = makeEven(traceQuantity);
generator.generateRandomPosNeg(tracesToGenerate, 1, false, new RandomLengthGenerator() {
@Override
public int getLength() {
return (int)(traceLengthMultiplier*states*tracesAlphabet);
}
@Override
public int getPrefixLength(int len) {
return len;
}
});
if (onlyUsePositives)
{
pta.paths.augmentPTA(generator.getAllSequences(0).filter(new FilterPredicate() {
@Override
public boolean shouldBeReturned(Object name) {
return ((statechum.analysis.learning.rpnicore.RandomPathGenerator.StateName)name).accept;
}
}));
}
else
pta.paths.augmentPTA(generator.getAllSequences(0));
List<List<Label>> sPlus = generator.getAllSequences(0).getData(new FilterPredicate() {
@Override
public boolean shouldBeReturned(Object name) {
return ((statechum.analysis.learning.rpnicore.RandomPathGenerator.StateName)name).accept;
}
});
List<List<Label>> sMinus= generator.getAllSequences(0).getData(new FilterPredicate() {
@Override
public boolean shouldBeReturned(Object name) {
return !((statechum.analysis.learning.rpnicore.RandomPathGenerator.StateName)name).accept;
}
});
assert sPlus.size() > 0;
assert sMinus.size() > 0;
final MarkovModel m= new MarkovModel(chunkLen,true,true);
m.createMarkovLearner(sPlus, sMinus,false);
pta.clearColours();
if (!onlyUsePositives)
assert pta.getStateNumber() > pta.getAcceptStateNumber() : "graph with only accept states but onlyUsePositives is not set";
else
assert pta.getStateNumber() == pta.getAcceptStateNumber() : "graph with negatives but onlyUsePositives is set";
LearnerMarkovPassive learnerOfPairs = null;
LearnerGraph actualAutomaton = null;
final Configuration deepCopy = pta.config.copy();deepCopy.setLearnerCloneGraph(true);
LearnerGraph ptaCopy = new LearnerGraph(deepCopy);LearnerGraph.copyGraphs(pta, ptaCopy);
LearnerGraph trimmedReference = MarkovPassivePairSelection.trimUncoveredTransitions(pta,referenceGraph);
final ConsistencyChecker checker = new MarkovClassifier.DifferentPredictionsInconsistencyNoBlacklisting();
long inconsistencyForTheReferenceGraph = MarkovClassifier.computeInconsistency(referenceGraph, m, checker,false);
learnerOfPairs = new LearnerMarkovPassive(learnerEval,referenceGraph,pta);learnerOfPairs.setMarkovModel(m);
learnerOfPairs.setScoreComputationOverride(new statechum.analysis.learning.rpnicore.PairScoreComputation.RedNodeSelectionProcedure() {
@SuppressWarnings("unused")
@Override
public CmpVertex selectRedNode(LearnerGraph gr,Collection<CmpVertex> reds, Collection<CmpVertex> tentativeRedNodes)
{
return tentativeRedNodes.iterator().next();
}
@SuppressWarnings("unused")
@Override
public CmpVertex resolvePotentialDeadEnd(LearnerGraph gr, Collection<CmpVertex> reds, List<PairScore> pairs)
{
return null;
}
LearnerGraph coregraph = null;
LearnerGraph extendedGraph = null;
MarkovClassifier cl=null;
@Override
public void initComputation(LearnerGraph graph)
{
coregraph = graph;
cl = new MarkovClassifier(m, coregraph);
extendedGraph = cl.constructMarkovTentative();
}
@Override
public long overrideScoreComputation(PairScore p)
{
long pairScore = p.getScore();
if (pairScore >= 0)
pairScore = MarkovScoreComputation.computenewscore(p, extendedGraph);
return pairScore;
}
/** This one returns a set of transitions in all directions. */
@SuppressWarnings("unused")
@Override
public Collection<Entry<Label, CmpVertex>> getSurroundingTransitions(CmpVertex currentRed)
{
return null;
}
});
actualAutomaton = learnerOfPairs.learnMachine(new LinkedList<List<Label>>(),new LinkedList<List<Label>>());
SampleData dataSample = new SampleData(null,null);
//dataSample.difference = new DifferenceToReferenceDiff(0, 0);
//dataSample.differenceForReferenceLearner = new DifferenceToReferenceDiff(0, 0);
VertID rejectVertexID = null;
for(CmpVertex v:actualAutomaton.transitionMatrix.keySet())
if (!v.isAccept())
{
assert rejectVertexID == null : "multiple reject vertices in learnt automaton, such as "+rejectVertexID+" and "+v;
rejectVertexID = v;break;
}
if (rejectVertexID == null)
rejectVertexID = actualAutomaton.nextID(false);
actualAutomaton.pathroutines.completeGraphPossiblyUsingExistingVertex(rejectVertexID);// we need to complete the graph, otherwise we are not matching it with the original one that has been completed.
dataSample.actualLearner = estimateDifference(referenceGraph,actualAutomaton,testSet);
dataSample.actualLearner.inconsistency = MarkovClassifier.computeInconsistency(actualAutomaton, m, checker,false);
dataSample.referenceLearner = zeroScore;
LearnerGraph outcomeOfReferenceLearner = new LearnerGraph(config);
try
{
outcomeOfReferenceLearner = //new ReferenceLearnerUsingSiccoScoring(learnerEval,ptaCopy,false).learnMachine(new LinkedList<List<Label>>(),new LinkedList<List<Label>>());
new EDSMReferenceLearner(learnerEval,ptaCopy,2).learnMachine(new LinkedList<List<Label>>(),new LinkedList<List<Label>>());
dataSample.referenceLearner = estimateDifference(referenceGraph, outcomeOfReferenceLearner,testSet);
dataSample.referenceLearner.inconsistency = MarkovClassifier.computeInconsistency(outcomeOfReferenceLearner, m, checker,false);
}
catch(LearnerAbortedException ex)
{// the exception is thrown because the learner failed to learn anything completely. Ignore it because the default score is zero assigned via zeroScore.
}
dataSample.fractionOfStatesIdentifiedBySingletons=Math.round(100*MarkovClassifier.calculateFractionOfStatesIdentifiedBySingletons(referenceGraph));
dataSample.stateNumber = referenceGraph.getStateNumber();
dataSample.transitionsSampled = Math.round(100*trimmedReference.pathroutines.countEdges()/referenceGraph.pathroutines.countEdges());
statechum.Pair<Double,Double> correctnessOfMarkov = new MarkovClassifier(m, referenceGraph).evaluateCorrectnessOfMarkov();
dataSample.markovPrecision = Math.round(100*correctnessOfMarkov.firstElem);dataSample.markovRecall = Math.round(100*correctnessOfMarkov.secondElem);
Collection<List<Label>> wset=WMethod.computeWSet_reducedw(referenceGraph);
int wSeqLen=0;
for(List<Label> seq:wset)
{
int len = seq.size();if (len > wSeqLen) wSeqLen=len;
}
System.out.println("actual: "+actualAutomaton.getStateNumber()+" from reference learner: "+outcomeOfReferenceLearner.getStateNumber()+
" difference actual is "+dataSample.actualLearner.inconsistency+ " difference ref is "+dataSample.referenceLearner.inconsistency
+ " inconsistency learnt "+dataSample.actualLearner.inconsistency+" inconsistency reference: "+inconsistencyForTheReferenceGraph
+" transitions per state: "+(double)referenceGraph.pathroutines.countEdges()/referenceGraph.getStateNumber()+
" W seq max len "+wSeqLen+
" Uniquely identifiable by W "+Math.round(100*MarkovClassifier.calculateFractionOfIdentifiedStates(referenceGraph, wset))+" %"