SyGuS: Grammars
examples/api/cpp/sygus-grammar.cpp
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Abdalrhman Mohamed, Mathias Preiner, Andrew Reynolds
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2022 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 the Sygus API.
14 *
15 * A simple demonstration of how to use Grammar to add syntax constraints to
16 * the Sygus solution for the identity function.
17 */
18
19 #include <cvc5/cvc5.h>
20
21 #include <iostream>
22
23 #include "utils.h"
24
25 using namespace cvc5;
26
27 int main()
28 {
29 Solver slv;
30
31 // required options
32 slv.setOption("sygus", "true");
33 slv.setOption("incremental", "false");
34
35 // set the logic
36 slv.setLogic("LIA");
37
38 Sort integer = slv.getIntegerSort();
39
40 // declare input variable for the function-to-synthesize
41 Term x = slv.mkVar(integer, "x");
42
43 // declare the grammar non-terminal
44 Term start = slv.mkVar(integer, "Start");
45
46 // define the rules
47 Term zero = slv.mkInteger(0);
48 Term neg_x = slv.mkTerm(NEG, {x});
49 Term plus = slv.mkTerm(ADD, {x, start});
50
51 // create the grammar object
52 Grammar g1 = slv.mkGrammar({x}, {start});
53
54 // bind each non-terminal to its rules
55 g1.addRules(start, {neg_x, plus});
56
57 // copy the first grammar with all of its non-termainals and their rules
58 Grammar g2 = g1;
59 Grammar g3 = g1;
60
61 // add parameters as rules for the start symbol. Similar to "(Variable Int)"
62 g2.addAnyVariable(start);
63
64 // declare the functions-to-synthesize
65 Term id1 = slv.synthFun("id1", {x}, integer, g1);
66 Term id2 = slv.synthFun("id2", {x}, integer, g2);
67
68 g3.addRule(start, zero);
69
70 Term id3 = slv.synthFun("id3", {x}, integer, g3);
71
72 // g1 is reusable as long as it remains unmodified after first use
73 Term id4 = slv.synthFun("id4", {x}, integer, g1);
74
75 // declare universal variables.
76 Term varX = slv.declareSygusVar("x", integer);
77
78 Term id1_x = slv.mkTerm(APPLY_UF, {id1, varX});
79 Term id2_x = slv.mkTerm(APPLY_UF, {id2, varX});
80 Term id3_x = slv.mkTerm(APPLY_UF, {id3, varX});
81 Term id4_x = slv.mkTerm(APPLY_UF, {id4, varX});
82
83 // add semantic constraints
84 // (constraint (= (id1 x) (id2 x) (id3 x) (id4 x) x))
85 slv.addSygusConstraint(
86 slv.mkTerm(EQUAL, {{id1_x, id2_x, id3_x, id4_x, varX}}));
87
88 // print solutions if available
89 if (slv.checkSynth().hasSolution())
90 {
91 // Output should be equivalent to:
92 // (
93 // (define-fun id1 ((x Int)) Int (+ x (+ x (- x))))
94 // (define-fun id2 ((x Int)) Int x)
95 // (define-fun id3 ((x Int)) Int (+ x 0))
96 // (define-fun id4 ((x Int)) Int (+ x (+ x (- x))))
97 // )
98 std::vector<Term> terms = {id1, id2, id3, id4};
99 utils::printSynthSolutions(terms, slv.getSynthSolutions(terms));
100 }
101
102 return 0;
103 }
examples/api/java/SygusGrammar.java
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Mudathir Mohamed, Andrew Reynolds, Andres Noetzli
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2022 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 the Sygus API.
14 *
15 * A simple demonstration of how to use Grammar to add syntax constraints to
16 * the Sygus solution for the identity function. This is a direct translation
17 * of sygus-grammar.cpp.
18 */
19
20 import static io.github.cvc5.Kind.*;
21
22 import io.github.cvc5.*;
23
24 public class SygusGrammar
25 {
26 public static void main(String args[]) throws CVC5ApiException
27 {
28 try (Solver slv = new Solver())
29 {
30 // required options
31 slv.setOption("sygus", "true");
32 slv.setOption("incremental", "false");
33
34 // set the logic
35 slv.setLogic("LIA");
36
37 Sort integer = slv.getIntegerSort();
38
39 // declare input variable for the function-to-synthesize
40 Term x = slv.mkVar(integer, "x");
41
42 // declare the grammar non-terminal
43 Term start = slv.mkVar(integer, "Start");
44
45 // define the rules
46 Term zero = slv.mkInteger(0);
47 Term neg_x = slv.mkTerm(NEG, x);
48 Term plus = slv.mkTerm(ADD, x, start);
49
50 // create the grammar object
51 Grammar g1 = slv.mkGrammar(new Term[] {x}, new Term[] {start});
52
53 // bind each non-terminal to its rules
54 g1.addRules(start, new Term[] {neg_x, plus});
55
56 // copy the first grammar with all of its non-terminals and their rules
57 Grammar g2 = new Grammar(g1);
58 Grammar g3 = new Grammar(g1);
59
60 // add parameters as rules for the start symbol. Similar to "(Variable Int)"
61 g2.addAnyVariable(start);
62
63 // declare the functions-to-synthesize
64 Term id1 = slv.synthFun("id1", new Term[] {x}, integer, g1);
65 Term id2 = slv.synthFun("id2", new Term[] {x}, integer, g2);
66
67 g3.addRule(start, zero);
68
69 Term id3 = slv.synthFun("id3", new Term[] {x}, integer, g3);
70
71 // g1 is reusable as long as it remains unmodified after first use
72 Term id4 = slv.synthFun("id4", new Term[] {x}, integer, g1);
73
74 // declare universal variables.
75 Term varX = slv.declareSygusVar("x", integer);
76
77 Term id1_x = slv.mkTerm(APPLY_UF, id1, varX);
78 Term id2_x = slv.mkTerm(APPLY_UF, id2, varX);
79 Term id3_x = slv.mkTerm(APPLY_UF, id3, varX);
80 Term id4_x = slv.mkTerm(APPLY_UF, id4, varX);
81
82 // add semantic constraints
83 // (constraint (= (id1 x) (id2 x) (id3 x) (id4 x) x))
84 slv.addSygusConstraint(slv.mkTerm(EQUAL, new Term[] {id1_x, id2_x, id3_x, id4_x, varX}));
85
86 // print solutions if available
87 if (slv.checkSynth().hasSolution())
88 {
89 // Output should be equivalent to:
90 // (
91 // (define-fun id1 ((x Int)) Int (+ x (+ x (- x))))
92 // (define-fun id2 ((x Int)) Int x)
93 // (define-fun id3 ((x Int)) Int (+ x 0))
94 // (define-fun id4 ((x Int)) Int (+ x (+ x (- x))))
95 // )
96 Term[] terms = new Term[] {id1, id2, id3, id4};
97 Utils.printSynthSolutions(terms, slv.getSynthSolutions(terms));
98 }
99 }
100 }
101 }
examples/api/python/sygus-grammar.py
1 #!/usr/bin/env python
2 ###############################################################################
3 # Top contributors (to current version):
4 # Yoni Zohar, Aina Niemetz, Andrew Reynolds
5 #
6 # This file is part of the cvc5 project.
7 #
8 # Copyright (c) 2009-2022 by the authors listed in the file AUTHORS
9 # in the top-level source directory and their institutional affiliations.
10 # All rights reserved. See the file COPYING in the top-level source
11 # directory for licensing information.
12 # #############################################################################
13 #
14 # A simple demonstration of the solving capabilities of the cvc5
15 # sygus solver through the Python API. This is a direct
16 # translation of sygus-grammar.cpp.
17 ##
18
19 import copy
20 import utils
21 import cvc5
22 from cvc5 import Kind
23
24 if __name__ == "__main__":
25 slv = cvc5.Solver()
26
27 # required options
28 slv.setOption("sygus", "true")
29 slv.setOption("incremental", "false")
30
31 # set the logic
32 slv.setLogic("LIA")
33
34 integer = slv.getIntegerSort()
35
36 # declare input variable for the function-to-synthesize
37 x = slv.mkVar(integer, "x")
38
39 # declare the grammar non-terminal
40 start = slv.mkVar(integer, "Start")
41
42 # define the rules
43 zero = slv.mkInteger(0)
44 neg_x = slv.mkTerm(Kind.NEG, x)
45 plus = slv.mkTerm(Kind.ADD, x, start)
46
47 # create the grammar object
48 g1 = slv.mkGrammar({x}, {start})
49 g2 = slv.mkGrammar({x}, {start})
50 g3 = slv.mkGrammar({x}, {start})
51
52 # bind each non-terminal to its rules
53 g1.addRules(start, {neg_x, plus})
54 g2.addRules(start, {neg_x, plus})
55 g3.addRules(start, {neg_x, plus})
56
57 # add parameters as rules for the start symbol. Similar to "(Variable Int)"
58 g2.addAnyVariable(start)
59
60 # declare the functions-to-synthesize
61 id1 = slv.synthFun("id1", {x}, integer, g1)
62 id2 = slv.synthFun("id2", {x}, integer, g2)
63
64 g3.addRule(start, zero)
65
66 id3 = slv.synthFun("id3", {x}, integer, g3)
67
68 # g1 is reusable as long as it remains unmodified after first use
69 id4 = slv.synthFun("id4", {x}, integer, g1)
70
71 # declare universal variables.
72 varX = slv.declareSygusVar("x", integer)
73
74 id1_x = slv.mkTerm(Kind.APPLY_UF, id1, varX)
75 id2_x = slv.mkTerm(Kind.APPLY_UF, id2, varX)
76 id3_x = slv.mkTerm(Kind.APPLY_UF, id3, varX)
77 id4_x = slv.mkTerm(Kind.APPLY_UF, id4, varX)
78
79 # add semantic constraints
80 # (constraint (= (id1 x) (id2 x) (id3 x) (id4 x) x))
81 slv.addSygusConstraint(
82 slv.mkTerm(Kind.AND,
83 slv.mkTerm(Kind.EQUAL, id1_x, id2_x),
84 slv.mkTerm(Kind.EQUAL, id1_x, id3_x),
85 slv.mkTerm(Kind.EQUAL, id1_x, id4_x),
86 slv.mkTerm(Kind.EQUAL, id1_x, varX)))
87
88 # print solutions if available
89 if (slv.checkSynth().hasSolution()):
90 # Output should be equivalent to:
91 # (define-fun id1 ((x Int)) Int (+ x (+ x (- x))))
92 # (define-fun id2 ((x Int)) Int x)
93 # (define-fun id3 ((x Int)) Int (+ x 0))
94 # (define-fun id4 ((x Int)) Int (+ x (+ x (- x))))
95 terms = [id1, id2, id3, id4]
96 utils.print_synth_solutions(terms, slv.getSynthSolutions(terms))
examples/api/smtlib/sygus-grammar.sy
1 ; The printed output for this example should look like:
2 ; (
3 ; (define-fun id1 ((x Int)) Int (+ x (+ x (- x))))
4 ; (define-fun id2 ((x Int)) Int x)
5 ; (define-fun id3 ((x Int)) Int (+ x 0))
6 ; (define-fun id4 ((x Int)) Int (+ x (+ x (- x))))
7 ; )
8
9 (set-logic LIA)
10 (synth-fun id1 ((x Int)) Int ((Start Int)) ((Start Int ((- x) (+ x Start)))))
11 (synth-fun id2 ((x Int)) Int ((Start Int)) ((Start Int ((Variable Int) (- x) (+ x Start)))))
12 (synth-fun id3 ((x Int)) Int ((Start Int)) ((Start Int (0 (- x) (+ x Start)))))
13 (synth-fun id4 ((x Int)) Int ((Start Int)) ((Start Int ((- x) (+ x Start)))))
14 (declare-var x Int)
15 (constraint (= (id1 x) (id2 x) (id3 x) (id4 x) x))
16 (check-synth)
The utility method used for printing the synthesis solutions in the examples
above is defined separately in the
utils
module:
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Abdalrhman Mohamed, Mathias Preiner
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2022 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 * Utility methods.
14 */
15
16 #ifndef CVC5__UTILS_H
17 #define CVC5__UTILS_H
18
19 #include <cvc5/cvc5.h>
20
21 namespace utils {
22
23 /**
24 * Print solutions for synthesis conjecture to the standard output stream.
25 * @param terms the terms for which the synthesis solutions were retrieved
26 * @param sols the synthesis solutions of the given terms
27 */
28 void printSynthSolutions(const std::vector<cvc5::Term>& terms,
29 const std::vector<cvc5::Term>& sols);
30
31 } // namespace utils
32
33 #endif // CVC5__UTILS_H
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Abdalrhman Mohamed, Mathias Preiner, Yoni Zohar
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2022 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 * Implementations of utility methods.
14 */
15
16 #include "utils.h"
17
18 #include <iostream>
19
20 namespace utils {
21
22 using namespace cvc5;
23
24 /**
25 * Get the string version of define-fun command.
26 * @param f the function to print
27 * @param params the function parameters
28 * @param body the function body
29 * @return a string version of define-fun
30 */
31 std::string defineFunToString(const cvc5::Term& f,
32 const std::vector<cvc5::Term>& params,
33 const cvc5::Term& body)
34 {
35 cvc5::Sort sort = f.getSort();
36 if (sort.isFunction())
37 {
38 sort = sort.getFunctionCodomainSort();
39 }
40 std::stringstream ss;
41 ss << "(define-fun " << f << " (";
42 for (size_t i = 0, n = params.size(); i < n; ++i)
43 {
44 if (i > 0)
45 {
46 ss << ' ';
47 }
48 ss << '(' << params[i] << ' ' << params[i].getSort() << ')';
49 }
50 ss << ") " << sort << ' ' << body << ')';
51 return ss.str();
52 }
53
54 void printSynthSolutions(const std::vector<cvc5::Term>& terms,
55 const std::vector<cvc5::Term>& sols)
56 {
57 std::cout << '(' << std::endl;
58 for (size_t i = 0, n = terms.size(); i < n; ++i)
59 {
60 std::vector<cvc5::Term> params;
61 cvc5::Term body = sols[i];
62 if (sols[i].getKind() == cvc5::LAMBDA)
63 {
64 params.insert(params.end(), sols[i][0].begin(), sols[i][0].end());
65 body = sols[i][1];
66 }
67 std::cout << " " << defineFunToString(terms[i], params, body) << std::endl;
68 }
69 std::cout << ')' << std::endl;
70 }
71
72 } // namespace utils
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Mudathir Mohamed, Abdalrhman Mohamed, Andres Noetzli
4 *
5 * This file is part of the cvc5 project.
6 *
7 * Copyright (c) 2009-2022 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 * Utility methods.
14 */
15
16 import io.github.cvc5.CVC5ApiException;
17 import io.github.cvc5.Kind;
18 import io.github.cvc5.Sort;
19 import io.github.cvc5.Term;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 public class Utils
24 {
25 /**
26 * Get the string version of define-fun command.
27 *
28 * @param f the function to print
29 * @param params the function parameters
30 * @param body the function body
31 * @return a string version of define-fun
32 */
33 private static String defineFunToString(Term f, Term[] params, Term body)
34 {
35 Sort sort = f.getSort();
36 if (sort.isFunction())
37 {
38 sort = sort.getFunctionCodomainSort();
39 }
40 StringBuilder ss = new StringBuilder();
41 ss.append("(define-fun ").append(f).append(" (");
42 for (int i = 0; i < params.length; ++i)
43 {
44 if (i > 0)
45 {
46 ss.append(' ');
47 }
48 ss.append('(').append(params[i]).append(' ').append(params[i].getSort()).append(')');
49 }
50 ss.append(") ").append(sort).append(' ').append(body).append(')');
51 return ss.toString();
52 }
53
54 /**
55 * Print solutions for synthesis conjecture to the standard output stream.
56 *
57 * @param terms the terms for which the synthesis solutions were retrieved
58 * @param sols the synthesis solutions of the given terms
59 */
60 public static void printSynthSolutions(Term[] terms, Term[] sols) throws CVC5ApiException
61 {
62 System.out.println('(');
63 for (int i = 0; i < terms.length; ++i)
64 {
65 List<Term> params = new ArrayList<>();
66 Term body = sols[i];
67 if (sols[i].getKind() == Kind.LAMBDA)
68 {
69 for (Term t : sols[i].getChild(0))
70 {
71 params.add(t);
72 }
73 body = sols[i].getChild(1);
74 }
75 System.out.println(" " + defineFunToString(terms[i], params.toArray(new Term[0]), body));
76 }
77 System.out.println(')');
78 }
79 }
1 #!/usr/bin/env python
2 ###############################################################################
3 # Top contributors (to current version):
4 # Yoni Zohar, Abdalrhman Mohamed, Alex Ozdemir
5 #
6 # This file is part of the cvc5 project.
7 #
8 # Copyright (c) 2009-2022 by the authors listed in the file AUTHORS
9 # in the top-level source directory and their institutional affiliations.
10 # All rights reserved. See the file COPYING in the top-level source
11 # directory for licensing information.
12 # #############################################################################
13 #
14 # Utility Methods, translated from examples/api/utils.h
15 ##
16
17 import cvc5
18 from cvc5 import Kind
19
20 # Get the string version of define-fun command.
21 # @param f the function to print
22 # @param params the function parameters
23 # @param body the function body
24 # @return a string version of define-fun
25
26
27 def define_fun_to_string(f, params, body):
28 sort = f.getSort()
29 if sort.isFunction():
30 sort = f.getSort().getFunctionCodomainSort()
31 result = "(define-fun " + str(f) + " ("
32 for i in range(0, len(params)):
33 if i > 0:
34 result += " "
35 result += "(" + str(params[i]) + " " + str(params[i].getSort()) + ")"
36 result += ") " + str(sort) + " " + str(body) + ")"
37 return result
38
39
40 # Print solutions for synthesis conjecture to the standard output stream.
41 # @param terms the terms for which the synthesis solutions were retrieved
42 # @param sols the synthesis solutions of the given terms
43
44
45 def print_synth_solutions(terms, sols):
46 result = "(\n"
47 for i in range(0, len(terms)):
48 params = []
49 body = sols[i]
50 if sols[i].getKind() == Kind.LAMBDA:
51 params += sols[i][0]
52 body = sols[i][1]
53 result += " " + define_fun_to_string(terms[i], params, body) + "\n"
54 result += ")"
55 print(result)