Haskell код не компилируется с определенными именами переменных - PullRequest
0 голосов
/ 03 августа 2020

Я получаю сообщение об ошибке от GHCi, которое не могу объяснить. Я работаю со следующим кодом (подавляющее большинство которого, по-видимому, не имеет отношения к проблеме, но я не могу воспроизвести проблему с меньшим количеством кода; закомментированные строки - это те строки, которые я хотел бы добавить, чтобы заменить фиктивный in 0 строк)

import Linear
apply x f = f x
pos xs = -- smallest i where xs!!i > 0, else length xs
    let aux xs n = case xs of
                   x:t -> if x > 0 then n
                          else aux t (n+1)
                   [] -> n
    in aux xs 0
optimize d opt d_opt funs d_funs x0 p0 eps =
    let n = length funs in
    let aux x p f_best = let feas = map (apply x) funs in
                         let i = pos feas in
                         let (g,a,f_best) =
                                 if i == n then
                                    let g = d_opt x in
                                    let g' = p !* g in
                                    let prod = g `dot` g' in
                                    let g = g / (sqrt prod) in
                                    let f_best = min (opt x) f_best in
                                    let a = (opt x - f_best) / (sqrt prod) in
                                    (g,a,f_best)
                                 else
                                    let g = (d_funs!!i) x in
                                    let g' = p !* g in
                                    let prod = g `dot` g' in
                                    let g = g / (sqrt prod) in
                                    let a = ((funs!!i) x) / (sqrt prod) in
                                    (g,a,f_best)
                         in
                         let b = (1+d*a)/(d+1) in
                         let b' = 2/(1+a) in
                         let b'' = (1-a^2)*(d^2)/(d^2-1) in
                         let h = p !* g in
                         let y = x - b*g in
                         -- let q = (p - g'*(transpose g')*b*b')*b'' in
                         -- aux y q f_best
                         0
    -- in aux x0 p0 (1/0)
    in 0 

Этот код заставляет GHCi выдавать шесть ошибок, включая выделение p в let h = p !* g in; однако, когда я меняю эту строку на let g = p !* g in, она проходит. К сожалению, если сделать это и затем раскомментировать следующую строку (let x = x - b*g in), будут выданы те же ошибки (включая выделение p в том же месте).

p и p0 предполагается быть квадратными матрицами размером n на n с использованием пакета Linear, а g, x и x0 должны быть векторами (n на 1); d - целое число, opt - линейная функция в n-пространстве, funs - список выпуклых функций в n-пространстве, d_opt и d_funs - соответствующие градиенты, eps действительное .

Любая помощь с компиляцией будет принята с благодарностью. Спасибо!

Редактировать: вот одно из сообщений об ошибке. Есть аналогичные для let g = d_opt x, let f_best = min (opt x) f_best, let g = (d_funs!!i) x, let a = ((funs!!i) x) / (sqrt prod) и let b = (1+d*a)/(d+1).

