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 via the 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
34  // String type
35  Sort string = tm.getStringSort();
36
37  // std::string
38  std::string str_ab("ab");
39  // String constants
40  Term ab = tm.mkString(str_ab);
41  Term abc = tm.mkString("abc");
42  // String variables
43  Term x = tm.mkConst(string, "x");
44  Term y = tm.mkConst(string, "y");
45  Term z = tm.mkConst(string, "z");
46
47  // String concatenation: x.ab.y
48  Term lhs = tm.mkTerm(Kind::STRING_CONCAT, {x, ab, y});
49  // String concatenation: abc.z
50  Term rhs = tm.mkTerm(Kind::STRING_CONCAT, {abc, z});
51  // x.ab.y = abc.z
52  Term formula1 = tm.mkTerm(Kind::EQUAL, {lhs, rhs});
53
54  // Length of y: |y|
55  Term leny = tm.mkTerm(Kind::STRING_LENGTH, {y});
56  // |y| >= 0
57  Term formula2 = tm.mkTerm(Kind::GEQ, {leny, tm.mkInteger(0)});
58
59  // Regular expression: (ab[c-e]*f)|g|h
60  Term r = tm.mkTerm(
61      Kind::REGEXP_UNION,
62
63      {tm.mkTerm(Kind::REGEXP_CONCAT,
64                 {tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("ab")}),
65                  tm.mkTerm(Kind::REGEXP_STAR,
66                            {tm.mkTerm(Kind::REGEXP_RANGE,
67                                       {tm.mkString("c"), tm.mkString("e")})}),
68                  tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("f")})}),
69       tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("g")}),
70       tm.mkTerm(Kind::STRING_TO_REGEXP, {tm.mkString("h")})});
71
72  // String variables
73  Term s1 = tm.mkConst(string, "s1");
74  Term s2 = tm.mkConst(string, "s2");
75  // String concatenation: s1.s2
76  Term s = tm.mkTerm(Kind::STRING_CONCAT, {s1, s2});
77
78  // s1.s2 in (ab[c-e]*f)|g|h
79  Term formula3 = tm.mkTerm(Kind::STRING_IN_REGEXP, {s, r});
80
81  // Make a query
82  Term q = tm.mkTerm(Kind::AND, {formula1, formula2, formula3});
83
84  // check sat
85  Result result = slv.checkSatAssuming(q);
86  std::cout << "cvc5 reports: " << q << " is " << result << "." << std::endl;
87
88  if(result.isSat())
89  {
90    std::cout << "  x  = " << slv.getValue(x) << std::endl;
91    std::cout << "  s1.s2 = " << slv.getValue(s) << std::endl;
92  }
93}