/** * Selects an unexplored node from the tree to be explored next. * Calculates the constraint [hopefully] leading to the unexplored node it has chosen. * Returns true if an unexplored node was found (then the constraint can be retrieved with getTargetPC()) * and false when we reached the end of the tree. * N.B. in this case there may still be unexplored areas in the following cases: * * They were lower than the current search depth in the tree. * * They were skipped (i.e. the first attempt to explore them failed). * * A previously skipped node was explored "accidentally" by a later run. * * TODO: I think this mehtod assumes there will be at least one branch above any unexplored node. * This means we should only run it on a tree containing at least one trace for now. */ bool DepthFirstSearch::chooseNextTarget() { TraceNodePtr current; // Check if we are starting a new search or continuing an old one. if(mIsPreviousRun){ // Continue the search. // Check if the left/right (according to mPreviousDirection) child of mPreviousParent is still unexplored. // If so, skip it and search for the next unexplored node. // If not, we want to search the newly revealed area before continuing. // ASSUMPTION: if the true/false child of a branch eventually terminates in unexplored (without further branching) then it is immediately unexplored. if(mPreviousDirection){ // We are interested in the 'true' branch of mPreviousParent. current = mPreviousParent->getTrueBranch(); }else{ // We are interested in the 'false' branch of mPreviousParent. current = mPreviousParent->getFalseBranch(); } // The depth, PC, etc. are all already set from the previous call. if(isImmediatelyUnexplored(current)){ // Then the previous run did not reach the intended target. // Use the same method as continueFromLeaf() to jump to the next node to be searched. // If the parent stack is empty here, then we have reached the end of the search. if(mParentStack.empty()){ mFoundTarget = false; return deepenRestartAndChoose(); }else{ current = nextAfterLeaf(); } } }else{ // Strat a new search. current = mTree; } // Call the visitor to continue the search. current->accept(this); // Future runs should continue wherever we left off. mIsPreviousRun = true; // The visitor will set its own "output" in mCurrentPC. // This function returns whether we reached the end of the iteration or not. if(mFoundTarget) { mPreviousPassFoundTarget = true; return true; } else { // Attempt to increase the depth limit and restart, if possible. return deepenRestartAndChoose(); } }
void AvoidUnsatSelector::newTraceAdded(TraceNodePtr node, int branch, TraceNodePtr suffix, TraceNodePtr fullTrace) { // update count for current node TraceSymbolicBranchPtr branchNode = node.dynamicCast<TraceSymbolicBranch>(); if (!branchNode.isNull()) { QPair<QPair<uint, uint>, bool> id = getId(branchNode, branch == 1); this->counts[id].first++; } // process the new trace suffix suffix->accept(this); }
TraceViewerDialog::TraceViewerDialog(TraceNodePtr trace, QWidget* parent) : QDialog(parent), mNodeList(new QListWidget()) { // Set up this dialog setWindowTitle("View Previous Trace"); // Set up the list view used to display the trace items. mNodeList->addItem("Start"); trace->accept(this); // Set up close button QDialogButtonBox* buttonBox = new QDialogButtonBox(); buttonBox->addButton("Close", QDialogButtonBox::AcceptRole); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); // Set up layout/sizing QVBoxLayout* layout = new QVBoxLayout(); layout->addWidget(mNodeList); layout->addWidget(buttonBox); setLayout(layout); setMinimumSize(500, 400); }