define: expected only one expression for the function body, but found 1 extra part - racket

I got an error. Can someone help me please?
define: expected only one expression for the function body, but found 1 extra part
(sqrt (+ (* (- x2 x1) (- x2 x1)) (* (- y2 y1) (- y2 y1))))
(if( < circles-position abs(- r1 r2) "Interior" if(< (+ r1 r2) d) "External" "Intersect")))

The body of function must in the teaching languages be one expression only.
Above you have two expressions.
It's easier to read your code, if you indent if on three lines:
(sqrt (+ (* (- x2 x1) (- x2 x1))
(* (- y2 y1) (- y2 y1))))
(if (< circles-position (abs (- r1 r2)))
"Interior"
(if (< (+ r1 r2) d)
"External"
"Intersect")))

Related

Holding greater or equal relation between two terms

H:count k (match d with
|nil=>nil
|s::l=>(s::firstn n l))
end <=
count 0 (match d with
|nil=>nil
|s::l=>(s::firstn n l))
end
Where n is natural number and d is list nat. From above H may i extract information that (s::firstn n l) contains more zeros than k.

Is there anyone, who can help me with my smt homework?

Homework:
Lab 4
In the second SMT lab exercise (Lab 4) we are going to solve the Chicken McNugget problem with the help of an SMT solver (an instance of the Frobenious Coin Problem).
Assume that a fast food chain sells boxes with fried chicken pieces in the sizes A=7, B= 9, C=16. Your friends and you are hungry and want to eat X chicken pieces (a natural number). The first question we are going to address is whether it is possible to buy U boxes of size A, V boxes of size B and W boxes of size C such that you get exactly X chicken pieces (without left over). In the first part (1 point) formulate this as an SMT problem and try to solve it for the given A, B, C values and X=40. First determine the logic you need and then give a manual incoding into SMT lib. In the second part (1.5 point) check that X0 = X+0, ..., X6 = X + 6 also have similar representations in terms of U0,V0,W0, ..., U6,V6,W6. With the help of this encoding determine the minimal number X which gives a satisfiable solution. Then Y=X-1 is the solution of the Chicken McNuggets problem for the fixed A, B, C values above, which means that it is the largest number Y which can NOT be represented this way, or in terms of chicken pieces, no matter how many (U,V,W) boxes of the given sizes (A,B,C) you buy and your friends do eat exactly Y pieces, then there has to be some left over pieces. Generating these two SMT LIB encodings for these two parts for the given concrete A,B,C and being able to present the solution (and modify and check it manually for other values) will give you thus half the points (2.5) for the Lab. You will be required to bring your own laptop on which you have installed and can use the SMT solver for the presentation (the web interface is not enough).
My SMT Code:
(set-logic QF_AUFNIA)
(declare-const u Int)
(declare-const v Int)
(declare-const w Int)
(declare-const x Int)
(assert (>= u 0))
(assert (>= v 0))
(assert (>= w 0))
(assert (= 40(+ (* u 7)(* v 9)(* w 16))))
(assert (= 40(+ (* u 7)(* v 9))))
(assert (= 40(+ (* v 9)(* w 16))))
(assert (= 40(+ (* u 7)(* w 16))))
(assert (= 40(* v 9)))
(assert (= 40(* u 7)))
(assert (= 40(* w 16)))
(declare-const x0 Int)
(declare-const x1 Int)
(declare-const x2 Int)
(declare-const x3 Int)
(declare-const x4 Int)
(declare-const x5 Int)
(declare-const x6 Int)
(declare-const u0 Int)
(declare-const u1 Int)
(declare-const u2 Int)
(declare-const u3 Int)
(declare-const u4 Int)
(declare-const u5 Int)
(declare-const u6 Int)
(declare-const v0 Int)
(declare-const v1 Int)
(declare-const v2 Int)
(declare-const v3 Int)
(declare-const v4 Int)
(declare-const v5 Int)
(declare-const v6 Int)
(declare-const w0 Int)
(declare-const w1 Int)
(declare-const w2 Int)
(declare-const w3 Int)
(declare-const w4 Int)
(declare-const w5 Int)
(declare-const w6 Int)
(declare-const y Int)
(assert (= x0 (+ x 0)))
(assert (= x1 (+ x 1)))
(assert (= x2 (+ x 2)))
(assert (= x3 (+ x 3)))
(assert (= x4 (+ x 4)))
(assert (= x5 (+ x 5)))
(assert (= x6 (+ x 6)))
(assert (= u0 (+ u 0)))
(assert (= u1 (+ u 1)))
(assert (= u2 (+ u 2)))
(assert (= u3 (+ u 3)))
(assert (= u4 (+ u 4)))
(assert (= u5 (+ u 5)))
(assert (= u6 (+ u 6)))
(assert (= v0 (+ v 0)))
(assert (= v1 (+ v 1)))
(assert (= v2 (+ v 2)))
(assert (= v3 (+ v 3)))
(assert (= v4 (+ v 4)))
(assert (= v5 (+ v 5)))
(assert (= v6 (+ v 6)))
(assert (= w0 (+ w 0)))
(assert (= w1 (+ w 1)))
(assert (= w2 (+ w 2)))
(assert (= w3 (+ w 3)))
(assert (= w4 (+ w 4)))
(assert (= w5 (+ w 5)))
(assert (= w6 (+ w 6)))
(assert (= x 40))
(assert (= x (+ (* u 7)(* v 9)(* w 16))))
(check-sat)
(exit)
I wrote my code, but it is always unsatisfiable. It is said, that X should be satisfiable. I tried X almost with every figure to get it satisfiable, but it doesn't work.
Is there anyone who could help me?
You're getting unsat for a very simple reason. Consider this line:
(assert (= 40(* u 7)))
where u is an Int value. Z3 can easily determine that there is no such integer value, as 7 does not divide 40. Similarly, you have many other constraints that are just not satisfiable for similar reasons.
Here's a simple idea to push forward. If someone gave you u, v, and w values and asked you to just check that they are indeed a correct solution, how would you program that? Write down what properties these values would have to satisfy, and simply assert them. Through the magic of constraint solving, what you'd consider "checking" a solution will become "finding" the solution. Hope that helps!
Also, stack-overflow works the best when you ask specific and pointed questions, instead of dumping an entire problem set. You'll get much better answers if you ask specific questions. Best of luck!

