Theory of Strings

examples/api/cpp/strings.cpp

 1/******************************************************************************
 2 * Top contributors (to current version):
 3 *   Aina Niemetz, Tianyi Liang, Mathias Preiner
 4 *
 5 * This file is part of the cvc5 project.
 6 *
 7 * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
 8 * in the top-level source directory and their institutional affiliations.
 9 * All rights reserved.  See the file COPYING in the top-level source
10 * directory for licensing information.
11 * ****************************************************************************
12 *
13 * A simple demonstration of reasoning about strings with cvc5 via C++ API.
14 */
15
16#include <cvc5/cvc5.h>
17
18#include <iostream>
19
20using namespace cvc5;
21
22int main()
23{
24  TermManager tm;
25  Solver slv(tm);
26
27  // Set the logic
28  slv.setLogic("QF_SLIA");
29  // Produce models
30  slv.setOption("produce-models", "true");
31  // The option strings-exp is needed
32  slv.setOption("strings-exp", "true");
33  // Set output language to SMTLIB2
34  slv.setOption("output-language", "smt2");
35
36  // String type
37  Sort string = tm.getStringSort();
38
39  // std::string
40  std::string str_ab("ab");
41  // String constants
42  Term ab = tm.mkString(str_ab);
43  Term abc = tm.mkString("abc");
44  // String variables
45  Term x = tm.mkConst(string, "x");
46  Term y = tm.mkConst(string, "y");
47  Term z = tm.mkConst(string, "z");
48
49  // String concatenation: x.ab.y
50  Term lhs = tm.mkTerm(Kind::STRING_CONCAT, {x, ab, y});
51  // String concatenation: abc.z
52  Term rhs = tm.mkTerm(Kind::STRING_CONCAT, {abc, z});
53  // x.ab.y = abc.z
54  Term formula1 = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
55
56  // Length of y: |y|
57  Term leny = tm.mkTerm(Kind::STRING_LENGTH, {y});
58  // |y| >= 0
59  Term formula2 = tm.mkTerm(Kind::GEQ, {leny, tm.mkInteger(0)});
60
61  // Regular expression: (ab[c-e]*f)|g|h
62  Term r = tm.mkTerm(
63      Kind::REGEXP_UNION,
64
65      {tm.mkTerm(Kind::REGEXP_CONCAT,
66                 {tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("ab")}),
67                  tm.mkTerm(Kind::REGEXP_STAR,
68                            {tm.mkTerm(Kind::REGEXP_RANGE,
69                                       {tm.mkString("c"), tm.mkString("e")})}),
70                  tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("f")})}),
71       tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("g")}),
72       tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("h")})});
73
74  // String variables
75  Term s1 = tm.mkConst(string, "s1");
76  Term s2 = tm.mkConst(string, "s2");
77  // String concatenation: s1.s2
78  Term s = tm.mkTerm(Kind::STRING_CONCAT, {s1, s2});
79
80  // s1.s2 in (ab[c-e]*f)|g|h
81  Term formula3 = tm.mkTerm(Kind::STRING_IN_REGEXP, {s, r});
82
83  // Make a query
84  Term q = tm.mkTerm(Kind::AND, {formula1, formula2, formula3});
85
86  // check sat
87  Result result = slv.checkSatAssuming(q);
88  std::cout << "cvc5 reports: " << q << " is " << result << "." << std::endl;
89
90  if(result.isSat())
91  {
92    std::cout << "  x  = " << slv.getValue(x) << std::endl;
93    std::cout << "  s1.s2 = " << slv.getValue(s) << std::endl;
94  }
95}