throw new IllegalArgumentException(getHardFactsContradictionErrorMessage(ifthenAutomataAsText, sr.getCounters()));
}
Stack<PairScore> possibleMerges = topLevelListener.ChooseStatePairs(getTentativeAutomaton());
int iterations = 0, currentNonAmber = ptaHardFacts.getStateNumber()-ptaHardFacts.getAmberStateNumber();
JUConstants colourToAugmentWith = getTentativeAutomaton().config.getUseAmber()? JUConstants.AMBER:null;
updateGraph(getTentativeAutomaton(),ptaHardFacts);
while (!possibleMerges.isEmpty())
{
iterations++;
PairScore pair = possibleMerges.pop();
final LearnerGraph temp = topLevelListener.MergeAndDeterminize(getTentativeAutomaton(), pair);
Collection<List<Label>> questions = new LinkedList<List<Label>>();
long score = pair.getScore();
RestartLearningEnum restartLearning = RestartLearningEnum.restartNONE;// whether we need to rebuild a PTA and restart learning.
if (getTentativeAutomaton().config.getUseLTL() && getTentativeAutomaton().config.getUseSpin() && !ifthenAutomataAsText.isEmpty()){
Collection<List<Label>> counterExamples = spin.check(temp, getTentativeAutomaton(), ifthenAutomataAsText).getCounters();
Iterator<List<Label>> counterExampleIt = counterExamples.iterator();
while(counterExampleIt.hasNext())
{
List<Label> counterExample = counterExampleIt.next();
topLevelListener.AugmentPTA(ptaSoftFacts, RestartLearningEnum.restartSOFT, counterExample, false,colourToAugmentWith);
System.out.println("<temp> "+counterExample);
}
if(counterExamples.size()>0)
restartLearning = RestartLearningEnum.restartSOFT;
}
if (config.isUseConstraints())
{
LearnerGraph updatedTentativeAutomaton = new LearnerGraph(shallowCopy);
StringBuffer counterExampleHolder = new StringBuffer();
if (!topLevelListener.AddConstraints(temp,updatedTentativeAutomaton,counterExampleHolder))
{
getTentativeAutomaton().addToCompatibility(pair.firstElem, pair.secondElem, PAIRCOMPATIBILITY.INCOMPATIBLE);
restartLearning = RestartLearningEnum.restartRECOMPUTEPAIRS;
System.out.println("<info> pair "+pair+" contradicts constraints, hence recorded as incompatible");
}
// since we still need the outcome of merging to ask questions,
// we delay actually performing augmentation until the time we are
// finished with questions.
}
Iterator<List<Label>> questionIt = null;
if (restartLearning == RestartLearningEnum.restartNONE)
{
Map<CmpVertex,JUConstants.PAIRCOMPATIBILITY> compatibilityMap = ptaHardFacts.pairCompatibility.compatibility.get(pair.getQ());
if (pair.getScore() > config.getScoreForAutomergeUponRestart() && compatibilityMap != null && compatibilityMap.get(pair.getR()) == JUConstants.PAIRCOMPATIBILITY.MERGED)
System.out.println("<automerge of previously merged pair> "+pair);
else
{
// ask questions if needed
if (shouldAskQuestions(score))
{
temp.setName(getGraphName()+"_"+iterations);
//LearnerGraph updatedGraphActual = ComputeQuestions.constructGraphWithQuestions(pair, tentativeAutomaton, temp);
//updatedGraphActual.setName(getGraphName(config)+"questions "+iterations);setChanged();updateGraph(updatedGraphActual,ptaHardFacts);
questions = topLevelListener.ComputeQuestions(pair, getTentativeAutomaton(), temp);// all answers are considered "hard", hence we have to ask questions based on hard facts in order to avoid prefixes which are not valid in hard facts
questionIt = questions.iterator();
if (questionIt.hasNext())
{
pair.firstElem.setHighlight(true);
pair.secondElem.setHighlight(true);
updateGraph(getTentativeAutomaton(),ptaHardFacts);
pair.firstElem.setHighlight(false);
pair.secondElem.setHighlight(false);
}
}
}
}
while (restartLearning == RestartLearningEnum.restartNONE && questionIt != null && questionIt.hasNext())
{
List<Label> question = questionIt.next();
boolean accepted = pair.getQ().isAccept();
Pair<Integer,String> answer = null;
if (getTentativeAutomaton().config.getUseLTL() && getTentativeAutomaton().config.getUseSpin() && !ifthenAutomataAsText.isEmpty())
answer = new Pair<Integer,String>(spin.check(question, ifthenAutomataAsText),null);
CmpVertex tempVertex = temp.getVertex(question);
boolean answerFromSpin = false;
if(answer != null && answer.firstElem >= 0)
answerFromSpin = true;
else
{
if (GlobalConfiguration.getConfiguration().isAssertEnabled())
if (ptaHardFacts.paths.tracePathPrefixClosed(question) == AbstractOracle.USER_ACCEPTED) {
throw new IllegalArgumentException("question "+ question+ " has already been answered");
}
List<Boolean> acceptedElements = PathRoutines.mapPathToConfirmedElements(ptaHardFacts,question,ifthenAutomata);
answer = topLevelListener.CheckWithEndUser(getTentativeAutomaton(), question,
tempVertex.isAccept()?AbstractOracle.USER_ACCEPTED:question.size() - 1,
acceptedElements, pair,
new Object[] { "LTL","IFTHEN","IGNORE QUESTION","MARK AS INCOMPATIBLE","Add trace"});
}
if (answer.firstElem == AbstractOracle.USER_CANCELLED)
{
System.out.println("CANCELLED");
return null;
}
else
if (answer.firstElem == AbstractOracle.USER_IGNORED)
{// do nothing
restartLearning = RestartLearningEnum.restartNONE;
}
else
if (answer.firstElem == AbstractOracle.USER_INCOMPATIBLE)
{
/* When autoanswers says that a particular pair is incompatible, <em>StoredAnswers</em> the answer refers to the current
* question, but we have to return a pair which is incompatible. Although strange, it is not really surprising - the whole
* AutoAnswers framework aims to automate debugging hence we are expected to go through the same sequence of questions
* over and over again - it is enough to validate that we do not deviate and hence all that is necessary is to check that
* the current pair to be merged is the same as the one recorded as incompatible when an answer was recorded.
*/
getTentativeAutomaton().addToCompatibility(pair.firstElem, pair.secondElem, PAIRCOMPATIBILITY.INCOMPATIBLE);
restartLearning = RestartLearningEnum.restartRECOMPUTEPAIRS;
}
else
if (answer.firstElem == AbstractOracle.USER_NEWTRACE)
{
String traceDescr = answer.secondElem;
boolean obtainedViaAuto = answer.secondElem != null;
if (traceDescr == null) traceDescr = JOptionPane.showInputDialog("New trace :");
if(traceDescr != null && traceDescr.length() != 0)
{
final JUConstants colour = colourToAugmentWith;
final AtomicBoolean whetherToRestart = new AtomicBoolean(false);
QSMTool.parseSequenceOfTraces(traceDescr, config, new TraceAdder() {
@Override
public void addTrace(List<Label> trace, boolean positive) {