diff --git a/checkerDefsScript.sml b/checkerDefsScript.sml index a54a700be03bd94d29d437ec1984d3d9651cfe15..4299164aa9e6032dbe4b1f2cab0d007ec0b32a1b 100644 --- a/checkerDefsScript.sml +++ b/checkerDefsScript.sml @@ -1,21 +1,24 @@ open realTheory realLib RealArith stringTheory; -open renameTheory realPolyTheory; +open renameTheory realPolyTheory transcLangTheory; open preamble; val _ = new_theory"checkerDefs"; Datatype: - certificate = <| - transc : real->real; (* transcendental function to be approximated *) - poly : poly; (* real-number polynomial approximation *) - omega: real list; (* the x_i's from Remez *) - eps: real (* approximation error *) - |> + certificate = + <| + transc : transc; (* transcendental function to be approximated *) + poly : poly; (* real-number polynomial approximation *) + omega : real list; (* the x_i's from Remez *) + eps : real; (* approximation error *) + iv: real # real; (* the interval on which the function is approximated *) + zeroes : (real # real) list (* list of intervals in which a zero could be found *) + |> End Datatype: - result = VALID (* the checker succeeded *) - | INVALID string (* the checker failed with an error message *) + result = Valid (* the checker succeeded *) + | Invalid string (* the checker failed with an error message *) End Definition interpResult_def: diff --git a/checkerScript.sml b/checkerScript.sml index 52546e8379da76f3ad6b66f17cecb67c2c8efa29..4e4b78ccdf1e94dde308added283ff937ba7eea2 100644 --- a/checkerScript.sml +++ b/checkerScript.sml @@ -3,17 +3,77 @@ Dandelion **) open realTheory realLib RealArith stringTheory; -open renameTheory realPolyTheory checkerDefsTheory pointCheckerTheory; +open renameTheory realPolyTheory transcLangTheory sturmComputeTheory + checkerDefsTheory pointCheckerTheory; open preamble; val _ = new_theory "checker"; +(** + Approximate a function described by transcLang with a real-number polynomial, + also returns the approximation error +**) +(* TODO: Approximate transcendental functions on a case-by-case basis *) +Definition approx_def: + approx transc (iv:real#real) :(poly#real) = + case transc of + | FUN "exp" VAR => + if iv = (0, 0.5) then ([], 0) else ([], 0) + | _ => ([],0) +End + +(** + Checks that the zero intervals encoded in the certificate actually are + all of the zeroes of derivative of the difference between the approximated + polynomial and the transcendental function +**) +(* TODO: Is this sufficient for a check? *) +Definition checkZeroes_def: + checkZeroes numZeroes deriv zeroes = + if LENGTH zeroes ≠numZeroes + then Invalid "Incorrect number of zeroes found" + else Valid +End + +(** + Checks that the value at the extrema of the error polynomial are less than or + equal to the actual error encoded in the certificate **) +(* TODO: Is this the correct way of checking the zeroes?? Check Harrison paper *) +Definition validateZeroesLeqErr_def: + validateZeroesLeqErr diffPoly iv [] approxErr eps = + (if poly diffPoly (FST iv) + approxErr ≤ eps ∧ poly diffPoly (SND iv) + approxErr ≤ eps + then Valid + else Invalid "Outer points") + ∧ + validateZeroesLeqErr diffPoly iv ((z1,z2)::zeroes) approxErr eps = + (if poly diffPoly z1 + approxErr ≤ eps ∧ poly diffPoly z2 + approxErr ≤ eps + then validateZeroesLeqErr diffPoly iv zeroes approxErr eps + else Invalid "Zero of derivate not an extremal point or extrema too big") +End + +(** + Overall certificate checker combines all of the above functions into one that + runs over the full certificate **) Definition checker_def: checker (cert:certificate) :result = - let pointRes = pointChecker cert in - if pointRes = VALID then - INVALID "Not implemented" - else pointRes + case pointChecker cert of + | Invalid s => Invalid s + | Valid => + let (transp, err) = approx cert.transc cert.iv; + errorp = transp -p cert.poly; + deriv = derive errorp + in + case sturm_seq errorp deriv of + NONE => Invalid "Could not compute sturm sequence" + | SOME sseq => + let numZeroes = + (variation (MAP (λp. poly p (FST cert.iv)) sseq) - + variation (MAP (λp. poly p (SND cert.iv)) sseq)); + in + case checkZeroes numZeroes deriv cert.zeroes of + | Valid => + validateZeroesLeqErr errorp cert.iv cert.zeroes err cert.eps + | Invalid s => Invalid s End val _ = export_theory(); diff --git a/pointCheckerProofsScript.sml b/pointCheckerProofsScript.sml index 77f715d1ba9e3e1c02bc936485d3e6d7f1f18388..96e63db295efbf3520ee655435055de94e23503e 100644 --- a/pointCheckerProofsScript.sml +++ b/pointCheckerProofsScript.sml @@ -10,7 +10,7 @@ val _ = new_theory "pointCheckerProofs"; Theorem pointChecker_intermed: ∀ omega transc poly eps. - pointCheckerHelper omega transc poly eps = VALID ⇒ + pointCheckerHelper omega transc poly eps = Valid ⇒ ∀xi. MEM xi omega ⇒ abs (evalPoly poly xi − transc xi) = eps @@ -24,10 +24,10 @@ QED Theorem pointCheckerSound: ∀ (cert:certificate). - pointChecker cert = VALID ⇒ + pointChecker cert = Valid ⇒ ∀ xi. MEM xi cert.omega ⇒ - abs ((evalPoly cert.poly xi) - cert.transc xi) = cert.eps + abs ((evalPoly cert.poly xi) - (λ x. interp cert.transc x) xi) = cert.eps Proof gs[pointChecker_def] >> rpt gen_tac >> cond_cases_tac >> gs[] diff --git a/pointCheckerScript.sml b/pointCheckerScript.sml index 947ec1f0f665e13645bb174e6824b5863d201287..6db9b5ae100acea0a32f8823a1ed561e6f05eaf5 100644 --- a/pointCheckerScript.sml +++ b/pointCheckerScript.sml @@ -6,28 +6,25 @@ **) open realTheory realLib RealArith stringTheory; -open renameTheory realPolyTheory checkerDefsTheory; +open renameTheory realPolyTheory transcLangTheory checkerDefsTheory; open preamble; val _ = new_theory "pointChecker"; (* TODO: Check for each xi in Omega that p(xi) - f(xi) = cert.eps *) - Definition pointCheckerHelper_def: - pointCheckerHelper [] transc poly eps = VALID ∧ + pointCheckerHelper [] transc poly eps = Valid ∧ pointCheckerHelper (x1::xs) transc poly eps = if (abs (evalPoly poly x1 - transc x1) = eps) then (pointCheckerHelper xs transc poly eps) - else INVALID "Point discrepancy" + else Invalid "Point discrepancy" End - - Definition pointChecker_def: pointChecker (cert:certificate): result = - if (LENGTH cert.omega = 0) then INVALID "Empty set" else - (pointCheckerHelper cert.omega cert.transc cert.poly cert.eps) + if (LENGTH cert.omega = 0) then Invalid "Empty set" else + (pointCheckerHelper cert.omega (λ x. interp cert.transc x) cert.poly cert.eps) End val _ = export_theory(); diff --git a/transcLangScript.sml b/transcLangScript.sml new file mode 100644 index 0000000000000000000000000000000000000000..175c0f490321fc84a8526e50e8a20f64a54d9dce --- /dev/null +++ b/transcLangScript.sml @@ -0,0 +1,32 @@ +(** + Define a simple "language" for describing transcendental + functions. For now we only allow combinations, i.e. + exp (sin (cos ...) but no additional operators like +,-,*,/ +**) +open realTheory realLib RealArith transcTheory; +open preamble; + +val _ = new_theory "transcLang"; + +Datatype: + transc = FUN string transc | VAR +End + +Definition getFun_def: + getFun s = + case s of + |"sqrt" => sqrt + | "exp" => exp + | "sin" => sin + | "cos" => cos + | "tan" => tan + | _ => λ x. x +End + +Definition interp_def: + interp VAR x = x ∧ + interp (FUN s trans) x = + (getFun s) (interp trans x) +End + +val _ = export_theory();