In computer science, program synthesis is the task to construct a program that provably satisfies a given high-level formal specification. In contrast to program verification, the program is to be constructed rather than given; however, both fields make use of formal proof techniques, and both comprise approaches of different degrees of automation. In contrast to automatic programming techniques, specifications in program synthesis are usually non-algorithmic statements in an appropriate logical calculus. [1]
The primary application of program synthesis is to relieve the programmer of the burden of writing correct, efficient code that satisfies a specification. However, program synthesis also has applications to superoptimization and inference of loop invariants. [2]
During the Summer Institute of Symbolic Logic at Cornell University in 1957, Alonzo Church defined the problem to synthesize a circuit from mathematical requirements. [3] Even though the work only refers to circuits and not programs, the work is considered to be one of the earliest descriptions of program synthesis and some researchers refer to program synthesis as "Church's Problem". In the 1960s, a similar idea for an "automatic programmer" was explored by researchers in artificial intelligence.[ citation needed ]
Since then, various research communities considered the problem of program synthesis. Notable works include the 1969 automata-theoretic approach by Büchi and Landweber, [4] and the works by Manna and Waldinger (c. 1980). The development of modern high-level programming languages can also be understood as a form of program synthesis.
![]() | This section needs expansionwith: a more detailed overview of contemporary approaches. You can help by adding to it. (December 2022) |
The early 21st century has seen a surge of practical interest in the idea of program synthesis in the formal verification community and related fields. Armando Solar-Lezama showed that it is possible to encode program synthesis problems in Boolean logic and use algorithms for the Boolean satisfiability problem to automatically find programs. [5]
In 2013, a unified framework for program synthesis problems called Syntax-guided Synthesis (stylized SyGuS) was proposed by researchers at UPenn, UC Berkeley, and MIT. [6] The input to a SyGuS algorithm consists of a logical specification along with a context-free grammar of expressions that constrains the syntax of valid solutions. [7] For example, to synthesize a function f that returns the maximum of two integers, the logical specification might look like this:
(f(x,y) = x ∨ f(x,y) = y) ∧ f(x,y) ≥ x ∧ f(x,y) ≥ y
and the grammar might be:
<Exp>::= x | y | 0 | 1 | <Exp> + <Exp> | ite(<Cond>, <Exp>, <Exp>) <Cond>::=<Exp> <= <Exp>
where "ite" stands for "if-then-else". The expression
ite(x <= y, y, x)
would be a valid solution, because it conforms to the grammar and the specification.
From 2014 through 2019, the yearly Syntax-Guided Synthesis Competition (or SyGuS-Comp) compared the different algorithms for program synthesis in a competitive event. [8] The competition used a standardized input format, SyGuS-IF, based on SMT-Lib 2. For example, the following SyGuS-IF encodes the problem of synthesizing the maximum of two integers (as presented above):
(set-logic LIA) (synth-fun f ((x Int) (y Int)) Int ((i Int) (c Int) (b Bool)) ((i Int (c x y (+ i i) (ite b i i))) (c Int (0 1)) (b Bool ((<= i i))))) (declare-var x Int) (declare-var y Int) (constraint (>= (f x y) x)) (constraint (>= (f x y) y)) (constraint (or (= (f x y) x) (= (f x y) y))) (check-synth)
A compliant solver might return the following output:
((define-fun f ((x Int) (y Int)) Int (ite (<= x y) y x)))
Counter-example guided inductive synthesis (CEGIS) is an effective approach to building sound program synthesizers. [9] [10] CEGIS involves the interplay of two components: a generator which generates candidate programs, and a verifier which checks whether the candidates satisfy the specification.
Given a set of inputs I, a set of possible programs P, and a specification S, the goal of program synthesis is to find a program p in P such that for all inputs i in I, S(p, i) holds. CEGIS is parameterized over a generator and a verifier:
CEGIS runs the generator and verifier run in a loop, accumulating counter-examples:
algorithm cegis isinput: Program generator generate, verifier verify, specification spec, output: Program that satisifies spec, or failure inputs := empty set loopcandidate := generate(spec, inputs) ifverify(spec, candidate) thenreturncandidateelseverify yields a counterexample e add e to inputsend if
Implementations of CEGIS typically use SMT solvers as verifiers.
CEGIS was inspired by counterexample-guided abstraction refinement (CEGAR). [11]
Nr | Assertions | Goals | Program | Origin |
---|---|---|---|---|
51 | ||||
52 | ||||
53 | s | |||
54 | t | |||
55 | Resolve(51,52) | |||
56 | s | Resolve(52,53) | ||
57 | s | Resolve(53,52) | ||
58 | p ? s : t | Resolve(53,54) |
The framework of Manna and Waldinger, published in 1980, [12] [13] starts from a user-given first-order specification formula. For that formula, a proof is constructed, thereby also synthesizing a functional program from unifying substitutions.
The framework is presented in a table layout, the columns containing:
Initially, background knowledge, pre-conditions, and post-conditions are entered into the table. After that, appropriate proof rules are applied manually. The framework has been designed to enhance human readability of intermediate formulas: contrary to classical resolution, it does not require clausal normal form, but allows one to reason with formulas of arbitrary structure and containing any junctors ("non-clausal resolution"). The proof is complete when has been derived in the Goals column, or, equivalently, in the Assertions column. Programs obtained by this approach are guaranteed to satisfy the specification formula started from; in this sense they are correct by construction. [14] Only a minimalist, yet Turing-complete, [15] purely functional programming language, consisting of conditional, recursion, and arithmetic and other operators [note 3] is supported. Case studies performed within this framework synthesized algorithms to compute e.g. division, remainder, [16] square root, [17] term unification, [18] answers to relational database queries [19] and several sorting algorithms. [20] [21]
Proof rules include:
Murray has shown these rules to be complete for first-order logic. [24] In 1986, Manna and Waldinger added generalized E-resolution and paramodulation rules to handle also equality; [25] later, these rules turned out to be incomplete (but nevertheless sound). [26]
Nr | Assertions | Goals | Program | Origin |
---|---|---|---|---|
1 | Axiom | |||
2 | Axiom | |||
3 | Axiom | |||
10 | M | Specification | ||
11 | M | Distr(10) | ||
12 | M | Split(11) | ||
13 | M | Split(11) | ||
14 | x | Resolve(12,1) | ||
15 | x | Resolve(14,2) | ||
16 | x | Resolve(15,3) | ||
17 | y | Resolve(13,1) | ||
18 | y | Resolve(17,2) | ||
19 | x<y ? y : x | Resolve(18,16) |
As a toy example, a functional program to compute the maximum of two numbers and can be derived as follows.[ citation needed ]
Starting from the requirement description "The maximum is larger than or equal to any given number, and is one of the given numbers", the first-order formula is obtained as its formal translation. This formula is to be proved. By reverse Skolemization, [note 4] the specification in line 10 is obtained, an upper- and lower-case letter denoting a variable and a Skolem constant, respectively.
After applying a transformation rule for the distributive law in line 11, the proof goal is a disjunction, and hence can be split into two cases, viz. lines 12 and 13.
Turning to the first case, resolving line 12 with the axiom in line 1 leads to instantiation of the program variable in line 14. Intuitively, the last conjunct of line 12 prescribes the value that must take in this case. Formally, the non-clausal resolution rule shown in line 57 above is applied to lines 12 and 1, with
yielding true ∧ false) ∧ (x ≤ x ∧ y ≤ x ∧ true, which simplifies to .
In a similar way, line 14 yields line 15 and then line 16 by resolution. Also, the second case, in line 13, is handled similarly, yielding eventually line 18.
In a last step, both cases (i.e. lines 16 and 18) are joined, using the resolution rule from line 58; to make that rule applicable, the preparatory step 15→16 was needed. Intuitively, line 18 could be read as "in case , the output is valid (with respect to the original specification), while line 15 says "in case , the output is valid; the step 15→16 established that both cases 16 and 18 are complementary. [note 5] Since both line 16 and 18 comes with a program term, a conditional expression results in the program column. Since the goal formula has been derived, the proof is done, and the program column of the "" line contains the program.
In algorithmic information theory, the Kolmogorov complexity of an object, such as a piece of text, is the length of a shortest computer program that produces the object as output. It is a measure of the computational resources needed to specify the object, and is also known as algorithmic complexity, Solomonoff–Kolmogorov–Chaitin complexity, program-size complexity, descriptive complexity, or algorithmic entropy. It is named after Andrey Kolmogorov, who first published on the subject in 1963 and is a generalization of classical information theory.
The P versus NP problem is a major unsolved problem in theoretical computer science. Informally, it asks whether every problem whose solution can be quickly verified can also be quickly solved.
First-order logic—also called predicate logic, predicate calculus, quantificational logic—is a collection of formal systems used in mathematics, philosophy, linguistics, and computer science. First-order logic uses quantified variables over non-logical objects, and allows the use of sentences that contain variables, so that rather than propositions such as "Socrates is a man", one can have expressions in the form "there exists x such that x is Socrates and x is a man", where "there exists" is a quantifier, while x is a variable. This distinguishes it from propositional logic, which does not use quantifiers or relations; in this sense, propositional logic is the foundation of first-order logic.
In propositional logic, modus ponens, also known as modus ponendo ponens, implication elimination, or affirming the antecedent, is a deductive argument form and rule of inference. It can be summarized as "P implies Q.P is true. Therefore, Q must also be true."
In computability theory, a primitive recursive function is, roughly speaking, a function that can be computed by a computer program whose loops are all "for" loops. Primitive recursive functions form a strict subset of those general recursive functions that are also total functions.
The McCarthy 91 function is a recursive function, defined by the computer scientist John McCarthy as a test case for formal verification within computer science.
In computer science, model checking or property checking is a method for checking whether a finite-state model of a system meets a given specification. This is typically associated with hardware or software systems, where the specification contains liveness requirements as well as safety requirements.
In theoretical computer science, an algorithm is correct with respect to a specification if it behaves as specified. Best explored is functional correctness, which refers to the input-output behavior of the algorithm: for each input it produces an output satisfying the specification.
In computer science, a loop invariant is a property of a program loop that is true before each iteration. It is a logical assertion, sometimes checked with a code assertion. Knowing its invariant(s) is essential in understanding the effect of a loop.
The situation calculus is a logic formalism designed for representing and reasoning about dynamical domains. It was first introduced by John McCarthy in 1963. The main version of the situational calculus that is presented in this article is based on that introduced by Ray Reiter in 1991. It is followed by sections about McCarthy's 1986 version and a logic programming formulation.
In mathematical logic and automated theorem proving, resolution is a rule of inference leading to a refutation-complete theorem-proving technique for sentences in propositional logic and first-order logic. For propositional logic, systematically applying the resolution rule acts as a decision procedure for formula unsatisfiability, solving the Boolean satisfiability problem. For first-order logic, resolution can be used as the basis for a semi-algorithm for the unsatisfiability problem of first-order logic, providing a more practical method than one following from Gödel's completeness theorem.
In computer science, separation logic is an extension of Hoare logic, a way of reasoning about programs. It was developed by John C. Reynolds, Peter O'Hearn, Samin Ishtiaq and Hongseok Yang, drawing upon early work by Rod Burstall. The assertion language of separation logic is a special case of the logic of bunched implications (BI). A CACM review article by O'Hearn charts developments in the subject to early 2019.
In computer science and mathematical logic, satisfiability modulo theories (SMT) is the problem of determining whether a mathematical formula is satisfiable. It generalizes the Boolean satisfiability problem (SAT) to more complex formulas involving real numbers, integers, and/or various data structures such as lists, arrays, bit vectors, and strings. The name is derived from the fact that these expressions are interpreted within ("modulo") a certain formal theory in first-order logic with equality. SMT solvers are tools that aim to solve the SMT problem for a practical subset of inputs. SMT solvers such as Z3 and cvc5 have been used as a building block for a wide range of applications across computer science, including in automated theorem proving, program analysis, program verification, and software testing.
Richard Jay Waldinger is a computer science researcher at SRI International's Artificial Intelligence Center whose interests focus on the application of automated deductive reasoning to problems in software engineering and artificial intelligence.
The KeY tool is used in formal verification of Java programs. It accepts specifications written in the Java Modeling Language to Java source files. These are transformed into theorems of dynamic logic and then compared against program semantics that are likewise defined in terms of dynamic logic. KeY is significantly powerful in that it supports both interactive and fully automated correctness proofs. Failed proof attempts can be used for a more efficient debugging or verification-based testing. There have been several extensions to KeY in order to apply it to the verification of C programs or hybrid systems. KeY is jointly developed by Karlsruhe Institute of Technology, Germany; Technische Universität Darmstadt, Germany; and Chalmers University of Technology in Gothenburg, Sweden and is licensed under the GPL.
DEVS, abbreviating Discrete Event System Specification, is a modular and hierarchical formalism for modeling and analyzing general systems that can be discrete event systems which might be described by state transition tables, and continuous state systems which might be described by differential equations, and hybrid continuous state and discrete event systems. DEVS is a timed event system.
In computational complexity theory, the language TQBF is a formal language consisting of the true quantified Boolean formulas. A (fully) quantified Boolean formula is a formula in quantified propositional logic where every variable is quantified, using either existential or universal quantifiers, at the beginning of the sentence. Such a formula is equivalent to either true or false. If such a formula evaluates to true, then that formula is in the language TQBF. It is also known as QSAT.
In formal verification, finite state model checking needs to find a Büchi automaton (BA) equivalent to a given linear temporal logic (LTL) formula, i.e., such that the LTL formula and the BA recognize the same ω-language. There are algorithms that translate an LTL formula to a BA. This transformation is normally done in two steps. The first step produces a generalized Büchi automaton (GBA) from a LTL formula. The second step translates this GBA into a BA, which involves a relatively easy construction. Since LTL is strictly less expressive than BA, the reverse construction is not always possible.
Structural synthesis of programs (SSP) is a special form of (automatic) program synthesis that is based on propositional calculus. More precisely, it uses intuitionistic logic for describing the structure of a program in such a detail that the program can be automatically composed from pieces like subroutines or even computer commands. It is assumed that these pieces have been implemented correctly, hence no correctness verification of these pieces is needed. SSP is well suited for automatic composition of services for service-oriented architectures and for synthesis of large simulation programs.
Anti-unification is the process of constructing a generalization common to two given symbolic expressions. As in unification, several frameworks are distinguished depending on which expressions are allowed, and which expressions are considered equal. If variables representing functions are allowed in an expression, the process is called "higher-order anti-unification", otherwise "first-order anti-unification". If the generalization is required to have an instance literally equal to each input expression, the process is called "syntactical anti-unification", otherwise "E-anti-unification", or "anti-unification modulo theory".