}
}
}
while(pickUniqueFromInitial && uniqueFromInitial == null);
LearnerEvaluationConfiguration learnerEval = new LearnerEvaluationConfiguration(config);learnerEval.setLabelConverter(converter);
final Collection<List<Label>> testSet = PaperUAS.computeEvaluationSet(referenceGraph,states*3,states*alphabet);
for(int attempt=0;attempt<3;++attempt)
{// try learning the same machine a few times
LearnerGraph pta = new LearnerGraph(config);
RandomPathGenerator generator = new RandomPathGenerator(referenceGraph,new Random(attempt),5,referenceGraph.getVertex(Arrays.asList(new Label[]{uniqueFromInitial})));
generator.setWalksShouldLeadToInitialState();
// test sequences will be distributed around
final int pathLength = generator.getPathLength();
final int sequencesPerChunk = PairQualityLearner.makeEven(alphabet*states*traceQuantity);// we are only using one chunk here but the name is unchanged.
// Usually, the total number of elements in test sequences (alphabet*states*traceQuantity) will be distributed around (random(pathLength)+1). The total size of PTA is a product of these two.
// For the purpose of generating long traces, we construct as many traces as there are states but these traces have to be rather long,
// that is, length of traces will be (random(pathLength)+1)*sequencesPerChunk/states and the number of traces generated will be the same as the number of states.
final int tracesToGenerate = 20;//PairQualityLearner.makeEven(states*traceQuantity*3);
final Random rnd = new Random(seed*31+attempt);
generator.generateRandomPosNeg(tracesToGenerate, 1, false, new RandomLengthGenerator() {
@Override
public int getLength() {
return 6;//10*(rnd.nextInt(pathLength)+1)*sequencesPerChunk/tracesToGenerate;
}
@Override
public int getPrefixLength(int len) {
return len;
}
},true,true,null,Arrays.asList(new Label[]{uniqueFromInitial}));
//System.out.println(generator.getAllSequences(0).getData(PTASequenceEngine.truePred));
/*
for(List<Label> seq:referenceGraph.wmethod.computeNewTestSet(1))
{
pta.paths.augmentPTA(seq, referenceGraph.getVertex(seq) != null, false, null);
}*/
//pta.paths.augmentPTA(referenceGraph.wmethod.computeNewTestSet(referenceGraph.getInit(),1));// this one will not set any states as rejects because it uses shouldbereturned
//referenceGraph.pathroutines.completeGraph(referenceGraph.nextID(false));
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));// the PTA will have very few reject-states because we are generating few sequences and hence there will be few negative sequences.
// In order to approximate the behaviour of our case study, we need to compute which pairs are not allowed from a reference graph and use those as if-then automata to start the inference.
/*
synchronized (AbstractLearnerGraph.syncObj) {
PaperUAS.computePTASize(selectionID+" with unique "+uniqueFromInitial+" : ", pta, referenceGraph);
}*/
//Visualiser.updateFrame(referenceGraph, pta);
//Visualiser.waitForKey();
pta.clearColours();
if (!onlyUsePositives)
{
assert pta.getStateNumber() > pta.getAcceptStateNumber() : "graph with only accept states but onlyUsePositives is not set";
Map<Label,Set<Label>> infeasiblePairs = PairQualityLearner.computeInfeasiblePairs(referenceGraph);
Map<Label,Set<Label>> subsetOfPairs = new TreeMap<Label,Set<Label>>();
for(Entry<Label,Set<Label>> entry:infeasiblePairs.entrySet())
{
Set<Label> value = new TreeSet<Label>();
if (!entry.getValue().isEmpty())
{
Label possibleLabels[]=entry.getValue().toArray(new Label[]{});
if (possibleLabels.length == 1)
value.add(possibleLabels[0]);
else
value.add(possibleLabels[rnd.nextInt(possibleLabels.length)]);
}
subsetOfPairs.put(entry.getKey(),value);
}
PairQualityLearner.addIfThenForPairwiseConstraints(learnerEval,subsetOfPairs);
LearnerGraph [] ifthenAutomata = Transform.buildIfThenAutomata(learnerEval.ifthenSequences, null, referenceGraph, learnerEval.config, learnerEval.getLabelConverter()).toArray(new LearnerGraph[0]);
learnerEval.config.setUseConstraints(false);// do not use if-then during learning (refer to the explanation above)
int statesToAdd = 1;// we are adding pairwise constraints hence only one has to be added.
//System.out.println(new Date().toString()+" Graph loaded: "+pta.getStateNumber()+" states ("+pta.getAcceptStateNumber()+" accept states), adding at most "+ statesToAdd+" if-then states");
Transform.augmentFromIfThenAutomaton(pta, null, ifthenAutomata, statesToAdd);// we only need to augment our PTA once (refer to the explanation above).
//System.out.println(new Date().toString()+" Graph augmented: "+pta.getStateNumber()+" states ("+pta.getAcceptStateNumber()+" accept states)");