[Agda] summing rationals
Ulf Norell
ulf.norell at gmail.com
Sun Jun 25 09:46:28 CEST 2017
The rationals are not very well-developed in agda-prelude. Nevertheless I
get unsurprising performance compared to ghc (~2min for n = 20,000 on my
machine) with the following benchmark:
module Harmonic where
open import Prelude
open import Numeric.Rational
-- sum [ 1/k | k <- [1..n] ]
harmonic : Nat → Rational
harmonic 0 = 0
harmonic (suc n) = sum (map (λ k → ratio 1 (suc k) refl) (from 0 to n))
test : Nat → Rational
test n = harmonic n * 0
main : IO ⊤
main =
caseM getArgs of λ where
(s ∷ []) → print (test <$> parseNat s)
_ → pure _
The reason that DoCon performs so well is that it has a more clever
implementation of _+_. agda-prelude and GHC implements _+_ as
(p :% q) + (p1 :% q1) = (p * q1 + p1 * q) % (q * q1)
where a % b = let d = gcd a b in div a d :% div d b
DoCon implements _+_ as
(p :% q) + (p1 :% q1) = div n dd :% (q' * q1' * div d dd)
where
d = gcd q q1
q' = div q d
q1' = div q1 d
n = p * q1' + p1 * q'
dd = gcd n d
I can't claim to understand why this is so much faster, but it is.
/ Ulf
On Sat, Jun 24, 2017 at 9:06 PM, Sergei Meshveliani <mechvel at botik.ru>
wrote:
> Dear all,
>
> Consider the following performance test for rational arithmetic.
> Call this test call "Harmonic":
>
> f n = sum [1/k | k <- [1 .. n]] for n : Nat, 1/k : Rational,
>
> sum = foldr _+_ 0 where _+_ = fraction addition
>
> test n = let fn = f n
> in fn - fn
>
> Read from file n = 100, 1000, 2000, 100.000 ...,
>
> print (test n) and check time.
>
> (fn - fn) is applied here in order to avoid printing large values.
>
>
> --------------------------- Haskell code -------
> import Data.Ratio ((%))
>
> f :: Integer -> Rational -- :: Ratio Integer
> f n =
> sum [1 % k | k <- [1 .. n]]
> -------------------------------------------------
>
>
> I compare the three libraries:
>
> (GHC) GHC (Glasgow Haskell 7.10.2),
>
> (D) DoCon-2.12 written in Haskell, running under GHC,
>
> (DA) DoCon-A 2.00-pre written in Agda,
> running under Agda 2.5.2 -like.
>
> (D) and (DA) keep fractions with numerator and denominator mutually
> coprime, and cancel fractions most eagerly by gcd.
>
> (GHC) does not cancel by gcd so eagerly.
>
> The performance comparison on Harmonic is:
>
> (D) >> (GHC) > (DA).
>
> (D) takes n = 200.000 easily, while GHC "hangs" on 20.000
> -- for a 3 GHz machine.
>
> (GHC) is considerably faster (DA)
> (DA hangs for long on 4000).
>
> The method in (DA) is the same as (D).
> gcd is almost as fast as GHC.gcd, this has been tested.
> Division (with remainder) is via dimMod of Agda-prelude, it is fast.
>
> And I wonder why (DA) is so slow.
> (DA) carries all the needed proofs (for coprimality, and such).
> But I hope, this does not effect performance any essentially.
>
> Can anybody provide the code for testing Harmonic for Rational numbers
> in agda-prelude ?
>
> The (DA) test for (Fraction Integer) is like this:
>
> ------------------------------------------------------------------------
> ...
> open Fraction.F0 Int1.integralRing-with∣? Int1.gcdRing using
> (Fraction; fraction; fraction-showInst)
> open Fraction.F1 Int1.integralRing-with∣? Int1.gcdRing using (frRingoid)
> open Ringoid frRingoid using (_-_)
> open Fraction
>
> inv-n : ℕ → Fraction -- \n → 1/(1+n)
> inv-n n =
> fraction (+ 1) (+ (suc n)) +suc≢+0
>
> f : ℕ → Fraction -- sum [1/n | n <- [1 .. n+1]]
> f n =
> sum frRingoid (map inv-n (natSegment 0 n))
>
> main : IO Unit
> main = (readFiniteFile "data.txt") >>= putStrLn ∘ toCostring ∘ g
> where
> g : String -> String
> g str =
> -- n is first read from file data.txt
>
> concatStr
> ("n = " ∷ showNat n ∷ ", " ∷
> "num (f n - f n) = " ∷ showInt (num (fn - fn)) ∷ "\n\n"
> ∷ []
> )
> where
> n = stringToNat $ filterStr decimalDigit? str
> fn = f n
> -------------------------------------------------------------------------
>
>
> So far, I do not find the performance bottleneck in (DA).
>
> Thanks,
>
> ------
> Sergei
>
>
>
> _______________________________________________
> Agda mailing list
> Agda at lists.chalmers.se
> https://lists.chalmers.se/mailman/listinfo/agda
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.chalmers.se/pipermail/agda/attachments/20170625/ef6b8de9/attachment.html>
More information about the Agda
mailing list