Example #1
0
int TransitionGraph::eliminateBackEdges() {
    const EState* startState=getStartEState();
    set<const EState*> visited;
    visited.insert(startState);
    TransitionPtrSet backEdges; // default empty
    determineBackEdges(startState, visited, backEdges);
    for(TransitionPtrSet::iterator i=backEdges.begin(); i!=backEdges.end(); ++i) {

    }
    return backEdges.size();
}
Example #2
0
void TransitionGraph::determineBackEdges(const EState* state, set<const EState*>& visited, TransitionPtrSet& tpSet) {
    TransitionPtrSet succPtrs=outEdges(state);
    for(TransitionPtrSet::iterator i=succPtrs.begin(); i!=succPtrs.end(); ++i) {
        if(visited.find((*i)->target)!=visited.end()) {
            // target node exists in visited-set
            tpSet.insert(*i);
            return;
        }
        visited.insert((*i)->target);
        determineBackEdges((*i)->target,visited,tpSet);
    }
    return;
}
Example #3
0
/*!
  * \author Markus Schordan
  * \date 2012.
 */
void TransitionGraph::reduceEState2(const EState* estate) {
    /* description of essential operations:
     *   inedges: (n_i,b)
     *   outedges: (b,n_j)
     *   insert(ni,t,nj) where t=union(t(n_i))+union(t(n_j))+{EDGE_PATH}
     *   remove(n_i,b)
     *   remove(b,n_j)
     *   delete b

     * ea: (n1,cfge,n2) == ((l1,p1,c1,io1),(l1,t12,l2),(l2,p2,c2,io2))
     * eb: (n2,cfge,n3) == ((l2,p2,c2,io2),(l2,t23,l3),(l3,p3,c3,io3))
     * ==> (n1,cfge',n3) == ((l1,p1,c1,io1),(l1,{t12,t13,EDGE_PATH}},l3),(l3,p3,c3,io3))

     */
    ROSE_ASSERT(estate);
    // check self-edge
    if(const Transition* trans=hasSelfEdge(estate)) {
        this->erase(*trans);
    }
    TransitionGraph::TransitionPtrSet in=inEdges(estate);
    TransitionGraph::TransitionPtrSet out=outEdges(estate);
    if(in.size()!=0 && out.size()!=0 ) {
        set<Transition> newTransitions;
        for(TransitionPtrSet::iterator i=in.begin(); i!=in.end(); ++i) {
            for(TransitionPtrSet::iterator j=out.begin(); j!=out.end(); ++j) {
                if((*i)->source!=estate && (*j)->target!=estate) {
                    Edge newEdge((*i)->source->label(),EDGE_PATH,(*j)->target->label());
                    Transition t((*i)->source,newEdge,(*j)->target);
                    newTransitions.insert(t);
                    //assert(newTransitions.find(t)!=newTransitions.end());
                }
            }
        }
        //cout << "DEBUG: number of new transitions: "<<newTransitions.size()<<endl;

        TransitionPtrSet all=in;
        for(TransitionPtrSet::iterator j=out.begin(); j!=out.end(); ++j) {
            all.insert(*j);
        }
        // 1. remove all old transitions
        for(TransitionPtrSet::iterator i=all.begin(); i!=all.end(); ++i) {
            this->erase(**i);
        }

        // 2. add new transitions
        for(set<Transition>::iterator k=newTransitions.begin(); k!=newTransitions.end(); ++k) {
            //check if a single transition to the target already exists, delete this shorter path
            TransitionPtrSet outEdgesTransSource = outEdges((*k).source);
            for (TransitionPtrSet::iterator iter = outEdgesTransSource.begin(); iter != outEdgesTransSource.end(); ++iter) {
                if ((*iter)->target == (*k).target) {
                    erase(**iter);
                }
            }
            this->add(*k);
            //assert(find(*k)!=end());
        }
        eliminateEState(estate);
        assert(newTransitions.size()<=in.size()*out.size());
    } else {
        // need to eliminate node instead
        eliminateEState(estate);
    }
}
Example #4
0
PropertyValueTable* CounterexampleAnalyzer::cegarPrefixAnalysisForLtl(int property, SpotConnection& spotConnection, 
									set<int> ltlInAlphabet, set<int> ltlOutAlphabet) {
  // visualizer for in-depth model outputs (.dot files)
  Visualizer visualizer(_analyzer->getLabeler(),_analyzer->getVariableIdMapping(),
                          _analyzer->getFlow(),_analyzer->getPStateSet(),_analyzer->getEStateSet(),_analyzer->getTransitionGraph());
  string vizFilenamePrefix = "";
  if(args.count("viz-cegpra-detailed")) {
    vizFilenamePrefix=args["viz-cegpra-detailed"].as<string>();
    string filename = vizFilenamePrefix + "_cegpra_init.dot";
    writeDotGraphToDisk(filename, visualizer);
  }
  // OVERVIEW
  // (0) check if the initial model already satsifies the property
  // (0.5) initialization
  // (while (property != satisfied)) do
  //   (1) Disconnect the concrete prefix (initially the start state) from the over-approx. part of the model
  //   (2) Anaylze the most recent counterexample while adding the trace of the original program to the prefix part of the model
  //       If the counterexample is real: reconnect once more to determine the model's size, ESCAPE the loop and return results 
  //   (3) Reconnect both parts of the model
  //   (4) Check the property on the now slightly refined model
  // od
  // (5) return results;
  cout << "STATUS: CEGPRA is now analyzing LTL property " << property << "..." << endl;
  if (_csvOutput) {
    (*_csvOutput) << endl << property << ",";
  }
  TransitionGraph* model = _analyzer->getTransitionGraph();
  assert(model->isComplete());
  // (0) check if the given property already holds on the initial over-approximated model
  PropertyValueTable* currentResults = spotConnection.getLtlResults();
  if (currentResults->getPropertyValue(property) != PROPERTY_VALUE_UNKNOWN) {
    cout << "STATUS: property " << property << " was already analyzed. CEGAR analysis will not be started." << endl;
    return currentResults;
  }
  spotConnection.checkSingleProperty(property, *model, ltlInAlphabet, ltlOutAlphabet, true, true);
  currentResults = spotConnection.getLtlResults();
  // (0.5) prepare for the continuous tracing of concrete states (will become the prefix of a refined abstract model)
  // store connectors in the over-approx. part of the model (single row of input states in the initial "topified" model)
  const EState* startEState = model->getStartEState();
  pair<EStatePtrSet, EStatePtrSet> concOutputAndAbstrInput = getConcreteOutputAndAbstractInput(model); 
  EStatePtrSet startAndOuputStatesPrefix = concOutputAndAbstrInput.first;
  vector<const EState*> firstInputOverApprox(ltlInAlphabet.size());
  firstInputOverApprox = sortAbstractInputStates(firstInputOverApprox, concOutputAndAbstrInput.second);
  int loopCount = 0;
  bool falsified = false;
  bool verified = true;   // the usual case for the loop below to terminate is a verified property.
  string ce = "no counterexample yet";
  // as long as the property is not satisfiable yet, refine by enlarging the prefix of concrete states according to counterexamples
  while (currentResults->getPropertyValue(property) != PROPERTY_VALUE_YES) { 
    if (_maxCounterexamples > -1 && (loopCount + 1) > _maxCounterexamples) {
      verified = false;
      spotConnection.resetLtlResults(property);
      break;
    }
    loopCount++;
    if (loopCount % 50 == 0) {
      cout << "STATUS: " << loopCount << " counterexamples analyzed. most recent counterexample: " << endl;
      cout << ce << endl;
    }
    // (1) disconnect prefix and over-approx. part of the model
    model->setIsComplete(false);
    for (unsigned int i = 0; i < firstInputOverApprox.size(); i++) {
       TransitionPtrSet connectionsToPrefix = model->inEdges(firstInputOverApprox[i]);
       for (TransitionPtrSet::iterator k=connectionsToPrefix.begin(); k!=connectionsToPrefix.end(); ++k) {
         // check if predeccesor at the source of that transition is a concrete (prefix) state
         if ( !(*k)->source->isRersTopified(_analyzer->getVariableIdMapping()) ) {
           model->erase(**k);
         }
       }
    }
    model->setIsPrecise(true);
    if(args.count("viz-cegpra-detailed")) {
      stringstream filenameStream;
      filenameStream << vizFilenamePrefix << "cegpra_afterDisconnect_i" << loopCount << ".dot";
      writeDotGraphToDisk(filenameStream.str(), visualizer);
    }
    // (2) add a trace to the prefix according to the most recent counterexample. Analyze the counterexample while adding the trace.
    ce = currentResults->getCounterexample(property);
    //cout << "STATUS: counterexample: " << ce << endl;
    CEAnalysisResult ceaResult = analyzeCounterexample(ce, startEState, false, false);
    if (ceaResult.analysisResult == CE_TYPE_REAL) {
      // still reconnect the concrete prefix with the over-approx. part of the model (step (3)) in order to report the size.
      falsified = true;
      verified = false;
    } else if (ceaResult.analysisResult == CE_TYPE_SPURIOUS) {
      if(!boolOptions["keep-error-states"]) {
        // remove a trace leading to an error state and mark the branches to it (do not reconnect in phase 3) 
        removeAndMarkErroneousBranches(model);
      }
      //the trace eliminating the spurious counterexample (maybe including a few extra states) was added to the prefix during analysis.
      // --> nothing to do here
    } else {
      assert(0);  //counterexample analysis not successfully completed
    }
    if(args.count("viz-cegpra-detailed")) {
      stringstream filenameStream;
      filenameStream << vizFilenamePrefix << "cegpra_afterCECheck_i" << loopCount << ".dot";
      writeDotGraphToDisk(filenameStream.str(), visualizer);
    }
    // (3) reconnect both parts of the model
    model->setIsPrecise(false);
    //update set of output states (plus start state) in the precise prefix
    addAllPrefixOutputStates(startAndOuputStatesPrefix, model);
    for (set<const EState*>::iterator i=startAndOuputStatesPrefix.begin(); i!=startAndOuputStatesPrefix.end(); ++i) {
      vector<bool> inputSuccessors(ltlInAlphabet.size(), false);
      if(!boolOptions["keep-error-states"]) {
        inputSuccessors = setErrorBranches(inputSuccessors, *i); 
      }
      // determine which input states exist as successors in the prefix
      inputSuccessors = hasFollowingInputStates(inputSuccessors, *i, model);
      //connect with the approx. part of the model for all input values not found among the successor states
      for (unsigned int k = 0; k < inputSuccessors.size(); k++) {
        if (!inputSuccessors[k]) {
          Edge newEdge;
          model->add(Transition((*i), newEdge, firstInputOverApprox[k]));
        }
      }
    }
    model->setIsComplete(true);
    if(args.count("viz-cegpra-detailed")) {
      stringstream filenameStream;
      filenameStream << vizFilenamePrefix << "cegpra_afterReconnect_i" << loopCount << ".dot";
      writeDotGraphToDisk(filenameStream.str(), visualizer);
    }
    // if falsified: after reconnecting, leave the analysis loop, report size of the model and return the results
    if (falsified) {
      break;
    }
    // (4) check if the property holds on the refined model
    spotConnection.resetLtlResults(property);
    spotConnection.checkSingleProperty(property, *model, ltlInAlphabet, ltlOutAlphabet, true, true);
    currentResults = spotConnection.getLtlResults();
  }
  // (5) check all properties using the current model and return the result
  spotConnection.checkLtlProperties(*model, ltlInAlphabet, ltlOutAlphabet, true, false);
  currentResults = spotConnection.getLtlResults();
  printStgSizeAndCeCount(model, loopCount, property);
  if (_csvOutput) {
    if (verified && !falsified)
      (*_csvOutput) << "y,";
    if (!verified && falsified)
      (*_csvOutput) << "n,";
    if (!verified && !falsified)
      (*_csvOutput) << "?,";
    if (verified && falsified) {
      cout << "ERROR: property can not be both verified and falsified. " << endl;
      assert(0);
    }
    (*_csvOutput) << currentResults->entriesWithValue(PROPERTY_VALUE_YES)<<",";
    (*_csvOutput) << currentResults->entriesWithValue(PROPERTY_VALUE_NO)<<",";
    (*_csvOutput) << currentResults->entriesWithValue(PROPERTY_VALUE_UNKNOWN);
  }
  return currentResults;
}