module Hopfield.Analysis where
-- Module for computing the theoretical error of a network
-- Uses the error derivations for independent patterns and super attractors
-- which can be found at the appendix of the report
import Data.List
import Data.Number.Erf
import qualified Data.Vector as V
import Hopfield.Hopfield
import Hopfield.Util
-- | Computes the probability of error for one element given a hopfield data
-- structure. Note that I claim that the actuall error of probability depends
-- on this, but is not the whole term
-- The assumption is that the patterns which were used to train the network
-- are independent.
computeErrorIndependentPats :: HopfieldData -> Double
computeErrorIndependentPats hopfield = computeErrorIndependentPatsNumbers p n
where pats = patterns hopfield
n = V.length $ pats !! 0
p = length pats
-- | computes the error of a super attractor of a hopfield network. The assumption
-- is that there is only one super attractor and the other patterns are independent.
computeErrorSuperAttractor :: HopfieldData -> Double
computeErrorSuperAttractor hopfield = computeErrorSuperAttractorNumbers d n p
where pats = patterns hopfield
n = V.length $ pats !! 0
p = length pats
d = snd $ maximumBy (compareBy snd) (getElemOccurrences pats)
computeErrorIndependentPatsNumbers :: Int -> Int -> Double
computeErrorIndependentPatsNumbers p n
= 1.0 / 2.0 * (1 - (erf $ sqrt $ n ./. (2 * p)))
-- | @computeErrorSuperAttractorNumbers d p n@
-- Computes the probability of error for a super attractor with degree @d@, in
-- a Hopfield network with @n@ neurons, which has been trained with @p@ patterns.
-- The assumption is that the other patterns are independent
-- for mathematical derivation of the equation, see report.
computeErrorSuperAttractorNumbers :: Int -> Int -> Int -> Double
computeErrorSuperAttractorNumbers d p n
= 1.0 / 2.0 * (1.0 - (erf $ (sqrt (n ./. (2 * (p - d)) ))))
-- @patternsToNeuronsRatioFromError err@. Given that the err we accept is @err@,
-- returns the maximum ratio between the number of patterns and the number of
-- neurons which can be used to ensure that the probability of error is just @err@.
-- if p/n is grater than @patternsToNeuronsRatioFromError err@ then the error
-- of a Hopfield network will be greater than err. This method is used to compute
-- the minimum number of neurons given the number of training patterns and the
-- maximum error accepted error.
patternsToNeuronsRatioFromError :: Double -> Double
patternsToNeuronsRatioFromError err = 1.0 / (2.0 * (inverf (1.0 - 2.0 * err)) ^ (2 :: Int))
-- @minNumberOfNeurons p err@ Given the number of patterns used to train a Hopfield
-- network and the maximum error accepted, returns the minimum number of neurons
-- required for the network.
minNumberOfNeurons :: Int -> Double -> Int
minNumberOfNeurons p err
= 1 + floor (p ./ (patternsToNeuronsRatioFromError err))
maxNumberOfPatterns :: Int -> Double -> Int
maxNumberOfPatterns n err
= floor (patternsToNeuronsRatioFromError err *. n)