Theory Combination

examples/api/cpp/combination.cpp

  1/******************************************************************************
  2 * This file is part of the cvc5 project.
  3 *
  4 * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
  5 * in the top-level source directory and their institutional affiliations.
  6 * All rights reserved.  See the file COPYING in the top-level source
  7 * directory for licensing information.
  8 * ****************************************************************************
  9 *
 10 * A simple demonstration of the capabilities of cvc5
 11 *
 12 * A simple demonstration of how to use uninterpreted functions, combining this
 13 * with arithmetic, and extracting a model at the end of a satisfiable query.
 14 * The model is displayed using getValue().
 15 */
 16
 17#include <cvc5/cvc5.h>
 18
 19#include <iostream>
 20
 21using namespace std;
 22using namespace cvc5;
 23
 24void prefixPrintGetValue(Solver& slv, Term t, int level = 0)
 25{
 26  cout << "slv.getValue(" << t << "): " << slv.getValue(t) << endl;
 27
 28  for (const Term& c : t)
 29  {
 30    prefixPrintGetValue(slv, c, level + 1);
 31  }
 32}
 33
 34int main()
 35{
 36  TermManager tm;
 37  Solver slv(tm);
 38  slv.setOption("produce-models", "true");  // Produce Models
 39  slv.setOption("dag-thresh", "0"); // Disable dagifying the output
 40  slv.setLogic("QF_UFLIRA");
 41
 42  // Sorts
 43  Sort u = tm.mkUninterpretedSort("u");
 44  Sort integer = tm.getIntegerSort();
 45  Sort boolean = tm.getBooleanSort();
 46  Sort uToInt = tm.mkFunctionSort({u}, integer);
 47  Sort intPred = tm.mkFunctionSort({integer}, boolean);
 48
 49  // Variables
 50  Term x = tm.mkConst(u, "x");
 51  Term y = tm.mkConst(u, "y");
 52
 53  // Functions
 54  Term f = tm.mkConst(uToInt, "f");
 55  Term p = tm.mkConst(intPred, "p");
 56
 57  // Constants
 58  Term zero = tm.mkInteger(0);
 59  Term one = tm.mkInteger(1);
 60
 61  // Terms
 62  Term f_x = tm.mkTerm(Kind::APPLY_UF, {f, x});
 63  Term f_y = tm.mkTerm(Kind::APPLY_UF, {f, y});
 64  Term sum = tm.mkTerm(Kind::ADD, {f_x, f_y});
 65  Term p_0 = tm.mkTerm(Kind::APPLY_UF, {p, zero});
 66  Term p_f_y = tm.mkTerm(Kind::APPLY_UF, {p, f_y});
 67
 68  // Construct the assertions
 69  Term assertions =
 70      tm.mkTerm(Kind::AND,
 71                {
 72                    tm.mkTerm(Kind::LEQ, {zero, f_x}),  // 0 <= f(x)
 73                    tm.mkTerm(Kind::LEQ, {zero, f_y}),  // 0 <= f(y)
 74                    tm.mkTerm(Kind::LEQ, {sum, one}),   // f(x) + f(y) <= 1
 75                    p_0.notTerm(),                      // not p(0)
 76                    p_f_y                               // p(f(y))
 77                });
 78  slv.assertFormula(assertions);
 79
 80  cout << "Given the following assertions:" << endl
 81       << assertions << endl << endl;
 82
 83  cout << "Prove x /= y is entailed." << endl
 84       << "cvc5: " << slv.checkSatAssuming(tm.mkTerm(Kind::EQUAL, {x, y}))
 85       << "." << endl
 86       << endl;
 87
 88  cout << "Call checkSat to show that the assertions are satisfiable." << endl
 89       << "cvc5: " << slv.checkSat() << "." << endl
 90       << endl;
 91
 92  cout << "Call slv.getValue(...) on terms of interest."
 93       << endl;
 94  cout << "slv.getValue(" << f_x << "): " << slv.getValue(f_x) << endl;
 95  cout << "slv.getValue(" << f_y << "): " << slv.getValue(f_y) << endl;
 96  cout << "slv.getValue(" << sum << "): " << slv.getValue(sum) << endl;
 97  cout << "slv.getValue(" << p_0 << "): " << slv.getValue(p_0) << endl;
 98  cout << "slv.getValue(" << p_f_y << "): " << slv.getValue(p_f_y)
 99       << endl << endl;
100
101  cout << "Alternatively, iterate over assertions and call slv.getValue(...) "
102       << "on all terms."
103       << endl;
104  prefixPrintGetValue(slv, assertions);
105
106  cout << endl;
107  cout << "You can also use nested loops to iterate over terms." << endl;
108  for (Term::const_iterator it = assertions.begin();
109       it != assertions.end();
110       ++it)
111  {
112    cout << "term: " << *it << endl;
113    for (Term::const_iterator it2 = (*it).begin();
114         it2 != (*it).end();
115         ++it2)
116    {
117      cout << " + child: " << *it2 << std::endl;
118    }
119  }
120  cout << endl;
121  cout << "Alternatively, you can also use for-each loops." << endl;
122  for (const Term& t : assertions)
123  {
124    cout << "term: " << t << endl;
125    for (const Term& c : t)
126    {
127      cout << " + child: " << c << endl;
128    }
129  }
130
131  return 0;
132}