Пример #1
0
void Egraph::expEnqueueArguments( Enode * x, Enode * y )
{
    assert( x->isTerm( ) );
    assert( y->isTerm( ) );
    assert( x->getArity( ) == y->getArity( ) );
    // No explanation needed if they are the same
    if ( x == y )
        return;

    // Simple explanation if they are arity 0 terms
    if ( x->getArity( ) == 0 )
    {
        exp_pending.push_back( x );
        exp_pending.push_back( y );
        return;
    }
    // Otherwise they are the same function symbol
    // Recursively enqueue the explanations for the args
    assert( x->getCar( ) == y->getCar( ) );
    Enode * xptr = x->getCdr( );
    Enode * yptr = y->getCdr( );
    while ( !xptr->isEnil( ) )
    {
        exp_pending.push_back( xptr->getCar( ) );
        exp_pending.push_back( yptr->getCar( ) );
        xptr = xptr->getCdr( );
        yptr = yptr->getCdr( );
    }
    // Check both lists have the same length
    assert( yptr->isEnil( ) );
}
Пример #2
0
IVector ode_solver::extract_invariants() {
    map<Enode*, pair<double, double>> inv_map;
    for (auto inv : m_invs) {
        Enode * p = inv->getCdr()->getCdr()->getCdr()->getCdr()->getCar();
        Enode * op = p->getCar();
        bool pos = true;

        // Handle Negation
        if (op->getId() == ENODE_ID_NOT) {
            p = p->getCdr()->getCar();
            op = p->getCar();
            pos = false;
        }
        switch (op->getId()) {
        case ENODE_ID_GEQ:
        case ENODE_ID_GT:
            // Handle >= & >
            pos = !pos;
        case ENODE_ID_LEQ:
        case ENODE_ID_LT: {
            // Handle <= & <
            Enode * lhs = pos ? p->getCdr()->getCar() : p->getCdr()->getCdr()->getCar();
            Enode * rhs = pos ? p->getCdr()->getCdr()->getCar() : p->getCdr()->getCar();
            if (lhs->isVar() && rhs->isConstant()) {
                if (inv_map.find(lhs) != inv_map.end()) {
                    inv_map[lhs].second = rhs->getValue();
                } else {
                    inv_map.emplace(lhs, make_pair(lhs->getLowerBound(), rhs->getValue()));
                }
            } else if (lhs->isConstant() && rhs->isVar()) {
                if (inv_map.find(rhs) != inv_map.end()) {
                    inv_map[rhs].first = lhs->getValue();
                } else {
                    inv_map.emplace(rhs, make_pair(lhs->getValue(), rhs->getUpperBound()));
                }
            } else {
                cerr << "ode_solver::extract_invariant: error:" << p << endl;
            }
        }
            break;
        default:
            cerr << "ode_solver::extract_invariant: error" << p << endl;
        }
    }
    IVector ret (m_t_vars.size());
    unsigned i = 0;
    for (auto const & m_t_var : m_t_vars) {
        if (inv_map.find(m_t_var) != inv_map.end()) {
            auto inv = interval(inv_map[m_t_var].first, inv_map[m_t_var].second);
            DREAL_LOG_INFO << "Invariant extracted from  " << m_t_var << " = " << inv;
            ret[i++] = inv;
        } else {
            auto inv = interval(m_t_var->getLowerBound(), m_t_var->getUpperBound());
            DREAL_LOG_INFO << "Default Invariant set for " << m_t_var << " = " << inv;
            ret[i++] = inv;
        }
    }
    return ret;
}
Пример #3
0
//
// Check if a formula is a clause
//
bool Cnfizer::checkClause( Enode * e, set< enodeid_t > & check_cache )
{
  assert( e );

  if ( e->isLit( ) )
  {
    check_cache.insert( e->getId( ) );                           // Don't check again
    return true;
  }

  if ( !e->isOr( ) )
    return false;

  if ( check_cache.find( e->getId( ) ) != check_cache.end( ) )   // Already visited term
    return true;

  bool is_clause = true;
  for ( Enode * list = e->getCdr( ) ;
        list != egraph.enil && is_clause ;
        list = list->getCdr( ) )
    is_clause = checkClause( list->getCar( ), check_cache );

  if ( !is_clause )
    return false;

  check_cache.insert( e->getId( ) );                             // Don't check again

  return true;
}
Пример #4
0
//
// Check if its a pure conjunction of literals
//
bool Cnfizer::checkPureConj( Enode * e, set< enodeid_t > & check_cache )
{
  if ( check_cache.find( e->getId( ) ) != check_cache.end( ) )
    return true;

  if ( e->isLit( ) )
  {
    check_cache.insert( e->getId( ) );
    return true;
  }

  if ( !e->isAnd( ) )
    return false;

  bool is_pure_conj = true;
  for ( Enode * list = e->getCdr( ) ;
        list != egraph.enil && is_pure_conj ;
        list = list->getCdr( ) )
    is_pure_conj = checkPureConj( list->getCar( ), check_cache );

  if ( !is_pure_conj )
   return false;

  check_cache.insert( e->getId( ) );

  return true;
}
Пример #5
0
vector<shared_ptr<nonlinear_constraint>> make_nlctrs(Enode * const e,
                                                     unordered_set<Enode *> const & var_set,
                                                     lbool const p) {
    vector<shared_ptr<nonlinear_constraint>> ret;
    if (e->isTrue()) {
        return ret;
    }
    if (e->isFalse()) {
        DREAL_LOG_FATAL << "false is not a valid invariant (forall_t constraint)";
        throw logic_error("false is not a valid invariant (forall_t constraint)");
    }
    if (e->isNot()) {
        return make_nlctrs(e->get1st(), var_set, !p);
    }
    if (e->isAnd()) {
        Enode * tmp = e->getCdr();
        while (!tmp->isEnil()) {
            auto const nlctrs = make_nlctrs(e->get1st(), var_set, p);
            ret.insert(ret.end(), nlctrs.begin(), nlctrs.end());
            tmp = tmp->getCdr();
        }
        return ret;
    }
    if (e->isOr()) {
        DREAL_LOG_FATAL << "or is not a valid invariant for now, (forall_t constraint)";
        throw logic_error("false is not a valid invariant for now, (forall_t constraint)");
    }
    ret.push_back(make_shared<nonlinear_constraint>(e, var_set, p));
    return ret;
}
Пример #6
0
//
// Retrieve the formulae at the top-level
//
void Cnfizer::retrieveTopLevelFormulae( Enode * f, vector< Enode * > & top_level_formulae )
{
  if ( f->isAnd( ) )
    for ( Enode * list = f->getCdr( ) ;
          list != egraph.enil ;
          list = list->getCdr( ) )
      retrieveTopLevelFormulae( list->getCar( ), top_level_formulae );
  else
    top_level_formulae.push_back( f );
}
Пример #7
0
ostream & print_infix_op(ostream & out, Enode * const e, string const & op,
                         std::function<ostream &(ostream &, Enode * const)> const & f) {
    assert(e->getArity() >= 2);
    out << "(";
    f(out, e->get1st());
    Enode * tmp = e->getCdr()->getCdr();
    while (!tmp->isEnil()) {
        out << " " << op << " ";
        f(out, tmp->getCar());
        tmp = tmp->getCdr();
    }
    out << ")";
    return out;
}
Пример #8
0
//
// Merge collected arguments for nodes
//
Enode * Cnfizer::mergeEnodeArgs( Enode * e
                               , map< enodeid_t, Enode * > & cache
                               , map< enodeid_t, int > & enodeid_to_incoming_edges )
{
  assert( e->isAnd( ) || e->isOr( ) );

  Enode * e_symb = e->getCar( );
  vector< Enode * > new_args;

  for ( Enode * list = e->getCdr( ) ;
        !list->isEnil( ) ;
        list = list->getCdr( ) )
  {
    Enode * arg = list->getCar( );
    Enode * sub_arg = cache[ arg->getId( ) ];
    Enode * sym = arg->getCar( );

    if ( sym->getId( ) != e_symb->getId( ) )
    {
      new_args.push_back( sub_arg );
      continue;
    }

    assert( enodeid_to_incoming_edges.find( arg->getId( ) ) != enodeid_to_incoming_edges.end( ) );
    assert( enodeid_to_incoming_edges[ arg->getId( ) ] >= 1 );

    if ( enodeid_to_incoming_edges[ arg->getId( ) ] > 1 )
    {
      new_args.push_back( sub_arg );
      continue;
    }

    for ( Enode * sub_arg_list = sub_arg->getCdr( ) ;
          !sub_arg_list->isEnil( ) ;
          sub_arg_list = sub_arg_list->getCdr( ) )
      new_args.push_back( sub_arg_list->getCar( ) );
  }

  Enode * new_list = const_cast< Enode * >(egraph.enil);

  while ( !new_args.empty( ) )
  {
    new_list = egraph.cons( new_args.back( ), new_list );
    new_args.pop_back( );
  }

  return egraph.cons( e_symb, new_list );
}
Пример #9
0
ostream & print_call(ostream & out, Enode * const e, string const & fname,
                     std::function<ostream &(ostream &, Enode * const)> const & f,
                     string const & lp, string const & rp) {
    assert(e->getArity() >= 1);
    out << fname;
    out << lp;
    f(out, e->get1st());
    Enode * tmp = e->getCdr()->getCdr();
    while (!tmp->isEnil()) {
        out << ", ";
        f(out, tmp->getCar());
        tmp = tmp->getCdr();
    }
    out << rp;
    return out;
}
Пример #10
0
//
// Retrieve a clause
//
void Cnfizer::retrieveClause( Enode * f, vector< Enode * > & clause )
{
  assert( f->isLit( ) || f->isOr( ) );

  if ( f->isLit( ) )
  {
    clause.push_back( f );
  }
  else if ( f->isOr( ) )
  {
    for ( Enode * list = f->getCdr( ) ;
          list != egraph.enil ;
          list = list->getCdr( ) )
      retrieveClause( list->getCar( ), clause );
  }
}
Пример #11
0
//
// Retrieve conjuncts
//
void Cnfizer::retrieveConjuncts( Enode * f, vector< Enode * > & conjuncts )
{
  assert( f->isLit( ) || f->isAnd( ) );

  if ( f->isLit( ) )
  {
    conjuncts.push_back( f );
  }
  else if ( f->isAnd( ) )
  {
    for ( Enode * list = f->getCdr( ) ;
          list != egraph.enil ;
          list = list->getCdr( ) )
      retrieveConjuncts( list->getCar( ), conjuncts );
  }
}
Пример #12
0
//
// Check if a formula is a conjunction of clauses
//
bool Cnfizer::checkConj( Enode * e, set< enodeid_t > & check_cache )
{
  if ( !e->isAnd( ) )
    return false;

  if ( check_cache.find( e->getId( ) ) != check_cache.end( ) )   // Already visited term
    return true;

  Enode * list = e->getCdr( );
  for ( ; list != egraph.enil ; list = list->getCdr( ) )
  {
    Enode * arg = list->getCar( );
    if( !checkConj( arg, check_cache ) && !checkClause( arg, check_cache ) )
      return false;
  }

  check_cache.insert( e->getId( ) );

  return true;
}
Пример #13
0
cgcolor_t CGraph::colorNodesRec( CNode * c, const uint64_t mask )
{
  // Already done
  if ( colored_nodes.find( c ) != colored_nodes.end( ) )
    return c->color;
  // Base case, color variables
  if ( c->e->getArity( ) == 0 )
  {
    cgcolor_t color = CG_UNDEF;
    // Belongs to B
    if ( (egraph.getIPartitions( c->e ) &  mask) != 0 )
      color |= CG_B;
    // Belongs to A
    if ( (egraph.getIPartitions( c->e ) & ~mask) != 0 )
      color |= CG_A;
    c->color = color;
  }
  else
  {
    // Function symbol: color depending on the arguments
    // Decide color of term as intersection
    cgcolor_t color = CG_AB;
    Enode * args = c->e->getCdr( );
    for ( args = c->e->getCdr( )
        ; !args->isEnil( )
        ; args = args->getCdr( ) )
    {
      Enode * arg = args->getCar( );
      // Not necessairly an argument is needed in the graph
      if ( cnodes_store.find( arg->getId( ) ) != cnodes_store.end( ) )
        color &= colorNodesRec( cnodes_store[ arg->getId( ) ], mask );
    }
    c->color = color;
  }
  assert( colored_nodes.find( c ) == colored_nodes.end( ) );
  colored_nodes.insert( c );
  return c->color;
}
Пример #14
0
double deriv_enode(Enode * const e, Enode * const v, unordered_map<Enode*, double> const & var_map) {
    if (e == v) {
        return 1.0;
    }
    if (e->isVar()) {
        auto const it = var_map.find(e);
        if (it == var_map.cend()) {
            throw runtime_error("variable not found");
        } else {
            // Variable is found in var_map
            return 0.0;
        }
    } else if (e->isConstant()) {
        return 0.0;
    } else if (e->isSymb()) {
        throw runtime_error("eval_enode: Symb");
    } else if (e->isNumb()) {
        throw runtime_error("eval_enode: Numb");
    } else if (e->isTerm()) {
        assert(e->getArity() >= 1);
        enodeid_t id = e->getCar()->getId();
        double ret = 0.0;
        Enode * tmp = e;
        switch (id) {
        case ENODE_ID_PLUS:
            ret = deriv_enode(tmp->get1st(), v, var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret + deriv_enode(tmp->getCar(), v, var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_MINUS:
            ret = deriv_enode(tmp->get1st(), v, var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret - deriv_enode(tmp->getCar(), v, var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_UMINUS:
            ret = deriv_enode(tmp->get1st(), v, var_map);
            assert(tmp->getArity() == 1);
            return (- ret);
        case ENODE_ID_TIMES: {
            // (f * g)' = f' * g + f * g'
            if (tmp->getArity() != 2) {
                throw runtime_error("deriv_enode: only support arity = 2 case for multiplication");
            }
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            double const g = eval_enode(e->get2nd(), var_map);
            double const g_ = deriv_enode(e->get2nd(), v, var_map);
            return f_ * g + f * g_;
        }
        case ENODE_ID_DIV: {
            // (f / g)' = (f' * g - f * g') / g^2
            if (tmp->getArity() != 2) {
                throw runtime_error("deriv_enode: only support arity = 2 case for division");
            }
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            double const g = eval_enode(e->get2nd(), var_map);
            double const g_ = deriv_enode(e->get2nd(), v, var_map);
            return (f_ * g - f * g_) / (g * g);
        }
        case ENODE_ID_ACOS: {
            // (acos f)' = -(1 / sqrt(1 - f^2)) f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return - (1 / sqrt(1 - f * f)) * f_;
        }
        case ENODE_ID_ASIN: {
            // (asin f)' = (1 / sqrt(1 - f^2)) f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return 1 / sqrt(1 - f * f) * f_;
        }
        case ENODE_ID_ATAN: {
            // (atan f)' = (1 / (1 + f^2)) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return 1 / (1 + f * f) * f_;
        }
        case ENODE_ID_ATAN2: {
            // atan2(x,y)' = -y / (x^2 + y^2) dx + x / (x^2 + y^2) dy
            //             = (-y dx + x dy) / (x^2 + y^2)
            assert(e->getArity() == 2);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            double const g = eval_enode(e->get2nd(), var_map);
            double const g_ = deriv_enode(e->get2nd(), v, var_map);
            return (-g * f_ + f * g_) / (f * f + g * g);
        }
        case ENODE_ID_MIN:
            assert(e->getArity() == 2);
            throw runtime_error("deriv_enode: no support for min");
        case ENODE_ID_MAX:
            assert(e->getArity() == 2);
            throw runtime_error("deriv_enode: no support for max");
        case ENODE_ID_MATAN:
            assert(e->getArity() == 1);
            throw runtime_error("deriv_enode: no support for matan");
        case ENODE_ID_SAFESQRT:
            assert(e->getArity() == 1);
            throw runtime_error("deriv_enode: no support for safesqrt");
        case ENODE_ID_SQRT: {
            // (sqrt(f))' = 1/2 * 1/(sqrt(f)) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return 0.5 * 1 / sqrt(f) * f_;
        }
        case ENODE_ID_EXP: {
            // (exp f)' = (exp f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return exp(f) * f_;
        }
        case ENODE_ID_LOG: {
            // (log f)' = f' / f
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return f_ / f;
        }
        case ENODE_ID_POW: {
            // (f^g)' = f^g (f' * g / f + g' * ln g)
            assert(e->getArity() == 2);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            double const g = eval_enode(e->get2nd(), var_map);
            double const g_ = deriv_enode(e->get2nd(), v, var_map);
            return pow(f, g) * (f_ * g / f + g_ * log(g));
        }
        case ENODE_ID_ABS: {
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            if (f > 0) {
                return f_;
            } else {
                return - f_;
            }
        }
        case ENODE_ID_SIN: {
            // (sin f)' = (cos f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return cos(f) * f_;
        }
        case ENODE_ID_COS: {
            // (cos f)' = - (sin f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return - sin(f) * f_;
        }
        case ENODE_ID_TAN: {
            // (tan f)' = (1 + tan^2 f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return (1 + tan(f) * tan(f)) * f_;
        }
        case ENODE_ID_SINH: {
            // (sinh f)' = (e^f + e^(-f))/2 * f'
            //           = cosh(f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return cosh(f) * f_;
        }
        case ENODE_ID_COSH: {
            // (cosh f)' = (e^f - e^(-f))/2 * f'
            //           = sinh(f) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return sinh(f) * f_;
        }
        case ENODE_ID_TANH: {
            // (tanh f)' = (sech^2 f) * f'
            //           = (1 - tanh(f) ^ 2) * f'
            assert(e->getArity() == 1);
            double const f = eval_enode(e->get1st(), var_map);
            double const f_ = deriv_enode(e->get1st(), v, var_map);
            return (1 - tanh(f) * tanh(f)) * f_;
        }
        default:
            throw runtime_error("deriv_enode: Unknown Term");
        }
    } else if (e->isList()) {
        throw runtime_error("deriv_enode: List");
    } else if (e->isDef()) {
        throw runtime_error("deriv_enode: Def");
    } else if (e->isEnil()) {
        throw runtime_error("deriv_enode: Nil");
    } else {
        throw runtime_error("deriv_enode: unknown case");
    }
    throw runtime_error("Not implemented yet: deriv_enode");
}
Пример #15
0
//
// Ackermann related routines
//
void
Egraph::retrieveFunctionApplications( Enode * formula )
{
  assert( formula );
  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( formula );

  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    // 
    // Skip if the node has already been processed before
    //
    if ( isDup1( enode ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ; 
	  arg_list != enil ; 
	  arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      
    //
    // At this point, every child has been processed
    //
    if ( enode->isUf( ) || enode->isUp( ) )
    {
      if ( uf_to_appl_cache[ enode->getCar( ) ].insert( enode ).second )
      {
	uf_to_appl[ enode->getCar( ) ].push_back( enode );
	undo_stack_oper.push_back( ACK_APPL );
	undo_stack_term.push_back( enode );
      }
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}
Пример #16
0
void Egraph::gatherInterfaceTerms( Enode * e )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );

  if ( config.verbosity > 2 )
    cerr << "# Egraph::Gathering interface terms" << endl;

  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( isDup1( enode ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );
      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( !isDup1( arg ) )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    //
    // At this point, every child has been processed
    //
    if ( enode->isUFOp( ) )
    {
      // Retrieve arguments
      for ( Enode * arg_list = enode->getCdr( )
          ; !arg_list->isEnil( )
          ; arg_list = arg_list->getCdr( ) )
      {
        Enode * arg = arg_list->getCar( );
        // This is for sure an interface term
        if ( ( arg->isArithmeticOp( )
            || arg->isConstant( ) )
          && interface_terms_cache.insert( arg ).second )
        {
          interface_terms.push_back( arg );
          if ( config.verbosity > 2 )
            cerr << "# Egraph::Added interface term: " << arg << endl;
        }
        // We add this variable to the potential
        // interface terms or to interface terms if
        // already seen in LA
        else if ( arg->isVar( ) || arg->isConstant( ) )
        {
          if ( it_la.find( arg ) == it_la.end( ) )
            it_uf.insert( arg );
          else if ( interface_terms_cache.insert( arg ).second )
          {
            interface_terms.push_back( arg );
            if ( config.verbosity > 2 )
              cerr << "# Egraph::Added interface term: " << arg << endl;
          }
        }
      }
    }

    if ( enode->isArithmeticOp( )
      && !isRootUF( enode ) )
    {
      // Retrieve arguments
      for ( Enode * arg_list = enode->getCdr( )
          ; !arg_list->isEnil( )
          ; arg_list = arg_list->getCdr( ) )
      {
        Enode * arg = arg_list->getCar( );
        // This is for sure an interface term
        if ( arg->isUFOp( )
          && interface_terms_cache.insert( arg ).second )
        {
          interface_terms.push_back( arg );
          if ( config.verbosity > 2 )
            cerr << "# Egraph::Added interface term: " << arg << endl;
        }
        // We add this variable to the potential
        // interface terms or to interface terms if
        // already seen in UF
        else if ( arg->isVar( ) || arg->isConstant( ) )
        {
          if ( it_uf.find( arg ) == it_uf.end( ) )
            it_la.insert( arg );
          else if ( interface_terms_cache.insert( arg ).second )
          {
            interface_terms.push_back( arg );
            if ( config.verbosity > 2 )
              cerr << "# Egraph::Added interface term: " << arg << endl;
          }
        }
      }
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}
Пример #17
0
Enode * Egraph::canonizeDTC( Enode * formula, bool split_eqs )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFLRA
       || config.logic == QF_UFIDL );

  list< Enode * > dtc_axioms;
  vector< Enode * > unprocessed_enodes;
  initDupMap1( );

  unprocessed_enodes.push_back( formula );
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( valDupMap1( enode ) != NULL )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( )
        ; arg_list != enil
        ; arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );
      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( valDupMap1( arg ) == NULL )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // Replace arithmetic atoms with canonized version
    //
    if (  enode->isTAtom( )
      && !enode->isUp( ) )
    {
      // No need to do anything if node is purely UF
      if ( isRootUF( enode ) )
      {
        if ( config.verbosity > 2 )
          cerr << "# Egraph::Skipping canonization of " << enode << " as it's root is purely UF" << endl;
        result = enode;
      }
      else
      {
        LAExpression a( enode );
        result = a.toEnode( *this );
#ifdef PRODUCE_PROOF
        const uint64_t partitions = getIPartitions( enode );
        assert( partitions != 0 );
        setIPartitions( result, partitions );
#endif

        if ( split_eqs && result->isEq( ) )
        {
#ifdef PRODUCE_PROOF
          if ( config.produce_inter > 0 )
            opensmt_error2( "can't compute interpolant for equalities at the moment ", enode );
#endif
          LAExpression aa( enode );
          Enode * e = aa.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( e, partitions );
#endif
          Enode * lhs = e->get1st( );
          Enode * rhs = e->get2nd( );
          Enode * leq = mkLeq( cons( lhs, cons( rhs ) ) );
          LAExpression b( leq );
          leq = b.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( leq, partitions );
#endif
          Enode * geq = mkGeq( cons( lhs, cons( rhs ) ) );
          LAExpression c( geq );
          geq = c.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( geq, partitions );
#endif
          Enode * not_e = mkNot( cons( enode ) );
          Enode * not_l = mkNot( cons( leq ) );
          Enode * not_g = mkNot( cons( geq ) );
          // Add clause ( !x=y v x<=y )
          Enode * c1 = mkOr( cons( not_e
                           , cons( leq ) ) );
          // Add clause ( !x=y v x>=y )
          Enode * c2 = mkOr( cons( not_e
                           , cons( geq ) ) );
          // Add clause ( x=y v !x>=y v !x<=y )
          Enode * c3 = mkOr( cons( enode
                           , cons( not_l
                           , cons( not_g ) ) ) );
          // Add conjunction of clauses
          Enode * ax = mkAnd( cons( c1
                            , cons( c2
                            , cons( c3 ) ) ) );

          dtc_axioms.push_back( ax );
          result = enode;
        }
      }
    }
    //
    // If nothing have been done copy and simplify
    //
    if ( result == NULL )
      result = copyEnodeEtypeTermWithCache( enode );

    assert( valDupMap1( enode ) == NULL );
    storeDupMap1( enode, result );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
    {
      // Setting partitions for result
      setIPartitions( result, getIPartitions( enode ) );
      // Setting partitions for negation as well occ if atom
      if ( result->hasSortBool( ) )
      {
        setIPartitions( mkNot( cons( result ) )
                      , getIPartitions( enode ) );
      }
    }
#endif
  }

  Enode * new_formula = valDupMap1( formula );
  assert( new_formula );
  doneDupMap1( );

  if ( !dtc_axioms.empty( ) )
  {
    dtc_axioms.push_back( new_formula );
    new_formula = mkAnd( cons( dtc_axioms ) );
  }

  return new_formula;
}
Пример #18
0
bool Egraph::isPureUF( Enode * e )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );
  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( isDup1( enode ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );
      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( !isDup1( arg ) )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );

    //
    // At this point, every child has been processed
    //
    if ( enode->isArithmeticOp( ) )
    {
      doneDup1( );
      return false;
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
  return true;
}
Пример #19
0
//
// Performs the actual cnfization
//
bool Tseitin::cnfize( Enode * formula, map< enodeid_t, Enode * > & cnf_cache )
{
  (void)cnf_cache;
  assert( formula );
  assert( !formula->isAnd( ) );

  Enode * arg_def = egraph.valDupMap1( formula );
  if ( arg_def != NULL )
  {
    vector< Enode * > clause;
    clause.push_back( arg_def );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
      return solver.addSMTClause( clause, egraph.getIPartitions( formula ) );
#endif
    return solver.addSMTClause( clause );
  }

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( formula );    // formula needs to be processed
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( egraph.valDupMap1( enode ) != NULL )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != egraph.enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is an unprocessed boolean operator
      //
      if ( enode->isBooleanOperator( )
        && egraph.valDupMap1( arg ) == NULL )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
      //
      // If it is an atom (either boolean or theory) just
      // store it in the cache
      //
      else if ( arg->isAtom( ) )
      {
        egraph.storeDupMap1( arg, arg );
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // At this point, every child has been processed
    //
    //
    // Do the actual cnfization, according to the node type
    //
    char def_name[ 32 ];

    if ( enode->isLit( ) )
    {
      result = enode;
    }
    else if ( enode->isNot( ) )
    {
      Enode * arg_def = egraph.valDupMap1( enode->get1st( ) );
      assert( arg_def );
      result = egraph.mkNot( egraph.cons( arg_def ) ); // Toggle the literal
    }
    else
    {
      Enode * arg_def = NULL;
      Enode * new_arg_list = egraph.copyEnodeEtypeListWithCache( enode->getCdr( ) );
      //
      // If the enode is not top-level it needs a definition
      //
      if ( formula != enode )
      {
        sprintf( def_name, CNF_STR, formula->getId( ), enode->getId( ) );
        egraph.newSymbol( def_name, sstore.mkBool( ) );
        arg_def = egraph.mkVar( def_name );
#ifdef PRODUCE_PROOF
        if ( config.produce_inter > 0 )
        {
          // Tag Positive and negative literals
          egraph.tagIFormula( arg_def
                            , egraph.getIPartitions( enode ) );
          egraph.tagIFormula( egraph.mkNot( egraph.cons( arg_def ) )
                            , egraph.getIPartitions( enode ) );
        }
#endif
      }
#ifdef PRODUCE_PROOF
      uint64_t partitions = 0;
      if ( config.produce_inter > 0 )
      {
        partitions = egraph.getIPartitions( enode );
        assert( partitions != 0 );
      }
#endif
      //
      // Handle boolean operators
      //
      if ( enode->isAnd( ) )
        cnfizeAnd( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isOr( ) )
        cnfizeOr( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isIff( ) )
        cnfizeIff( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isXor( ) )
        cnfizeXor( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else
      {
        opensmt_error2( "operator not handled ", enode->getCar( ) );
      }

      if ( arg_def != NULL )
        result = arg_def;
    }

    assert( egraph.valDupMap1( enode ) == NULL );
    egraph.storeDupMap1( enode, result );
  }

  if ( formula->isNot( ) )
  {
    // Retrieve definition of argument
    Enode * arg_def = egraph.valDupMap1( formula->get1st( ) );
    assert( arg_def );
    vector< Enode * > clause;
    clause.push_back( toggleLit( arg_def ) );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
      return solver.addSMTClause( clause, egraph.getIPartitions( formula ) );
#endif
    return solver.addSMTClause( clause );
  }

  return true;
}
Пример #20
0
//
// Rewrite formula with maximum arity for operators
//
Enode * Cnfizer::rewriteMaxArity( Enode * formula, map< enodeid_t, int > & enodeid_to_incoming_edges )
{
  assert( formula );

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( formula );    // formula needs to be processed
  map< enodeid_t, Enode * > cache;            // Cache of processed nodes
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( cache.find( enode->getId( ) ) != cache.end( ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != egraph.enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is an unprocessed boolean operator
      //
      if ( arg->isBooleanOperator( )
        && cache.find( arg->getId( ) ) == cache.end( ) )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
      //
      // If it is an atom (either boolean or theory) just
      // store it in the cache
      //
      else if ( arg->isAtom( ) )
      {
        cache.insert( make_pair( arg->getId( ), arg ) );
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // At this point, every child has been processed
    //
    assert ( enode->isBooleanOperator( ) );

    if ( enode->isAnd( )
      || enode->isOr ( ) )
    {
      assert( enode->isAnd( ) || enode->isOr( ) );
      //
      // Construct the new lists for the operators
      //
      result = mergeEnodeArgs( enode, cache, enodeid_to_incoming_edges );
    }
    else
    {
      result = enode;
    }

    assert( result );
    assert( cache.find( enode->getId( ) ) == cache.end( ) );
    cache[ enode->getId( ) ] = result;
  }

  Enode * top_enode = cache[ formula->getId( ) ];
  return top_enode;
}
Пример #21
0
void Egraph::getInterfaceVars( Enode * e, set< Enode * > & iv )
{
  assert( config.produce_inter != 0 );
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );

  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    // 
    // Skip if the node has already been processed before
    //
    if ( isDup1( enode ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ; 
	  arg_list != enil ; 
	  arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );
      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      

    if ( enode->isVar( )
      && interface_terms_cache.find( enode ) != interface_terms_cache.end( ) )
      iv.insert( enode );

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}
Пример #22
0
bool CostSolver::assertLitImpl( Enode * e )
{
  assert( e );
  assert( belongsToT( e ) );
  assert( e->hasPolarity() );
  assert( e->getPolarity() != l_Undef );
#if DEBUG
  cout << "ct assert " << (e->getPolarity() == l_True ? "" : "!") << e << endl;
#endif

  assert( !conflict_ );

  Enode * atom = e;
  const bool negated = e->getPolarity() == l_False;

  if ( atom->isCostIncur() )
  {
    assert( nodemap_[ atom ] );
    costfun & fun = *nodemap_[ atom ];
#if DEBUG
    print_status( cout, fun );
#endif
    incurnode * node = incurmap_[ atom ];
    if ( node->prev )
    {
      node->prev->next = node->next;
      assert( node->prev->cost <= node->cost );
    }
    if ( node->next )
    {
      node->next->prev = node->prev;
      assert( node->cost <= node->next->cost );
    }
    else
    {
      fun.unassigned.last = node->prev;
    }
    if ( fun.unassigned.head == node )
    {
      fun.unassigned.head = node->next;
    }
    fun.slack -= node->cost;
    fun.assigned.push_back( node );
    if ( negated )
    {
      undo_ops_.push( undo_op( REMOVE_INCUR_NEG, node ) );
      if ( !fun.lowerbound.empty() &&
           get_bound( fun.lowerbound.top() ) > fun.incurred + fun.slack )
      {
        assert( explanation.empty() );
        conflict_ = atom;
        codomain potential = fun.incurred + fun.slack;
        for ( costfun::nodes_t::iterator it = fun.assigned.begin();
              it != fun.assigned.end();
              ++it )
        {
          incurnode * node = *it;
#if ELIM_REDUNDANT
          if ( node->atom->getPolarity() != l_False )
          {
            continue;
          }
          if ( potential + node->cost < get_bound( fun.lowerbound.top() ) )
          {
            potential += node->cost;
            continue;
          }
#endif
          if ( node->atom->getPolarity() == l_False )
          {
            explanation.push_back( node->atom );
          }
        }
        assert( potential < get_bound( fun.lowerbound.top() ) );
        assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() );
        explanation.push_back( fun.lowerbound.top() );
#if DEBUG_CONFLICT
            cout << " " << explanation << " : " << fun.slack << endl;
            print_status( cout, fun ); cout << endl;
#endif
#if DEBUG
        cout << "conflict found " << conflict_ << endl;
        print_status( cout, fun );
#endif
#if DEBUG_CHECK_STATUS
        check_status();
#endif
        return false;
      }
    }
    else
    {
      fun.incurred += node->cost;
      undo_ops_.push( undo_op( REMOVE_INCUR_POS, node ) );
      if ( !fun.upperbound.empty() &&
           get_bound( fun.upperbound.top() ) <= fun.incurred )
      {
        conflict_ = atom;
        codomain incurred = fun.incurred;
        for ( costfun::nodes_t::iterator it = fun.assigned.begin();
              it != fun.assigned.end();
              ++it )
        {
          incurnode * node = *it;
#if ELIM_REDUNDANT
          if ( node->atom->getPolarity() != l_True )
          {
            continue;
          }
          if ( incurred - node->cost >= get_bound( fun.upperbound.top() ) )
          {
            incurred -= node->cost;
            continue;
          }
#endif
          if ( node->atom->getPolarity() == l_True )
          {
            explanation.push_back( node->atom );
          }
        }
        assert( incurred >= get_bound( fun.upperbound.top() ) );
        assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() );
        explanation.push_back( fun.upperbound.top() );
#if DEBUG_CONFLICT
            cout << explanation << " : " << fun.slack << endl;
            print_status( cout, fun ); cout << endl;
#endif
#if DEBUG
        cout << "conflict found " << conflict_ << endl;
        print_status( cout, fun );
#endif
#if DEBUG_CHECK_STATUS
        check_status();
#endif
        return false;
      }
    }
  }
  else if ( atom->isCostBound() )
  {
#if DEBUG
    cout << "ct bound asserted " << atom << endl;
#endif
    assert( nodemap_.find( atom ) != nodemap_.end() );
    costfun & fun = *nodemap_[ atom ];
    Enode * args = atom->getCdr();
    Enode * val = args->getCdr()->getCar();
    assert( val->isConstant() );
#if DEBUG
    cout << atom->get2nd() << endl;
#endif
    const codomain & value = atom->get2nd()->getValue();
    if ( negated )
    {
#if DEBUG
      cout << "ct bound asserted negatively " << atom << endl;
#endif
      if ( ( !fun.lowerbound.empty() &&
             get_bound( fun.lowerbound.top() ) < value ) ||
           fun.lowerbound.empty() )
      {
#if DEBUG
        cout << "ct new lower bound " << atom << endl;
#endif
        fun.lowerbound.push( atom );
        undo_ops_.push( undo_op( REMOVE_LBOUND, &fun ) );
        if ( fun.incurred + fun.slack < get_bound( fun.lowerbound.top() ) )
        {
          conflict_ = atom;
          codomain potential = fun.incurred + fun.slack;
          for ( costfun::nodes_t::iterator it = fun.assigned.begin();
                it != fun.assigned.end();
                ++it )
          {
            incurnode * node = *it;
#if ELIM_REDUNDANT
            if ( node->atom->getPolarity() != l_False )
            {
              continue;
            }
            if ( potential + node->cost < get_bound( fun.lowerbound.top() ) )
            {
              potential += node->cost;
              continue;
            }
#endif
            if ( node->atom->getPolarity() == l_False )
            {
              explanation.push_back( node->atom );
            }
          }
          assert( find( explanation.begin(), explanation.end(), conflict_ ) == explanation.end() );
          explanation.push_back( conflict_ );
          assert( potential < get_bound( fun.lowerbound.top() ) );
          assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() );
#if DEBUG_CONFLICT
            cout << explanation << " : " << fun.slack << endl;
            print_status( cout, fun ); cout << endl;
#endif
#if DEBUG
          cout << "conflict found " << conflict_ << endl;
          print_status( cout, fun );
#endif
#if DEBUG_CHECK_STATUS
          check_status();
#endif
          return false;
        }
      }
    }
    else
    {
#if DEBUG
      cout << "ct bound asserted positively " << atom << endl;
#endif
      if ( ( !fun.upperbound.empty() &&
             get_bound( fun.upperbound.top() ) > value ) ||
           fun.upperbound.empty() )
      {
#if DEBUG
        cout << "ct new upper bound " << atom << endl;
#endif
        fun.upperbound.push( atom );
        undo_ops_.push( undo_op( REMOVE_UBOUND, &fun ) );
        if ( fun.incurred >= get_bound( fun.upperbound.top() ) )
        {
          conflict_ = atom;
          codomain incurred = fun.incurred;
          for ( costfun::nodes_t::iterator it = fun.assigned.begin();
                it != fun.assigned.end();
                ++it )
          {
            incurnode * node = *it;
#if ELIM_REDUNDANT
            if ( node->atom->getPolarity() != l_True )
            {
              continue;
            }
            if ( incurred - node->cost >= get_bound( fun.upperbound.top() ) )
            {
              incurred -= node->cost;
              continue;
            }
#endif
            if ( node->atom->getPolarity() == l_True )
            {
              explanation.push_back( node->atom );
            }
          }
          assert( find( explanation.begin(), explanation.end(), conflict_ ) == explanation.end() );
          assert( incurred >= get_bound( fun.upperbound.top() ) );
          explanation.push_back( conflict_ );
          assert( find( explanation.begin(), explanation.end(), conflict_ ) != explanation.end() );
#if DEBUG_CONFLICT
            cout << " " << explanation << " : " << fun.slack << endl;
            print_status( cout, fun ); cout << endl;
#endif
#if DEBUG
          cout << "conflict found " << conflict_ << endl;
          print_status( cout, fun );
#endif
#if DEBUG_CHECK_STATUS
          check_status();
#endif
          return false;
        }
      }
    }
    if ( !fun.lowerbound.empty() && !fun.upperbound.empty() &&
         get_bound( fun.lowerbound.top() ) >= get_bound( fun.upperbound.top() ) )
    {
      conflict_ = atom;
      explanation.push_back( fun.lowerbound.top() );
      explanation.push_back( fun.upperbound.top() );
#if DEBUG_CONFLICT
            cout << " " << explanation << " : " << fun.slack << endl;
            print_status( cout, fun ); cout << endl;
#endif
#if DEBUG
      cout << "conflict found " << conflict_ << endl;
      print_status( cout, fun );
#endif
#if DEBUG_CHECK_STATUS
      check_status();
#endif
      return false;
    }
  }
  else
  {
#if DEBUG
    cout << "ct unrecognized " << atom << endl;
#endif
  }

#if 1
  {
    // Deduction
    costfun & fun = *nodemap_[ atom ];
    if ( !fun.upperbound.empty() &&
         fun.lowerbound.empty() &&
         fun.unassigned.last &&
         get_bound( fun.upperbound.top() ) <= fun.unassigned.last->cost + fun.incurred  &&
         !fun.unassigned.last->atom->isDeduced() )
    {
#if DEBUG
      cout << "deducing !" << fun.unassigned.last->atom << endl;
#endif
      fun.unassigned.last->atom->setDeduced( l_False, id );
      deductions.push_back( fun.unassigned.last->atom );
    }
    else if ( !fun.lowerbound.empty() &&
         fun.upperbound.empty() &&
         fun.unassigned.last &&
         get_bound( fun.lowerbound.top() ) > fun.incurred + fun.slack - fun.unassigned.last->cost &&
         !fun.unassigned.last->atom->isDeduced() )
    {
#if DEBUG
      cout << "deducing " << fun.unassigned.last->atom << endl;
#endif
      fun.unassigned.last->atom->setDeduced( l_True, id );
      deductions.push_back( fun.unassigned.last->atom );
    }
    else if ( !fun.upperbound.empty() &&
              !fun.lowerbound.empty() &&
              fun.unassigned.last &&
              get_bound( fun.lowerbound.top() ) +1 == get_bound( fun.upperbound.top() ) )
    {
      if ( fun.unassigned.last->cost == fun.slack &&
           fun.incurred + fun.unassigned.last->cost ==
           get_bound( fun.lowerbound.top() ) &&
           fun.incurred + fun.slack - fun.unassigned.last->cost <
           get_bound( fun.lowerbound.top() ) )
      {
#if DEBUG
      cout << "deducing " << fun.unassigned.last->atom << endl;
      print_status( cout, fun );
#endif
        fun.unassigned.last->atom->setDeduced( l_True, 0 );
        deductions.push_back( fun.unassigned.last->atom );
      }
    }
  }
#endif

#if DEBUG_CHECK_STATUS
  check_status();
#endif
  return true;
}
Пример #23
0
static double eval(Enode * const e, double const values[], double const params[],
                   unordered_map<Enode *, unsigned> const & value_lookup,
                   unordered_map<Enode *, unsigned> const & param_lookup) {
    if (e->isNumb()) {
        return e->getNumb();
    } else if (e->isVar()) {
        auto it = value_lookup.find(e);
        if (it != value_lookup.end()) {
            return values[it->second];
        }
        it = param_lookup.find(e);
        if (it != param_lookup.end()) {
            return params[it->second];
        }
        DREAL_LOG_FATAL << "Can't find variable " << e;
        throw runtime_error("GSL eval: unmatched variable");
    } else if (e->isTerm()) {
        switch (e->getCar()->getId()) {
        case ENODE_ID_PLUS: {
            Enode * p = e->getCdr();
            double ret = eval(p->getCar(), values, params, value_lookup, param_lookup);
            p = p->getCdr();
            while (!p->isEnil()) {
                ret += eval(p->getCar(), values, params, value_lookup, param_lookup);
                p = p->getCdr();
            }
            return ret;
        }
        case ENODE_ID_MINUS: {
            Enode * p = e->getCdr();
            double ret = eval(p->getCar(), values, params, value_lookup, param_lookup);
            p = p->getCdr();
            while (!p->isEnil()) {
                ret -= eval(p->getCar(), values, params, value_lookup, param_lookup);
                p = p->getCdr();
            }
            return ret;
        }
        case ENODE_ID_TIMES: {
            Enode * p = e->getCdr();
            double ret = eval(p->getCar(), values, params, value_lookup, param_lookup);
            p = p->getCdr();
            while (!p->isEnil()) {
                ret *= eval(p->getCar(), values, params, value_lookup, param_lookup);
                p = p->getCdr();
            }
            return ret;
        }
        case ENODE_ID_DIV: {
            Enode * p = e->getCdr();
            double ret = eval(p->getCar(), values, params, value_lookup, param_lookup);
            p = p->getCdr();
            while (!p->isEnil()) {
                ret /= eval(p->getCar(), values, params, value_lookup, param_lookup);
                p = p->getCdr();
            }
            return ret;
        }
        case ENODE_ID_POW: {
            if (e->getArity() != 2) {
                throw runtime_error("GSL eval: pow not implemented");
            }
            double const arg1 = eval(e->get1st(), values, params, value_lookup, param_lookup);
            double const arg2 = eval(e->get2nd(), values, params, value_lookup, param_lookup);
            return pow(arg1, arg2);
        }
        case ENODE_ID_ATAN2: {
            double const arg1 = eval(e->get1st(), values, params, value_lookup, param_lookup);
            double const arg2 = eval(e->get2nd(), values, params, value_lookup, param_lookup);
            return atan2(arg1, arg2);
        }
        case ENODE_ID_UMINUS: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return -arg;
        }
        case ENODE_ID_SIN: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return sin(arg);
        }
        case ENODE_ID_COS: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return cos(arg);
        }
        case ENODE_ID_TAN: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return tan(arg);
        }
        case ENODE_ID_SQRT: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return sqrt(arg);
        }
        case ENODE_ID_SAFESQRT: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            assert(arg >= 0);
            return sqrt(arg);
        }
        case ENODE_ID_EXP: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return exp(arg);
        }
        case ENODE_ID_LOG: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return log(arg);
        }
        case ENODE_ID_ASIN: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return asin(arg);
        }
        case ENODE_ID_ACOS: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return acos(arg);
        }
        case ENODE_ID_ATAN: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return atan(arg);
        }
        case ENODE_ID_SINH: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return sinh(arg);
        }
        case ENODE_ID_COSH: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return cosh(arg);
        }
        case ENODE_ID_TANH: {
            assert(e->getArity() == 1);
            double const arg = eval(e->get1st(), values, params, value_lookup, param_lookup);
            return tanh(arg);
        }
        default:
            return eval(e->getCar(), values, params, value_lookup, param_lookup);
        }
    } else if (e->isList()) {
        throw runtime_error("GSL eval: list");
    } else if (e->isDef()) {
        throw runtime_error("GSL eval: def");
    } else if (e->isEnil()) {
        throw runtime_error("GSL eval: enil");
    }
    throw runtime_error("GSL eval: unknown");
}
Пример #24
0
double eval_enode(Enode * const e, unordered_map<Enode*, double> const & var_map) {
    if (e->isVar()) {
        auto const it = var_map.find(e);
        if (it == var_map.cend()) {
            throw runtime_error("variable not found");
        } else {
            // Variable is found in var_map
            return it->second;
        }
    } else if (e->isConstant()) {
        double const v = e->getValue();
        return v;
    } else if (e->isSymb()) {
        throw runtime_error("eval_enode: Symb");
    } else if (e->isNumb()) {
        throw runtime_error("eval_enode: Numb");
    } else if (e->isTerm()) {
        assert(e->getArity() >= 1);
        enodeid_t id = e->getCar()->getId();
        double ret = 0.0;
        Enode * tmp = e;
        switch (id) {
        case ENODE_ID_PLUS:
            ret = eval_enode(tmp->get1st(), var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret + eval_enode(tmp->getCar(), var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_MINUS:
            ret = eval_enode(tmp->get1st(), var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret - eval_enode(tmp->getCar(), var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_UMINUS:
            ret = eval_enode(tmp->get1st(), var_map);
            assert(tmp->getArity() == 1);
            return (- ret);
        case ENODE_ID_TIMES:
            ret = eval_enode(tmp->get1st(), var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret * eval_enode(tmp->getCar(), var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_DIV:
            ret = eval_enode(tmp->get1st(), var_map);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = ret / eval_enode(tmp->getCar(), var_map);
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_ACOS:
            assert(e->getArity() == 1);
            return acos(eval_enode(e->get1st(), var_map));
        case ENODE_ID_ASIN:
            assert(e->getArity() == 1);
            return asin(eval_enode(e->get1st(), var_map));
        case ENODE_ID_ATAN:
            assert(e->getArity() == 1);
            return atan(eval_enode(e->get1st(), var_map));
        case ENODE_ID_ATAN2:
            assert(e->getArity() == 2);
            return atan2(eval_enode(e->get1st(), var_map),
                         eval_enode(e->get2nd(), var_map));
        case ENODE_ID_MIN:
            assert(e->getArity() == 2);
            return fmin(eval_enode(e->get1st(), var_map),
                        eval_enode(e->get2nd(), var_map));
        case ENODE_ID_MAX:
            assert(e->getArity() == 2);
            return fmax(eval_enode(e->get1st(), var_map),
                        eval_enode(e->get2nd(), var_map));
        case ENODE_ID_MATAN:
            assert(e->getArity() == 1);
            throw runtime_error("eval_enode: MATAN");
        case ENODE_ID_SAFESQRT:
            assert(e->getArity() == 1);
            throw runtime_error("eval_enode: SAFESQRT");
        case ENODE_ID_SQRT:
            assert(e->getArity() == 1);
            return sqrt(eval_enode(e->get1st(), var_map));
        case ENODE_ID_EXP:
            assert(e->getArity() == 1);
            return exp(eval_enode(e->get1st(), var_map));
        case ENODE_ID_LOG:
            assert(e->getArity() == 1);
            return log(eval_enode(e->get1st(), var_map));
        case ENODE_ID_POW:
            assert(e->getArity() == 2);
            return pow(eval_enode(e->get1st(), var_map),
                       eval_enode(e->get2nd(), var_map));
        case ENODE_ID_ABS:
            assert(e->getArity() == 1);
            return fabs(eval_enode(e->get1st(), var_map));
        case ENODE_ID_SIN:
            assert(e->getArity() == 1);
            return sin(eval_enode(e->get1st(), var_map));
        case ENODE_ID_COS:
            assert(e->getArity() == 1);
            return cos(eval_enode(e->get1st(), var_map));
        case ENODE_ID_TAN:
            assert(e->getArity() == 1);
            return tan(eval_enode(e->get1st(), var_map));
        case ENODE_ID_SINH:
            assert(e->getArity() == 1);
            return sinh(eval_enode(e->get1st(), var_map));
        case ENODE_ID_COSH:
            assert(e->getArity() == 1);
            return cosh(eval_enode(e->get1st(), var_map));
        case ENODE_ID_TANH:
            assert(e->getArity() == 1);
            return tanh(eval_enode(e->get1st(), var_map));
        default:
            throw runtime_error("eval_enode: Unknown Term");
        }
    } else if (e->isList()) {
        throw runtime_error("eval_enode: List");
    } else if (e->isDef()) {
        throw runtime_error("eval_enode: Def");
    } else if (e->isEnil()) {
        throw runtime_error("eval_enode: Nil");
    } else {
        throw runtime_error("eval_enode: unknown case");
    }
    throw runtime_error("Not implemented yet: eval_enode");
}
Пример #25
0
void THandler::verifyInterpolantWithExternalTool( vector< Enode * > & expl
                                                , Enode * interp_list )
{
  uint64_t mask = 0xFFFFFFFFFFFFFFFEULL;
  for ( unsigned in = 1 ; in < core_solver.getNofPartitions( ) ; in ++ )
  {
    Enode * args = interp_list;
    // Advance in the interpolants list
    for ( unsigned i = 0 ; i < in - 1 ; i ++ )
      args = args->getCdr( );
    Enode * interp = args->getCar( );
    mask &= ~SETBIT( in );
    // Check A -> I, i.e., A & !I
    // First stage: print declarations
    const char * name = "/tmp/verifyinterp.smt2";
    std::ofstream dump_out( name );
    core_solver.dumpHeaderToFile( dump_out );
    // Print only A atoms
    dump_out << "(assert " << endl;
    dump_out << "(and" << endl;
    for ( size_t j = 0 ; j < expl.size( ) ; j ++ )
    {
      Enode * e = expl[ j ];
      assert( e->isTAtom( ) );
      assert( e->getPolarity( ) != l_Undef );
      assert( (core_solver.getIPartitions( e ) &  mask) != 0
           || (core_solver.getIPartitions( e ) & ~mask) != 0 );
      if ( (core_solver.getIPartitions( e ) & ~mask) != 0 )
      {
        bool negated = e->getPolarity( ) == l_False;
        if ( negated )
          dump_out << "(not ";
        e->print( dump_out );
        if ( negated )
          dump_out << ")";
        dump_out << endl;
      }
    }

    dump_out << "(not " << interp << ")" << endl;
    dump_out << "))" << endl;
    dump_out << "(check-sat)" << endl;
    dump_out << "(exit)" << endl;
    dump_out.close( );
    // Check !
    bool tool_res;
    if ( int pid = fork() )
    {
      int status;
      waitpid(pid, &status, 0);
      switch ( WEXITSTATUS( status ) )
      {
        case 0:
          tool_res = false;
          break;
        case 1:
          tool_res = true;
          break;
        default:
          perror( "Tool" );
          exit( EXIT_FAILURE );
      }
    }
    else
    {
      execlp( "tool_wrapper.sh", "tool_wrapper.sh", name, 0 );
      perror( "Tool" );
      exit( 1 );
    }

    if ( tool_res == true )
      opensmt_error2( config.certifying_solver, " says A -> I does not hold" );
    // Now check B & I
    dump_out.open( name );
    core_solver.dumpHeaderToFile( dump_out );
    // Print only B atoms
    dump_out << "(assert " << endl;
    dump_out << "(and" << endl;
    for ( size_t j = 0 ; j < expl.size( ) ; j ++ )
    {
      Enode * e = expl[ j ];
      assert( e->isTAtom( ) );
      assert( e->getPolarity( ) != l_Undef );
      assert( (core_solver.getIPartitions( e ) &  mask) != 0
           || (core_solver.getIPartitions( e ) & ~mask) != 0 );
      if ( (core_solver.getIPartitions( e ) & mask) != 0 )
      {
        bool negated = e->getPolarity( ) == l_False;
        if ( negated )
          dump_out << "(not ";
        e->print( dump_out );
        if ( negated )
          dump_out << ")";
        dump_out << endl;
      }
    }
    dump_out << interp << endl;
    dump_out << "))" << endl;
    dump_out << "(check-sat)" << endl;
    dump_out << "(exit)" << endl;
    dump_out.close( );
    // Check !
    tool_res;
    if ( int pid = fork() )
    {
      int status;
      waitpid(pid, &status, 0);
      switch ( WEXITSTATUS( status ) )
      {
        case 0:
          tool_res = false;
          break;
        case 1:
          tool_res = true;
          break;
        default:
          perror( "Tool" );
          exit( EXIT_FAILURE );
      }
    }
    else
    {
      execlp( "tool_wrapper.sh", "tool_wrapper.sh", name, 0 );
      perror( "Tool" );
      exit( 1 );
    }
    if ( tool_res == true )
      opensmt_error2( config.certifying_solver, " says B & I does not hold" );
  }
}
Пример #26
0
Enode *
ExpandITEs::doit( Enode * formula )
{
  assert( formula );
  list< Enode * > new_clauses;
  vector< Enode * > unprocessed_enodes;
  egraph.initDupMap1( );

  unprocessed_enodes.push_back( formula );
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( egraph.valDupMap1( enode ) != NULL )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != egraph.enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( egraph.valDupMap1( arg ) == NULL )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // At this point, every child has been processed
    //
    char def_name[ 32 ];

    if ( enode->isIte( ) )
    {
      //
      // Retrieve arguments
      //
      Enode * i = egraph.valDupMap1( enode->get1st( ) );
      Enode * t = egraph.valDupMap1( enode->get2nd( ) );
      Enode * e = egraph.valDupMap1( enode->get3rd( ) );
      Enode * not_i = egraph.mkNot( egraph.cons( i ) );
      //
      // Generate variable symbol
      //
      sprintf( def_name, ITE_STR, enode->getId( ) );
      Snode * sort = enode->getLastSort( );
      egraph.newSymbol( def_name, sort );
      //
      // Generate placeholder
      //
      result = egraph.mkVar( def_name );
      //
      // Generate additional clauses
      //
      Enode * eq_then = egraph.mkEq( egraph.cons( result
                                   , egraph.cons( t ) ) );
      Enode * eq_else = egraph.mkEq( egraph.cons( result
                                   , egraph.cons( e ) ) );
      new_clauses.push_back( egraph.mkOr( egraph.cons( not_i
                                        , egraph.cons( eq_then ) ) ) );
      new_clauses.push_back( egraph.mkOr( egraph.cons( i
                                        , egraph.cons( eq_else ) ) ) );
    }
    else
    {
      result = egraph.copyEnodeEtypeTermWithCache( enode );
    }

    assert( result );
    assert( egraph.valDupMap1( enode ) == NULL );
    egraph.storeDupMap1( enode, result );
  }

  Enode * new_formula = egraph.valDupMap1( formula );
  assert( new_formula );
  egraph.doneDupMap1( );

  new_clauses.push_back( new_formula );

  return egraph.mkAnd( egraph.cons( new_clauses ) );
}
Пример #27
0
//
// Compute the number of incoming edges for e and children
//
void Cnfizer::computeIncomingEdges( Enode * e
                                  , map< enodeid_t, int > & enodeid_to_incoming_edges )
{
  assert( e );

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( e );    // formula needs to be processed
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    map< enodeid_t, int >::iterator it = enodeid_to_incoming_edges.find( enode->getId( ) );
    if ( it != enodeid_to_incoming_edges.end( ) )
    {
      it->second++;
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    if ( enode->isBooleanOperator( ) )
    {
      for ( Enode * arg_list = enode->getCdr( )
          ; !arg_list->isEnil( )
          ; arg_list = arg_list->getCdr( ) )
      {
        Enode * arg = arg_list->getCar( );
        //
        // Push only if it is an unprocessed boolean operator
        //
        map< enodeid_t, int >::iterator it = enodeid_to_incoming_edges.find( arg->getId( ) );
        if ( it == enodeid_to_incoming_edges.end( ) )
        {
          unprocessed_enodes.push_back( arg );
          unprocessed_children = true;
        }
        else
        {
          it->second ++;
        }
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    //
    // At this point, every child has been processed
    //
    assert ( enode->isBooleanOperator( ) || enode->isAtom( ) );
    assert ( enodeid_to_incoming_edges.find( enode->getId( ) ) == enodeid_to_incoming_edges.end( ) );
    enodeid_to_incoming_edges[ enode->getId( ) ] = 1;
  }
}
Пример #28
0
lbool CostSolver::inform( Enode * e )  
{ 
  assert( e );
  assert( belongsToT( e ) );
#if DEBUG
  cout << "ct inform " << e << endl;
#endif
  if ( e->isCostIncur() )
  {
    assert( e->getArity() == 3 );
    Enode * args = e->getCdr();
    Enode * var = args->getCar();
    Enode * cost = args->getCdr()->getCar();
#if DEBUG
    cout << "ct inform var = " << var << endl;
    cout << "ct inform cost = " << cost << endl;
#endif
    assert( var->isVar() );
    assert( cost->isConstant() );

    nodemap_t::iterator it = nodemap_.find( var );
    if ( it != nodemap_.end() )
    {
      costfun & fun = *it->second;
      nodemap_[ e ] = &fun;
      add_incur( fun, e, cost );
    }
    else
    {
      costfun * fun = new costfun( var );
#if DEBUG
      cout << "ct new cost fun " << var << endl;
#endif
      nodemap_[ var ] = fun;
      nodemap_[ e ] = fun;
      costfuns_.push_back( fun );
      add_incur( *fun, e, cost );
    }
  }
  if ( e->isCostBound() )
  {
    assert( e->getArity() == 2 );
    Enode * args = e->getCdr();
    Enode * var = args->getCar();

    nodemap_t::iterator it = nodemap_.find( var );
    if ( it != nodemap_.end() )
    {
      costfun & fun = *it->second;
      nodemap_[ var ] = &fun;
      nodemap_[ e ] = &fun;
      add_bound( fun, e );
    }
    else
    {
      costfun * fun = new costfun( var );
#if DEBUG
      cout << "ct new cost fun " << var << endl;
#endif
      nodemap_[ var ] = fun;
      nodemap_[ e ] = fun;
      costfuns_.push_back( fun );
      add_bound( *fun, e );
    }
  }
#if DEBUG
  print_status( cout );
#endif
  return l_Undef;
}
Пример #29
0
// Translate an Enode e into ibex::ExprNode.
// Note: As a side-effect, update var_map : string -> ibex::Variable
// Note: Use subst map (Enode ->ibex::Interval)
ExprNode const * translate_enode_to_exprnode(map<string, Variable const> & var_map, Enode * const e, unordered_map<Enode*, ibex::Interval> const & subst) {
    // TODO(soonhok): for the simple case such as 0 <= x or x <= 10.
    // Handle it as a domain specification instead of constraints.
    if (e->isVar()) {
        auto const subst_it = subst.find(e);
        if (subst_it != subst.cend()) {
            auto const i = subst_it->second;
            return &ExprConstant::new_scalar(i);
        }
        string const & var_name = e->getCar()->getNameFull();
        auto const it = var_map.find(var_name);
        if (it == var_map.cend()) {
            // The variable is new, we need to make one.
            Variable v(var_name.c_str());
            // double const lb = e->getLowerBound();
            // double const ub = e->getUpperBound();
            var_map.emplace(var_name, v);
            return v.symbol;
        } else {
            // Variable is found in var_map
            Variable const & v = it->second;
            return v.symbol;
        }

    } else if (e->isConstant()) {
        double const lb = e->getValueLowerBound();
        double const ub = e->getValueUpperBound();
        return &ExprConstant::new_scalar(ibex::Interval(lb, ub));
    } else if (e->isSymb()) {
        throw logic_error("translateEnodeExprNode: Symb");
    } else if (e->isNumb()) {
        throw logic_error("translateEnodeExprNode: Numb");
    } else if (e->isTerm()) {
        assert(e->getArity() >= 1);
        enodeid_t id = e->getCar()->getId();
        ExprNode const * ret = nullptr;
        Enode * tmp = e;
        switch (id) {
        case ENODE_ID_PLUS:
            ret = translate_enode_to_exprnode(var_map, tmp->get1st(), subst);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = &(*ret + *translate_enode_to_exprnode(var_map, tmp->getCar(), subst));
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_MINUS:
            ret = translate_enode_to_exprnode(var_map, tmp->get1st(), subst);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = &(*ret - *translate_enode_to_exprnode(var_map, tmp->getCar(), subst));
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_UMINUS:
            ret = translate_enode_to_exprnode(var_map, tmp->get1st(), subst);
            assert(tmp->getArity() == 1);
            return &(- *ret);
        case ENODE_ID_TIMES:
            ret = translate_enode_to_exprnode(var_map, tmp->get1st(), subst);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = &(*ret * *translate_enode_to_exprnode(var_map, tmp->getCar(), subst));
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_DIV:
            ret = translate_enode_to_exprnode(var_map, tmp->get1st(), subst);
            tmp = tmp->getCdr()->getCdr();  // e is pointing to the 2nd arg
            while (!tmp->isEnil()) {
                ret = &(*ret / *translate_enode_to_exprnode(var_map, tmp->getCar(), subst));
                tmp = tmp->getCdr();
            }
            return ret;
        case ENODE_ID_ACOS:
            assert(e->getArity() == 1);
            return &acos(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_ASIN:
            assert(e->getArity() == 1);
            return &asin(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_ATAN:
            assert(e->getArity() == 1);
            return &atan(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_ATAN2:
            assert(e->getArity() == 2);
            return &atan2(*translate_enode_to_exprnode(var_map, e->get1st(), subst), *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
        case ENODE_ID_MIN:
            assert(e->getArity() == 2);
            return &min(*translate_enode_to_exprnode(var_map, e->get1st(), subst), *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
        case ENODE_ID_MAX:
            assert(e->getArity() == 2);
            return &max(*translate_enode_to_exprnode(var_map, e->get1st(), subst), *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
        case ENODE_ID_MATAN:
            // TODO(soonhok): MATAN
            throw logic_error("translateEnodeExprNode: MATAN");
        case ENODE_ID_SAFESQRT:
            // TODO(soonhok): SAFESQRT
            throw logic_error("translateEnodeExprNode: SAFESQRT");
        case ENODE_ID_SQRT:
            assert(e->getArity() == 1);
            return &sqrt(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_EXP:
            assert(e->getArity() == 1);
            return &exp(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_LOG:
            assert(e->getArity() == 1);
            return &log(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_POW: {
            assert(e->getArity() == 2);
            bool   is_1st_constant = false;
            bool   is_1st_int      = false;
            bool   is_2nd_constant = false;
            bool   is_2nd_int      = false;
            double dbl_1st = 0.0;
            int    int_1st = 0;
            double dbl_2nd = 0.0;
            int    int_2nd = 0;
            if (e->get1st()->isConstant()) {
                dbl_1st = e->get1st()->getValue();
                is_1st_constant = true;
                double tmp;
                if (modf(dbl_1st, &tmp) == 0.0) {
                    is_1st_int = true;
                    int_1st = static_cast<int>(tmp);
                }
            }
            if (e->get2nd()->isConstant()) {
                dbl_2nd = e->get2nd()->getValue();
                is_2nd_constant = true;
                double tmp;
                if (modf(dbl_2nd, &tmp) == 0.0) {
                    is_2nd_int = true;
                    int_2nd = static_cast<int>(tmp);
                }
            }
            if (is_1st_constant && is_2nd_constant) {
                // Both of them are constant, just compute and return a number
                return &ExprConstant::new_scalar(pow(dbl_1st, dbl_2nd));
            }
            // Now, either of them is non-constant.
            if (is_1st_int) {
                return &pow(int_1st, *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
            }
            if (is_1st_constant) {
                return &pow(dbl_1st, *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
            }
            if (is_2nd_int) {
                return &pow(*translate_enode_to_exprnode(var_map, e->get1st(), subst), int_2nd);
            }
            if (is_2nd_constant) {
                return &pow(*translate_enode_to_exprnode(var_map, e->get1st(), subst), dbl_2nd);
            }
            return &pow(*translate_enode_to_exprnode(var_map, e->get1st(), subst), *translate_enode_to_exprnode(var_map, e->get2nd(), subst));
        }
        case ENODE_ID_ABS:
            assert(e->getArity() == 1);
            return &abs(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_SIN:
            assert(e->getArity() == 1);
            return &sin(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_COS:
            assert(e->getArity() == 1);
            return &cos(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_TAN:
            assert(e->getArity() == 1);
            return &tan(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_SINH:
            assert(e->getArity() == 1);
            return &sinh(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_COSH:
            assert(e->getArity() == 1);
            return &cosh(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        case ENODE_ID_TANH:
            assert(e->getArity() == 1);
            return &tanh(*translate_enode_to_exprnode(var_map, e->get1st(), subst));
        default:
            throw logic_error("translateEnodeExprNode: Unknown Term");
        }
    } else if (e->isList()) {
        throw logic_error("translateEnodeExprNode: List");
    } else if (e->isDef()) {
        throw logic_error("translateEnodeExprNode: Def");
    } else if (e->isEnil()) {
        throw logic_error("translateEnodeExprNode: Nil");
    } else {
        throw logic_error("translateEnodeExprNode: unknown case");
    }
    throw logic_error("Not implemented yet: translateEnodeExprNode");
}