17 | module Spidr.Optimize
21 | import Data.List.HasLength
23 | import Spidr.Data.Nat
31 | Optimizer : (0 domain : Type) -> Type
32 | Optimizer a = (a -> Tag $
Tensor [] F64) -> Tag a
34 | fromVect : Vect n (Tensor (d :: ds) dtype) -> All (\n => Tensor (n :: ds) dtype) (replicate n d)
36 | fromVect (x :: xs) = x :: fromVect xs
38 | sumReplicateIsMult : (n, x : Nat) -> sum (List.replicate n x) === n * x
39 | sumReplicateIsMult 0 x = Refl
40 | sumReplicateIsMult (S n) x = cong (plus x) (sumReplicateIsMult n x)
42 | stack : Vect (S d) (Tensor ds dtype) -> Tensor (S d :: ds) dtype
44 | let 0 sr = sym $
trans (sumReplicateIsMult d 1) (multOneRightNeutral d)
45 | in rewrite sr in concat {leading = []} $
fromVect $
expand 0 <$> xs
47 | unstack : {d : _} -> Tensor (d :: ds) dtype -> Tag $
Vect d (Tensor ds dtype)
48 | unstack x = tag x <&> \x => Subset.tabulate $
\(Element i lt) => slice [at i] x
50 | vect : (xs : List a) -> {auto len : HasLength p xs} -> Vect p a
52 | vect (x :: xs) @{S len} = x :: vect xs
85 | (density : List Nat) ->
86 | {auto hl : HasLength d density} ->
87 | {auto nonEmpty : All (`GT` 1) density} ->
88 | (bound, bound' : Tensor [d] F64) ->
89 | Tag $
Vect d $
Tensor density F64
90 | meshGrid density bound bound' = do
91 | let iotas = Subset.tabulate $
\(Element dim lt) => iota {inBounds = ltLengthIsInBound lt hl} dim
92 | density' = F64.fromDouble . cast . pred <$> vect density
93 | bound <- traverse tag =<< unstack bound
94 | bound' <- traverse tag =<< unstack bound'
95 | pure [| rescale iotas density' bound bound' |]
98 | rescale : Tensor density F64 -> (dens, b, b' : Tensor [] F64) -> Tensor density F64
99 | rescale is dens b b' = broadcast (b' - b) * (is / broadcast dens) + broadcast b
101 | ltLengthIsInBound : {m : _} -> {xs : _} -> LT m n -> HasLength n xs -> InBounds m xs
102 | ltLengthIsInBound _ Z impossible
103 | ltLengthIsInBound {m = 0} {xs = _ :: _} _ _ = InFirst
104 | ltLengthIsInBound {m = S _} (LTESucc lt) (S hl) = InLater (ltLengthIsInBound lt hl)
115 | (density : List Nat) ->
116 | {auto hl : HasLength d density} ->
117 | {auto nonEmpty : All (`GT` 1) density} ->
118 | (bound, bound' : Tensor [d] F64) ->
119 | Optimizer $
Tensor [d] F64
120 | gridSearch {hl = Z} [] _ _ _ = pure (tensor [])
121 | gridSearch {hl = S _} density@(dn :: dns) bound bound' f = do
122 | grid <- meshGrid density bound bound'
123 | grid <- tag (stack $
reshape {sizesEqual = flattenable density} <$> grid).T
124 | [out] <- !(vmap {shapes = [_], dtypes = [_]} $
\x => do pure [!(f x)]) grid
125 | idx <- argminAS out $
sizeSuccIsSucc (dn :: dns)
126 | pure $
slice [at idx] grid
129 | argminAS : Tensor [s] F64 -> (0 _ : IsSucc s) -> Tag $
Tensor [] U64
130 | argminAS x ItIsSucc = argmin x
132 | 0 sizeSuccIsSucc : (xs : List Nat) -> {auto iss : All (`GT` 1) xs} -> IsSucc $
product xs
133 | sizeSuccIsSucc [] = ItIsSucc
134 | sizeSuccIsSucc (x :: xs) {iss = is :: _} = multSuccIsSucc (gtIsSucc is) (sizeSuccIsSucc xs)
149 | lbfgs : (initialPoints : Tensor [n] F64) -> Optimizer $
Tensor [n] F64