module MultidimensionalOptimizationMethods.Polak_sMethod

open DiffSharp
open FsAlg.Generic

open Types

let run (alpha: float) (betta: float) func initial_x (targetError: float) =
    let rec loop x_k x_k_previous i =
        if i = 0 then
            loop (x_k - alpha * (dsharp.grad func x_k)) initial_x 1
        else
            let gradient = dsharp.grad func x_k
            let actualError = gradient.toArray1D () |> Vector.ofArray |> Vector.l2norm

            if targetError.CompareTo(actualError) > 0 then
                { ResultTensor = x_k
                  StepsCount = i
                  Error = actualError }
            else
                let x_k_next = x_k - alpha * gradient + betta * (x_k - x_k_previous)
                loop x_k_next x_k (i + 1)

    loop initial_x initial_x 0