How do i get Cosine Product approximation to work in Racket?

For homework, I have to write a function which presents a product approximation of the cosine function which recurses until the difference between the current and newly calculated product is less than a threshold.
(define (p_cos x)
(let* ([n 1]
[xnew (* x (p_cos_aux x (+ n 1)))])
(if (< (abs (- x xnew)) TOL)
x
(p_cos_aux xnew (+ n 1)))))
(define (p_cos_aux x n)
(- 1 (/ (* 4 (square x)) (* (square pi) (square (- (* 2 n) 1))))))
the values are expected to be:
(p_cos 0)
=> 1
(p_cos (/ pi 2))
=> 0
however I am getting:
> (p_cos (/ pi 2))
0.9122085048010974
> (p_cos 0)
0
Can anyone explain to me why my outputs are so far from the expected values?
I'm basing my code off of this infinite product formula for approximations of cosine:
cos(x) = ∏n=1n→∞ [ 1 − (4x2)/(π2(2n - 1)2) ]
Since you're basing this on this math formula:
cos(x) = ∏n=1n→∞ [ 1 − (4x2)/(π2(2n - 1)2) ]
It looks like your p_cos_aux function is handling the stuff inside the square brackets in the formula. So you still need to define cosine to be equal to
cos(x) = ∏n=1n→∞ (p_cos_aux x n)
If you want your code to return an answer, then you should to do this for only a finite number n. You can do this with either recursion or a for loop. In this case, Racket's for/product loop is convenient:
(for/product ([n (in-range 1 ...some-large-number...)])
(p_cos_aux x n))
Let's try putting in 100 for the large number:
(define (p_cos x)
(for/product ([n (in-range 1 100)])
(p_cos_aux x n)))
Trying it out:
> (p_cos 0)
1
> (p_cos (* 1/4 pi))
0.707553324600212
> (p_cos (* 1/2 pi))
0.0
> (p_cos (* 3/4 pi))
-0.7111358730792002
> (p_cos pi)
-1.01015228426396
> (p_cos (* 5/4 pi))
-0.7183556654338034
> (p_cos (* 3/2 pi))
-0.0
> (p_cos (* 7/4 pi))
0.7293234913165205
> (p_cos (* 2 pi))
1.0412338930105425
It's not perfect, but you can get better approximations by increasing the 100 to even larger numbers.

Isabelle: this lemma about polynomials is only provable for idoms

