In many early constraint systems, constraints were little more than functions which were evaluated in a data-driven way. The logic programming paradigm, however, suggested that programs should be runnable ``in both directions''. In addition to evaluating a function yielding the result Y, it must be possible to solve the equation for a given value Y but unknown arguments .
Naturally when a function is evaluated ``backwards'' - i.e. from its result producing its input - it is no longer a function! Attempts to integrate functional and logic programming motivated much research on equation solving systems, and in the end spawned constraint logic programming.
It was recognised that constraint solving lies at the heart of logic programming, in its built-in unification. Researchers began to replace (syntactic) unification with other equation solvers. An important example of this was Boolean unification: this is a solver for equations between Boolean expressions, whose possible values are only true or false. This development has now found a commercially successful application for design and verification of digital circuits. Moreover Boolean unification is also being applied to the design and verification of real-time control software.