从 Numeric.AD 获取雅可比的函数类型

问题描述 投票:0回答:1

我需要构造一个函数来传递一个函数,从传递的函数中可以计算雅可比矩阵(稍后进一步探索)。我可以一步计算雅可比行列式,但当我尝试将函数作为参数传递到另一个函数时则不行。显然传递的函数类型不正确,但是正确的类型是什么呢?

...
import Numeric.AD 
...


lv3explore fun pt = return () 
    where 
        jaco = jacobian fun pt 

ghci
给出类型

lv3explore :: (MonadIO m, Traversable f, Num a) => p -> f a -> IO ()

这会产生一条错误消息,我无法理解。我期待一个类型

lv3explore :: (Show a, Floating a) => ([a] -> [a]) -> [a] -> IO ()

但收到一条(较小的)错误消息,从中我看不到如何纠正错误:

    src/LVmat.hs:88:25: error: [GHC-25897]
    • Couldn't match type ‘a’
                     with ‘Numeric.AD.Internal.Reverse.Reverse s a’
      Expected: [Numeric.AD.Internal.Reverse.Reverse s a]
                -> [Numeric.AD.Internal.Reverse.Reverse s a]
        Actual: [a] -> [a]
      ‘a’ is a rigid type variable bound by
        the type signature for:
          lv3explore :: forall a.
                        (Show a, Floating a) =>
                        ([a] -> [a]) -> [a] -> IO ()
        at src/LVmat.hs:84:1-66
    • In the first argument of ‘jacobian’, namely ‘fun’
      In the expression: jacobian fun pt
      In an equation for ‘jaco’: jaco = jacobian fun pt
    • Relevant bindings include
        jaco :: [[a]] (bound at src/LVmat.hs:88:9)
        pt :: [a] (bound at src/LVmat.hs:86:16)
        fun :: [a] -> [a] (bound at src/LVmat.hs:86:12)
        lv3explore :: ([a] -> [a]) -> [a] -> IO ()
          (bound at src/LVmat.hs:86:1)
   |
88 |         jaco = jacobian fun pt 

函数的正确类型是什么,以便可以计算雅可比行列式?

haskell
1个回答
0
投票

如果没有

-XRankNTypes
,你就无法做到这一点:
jacobian
的论据必须是普遍量化的。这就是为什么这实际上只能通过显式签名来实现,GHC 通常无法推断出更高阶函数的正确类型。 可以通过多种方法来完成此操作,但最明显的是仅从

jacobian

的签名进行复制,因为您的函数似乎基本上只是一个包装器:

jacobian :: (Traversable f, Functor g, Num a)
      => (∀ s. (Reifies s Tape, Typeable s) => f (Reverse s a) -> g (Reverse s a))
      -> f a -> g (f a)

所以 
lv3explore

是一样的,只是最终结果变得简单

IO ()
:
lv3explore :: (Traversable f, Functor g, Num a)
      => (∀ s. (Reifies s Tape, Typeable s) => f (Reverse s a) -> g (Reverse s a))
      -> f a -> IO ()

(大概也与 
Show a

一起使用,尽管您显示的存根不需要)。您可以制作一个列表专用的版本,这可能更容易理解

lv3explore :: Num a
      => (∀ s. (Reifies s Tape, Typeable s) => [Reverse s a] -> [Reverse s a])
      -> [a] -> IO ()

尽管我真的不建议这样做:从概念上讲,您在这里处理的是恒定长度的可遍历对象(可表示函子),而列表实例化根本无法表达。

切线咆哮

坦率地说,

ad

库签名中的所有这些笨重的磁带内容都很糟糕。反向模式自动微分从根本上来说并不需要这样的技巧,正如经典(?)论文中所证明的那样,自动微分的简单本质

令人费解的是,它似乎仍然没有产生一个可以推翻的库
ad。原则上,jacobian的签名应该是这样的(来自linearmap-category
的类型):
jacobian :: (LinearSpace v, LinearSpace w)
              => (v -> w) -> v -> (DualVector w +> DualVector v)
没有可遍历性、函子和磁带,只有数学上有意义的向量空间。


© www.soinside.com 2019 - 2024. All rights reserved.