Predict running times of extracted Coq code to Haskell

对着背影说爱祢 提交于 2019-12-13 03:54:35

问题


I have the following version of isPrime written (and proved) in Coq.

  • It takes around 30 seconds for Compute (isPrime 330) to finish on my machine.
  • The extracted Haskell code takes around 1 second to verify that 9767 is prime.

According to a comment in this post, the timing difference means nothing, but I wonder why is that? and is there any other way to predict performance when extracting Coq code? after all, sometimes performance does matter, and it's quite hard to change Coq source once you labored to prove it's correct. Here is my Coq code:

(***********)
(* IMPORTS *)
(***********)
Require Import Coq.Arith.PeanoNat.

(************)
(* helper'' *)
(************)
Fixpoint helper' (p m n : nat) : bool :=
  match m with
  | 0 => false
  | 1 => false
  | S m' => (orb ((mult m n) =? p) (helper' p m' n))
  end.

(**********)
(* helper *)
(**********)
Fixpoint helper (p m : nat) : bool :=
  match m with
  | 0 => false
  | S m' => (orb ((mult m m) =? p) (orb (helper' p m' m) (helper p m')))
  end.

(***********)
(* isPrime *)
(***********)
Fixpoint isPrime (p : nat) : bool :=
  match p with
  | 0 => false
  | 1 => false
  | S p' => (negb (helper p p'))
  end.

(***********************)
(* Compute isPrime 330 *)
(***********************)
Compute (isPrime 330).

(********************************)
(* Extraction Language: Haskell *)
(********************************)
Extraction Language Haskell.

(***************************)
(* Use Haskell basic types *)
(***************************)
Require Import ExtrHaskellBasic.

(****************************************)
(* Use Haskell support for Nat handling *)
(****************************************)
Require Import ExtrHaskellNatNum.
Extract Inductive Datatypes.nat => "Prelude.Integer" ["0" "succ"]
"(\fO fS n -> if n Prelude.== 0 then fO () else fS (n Prelude.- 1))".

(***************************)
(* Extract to Haskell file *)
(***************************)
Extraction "/home/oren/GIT/CoqIt/FOLDER_2_PRESENTATION/FOLDER_2_EXAMPLES/EXAMPLE_03_PrintPrimes_Performance_Haskell.hs" isPrime.

回答1:


Your Coq code is using a Peano encoding of the naturals. The evaluation of mult 2 2 literally proceeds by the reduction:

mult (S (S 0)) (S (S 0)))
= (S (S 0)) + mult (S 0) (S (S 0)))
= (S (S 0)) + ((S (S 0)) + mult 0 (S (S 0)))
= (S (S 0)) + ((S (S 0)) + 0)
= (S (S 0)) + ((S 0) + (S 0))
= (S (S 0)) + (0 + (S (S 0))
= (S (S 0)) + (S (S 0))
= (S 0) + (S (S (S 0)))
= 0 + (S (S (S (S 0)))
= (S (S (S (S 0))))

and then checking the equality mult 2 2 =? 5 proceeds by the further reduction:

(S (S (S (S 0)))) =? (S (S (S (S (S 0)))))
(S (S (S 0))) =? (S (S (S (S 0))))
(S (S 0)) =? (S (S (S 0)))
(S 0) =? (S (S 0))
0 =? (S 0)
false

Meanwhile, on the Haskell side, the evaluation of 2 * 2 == 5 proceeds by multiplying two Integers and comparing them to another Integer. This is somewhat faster. ;)

What's incredible here is that Coq's evaluation of isPrime 330 only takes 30 seconds instead of, say, 30 years.

I don't know what to say about predicting the speed of extracted code, except to say that primitive operations on Peano numbers will be massively accelerated, and other code will probably be modestly faster, simply because a lot of work has gone into making GHC generate fast code, and performance hasn't been an emphasis in Coq's development.



来源:https://stackoverflow.com/questions/55796487/predict-running-times-of-extracted-coq-code-to-haskell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!