In short: I have only a backgroung in computer science and not mathematics. I have proven a lemma in Isabelle for idoms and concluded that it cannot be proven for polynomials of rings 'a::comm_ring_1 poly. But I am not fully sure.
In the Isabelle library, there is the following lemma:
Polynomial.coeff_mult_degree_sum:
coeff (p * q) (degree p + degree q) = coeff p (degree p) * coeff q (degree q)
(where (p∷?'a∷comm_semiring_0 poly) and (q∷?'a∷comm_semiring_0 poly); the lemma is from HOL/Library/Polynomial.thy)
I have proven the following lemma in Isabelle (product/sum of polynomials):
lemma coeff_mult_setprod_setsum:
fixes S :: "'b::idom poly set"
shows "finite S ⟹ coeff (setprod (λx. x) S) (setsum (λx. degree x) S) = setprod (λ x. coeff x (degree x)) S"
by (induct rule: finite_induct, simp, simp_all add: coeff_setprod_setsum_induct_step)
My question:
Is it true that the above lemma requires idoms (i.e., without zero divisors) and cannot be proven for S :: "'a::comm_ring_1 poly set"?
..
..
Here is the full proof:
(* tested with Isabelle2013-2 *)
theory Notepad
imports
Main
"~~/src/HOL/Library/Polynomial"
begin
lemma degree_product_setsum:
fixes S :: "('a::comm_ring_1) poly set"
assumes "finite S"
shows "degree (∏S) ≤ setsum degree S"
using `finite S`
proof-
(* Sledgehammer proof *)
have th1: "⋀x⇩1 x⇩2 x⇩3. degree ((x⇩1∷'a poly) * x⇩2) ≤ degree x⇩1 + x⇩3 ∨ ¬ degree x⇩2 ≤ x⇩3"
by (metis add_le_cancel_right degree_mult_le dual_order.trans nat_add_commute)
show ?thesis using `finite S`
apply(induct)
apply(simp)
by (metis (full_types) th1 setprod.insert setsum.insert)
qed
lemma coeff_setprod_setsum_induct_step:
fixes x :: "'b::idom poly" and F :: "'b::idom poly set"
assumes a1: "finite F"
and a2: "x ∉ F"
and a3: "coeff (∏F) (setsum degree F) = (∏x∷'b poly∈F. coeff x (degree x))"
shows "coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏x∈F. coeff x (degree x))"
proof-
from coeff_mult_degree_sum[of x "∏F"]
have 1: "coeff (x * ∏F) (degree x + degree (∏F)) = coeff x (degree x) * coeff (∏F) (degree (∏F))" by fast
from a1
have 3: "degree (∏F) ≤ setsum degree F" using degree_product_setsum by fast
(** BEWARE SLEDGEHAMMER PROOF! (don't care at the moment about it) *)
show ?thesis
proof -
have "(∏R∈F. coeff R (degree R)) = 0 ∨ setsum degree F ≤ degree (∏F)"
by (metis a3 le_degree)
hence f1: "setsum degree F = degree (∏F) ∨ (∏R∈F. coeff R (degree R)) = 0"
by (metis "3" le_antisym)
have f2: "setsum degree F = degree (∏F) ∨ ¬ setsum degree F ≤ degree (∏F)"
by (metis "3" le_antisym)
hence "coeff (∏F) (degree (∏F)) = (∏R∈F. coeff R (degree R)) ⟶ coeff x (degree x) * (∏R∈F. coeff R (degree R)) = coeff (x * ∏F) (degree (x * ∏F))"
by (metis (full_types) "1" degree_mult_eq leading_coeff_0_iff mult_eq_0_iff)
moreover
{ assume "coeff (∏F) (degree (∏F)) ≠ (∏R∈F. coeff R (degree R))"
hence "setsum degree F ≠ degree (∏F)"
using a3 by force }
moreover
{ assume "coeff x (degree x) * (∏R∈F. coeff R (degree R)) = coeff (x * ∏F) (degree (x * ∏F))"
hence "setsum degree F = degree (∏F) ⟶ coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏R∈F. coeff R (degree R))"
by (metis (lifting, no_types) "1" calculation(2))}
ultimately have "setsum degree F = degree (∏F) ⟶ coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏R∈F. coeff R (degree R))"
by fastforce
hence "setsum degree F ≠ degree (∏F) ∧ ¬ degree x + setsum degree F ≤ degree x + degree (∏F) ∨ coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏R∈F. coeff R (degree R))"
using f2 add_le_cancel_left by blast
hence "setsum degree F ≠ degree (∏F) ∧ coeff (x * ∏F) (degree x + setsum degree F) = 0 ∨ coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏R∈F. coeff R (degree R))"
by (metis (full_types) coeff_0 degree_mult_eq le_degree mult_eq_0_iff)
thus "coeff (x * ∏F) (degree x + setsum degree F) = coeff x (degree x) * (∏x∈F. coeff x (degree x))"
using f1 by force
qed
qed
lemma coeff_setprod_setsum:
fixes S :: "'b::idom poly set" (* lemma is not true for S :: "'a::comm_ring_1 poly set"*)
shows "finite S ⟹ coeff (setprod (λx. x) S) (setsum (λx. degree x) S) = setprod (λ x. coeff x (degree x)) S"
by (induct rule: finite_induct, simp, simp_all add: coeff_setprod_setsum_induct_step)
Looking at three polynomials, the problem is visible:
notepad
begin
fix p q r :: "'a::comm_ring_1 poly"
have "coeff (p * q * r) (degree (p * q) + degree r) = coeff (p * q) (degree (p * q)) * coeff r (degree r)"
using Polynomial.coeff_mult_degree_sum[of "p * q" r] by fast
end
However, it is impossible to imply that degree (p * q) is equal to degree p + degree q for the type 'a::comm_ring_1 poly.
Consider this lemma that requires idoms:
Polynomial.degree_mult_eq: (?p∷?'a∷idom poly) ≠ (0∷?'a∷idom poly) ⟹ (?q∷?'a∷idom poly) ≠ (0∷?'a∷idom poly) ⟹
degree (?p * ?q) = degree ?p + degree ?q
..
..
..
Solution from Brian Huffman
lemma degree_setprod_le: "degree (∏i∈S. f i) ≤ (∑i∈S. degree (f i))"
apply(cases "finite S", simp_all, induct rule: finite_induct, simp_all)
by (metis (lifting) degree_mult_le dual_order.trans nat_add_left_cancel_le)
lemma coeff_mult_sum: "degree p ≤ m ⟹ degree q ≤ n ⟹ coeff (p * q) (m + n) = coeff p m * coeff q n"
apply(cases "degree p = m ∧ degree q = n")
apply(insert coeff_mult_degree_sum[of p q], simp) [1]
apply(cases "degree p < m", cases "degree q < n")
by(insert coeff_eq_0[of q n] coeff_eq_0[of p m] degree_mult_le[of p q] coeff_eq_0[of "p*q" "m + n"], simp_all)
lemma coeff_mult_setprod_setsum:
"coeff (setprod (λx. x) S) (setsum (λx. degree x) S) = setprod (λ x. coeff x (degree x)) S"
by(cases "finite S", induct rule: finite_induct, simp_all add: coeff_mult_sum degree_setprod_le)
Yes, your lemma coeff_mult_setprod_setsum is in fact provable for arbitrary comm_ring_1 types. The reason it works without the idom class constraint is that you are never actually computing the degree of the result of a polynomial multiplication, you only are using the degrees of the factors.
I was able to prove this by induction on S using the following two lemmas:
lemma degree_setprod_le: "degree (∏i∈S. f i) ≤ (∑i∈S. degree (f i))" Proof is by cases on whether S is finite, followed by induction on S, and using library lemma degree_mult_le to solve the inductive step.
lemma coeff_mult_sum: "degree p ≤ m ⟹ degree q ≤ n ⟹ coeff (p * q) (m + n) = coeff p m * coeff q n" Proof is by case analysis on whether degree p < m or degree p = m (similarly for q and n). In the less-than cases, library lemma coeff_eq_0 shows that both sides are zero; the final case follows from library lemma coeff_mult_degree_sum.
The problem is, quite simply, that if you don't have an integral domain, coefficients might become zero when multiplying two polynomials, in fact, even the entire polynomial can become zero. For example, consider the commutative ring ℤ/4ℤ, i.e. integers modulo 4. Then the polynomial 2X has degree 1, but 2X · 2X = 4X² = 0 has degree -∞ (or 0, by Isabelle convention).
You need the fact that there are no zero divisors for something like this.
On a related note: it is called “idom”, for “integral domain”, not “ideom”.

Degree of polynomial smaller than a number

I am working on a lemma that shows that the degree of a sum of monomials is always less or equal to n if the exponent of each monomial is less or equal to n.
lemma degree_poly_smaller:
fixes a :: "('a::comm_ring_1 poly)" and n::nat
shows "degree (∑x∷nat | x ≤ n . monom (coeff a x) x) ≤ n"
sorry
What I have to so far is the following (please mind that I am a beginner in Isabelle):
lemma degree_smaller:
fixes a :: "('a::comm_ring_1 poly)" and n::nat
shows "degree (∑x∷nat | x ≤ n . monom (coeff a x) x) ≤ n"
proof-
have th01: "⋀k. k ≤ n ⟹
degree (setsum (λ x . monom (coeff a x) k) {x∷nat. x ≤ n}) ≤ n"
by (metis degree_monom_le monom_setsum order_trans)
have min_lemma1: "k∈{x∷nat. x ≤ n} ⟹ k ≤ n" by simp
from this th01 have th02:
"⋀k. k∈{x∷nat. x ≤ n} ⟹
degree (setsum (λ x . monom (coeff a x) k) {x∷nat. x ≤ n}) ≤ n"
by (metis mem_Collect_eq)
have min_lemma2: "(SOME y . y ≤ n) ≤ n" by (metis (full_types) le0 some_eq_ex)
from this have th03:
"degree (∑x∷nat | x ≤ n . monom (coeff a x) (SOME y . y ≤ n)) ≤ n"
by (metis th01)
from min_lemma1 min_lemma2 have min_lemma3:
"(SOME y . y∈{x∷nat. x ≤ n}) ≤ n" by (metis (full_types) mem_Collect_eq some_eq_ex)
from this th01 th02 th03 have th04:
"degree (∑x∷nat | x ≤ n . monom (coeff a x) (SOME y . y∈{x∷nat. x ≤ n}) ) ≤ n"
by presburger
Here is the problem, I don't understand why the following lemma is not sufficient to finish the proof. In particular, I would expect the last part (where the sorry is) to be simple enough for sledgehammer to find a proof:
from this th01 th02 th03 th04 have th05:
"degree
(setsum (λ i . monom (coeff a i) (SOME y . y∈{x∷nat. x ≤ n})) {x∷nat. x ≤ n})
≤ n"
by linarith
(* how can I prove this last step ? *)
from this have
"degree (setsum (λ i . monom (coeff a i) i) {x∷nat. x ≤ n}) ≤ n" sorry
from this show ?thesis by auto
qed
.
SOLUTION from Brian Huffman's excellent answer:
.
lemma degree_setsum_smaller:
"finite A ⟹ ∀x∈A. degree (f x) ≤ n ⟹ degree (∑x∈A. f x) ≤ n"
apply(induct rule: finite_induct)
apply(auto)
by (metis degree_add_le)
lemma finiteSetSmallerThanNumber:
"finite {x∷nat. x ≤ n}"
by (metis finite_Collect_le_nat)
lemma degree_smaller:
fixes a :: "('a::comm_ring_1 poly)" and n::nat
shows "degree (∑x∷nat | x ≤ n . monom (coeff a x) x) ≤ n"
apply (rule degree_setsum_smaller)
apply(simp add: finiteSetSmallerThanNumber)
by (metis degree_0 degree_monom_eq le0 mem_Collect_eq monom_eq_0_iff) (* from sledgehammer *)
The last step does not follow from your th05. The problem is that you seem to want to unify (SOME y. y∈{x∷nat. x ≤ n}) with the bound variable i. However, in HOL (SOME y. y∈{x∷nat. x ≤ n}) has a single value that depends only on n and not on i. Furthermore, you don't get to choose the value; a theorem using SOME is not the same as a theorem with a universally quantified variable.
My advice is to avoid using SOME altogether, and instead try to prove a generalization of your theorem first:
lemma degree_setsum_smaller:
"finite A ⟹ ∀x∈A. degree (f x) ≤ n ⟹ degree (∑x∈A. f x) ≤ n"
You should be able to prove degree_setsum_smaller by induction over A (use induct rule: finite_induct), and then use it to prove degree_poly_smaller. Lemma degree_add_le from the polynomial library should be useful.
It is generally considered bad style to use auto as anything other than the last method in an apply script, because such proofs tend to be quite fragile. I would eliminate the "finiteSetSmallerThanNumber" lemma completely, it is a needlessly specific special case of Collect_le_nat. Also, camel case names for theorems are usually not used in Isabelle.
At any rate, this is my suggestion of how to make the proofs nicer:
lemma degree_setsum_smaller:
"finite A ⟹ ∀x∈A. degree (f x) ≤ n ⟹ degree (∑x∈A. f x) ≤ n"
by (induct rule: finite_induct, simp_all add: degree_add_le)
lemma degree_smaller:
fixes a :: "('a::comm_ring_1 poly)" and n::nat
shows "degree (∑x∷nat | x ≤ n . monom (coeff a x) x) ≤ n"
proof (rule degree_setsum_smaller)
show "finite {x. x ≤ n}" using finite_Collect_le_nat .
{
fix x assume "x ≤ n"
hence "degree (monom (coeff a x) x) ≤ n"
by (cases "coeff a x = 0", simp_all add: degree_monom_eq)
}
thus "∀x∈{x. x≤ n}. degree (monom (coeff a x) x) ≤ n" by simp
qed