Solving equations using propositional logic - logic

I'm looking for ideas on how to encode mathematical equations into cnf-sat form, so that they can be solved by an open source SAT solver like MiniSat.
So, how do I convert something like:
3x + 4y - z = 14
-2x - 4z <= -6
x - 3y + z >= 15
into a propositional equation that can be solved by using SAT Solvers.
Any suggestions because I'm stumped??

I'm assuming you're looking for an integer solution to your equations since Integer Linear Programming is a known NP-hard problem, as is SAT. (Linear programming without the integer constraint is in P, of course.)
You could convert your equations to a SAT instance but your time would be more fruitfully spent learning how to use an SMT solver, which will let you express your equations much more naturally. As an example, using Microsoft's Z3 solver, your equations above could be solved with this simple program:
(declare-fun x () Int)
(declare-fun y () Int)
(declare-fun z () Int)
(assert (= (+ (* 3 x) (* 4 y) (- z)) 14))
(assert (<= (- (* (- 2) x) (* 4 z)) (- 6)))
(assert (>= (+ (- x (* (- 3) y)) z) 15))
(check-sat)
(get-model)
You can paste that program into an online Z3 sandbox and click the play button to see it solve the equations.

Related

SICP Exercise 1.8 - Why doesn't my function terminate?

I'm trying to implement Newton's method for cube roots, but my function seems to hang. My code is almost identical to the code the book shows for the square root, with the improve function modified as appropriate.
Here is my code...
(define (cube-root x)
(cube-root-iter 1.0 x))
(define (cube-root-iter guess x)
(if (good-enough? guess x)
guess
(cube-root-iter (improve x guess) x)
)
)
(define (good-enough? guess x)
(< (abs (- (* guess guess) x)) 0.001))
(define (improve x guess)
(/ (+ (/ x (* guess guess)) (* 2 guess)) 3)
)
I tested improve and good-enough? independently, and they seem to give the right answers. Anyone know why my code doesn't terminate?
I'm doing this in Racket with the sicp package in case that makes any difference.
You want to compute the cube root. The cube root of x means a value y for which y*y*y = x, by definition. You try to approximate y using guess, but you compute only y^2. Need to multiply it 3 times:
(define (good-enough? guess x)
(< (abs (- (* guess guess guess) x))
0.001))
If you multiply it only 2 times, y^2 will never get close enough to y^3, which gets closer to x. If you try to compute cube root of 1 or of 0 with your code it might work however (and only for these inputs it might work).

SICP 2.16 interval-arithmetic (scheme)