Lenstra.hs:57:34: error:
    • Occurs check: cannot construct the infinite type: a1 ~ m a1
      Expected type: m (m a1)
        Actual type: m (m (m a1))
    • In the first argument of ‘(!*)’, namely ‘p’
      In the expression: p !* g
      In an equation for ‘h’: h = p !* g
    • Relevant bindings include
        h :: m a1 (bound at Lenstra.hs:57:30)
        b'' :: m a1 (bound at Lenstra.hs:56:30)
        b' :: m a1 (bound at Lenstra.hs:55:30)
        b :: m a1 (bound at Lenstra.hs:54:30)
        g :: m a1 (bound at Lenstra.hs:37:31)
        a :: m a1 (bound at Lenstra.hs:37:33)
        aux :: m a1 -> m (m (m a1)) -> p8 -> p9 (bound at Lenstra.hs:35:9)
        (Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
   |
57 |                          let h = p !* g in
   |                                  ^
Failed, no modules loaded.

1 Ответ

5 голосов
/ 03 августа 2020

Есть несколько ошибок:

  • Если целое число d используется как число с плавающей запятой, вам нужно использовать fromIntegral, например: b = (1 + fromIntegral d * a)/(fromIntegral d + 1)
  • Скалярное умножение / деление векторов и матриц не может использовать * и /. Вы должны использовать операторы *^, ^* и ^/ для векторов и !!* и !!/ для матриц.
  • Точечные суммы и разности векторов и матриц не могут использовать + и -. Вы должны использовать ^+^ и ^-^ для векторов и !+! и !-! для матриц.
  • Для вектора g', transpose g' не будет работать, поэтому g' * transpose g' нет молитвы. Используйте outer g' g', чтобы получить матрицу, полученную в результате произведения g' как вектора-столбца с g' как вектор-строку, если это то, что вы пытаетесь сделать.
  • Не было g' в области, где определено q. Может быть, вы хотели вернуть g' из оператора if?
  • let g = some expression with g не будет работать, так как вы создадите рекурсивное определение, которое будет повторяться бесконечно. Вам нужно будет использовать переменную fre sh - в некоторых местах вы сделали это правильно, а в других - нет.

Также имеется значительная ошибка logi c, по крайней мере, в версия с вашими комментариями без комментариев. Функция aux никогда не возвращает ничего, кроме хвостового вызова aux, поэтому она обязательно будет l oop навсегда. Я даже не знаю, какой тип должен возвращать. Вам нужно какое-то условие остановки (вероятно, возвращающее f_best или что-то в этом роде).

Вам будет полезно добавить сигнатуры типов в optimize и его функцию aux, чтобы держать эти ошибки под контролем. Следующие проверки типов, но все еще содержат несколько ошибок (бесконечные циклы и т. Д. c.):

import Linear
import Data.Vector (Vector)

apply x f = f x

pos :: (Ord a, Num a) => [a] -> Int
pos xs = -- smallest i where xs!!i > 0, else length xs
    let aux xs n = case xs of
                   x:t -> if x > 0 then n
                          else aux t (n+1)
                   [] -> n
    in aux xs 0

type Matrix a = Vector (Vector a)

optimize
  :: Integer
  -> (Vector Double -> Double)
  -> (Vector Double -> Vector Double)
  -> [Vector Double -> Double]
  -> [Vector Double -> Vector Double]
  -> Vector Double
  -> Matrix Double
  -> Double
  -> a
optimize d opt d_opt funs d_funs x0 p0 eps =
    let n = length funs in
    let aux
          :: Vector Double
          -> Matrix Double
          -> Double
          -> a
        aux x p f_best = let feas = map (apply x) funs in
                         let i = pos feas in
                         let g :: Vector Double
                             (g,g',a,f_best) =
                                 if i == n then
                                    let g = d_opt x in
                                    let g' = p !* g in
                                    let prod = g `dot` g' in
                                    let g = g ^/ (sqrt prod) in  -- **LOOP**
                                    let f_best = min (opt x) f_best in
                                    let a = (opt x - f_best) / (sqrt prod) in
                                    (g,g',a,f_best)
                                 else
                                    let g = (d_funs!!i) x in
                                    let g' = p !* g in
                                    let prod = g `dot` g' in
                                    let g = g ^/ (sqrt prod) in  -- **LOOP**
                                    let a = ((funs!!i) x) / (sqrt prod) in
                                    (g,g',a,f_best)
                         in
                         let b = (1+fromIntegral d*a)/(fromIntegral d+1) in
                         let b' = 2/(1+a) in
                         let b'' = (1-a^2)*(fromIntegral d^2)/(fromIntegral d^2-1) in
                         let h = p !* g in
                         let y = x ^-^ b*^g in
                         let q = (p !-! outer g' g' !!* (b*b')) !!* b'' in
                         aux y q f_best
    in aux x0 p0 (1/0)

Наконец, когда вы запустите это, вы можете отправить его в код . Просмотрите Stack Exchange вместе с объяснением алгоритма и некоторыми работающими примерами. Есть множество улучшений стиля c, которые, я думаю, могут сделать его более выразительным c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...