@@ -67,6 +67,7 @@ smt2_convt::smt2_convt(
6767    use_datatypes(false ),
6868    use_lambda_for_array(false ),
6969    emit_set_logic(true ),
70+     quantifier_as_defined_expr(false ),
7071    ns(_ns),
7172    out(_out),
7273    benchmark(_benchmark),
@@ -136,6 +137,7 @@ smt2_convt::smt2_convt(
136137    use_lambda_for_array = true ;
137138    emit_set_logic = false ;
138139    use_datatypes = true ;
140+     quantifier_as_defined_expr = true ;
139141    break ;
140142  }
141143
@@ -888,16 +890,6 @@ void smt2_convt::convert_address_of_rec(
888890        expr.id_string ());
889891}
890892
891- static  bool  has_quantifier (const  exprt &expr)
892- {
893-   bool  result = false ;
894-   expr.visit_post ([&result](const  exprt &node) {
895-     if (node.id () == ID_exists || node.id () == ID_forall)
896-       result = true ;
897-   });
898-   return  result;
899- }
900- 
901893literalt smt2_convt::convert (const  exprt &expr)
902894{
903895  PRECONDITION (expr.is_boolean ());
@@ -928,28 +920,13 @@ literalt smt2_convt::convert(const exprt &expr)
928920  //  Note that here we are always converting, so we do not need to consider
929921  //  other literal kinds, only "|B###|"
930922
931-   //  Z3 refuses get-value when a defined symbol contains a quantifier.
932-   if (has_quantifier (prepared_expr))
933-   {
934-     out << " (declare-fun " 
935-     convert_literal (l);
936-     out << "  () Bool)\n " 
937-     out << " (assert (= " 
938-     convert_literal (l);
939-     out << '  ' 
940-     convert_expr (prepared_expr);
941-     out << " ))\n " 
942-   }
943-   else 
944-   {
945-     auto  identifier =
946-       convert_identifier (std::string{" B" std::to_string (l.var_no ()));
947-     defined_expressions[expr] = identifier;
948-     smt2_identifiers.insert (identifier);
949-     out << " (define-fun " "  () Bool " 
950-     convert_expr (prepared_expr);
951-     out << " )\n " 
952-   }
923+   auto  identifier =
924+     convert_identifier (std::string{" B" std::to_string (l.var_no ()));
925+   defined_expressions[expr] = identifier;
926+   smt2_identifiers.insert (identifier);
927+   out << " (define-fun " "  () Bool " 
928+   convert_expr (prepared_expr);
929+   out << " )\n " 
953930
954931  return  l;
955932}
@@ -2439,36 +2416,50 @@ void smt2_convt::convert_expr(const exprt &expr)
24392416  else  if (expr.id ()==ID_forall ||
24402417          expr.id ()==ID_exists)
24412418  {
2442-     const  quantifier_exprt &quantifier_expr = to_quantifier_expr (expr);
2419+     bool  already_converted = false ;
2420+     if (quantifier_as_defined_expr)
2421+     {
2422+       defined_expressionst::const_iterator it = defined_expressions.find (expr);
2423+       if (it != defined_expressions.end ())
2424+       {
2425+         already_converted = true ;
2426+         out << it->second ;
2427+       }
2428+     }
24432429
2444-     if (solver==solvert::MATHSAT )
2445-        //  NOLINTNEXTLINE(readability/throw) 
2446-       throw   " MathSAT does not support quantifiers " 
2430+     if (!already_converted )
2431+     { 
2432+       const  quantifier_exprt &quantifier_expr =  to_quantifier_expr (expr) ;
24472433
2448-     if (quantifier_expr.id () == ID_forall)
2449-       out << " (forall " 
2450-     else  if (quantifier_expr.id () == ID_exists)
2451-       out << " (exists " 
2434+       if (solver == solvert::MATHSAT)
2435+         //  NOLINTNEXTLINE(readability/throw)
2436+         throw  " MathSAT does not support quantifiers" 
2437+ 
2438+       if (quantifier_expr.id () == ID_forall)
2439+         out << " (forall " 
2440+       else  if (quantifier_expr.id () == ID_exists)
2441+         out << " (exists " 
24522442
2453-     out << ' (' 
2454-     bool  first = true ;
2455-     for (const  auto  &bound : quantifier_expr.variables ())
2456-     {
2457-       if (first)
2458-         first = false ;
2459-       else 
2460-         out << '  ' 
24612443      out << ' (' 
2462-       convert_expr (bound);
2463-       out << '  ' 
2464-       convert_type (bound.type ());
2465-       out << ' )' 
2466-     }
2467-     out << " ) " 
2444+       bool  first = true ;
2445+       for (const  auto  &bound : quantifier_expr.variables ())
2446+       {
2447+         if (first)
2448+           first = false ;
2449+         else 
2450+           out << '  ' 
2451+         out << ' (' 
2452+         convert_expr (bound);
2453+         out << '  ' 
2454+         convert_type (bound.type ());
2455+         out << ' )' 
2456+       }
2457+       out << " ) " 
24682458
2469-     convert_expr (quantifier_expr.where ());
2459+        convert_expr (quantifier_expr.where ());
24702460
2471-     out << ' )' 
2461+       out << ' )' 
2462+     }
24722463  }
24732464  else  if (
24742465    const  auto  object_size = expr_try_dynamic_cast<object_size_exprt>(expr))
@@ -5137,6 +5128,13 @@ void smt2_convt::find_symbols(const exprt &expr)
51375128
51385129  if (expr.id () == ID_exists || expr.id () == ID_forall)
51395130  {
5131+     if (
5132+       quantifier_as_defined_expr &&
5133+       defined_expressions.find (expr) != defined_expressions.end ())
5134+     {
5135+       return ;
5136+     }
5137+ 
51405138    std::unordered_map<irep_idt, std::optional<identifiert>> shadowed_syms;
51415139
51425140    //  do not declare the quantified symbol, but record
@@ -5161,6 +5159,26 @@ void smt2_convt::find_symbols(const exprt &expr)
51615159      else 
51625160        previous_entry->second  = std::move (*shadowed_val);
51635161    }
5162+ 
5163+     if (quantifier_as_defined_expr)
5164+     {
5165+       const  irep_idt id =
5166+         " quantified_expr." std::to_string (defined_expressions.size ());
5167+ 
5168+       out << " ; the following is a workaround for solvers removing quantified " 
5169+              " expression during preprocessing\n " 
5170+       out << " (declare-fun " "  () Bool)\n " 
5171+ 
5172+       out << " (assert (=> " '  ' 
5173+       convert_expr (expr);
5174+       out << " ))\n " 
5175+       out << " (assert (=> " 
5176+       convert_expr (expr);
5177+       out << '  ' " ))\n " 
5178+ 
5179+       defined_expressions[expr] = id;
5180+     }
5181+ 
51645182    return ;
51655183  }
51665184
0 commit comments