This isn't a homework question, I'm just left unsatisfied with my understanding of interval arithmetic and the implications of exercise 2.16.
The interval arithmetic defined by section 2.14 does not exhibit the properties of normal arithmetic. Two should be equivalent operations, (r1*r2)/(r1 + r2) and 1/(1/r1 + 1/r2),
give different results. The exercise asks why this is the case, and if it is possible to construct an interval-arithmetic system in which this is not the case.
The section is addressing the calculation of error margins of resistance of electrical components. I'm not sure I understand what it would mean, in these terms, to multiply and divide intervals. What is the application to multiplying two intervals together?
Is it possible to construct an interval-arithmetic system without the problem in this example?
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#%_sec_2.1.4
(define (make-interval a b)
(cons a b))
(define (make-center-width c w)
(make-interval (- c w) (+ c w)))
(define (make-center-percent c p)
(make-center-width c (* c (/ p 100.0))))
(define (lower-bound i)
(car i))
(define (upper-bound i)
(cdr i))
(define (center i)
(/ (+ (upper-bound i) (lower-bound i)) 2))
(define (width i)
(/ (- (upper-bound i) (lower-bound i)) 2))
(define (percent i)
(* 100.0 (/ (width i) (center i))))
(define (add-interval x y)
(make-interval (+ (lower-bound x) (lower-bound y))
(+ (upper-bound x) (upper-bound y))))
(define (sub-interval x y)
(make-interval (- (lower-bound x) (lower-bound y))
(- (upper-bound x) (upper-bound y))))
(define (mul-interval x y)
(let ((p1 (* (lower-bound x) (lower-bound y)))
(p2 (* (lower-bound x) (lower-bound y)))
(p3 (* (lower-bound x) (lower-bound y)))
(p4 (* (lower-bound x) (lower-bound y))))
(make-interval (min p1 p2 p3 p4)
(max p1 p2 p3 p4))))
(define (div-interval x y)
(if (= (width y ) 0)
(error "division by interval with width 0")
(mul-interval x
(make-interval (/ 1.0 (upper-bound y))
(/ 1.0 (lower-bound y))))))
(define (parl1 r1 r2)
(div-interval (mul-interval r1 r2)
(add-interval r1 r2)))
(define (parl2 r1 r2)
(let ((one (make-interval 1 1)))
(div-interval one
(add-interval (div-interval one r1)
(div-interval one r2))))
(define (r1 (make-interval 4.0 3.2)))
(define (r2 (make-interval 3.0 7.2)))
(center (parl1 r1 r2))
(width (parl1 r1 r2))
(newline)
(center (parl2 r1 r2))
(width (parl2 r1 r2))
This happens because the operations in the interval arithmetic do not have the arithmetic structure of a field.
As Sussman says, the exercise is difficult -- you need to check each of the operations of the field structure, and see which one is not satisfied.
The exercise asks us to show that the interval arithmetic is not the arithmetic of the ranges of functions.
A function like f (x) = x^2 defined on a domain [-1, 1] has the
range [0,1], which is included in [-1,1] * [-1,1] = [-1,1], obtained by replacing the symbol x by the domain of the symbol x.
If we define a similar function that uses a different variable for each dimension, like in f(x,y) = x * y, then the range of this function, when defined on the domain [-1,1] * [-1,1], is the same as the interval [-1,1] * [-1,1] = [-1, 1], because x is used once, and so with y.
It happens that all the time when the function f(.., x, ..) is continous in each variable x we have the range arithmetics to be identical with interval arithmetics if each symbol is used only once in definition of f.
In the first formula of Alice, parallel resistor is computed
repeating 2 times the variable R1, and 2 times the variable R2,
and using the same argument the range of this function is included
in the product of the corresponding intervals obtained from the
formula of the function, by replacing each name by corresponding
domain interval, but it is not strictly the same.
We are asked either to rewrite any function such that the range of the rewritten function be the same as the interval obtained by applying the rewritten function's formula, wih names replaced by intervals equal to the domain of the corresponding name from the rewritten function, or to show that this is not possible for each possible function.
This problem is called dependency problem, and it is a large
problem, whose understanding is out of the purpose of SICP, and requires differential equations in multiple variables to solve it.
The purpose of this exercise is , as Sussman himself said, just to show that data can be encoded in multiple ways. The focus is not on mathematics , but on data abstraction.
The easiest way to understand the problem is looking at the very simple expression e = x/x where x is in [2,3]. If we use interval arithmetic, we get that e is in [2/3, 3/2], however second grade arithmetic shows that e=x/x=1. So what gives?
Well it is actually very simple: when using interval arithmetic I made the mistake of assuming x can have two different values at the same time.
the maximum value of e is given when the numerator is 3 and the denominator is 2, however since both should always be the same this is not possible.
So, is it ever possible to use interval arithmetic? Yes, when all intervals appear only once, since then you would not have the problem of different values for the same variable in different interval calculations.
Is it possible to create an arithmetic package which does not have this problem? No, since not every function can be written where every variable appears only once. This problem is known as the dependency problem.

Scheme Programming Language

I am trying to write a scheme program, but I am trying to figure out how can i do this:
suppose, I have called a function named addFunc, that takes two input numbers,
computes the sum squares of each number and returns the sum of the two sum
squares
in math, : if addFunc were called with 3 and 2, it will computer the sum squares of 3 as 1*1
+ 2*2 + 3*3 = 14 and sum squares of 2 as 1*1 + 2*2 = 5 and then returns 19 as a
result.
how can i write this in scheme programing language?
SICP is a good resource for learning scheme.
(define (sum-of-squares x)
(if (= 1 x)
1
(+ (* x x) (sum-of-squares (- x 1)))))
(define (homework x y)
(+ (sum-of-squares x) (sum-of-squares y)))

SICP exercise 1.16, where is my bug, because it looks right to me

I've just started working through this book for fun; I wish it were homework, but I could never afford to attend MIT, and there are tons of people smarter than me anyway. :p
fast-exp is supposed to find b^n, i.e. 4^2 = 16, 3^3 = 27
(define (fast-exp b n)
(define (fast-exp-iter n-prime a)
(cond ((= n-prime 1) a)
((= (remainder n-prime 2) 1) (fast-exp-iter (- n-prime 1) (* a b)))
(else (fast-exp-iter (/ n-prime 2) (* a b b)))))
(fast-exp-iter n 1))
fast-exp 4 2; Expected 16, Actual 2
You forgot to call fast-exp. Instead, you evaluated three separate atoms. To actually evaluate the fast-exp of 4 to the 2, you'd have to write
(fast-exp 4 2)
The solution you have written here is also incorrect. e.g. Check out (fast-exp 2 6). Expected: 64, actual: 32.
Your solution is calculating wrong answers. (See http://ideone.com/quT6A) In fact, how you in principle can write a tail-recursive fast exponentiation passing only two numbers as arguments? I don't think it's even possible, because in the middle of computation you don't know what multiplier to use if you encounter odd exponent.
But I can give an example of working solution that is exactly what is expected by SICP authors (iterative process using "invariant quantity" (a * b^n), where a is initially 1)
(define (pow x y)
(define (powi acc x y)
(cond
((= y 0) acc)
((odd? y) (powi (* acc x) x (- y 1)))
(else (powi acc (* x x) (/ y 2)))))
(powi 1 x y))

Expression Simplification

I have this code to calculate derivatives:
(define (diff x expr)
(if (not (list? expr))
(if (equal? x expr) 1 0)
(let ((u (cadr expr)) (v (caddr expr)))
(case (car expr)
((+) (list '+ (diff x u) (diff x v)))
((-) (list '- (diff x u) (diff x v)))
((*) (list '+
(list '* u (diff x v))
(list '* v (diff x u))))
((/) (list ‘div (list '-
(list '* v (diff x u))
(list '* u (diff x v)))
(list '* u v)))
))))
How can I simplify algebraic expressions?
instead of x + x show 2x
and
instead of x * x show x^2
Simplification of algegraic expressions is quite hard, especially compared to the computation of derivates. Simplification should be done recursively. You simplify the innermost expressions first. Don't try too much at a time. I'd start with the most basic simplifications only e.g:
0 + x -> x
0 * x -> 0
1 * x -> x
x ^ 0 -> 1
x ^ 1 -> x
Replace subtraction by addition and division by multiplication
x - y -> x + (-1)*x
x / y -> x ^ (-1)
This may not look as a simplification, but it will simplify your code. You can always reverse this step at the end.
Then you use associativity and commutativity to sort your terms. Move numerical values to the left side, sort variables by some predefined order (it doesn't have to be alphabetical but it should always be the same)
(x * y) * z -> x * (y * z)
x * 2 -> 2 * x
2 * (x * 3) -> 2 * (3 * x)
Simplify exponents
(x ^ y) ^ z -> x^(y * z)
Simplify the numerical parts.
2 * (3 * x) -> 6 * x
2 + (3 + x) -> 5 + x
Once you have done this you can think about collecting common expressions.
Perhaps this code from PAIP will be useful. It's Common Lisp, which is quite similar to Scheme. The entry point is the simp function.
Note that it also uses this file.
Historical note: The relevant PAIP chapter refers to Macsyma, the computer algebra system developed in MIT in the 1960s, and was the basis for Mathematica, Maple (now in Matlab) and other tools.
Here's a start:
Change the your derivative function from (define (diff x expr) ...) to something like (define (simp expr) ...).
for the x + x case, do something like
(case (car expr)
((+) (if (equal u v) ; check for identical subexpressions
`(* ,(simp u) 2) ; if u==v, simplify 2u
`(+ ,(simp u) ,(simp v))))
...)
The x * x case should be similar. Eventually you may want to convert the if into a cond if you need to do a lot of different simplifications.
This is a Hard Problem to solve completely and the links eliben gives are worth looking at.
The general problem is hard, but you can get a long way with a sum-of-products normal form, represented as a finite map from key (variable name) to coefficient. This form is great for linear equations and linear solving, and it can be extended to multiplication and powers without too much trouble. If you define "smart constructors" for arithmetic on this form you can get some reasonable symbolic differentiation and equation solving going.
This is a quick hack, but I've used it in a few applications. Several it worked in; a couple times it wasn't good enough. For something more serious you're talking years of work.
If you want code examples you can read about one of my equation solvers.

Resources