When using the vector-space package for derivative towers (see derivative towers) I come across the need to differentiate integrals.
From math it is quite clear how to achieve this:
f(x) = int g(y) dy from 0 to x
with a function
g : R -> R
for example.
The derivative with respect to x would be:
f'(x) = g(x)
I tried to get this behaviour by first defining a class "Integration"
class Integration a b where
--standard integration function
integrate :: (a -> b) -> a -> a -> b
a basic instance is
instance Integration Double Double where
integrate f a b = fst $ integrateQAGS prec 1000 f a b
with integrateQAGS from hmatrix
the problem comes with values b which represent towers of derivatives:
instance Integration Double (Double :> (NC.T Double)) where
integrate = integrateD
NC.T is from Numeric.Complex (numeric-prelude).
The function integrateD is defined as follows (but wrong):
integrateD ::(Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b) => (a -> a :> b) -> a -> a -> (a :> b)
integrateD f l u = D (integrate (powVal . f) l u) (derivative $ f u)
The function does not return what I want, it derives the integrand, but not the integral. The problem is, that I need a linear map which returns f u. The a :> b is defined as follows:
data a :> b = D { powVal :: b, derivative :: a :-* (a :> b) }
I don't know how to define derivative. Any help will be appreciated, thanks
edit:
I forgot to provide the instance for Integration Double (NC.T Double):
instance Integration Double (NC.T Double) where
integrate f a b = bc $ (\g -> integrate g a b) <$> [NC.real . f, NC.imag . f]
where bc (x:y:[]) = x NC.+: y
and I can give an example of what I mean:
Let's say I have a function
f(x) = exp(2*x)*sin(x)
>let f = \x -> (Prelude.exp ((pureD 2.0) AR.* (idD x))) * (sin (idD x)) :: Double :> Double
(AR.*) means multiplication from Algebra.Ring (numeric-prelude)
I can easily integrate this function with the above function integrateD:
>integrateD f 0 1 :: Double :> Double
D 1.888605715258933 ...
When I take a look at the derivative of f:
f'(x) = 2*exp(2*x)*sin(x)+exp(2*x)*cos(x)
and evaluate this at 0 and pi/2 I get 1 and some value:
> derivAtBasis (f 0.0) ()
D 1.0 ...
> derivAtBasis (f (pi AF./ 2)) ()
D 46.281385265558534 ...
Now, when deriving the integral, I get the derivation of the function f not its value at the upper bound
> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 46.281385265558534 ...
But I expect:
> f (pi AF./ 2)
D 23.140692632779267 ...
If you just want to do AD on a function which involves numeric integration, without the AD system knowing about integration per-se, it should "just work". Here is an example. (This integration routine is pretty icky, hence the name.)
import Numeric.AD
import Data.Complex
intIcky :: (Integral a, Fractional b) => a -> (b -> b) -> b -> b -> b
intIcky n f a b = c/n' * sum [f (a+fromIntegral i*c/(n'-1)) | i<-[0..n-1]]
where n' = fromIntegral n
c = b-a
sinIcky t = intIcky 1000 cos 0 t
cosIcky t = diff sinIcky t
test1 = map sinIcky [0,pi/2..2*pi::Float]
-- [0.0,0.9997853,-4.4734867e-7,-0.9966421,6.282018e-3]
test2 = map sin [0,pi/2..2*pi::Float]
-- [0.0,1.0,-8.742278e-8,-1.0,-3.019916e-7]
test3 = map cosIcky [0,pi/2..2*pi::Float]
-- [1.0,-2.8568506e-4,-0.998999,2.857402e-3,0.999997]
test4 = map cos [0,pi/2..2*pi::Float]
-- [1.0,-4.371139e-8,-1.0,1.1924881e-8,1.0]
test5 = diffs sinIcky (2*pi::Float)
-- [6.282019e-3,0.99999696,-3.143549e-3,-1.0004976,3.1454563e-3,1.0014982,-3.1479746e-3,...]
test6 = diffs sinIcky (2*pi::Complex Float)
-- [6.282019e-3 :+ 0.0,0.99999696 :+ 0.0,(-3.143549e-3) :+ 0.0,(-1.0004976) :+ 0.0,...]
The only caveats are that the numeric integration routine needs to play well with AD, and also accept complex arguments. Something even more naive, like
intIcky' dx f x0 x1 = dx * sum [f x|x<-[x0,x0+dx..x1]]
is piecewise constant in the upper limit of integration, requires the limits of integration to be Enum and hence non-complex, and also often evaluates the integrand outside the given range due to this:
Prelude> last [0..9.5]
10.0
'hmatrix' is tied very closely to Double. You can't use its functions with other numeric data types like those provided by 'vector-space' or 'ad'.
I finally found a solution to my question.
The key to the solution is the >-< function from the vector-space package, it stands for the chain rule.
So, I define a function integrateD' like this:
integrateD' :: (Integration a b, HasTrie (Basis a), HasBasis a, AdditiveGroup b , b ~ Scalar b, VectorSpace b) => (a -> a :> b) -> a -> a -> (a:>b) -> (a :> b)
integrateD' f l u d_one = ((\_ -> integrate (powVal . f) l (u)) >-< (\_ -> f u)) (d_one)
the d_one means a derivation variable and its derivative must be 1. With this function I can now create some instances like
instance Integration Double (Double :> Double) where
integrate f l u = integrateD' f l u (idD 1)
and
instance Integration ( Double) (Double :> (NC.T Double)) where
integrate f l u = liftD2 (NC.+:) (integrateD' (\x -> NC.real <$>> f x) l u (idD 1.0 :: Double :> Double)) (integrateD' (\x -> NC.imag <$>> f x) l u (idD 1.0 :: Double :> Double))
unfortunately I can't use integrateD on complex values out of the box, I have to use liftD2. The reason for this seems to be the idD function, I don't know if there is a more elegant solution.
When I look at the example in the question, I now get my desired solution:
*Main> derivAtBasis (integrateD' f 0 (pi AF./ 2) (idD 1.0 :: Double :> Double )) ()
D 23.140692632779267 ...
or by using the instance:
*Main> derivAtBasis (integrate f 0 (pi AF./ 2)) ()
D 23.140692632779267 ...
Related
I am trying to implement my code based almost directly on a paper (pages 34-35). I am using Haskell's Num class instead of the user-defined Number class suggested in the paper.
I want to focus on implementing addition over dynamic time-varying Float values, and subsequently addition over time-varying Points.
Listing 1 is my attempt. How do I get addition of points with time-varying coordinates to work properly? My research requires a review of the code in that particular paper. As far as it is practical, I need to stick to the structure of the original code in the paper. In other words, what
do I need to add to Listing 1 to overload (+) from Num to perform addition on time varying points?
module T where
type Time = Float
type Moving v = Time -> v
instance Num v => Num (Moving v) where
(+) a b = \t -> (a t) + (b t)
(-) a b = \t -> (a t) - (b t)
(*) a b = \t -> (a t) * (b t)
-- tests for time varying Float values, seems OK
a,b::(Moving Float)
a = (\t -> 4.0)
b = (\t -> 5.0)
testA = a 1.0
testAddMV1 = (a + b ) 1.0
testAddMV2 = (a + b ) 2.0
-- Point Class
class Num s => Points p s where
x, y :: p s -> s
xy :: s -> s -> p s
data Point f = Point f f deriving Show
instance Num v => Points Point v where
x (Point x1 y1) = x1
y (Point x1 y1) = y1
xy x1 y1 = Point x1 y1
instance Num v => Num (Point (Moving v)) where
(+) a b = xy (x a + x b) (y a + y b)
(-) a b = xy (x a - x b) (y a - y b)
(*) a b = xy (x a * x b) (y a * y b)
-- Cannot get this to work as suggested in paper.
np1, np2 :: Point (Moving Float)
np1 = xy (\t -> 4.0 + 0.5 * t) (\t -> 4.0 - 0.5 * t)
np2 = xy (\t -> 0.0 + 1.0 * t) (\t -> 0.0 - 1.0 * t)
-- Error
-- testAddMP1 = (np1 + np2 ) 1.0
-- * Couldn't match expected type `Double -> t'
-- with actual type `Point (Moving Float)'
The error isn't really about the addition operation. You also can't write np1 1.0 because this is a vector (I don't particularly like calling it that) whose components are functions. Whereas you try to use it as a function whose values are vectors.
What you're trying to express here is, "evaluate both the component-functions at this time-slice, and give me back the point corresponding to both coordinates". The standard solution (which I don't recommend, though) is to give Point a Functor instance. This is something the compiler can do for you:
{-# LANGUAGE DeriveFunctor #-}
data Point f = Point f f
deriving (Show, Functor)
And then you can write e.g.
fmap ($1) (np1 + np2)
Various libraries have special operators for this, e.g.
import Control.Lens ((??))
np1 + np2 ?? 1
Why is a functor instance a bad idea? For the same reason it's a bad idea to implement multiplication on points as component-wise multiplication†: it does not make sense physically. Namely, it depends on a particular choice of coordinate system, but the choice of coordinate frame is in principle arbitrary and should not affect the results. For addition it indeed does not affect the result (disregarding float inaccuracy), but for multiplication or arbitrary function-mapping it can massively affect the result.
A better solution is to just not use "function-valued points" in the first place, but instead point-valued functions.
np1, np2 :: Moving (Point Float)
np1 = \t -> xy (4.0 + 0.5 * t) (4.0 - 0.5 * t)
np2 t = xy (0.0 + 1.0 * t) (0.0 - 1.0 * t)
†Actually a functor instance is a less bad idea than a Num instance. The particular operation fmap ($1) is in fact equivariant under coordinate transformation. That's because point-evaluation of functions is a linear mapping. To properly express this, you could make Point an endofunctor in the category of linear maps.
I include a renaming approach in Listing 2 and a qualified import approach in Listing 3 .
Listing 2 contains code that I believe is reasonably close to the original code. It was necessary rename the operations in Number by appending (!). This avoids a clash with the operations in Prelude Num class. I believe that there were two errors in the original code. The most serious is in the instance Number (Moving Float) where the same operation symbols are used on the left and right of the equations (e.g. +). The compiler has no way to distinguish these operations. The other error is a syntax error instance Number v => (Point v) there is no class name after =>. In sort the original code will not run, which was the motivation behind the question.
Listing 2
module T where
type Time = Float
type Moving v = Time -> v
class Number a where
(+!), (-!), (*!) :: a -> a -> a
sqr1, sqrt1 :: a -> a
-- Define Number operations in terms of Num operations from Prelude
-- Original code does not distinguish between these operation and will not compile.
instance Number (Moving Float) where
(+!) a b = \t -> (a t) + (b t)
(-!) a b = \t -> (a t) - (b t)
(*!) a b = \t -> (a t) * (b t)
sqrt1 a = \t -> sqrt (a t)
sqr1 a = \t -> ((a t) * (a t))
data Point f = Point f f deriving Show
class Number s => Points p s where
x, y :: p s -> s
xy :: s -> s -> p s
dist :: p s -> p s -> s
dist a b = sqrt1 (sqr1 ((x a) -! (x b)) +! sqr1 ((y a) -! (y b)))
instance Number v => Points Point v where
x (Point x1 y1) = x1
y (Point x1 y1) = y1
xy x1 y1 = Point x1 y1
-- Syntax error in instance header in original code.
instance Number (Point (Moving Float)) where
(+!) a b = xy (x a +! x b) (y a +! y b)
(-!) a b = xy (x a -! x b) (y a -! y b)
(*!) a b = xy (x a *! x b) (y a *! y b)
sqrt1 a = xy (sqrt1 (x a)) (sqrt1 (y a))
sqr1 a = xy (sqr1 (x a)) (sqr1 (y a))
mp1, mp2 :: Point (Moving Float)
mp1 = (xy (\t -> 4.0 + 0.5 * t) (\t -> 4.0 - 0.5 * t))
mp2 = xy (\t -> 0.0 + 1.0 * t) (\t -> 0.0 - 1.0 * t)
movingDist_1_2 = dist mp1 mp2
dist_at_2 = movingDist_1_2 2.0 -- gives 5.83
Listing 3 uses a qualified import as suggested by ben. Note we need an additional instance to define the operations in the Number class using the Num class.
Listing 3
module T where
import qualified Prelude as P
type Time = P.Float
type Moving v = Time -> v
class Number a where
(+), (-), (*) :: a -> a -> a
sqr, sqrt:: a -> a
instance Number P.Float where
(+) a b = a P.+ b
(-) a b = a P.- b
(*) a b = a P.* b
sqrt a = P.sqrt a
sqr a = a P.* a
instance Number (Moving P.Float) where
(+) a b = \t -> (a t) + (b t)
(-) a b = \t -> (a t) - (b t)
(*) a b = \t -> (a t) * (b t)
sqrt a = \t -> sqrt (a t)
sqr a = \t -> ((a t) * (a t))
data Point f = Point f f deriving P.Show
class Number s => Points p s where
x, y :: p s -> s
xy :: s -> s -> p s
dist :: p s -> p s -> s
dist a b = sqrt (sqr ((x a) - (x b)) + sqr ((y a) - (y b)))
instance Number v => Points Point v where
x (Point x1 y1) = x1
y (Point x1 y1) = y1
xy x1 y1 = Point x1 y1
instance Number (Point (Moving P.Float)) where
(+) a b = xy (x a + x b) (y a + y b)
(-) a b = xy (x a - x b) (y a - y b)
(*) a b = xy (x a * x b) (y a * y b)
sqrt a = xy (sqrt (x a)) (sqrt (y a))
sqr a = xy (sqr (x a)) (sqr (y a))
mp1, mp2 :: Point (Moving P.Float)
mp1 = xy (\t -> 4.0 + (0.5 * t)) (\t -> 4.0 - (0.5 * t))
mp2 = xy (\t -> 0.0 + (1.0 * t)) (\t -> 0.0 - (1.0 * t))
movingDist_1_2 = dist mp1 mp2
dist_at_2 = movingDist_1_2 2.0
I ran into the following error in Haskell:
"Type signatures are only allowed in patterns with ScopedTypeVariables"
How should I re-use the defined variables. Thanks in advance
sum :: (Double -> Double) -> (Double -> Double) -> Int ->
(Double -> Double)
sum f g n = (\x -> helper f g n x)
where
helper :: (Double -> Double) -> (Double -> Double) -> Int -> Double ->
Double
|n == 0 = 0
|mod n 2 == 1 = f(x) + helper f g n-1 f(x)
|otherwise = g(x) + helper f g n-1 g(x)
This actually looks more like a syntactical error: you never defined a function body for helper, indeed you defined the signature of helper, followed by guards (the | ... part), but you should again state helper f g n x = ....
Furthermore I don't think it is useful to define helper here with a variable for f, an g, since these remain fixed throughout the recursion.
You can probably define the function as:
sumfg :: (Double -> Double) -> (Double -> Double) -> Int -> Double -> Double
sumfg f g = helperf
where helperf 0 _ = 0
helperf i x = let fx = f x in fx + helperg (i-1) fx
helperg 0 _ = 0
helperg i x = let gx = g x in gx + helperf (i-1) gx
We here defined two "helper" functions helperf and helperg, helperf will sum up f x with helperg (i-1) (f x), and helperg does the same, except that we use g instead of f. We here thus use mutual recursion to solve the problem.
We can however solve this problem more elegantly, by making use of scanl :: (b -> a -> b) -> b -> [a] -> [b], take :: Int -> [a] and sum :: Num a => [a] -> a:
sumfg :: Num a => (a -> a) -> (a -> a) -> Int -> a -> a
sumfg f g n x = sum (take n (scanl (flip ($)) (f x) (cycle [g, f])))
Here we thus make an infinite list of g and f, like [g, f, g, f, g, f, ...] with cycle [f, g]. We then use scanl (flip ($)) to each time apply the accumulator to one of the functions, and yield that element. We take the first n items of that list with take n, and finally we use sum to sum up these values.
For example:
Prelude> sumfg (2+) (3*) 5 1
91
Since (2+1) + (3*(2+1)) + (2+(3*(2+1))) + (3*(2+(3*(2+1)))) + (2+(3*(2+(3*(2+1))))) is 91.
We also generalized the signature: we can now work with any numerical type a, with the two functions f and g of type f, g :: a -> a.
So I'm playing with the Cantor pairing function, and trying to follow the wikipedia formulas as close as possible.
type N = Int
toCantor :: (N, N) -> N
fromCantor :: N -> (N, N)
toCantor (x, y) = (x + y) * (x + y + 1) `div` 2 + y
type N so I can easily change to Integer later (some of the intermediate calcs will get big).
uncurried form, partly to follow wp, partly so (fromCantor . toCantor) === id and (toCantor . fromCantor) === id.
Again following wp:
fromCantor z = (x, y) where
x = w - y
y = z - t
t = (w * w + w) `div` 2
w = floor $ (sqrt (fromIntegral (z * 8 + 1)) - 1.0) / 2.0
This works and everything but gee that formula for w is ugly!
It needs all those parens because I've got a formula nested inside a function call and a loose-binding (-) nested inside a tight-binding (/).
(And both those operators are non-commutative, so I must be careful.)
Q 1. Is there a way to make that formula prettier/pointfree?
I see the formula starts from z and builds outwards. So I can pipeline the calculation:
(.|) :: a -> (a -> b) -> b -- pipelining
infixl 0 .|
x .| f = f x -- aka flip ($)
wP :: N -> N -- w with Pipelining
wP z = z
.| (* 8)
.| (+ 1)
.| fromIntegral
.| sqrt
.| subtract 1.0
.| (/ 2.0)
.| floor
Is this style prior art? Is (.|) a good way to spell that operation -- I think I've seen it as a Lens operator(?)
Q 2. I've (deliberately) laid that out in pseudo-monad style. Could it actually be a do block?
First I need a monad. I could use Maybe or (Either e) -- which would be a Good Thing because several of those functions are partial, and I ought to be using a safe version.
Then instead of z I'd put return z.
But the binding goes the wrong way round. Instead of Monad m => m a -> (a -> m b) -> m b, I want Monad m => m a -> (a -> b) -> m b. That looks like an fmap, but flipped.
I could apply some sort of lifting to the functions/operators, but that then obscures the arithmetic with monad plumbing.
Rebindable syntax?
Your operator .| already exists in Data.Function as &. To make it pointfree, you can either use >>> from Control.Arrow, or invert the order of everything and just use .. For Monad m => m a -> (a -> b) -> m b, you want <&>, from Data.Functor.
I have following code, implmenting inverse function calculation, basing on this formulas:
derivation :: (Fractional a) => (a -> a) -> (a -> a)
derivation f = \ x -> ( ( f (x + dx) - f (x) ) / dx ) where dx = 0.1
evalA k f
| k == 0 = \x -> x
| otherwise = \x -> (derivation (evalA (k-1) f) x) / (derivation f x)
inverseFun f x =
let
x0 = 3.0
eps = 0.001
iter k prev sum =
let
elemA = evalA k f x0
elemB = prev * (x - (f x0)) / (if k == 0 then 1 else k)
newItem = elemA * elemB
in
if abs (newItem) < eps
then sum
else iter (k + 1) elemB (sum + newItem)
in
iter 0 1.0 0.0
f1 = \x -> 1.0 * x * x
main = do
print $ inverseFun f1 2.5
I need to optimise it by moving evalA inside the inverseFun and store previous step calculation A'n/F' to reuse it on the next iteration, if possible. As far as I understand, each time evalA returns some sort of function and x applies afterwards, right before declaring elemA.
How can I convert my evalA or rewrite it to store previous results (by passing these results in iter, obviously)?
Don't mind if this calculations are not too precise, it requires good x0 and eps choice. My main question is in lambda conversion.
If you change your definition of inverseFun such that the (if k == 0 then 1 else k) is instead fromIntegral (if k == 0 then 1 :: Int else k), then you can provide type signatures to all of your functions:
derivation :: (Fractional a) => (a -> a) -> a -> a
evalA :: (Fractional a) => Int -> (a -> a) -> a -> a
inverseFun :: (Fractional a, Ord a) => (a -> a) -> a -> a
f1 :: (Fractional a) => a -> a
Which certainly helps out.
This is actually important for my solution to your problem, since we need k to be an Int, and you've used it as a Fractional a => a. The fromIntegral fixes that, but it needs to know that it's an Int, so I just added the inline type signature to help the compiler along.
Since your function only depends on the previous single value, you can use our handy friend from Prelude, iterate :: (a -> a) -> a -> [a]. This applies a function over and over again, producing an infinite list of values. We can then index it at any point to get the desired result (this is why having k an Int is important!).
Our function will look like
evalA :: Fractional a => Int -> (a -> a) -> a -> a
evalA k f = iterate go id !! k
where
go = ???
Here id is the same as your base case of \x -> x, just shorter and with more optimization rules. It serves as the initial value for generating this list. To implement go, the actual computation, we need it to accept the previous result as its argument:
where
go prev = \x -> derivation prev x / derivation f x
But this is considered "poor style" by hlint, and so it is suggested to convert this to the form
where
go prev x = derivation prev x / derivation f x
And that's it! I tested it and got the exact same result for your example input. The full code can be viewed here.
I have a program which produces a series of functions f and g which looks like the following:
step (f,g) = (newF f g, newG f g)
newF f g x = r (f x) (g x)
newG f g x = s (f x) (g x)
foo = iterate step (f0,g0)
Where r and s are some uninteresting functions of f x and g x. I naively hoped that having foo be a list would mean that when I call the n'th f it will not recompute the (n-1)th f if it has already computed it (as would have happened if f and g weren't functions). Is there any way to memoize this without ripping the whole program apart (e.g. evaluating f0 and g0 on all relevant arguments and then working upward)?
You may find Data.MemoCombinators useful (in the data-memocombinators package).
You don't say what argument types your f and g take --- if they both takes integral values then you would use it like this:
import qualified Data.MemoCombinators as Memo
foo = iterate step (Memo.integral f0, Memo.integral g0)
If required, you could memoise the output of each step as well
step (f,g) = (Memo.integral (newF f g), Memo.integral (newG f g))
I hope you don't see this as ripping the whole program apart.
In reply to your comment:
This is the best I can come up with. It's untested, but should be working along the right lines.
I worry that converting between Double and Rational is needlessly inefficient --- if there was a Bits instance for Double we could use Memo.bits instead. So this might not ultimately be of any practical use to you.
import Control.Arrow ((&&&))
import Data.Ratio (numerator, denominator, (%))
memoV :: Memo.Memo a -> Memo.Memo (V a)
memoV m f = \(V x y z) -> table x y z
where g x y z = f (V x y z)
table = Memo.memo3 m m m g
memoRealFrac :: RealFrac a => Memo.Memo a
memoRealFrac f = Memo.wrap (fromRational . uncurry (%))
((numerator &&& denominator) . toRational)
Memo.integral
A different approach.
You have
step :: (V Double -> V Double, V Double -> V Double)
-> (V Double -> V Double, V Double -> V Double)
How about you change that to
step :: (V Double -> (V Double, V Double))
-> (V Double -> (V Double, V Double))
step h x = (r fx gx, s fx gx)
where (fx, gx) = h x
And also change
foo = (fst . bar, snd . bar)
where bar = iterate step (f0 &&& g0)
Hopefully the shared fx and gx should result in a bit of a speed-up.
Is there any way to memoize this without ripping the whole program apart (e.g. evaluating f0 and g0 on all relevant arguments and then working upward)?
This may be what you mean by "ripping the whole program apart", but here is a solution in which (I believe but can't test ATM) fooX can be shared.
nthFooOnX :: Integer -> Int -> (Integer, Integer)
nthFooOnX x =
let fooX = iterate step' (f0 x, g0 x)
in \n-> fooX !! n
step' (fx,gx) = (r fx gx, s fx gx)
-- testing definitions:
r = (+)
s = (*)
f0 = (+1)
g0 = (+1)
I don't know if that preserves the spirit of your original implementation.