Skip to content

Instantly share code, notes, and snippets.

@oxinabox
Last active December 2, 2019 01:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oxinabox/33f862cd5a89c6107432a0179e22ee6f to your computer and use it in GitHub Desktop.
Save oxinabox/33f862cd5a89c6107432a0179e22ee6f to your computer and use it in GitHub Desktop.
A Particle Swarm Opotimizer in DexLang
:p optimize 42 rosenbrock2 ([-3.0, -3.0],[3.0, 3.0]) (0.4,0.3,0.3)
Compiler bug!Not an int: newPbests_2.v_15
context:
v_3::Real[2]{
v_3[0] := %copy -3.0
v_3[1] := %copy -3.0
v_4::Real[2]{
v_4[0] := %copy 3.0
v_4[1] := %copy 3.0
v_1::Int[]{
v_1[] := %%threefry2x32 42 0
v_5::Int[]{
v_5[] := %%threefry2x32 42 1
v_6::Int[]{
v_6[] := %%threefry2x32 v_5 0
v_7::Int[]{
v_7[] := %%threefry2x32 v_5 1
initPositions::Real[10, 2]{
for p < 10
v_2::Int[]{
v_2[] := %copy p
v_8::Int[]{
v_8[] := %%threefry2x32 v_1 v_2
for i < 2
v_9::Int[]{
v_9[] := %copy i
v_10::Int[]{
v_10[] := %%threefry2x32 v_8 v_9
v_11::Real[]{
v_11[] := %%randunif v_10
v_12::Real[]{
v_12[] := %fsub v_4.i v_3.i
v_13::Real[]{
v_13[] := %fmul v_11 v_12
initPositions[p, i] := %fadd v_3.i v_13}}}}}}}
initVelocities::Real[10, 2]{
for p < 10
v_2::Int[]{
v_2[] := %copy p
v_8::Int[]{
v_8[] := %%threefry2x32 v_6 v_2
for i < 2
v_9::Int[]{
v_9[] := %copy i
v_10::Int[]{
v_10[] := %%threefry2x32 v_8 v_9
v_11::Real[]{
v_11[] := %%randunif v_10
v_12::Real[]{
v_12[] := %fsub v_4.i v_3.i
v_13::Real[]{
v_13[] := %fmul v_11 v_12
initVelocities[p, i] := %fadd v_3.i v_13}}}}}}}
initPs::Real[10]{
for p < 10
v_8::Int[]{
v_8[] := %copy 0
v_2::Int[]{
v_2[] := %copy 1
v::Real[]{
v[] := %fsub 1.0 initPositions.p.v_8
v_9::Real[]{
v_9[] := %fmul v v
v_10::Real[]{
v_10[] := %fmul initPositions.p.v_8 initPositions.p.v_8
v_11::Real[]{
v_11[] := %fsub initPositions.p.v_2 v_10
v_12::Real[]{
v_12[] := %fmul v_11 v_11
v_13::Real[]{
v_13[] := %fmul 100.0 v_12
v_14::Real[]{
v_14[] := %fadd v_9 v_13
initPs[p] := %copy v_14}}}}}}}}}
v_2::Int[]{
v_2[] := %copy 0
v_8::Real[]{
v_9::Real[2]{
v_8[] := %copy initPs.v_2
v_9[] := %copy initPositions.v_2
for i < 10
v_10::Real[2]{
v_11::Real[2, 2]{
v_10[0] := %copy initPs.i
v_11[0] := %copy initPositions.i
v_10[1] := %copy v_8
v_11[1] := %copy v_9
v_12::Bool[]{
v_12[] := %flt initPs.i v_8
v_13::Int[]{
v_13[] := %booltoint v_12
v_14::Int[]{
v_14[] := %copy v_13
v_8[] := %copy v_10.v_14
v_9[] := %copy v_11.v_14}}}}}
v_10::Int[]{
v_10[] := %%threefry2x32 v_7 0
v_11::Int[]{
v_11[] := %%threefry2x32 v_7 1
v_12::Int[]{
v_12[] := %%threefry2x32 v_11 0
v_13::Int[]{
v_13[] := %%threefry2x32 v_11 1
v::Real[]{
v[] := %%randunif v_10
gWeight::Real[]{
gWeight[] := %fmul 0.3 v
v_14::Real[]{
v_14[] := %%randunif v_12
pWeight::Real[]{
pWeight[] := %fmul 0.3 v_14
gDirs::Real[10, 2]{
for p < 10
for i < 2
gDirs[p, i] := %fsub v_9.i initPositions.p.i
pDirs::Real[10, 2]{
for p < 10
for i < 2
pDirs[p, i] := %fsub initPositions.p.i initPositions.p.i
newVelocities::Real[10, 2]{
for p < 10
for i < 2
v_15::Real[]{
v_15[] := %fmul 0.4 initVelocities.p.i
v_16::Real[]{
v_16[] := %fmul gWeight gDirs.p.i
v_17::Real[]{
v_17[] := %fadd v_15 v_16
v_18::Real[]{
v_18[] := %fmul pWeight gDirs.p.i
newVelocities[p, i] := %fadd v_17 v_18}}}}
newPositions::Real[10, 2]{
for p < 10
for i < 2
newPositions[p, i] := %fadd initPositions.p.i initVelocities.p.i
newPbests::Real[10, 2]{
newPbests_1::Real[10, 2, 2]{
newPbests_2::Int[10]{
for p < 10
v_15::Int[]{
v_15[] := %copy 0
v_16::Int[]{
v_16[] := %copy 1
v_17::Real[]{
v_17[] := %fsub 1.0 newPositions.p.v_15
v_18::Real[]{
v_18[] := %fmul v_17 v_17
v_19::Real[]{
v_19[] := %fmul newPositions.p.v_15 newPositions.p.v_15
v_20::Real[]{
v_20[] := %fsub newPositions.p.v_16 v_19
v_21::Real[]{
v_21[] := %fmul v_20 v_20
v_22::Real[]{
v_22[] := %fmul 100.0 v_21
v_23::Real[]{
v_23[] := %fadd v_18 v_22
v_24::Real[2]{
v_25::Real[2, 2]{
v_24[0] := %copy initPs.p
v_25[0] := %copy initPositions.p
v_24[1] := %copy v_23
v_25[1] := %copy newPositions.p
v_26::Bool[]{
v_26[] := %flt initPs.p v_23
v_27::Int[]{
v_27[] := %booltoint v_26
v_28::Int[]{
v_28[] := %copy v_27
newPbests[p] := %copy v_24
newPbests_1[p] := %copy v_25
newPbests_2[p] := %copy v_28}}}}}}}}}}}}}}
v_15::Int[]{
v_15[] := %copy 0
v_16::Real[]{
v_17::Real[2]{
v_16[] := %copy newPbests.v_15.newPbests_2.v_15
v_17[] := %copy newPbests_1.v_15.newPbests_2.v_15
for i < 10
v_18::Real[2]{
v_19::Real[2, 2]{
v_18[0] := %copy newPbests.i.newPbests_2.i
v_19[0] := %copy newPbests_1.i.newPbests_2.i
v_18[1] := %copy v_16
v_19[1] := %copy v_17
v_20::Bool[]{
v_20[] := %flt newPbests.i.newPbests_2.i v_16
v_21::Int[]{
v_21[] := %booltoint v_20
v_22::Int[]{
v_22[] := %copy v_21
v_16[] := %copy v_18.v_22
v_17[] := %copy v_19.v_22}}}}}
v_18::Real[2]{
v_19::Real[2, 2]{
v_18[0] := %copy v_8
v_19[0] := %copy v_9
v_18[1] := %copy v_16
v_19[1] := %copy v_17
v_20::Bool[]{
v_20[] := %flt v_8 v_16
v_21::Int[]{
v_21[] := %booltoint v_20
v_22::Int[]{
v_22[] := %copy v_21
%imptmp[] := %copy v_19.v_22}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
' # Particle Swarm Optimizer
' ## Fitness function
rosenbrock:: Real -> Real -> Real
rosenbrock x y = sq (1.0 - x) + 100.0*sq (y - x*x)
' We write one that uses vector for input
rosenbrock2:: (2=>Real) -> Real
rosenbrock2 xs =
x = xs.(asidx 0)
y = xs.(asidx 1)
rosenbrock x y
' Min should be at 1.0, 1.0
:p rosenbrock 1.0 1.000
:p rosenbrock2 [1.0, 1.000]
:p rosenbrock 1.0 1.02
:p rosenbrock2 [1.0, 1.02]
:plotmat for i. for j. rosenbrock xs.i ys.j
' ## Helper functions
' make a random vector unifornly distrubuted between lb and ub
randBounded:: Key -> (d=>Real)->(d=>Real)->(d=>Real)
randBounded key lb ub =
for i. lb.i + ((rand $ ixkey key i) * (ub.i - lb.i))
randBounded 1 x y
' minby and minimumby
' to find the smallest values
minby:: (a->Real)->a->a->a
minby f x y = [x,y].(asidx $ b2i $ (f x) > (f y))
minby sq -1.0 0.5
minby fst (0.7, 10.0) (3.0, 12.0)
minimumby:: (q->Real)->(p=>q)->q
minimumby f xs = fold xs.(asidx 0) (for i. minby f xs.i)
minimumby sq [-1.0, -0.1, 2.0, 3.0]
' ## The Optimizer itself.
### TODO:
- Replace `res = optStep inits` with `res = fold inits (for iter::20. optStep)`
- workout how to pass nparticles and niters in as a variable
- Currrently hardcoded as 10 and 20 respectively
- workout more compact wa to define type sig
optimize:: Key->((d=>Real)->Real) -> (d=>Real,d=>Real) -> (Real,Real,Real) -> (d=>Real)
optimize key f (lb,ub) (momentum,gRate,pRate) =
optStep (keyL, gbest, pbests,positions,velocities) =
(keyG, keyP, keyNext) = splitKey3 keyL
gWeight::Real = gRate * rand keyG
pWeight::Real = pRate * rand keyP
(gscore, gloc) = gbest
plocs = map snd pbests
gDirs::(10=>d=>Real) = for p i. gloc.i - positions.p.i
pDirs::(10=>d=>Real) = for p i. plocs.p.i - positions.p.i
newVelocities::(10=>d=>Real) = for p i. momentum*velocities.p.i + gWeight*gDirs.p.i + pWeight*gDirs.p.i
newPositions::(10=>d=>Real) = for p i. positions.p.i + velocities.p.i
newPbests::(10=>(Real, d=>Real)) = for p. minby fst pbests.p (f newPositions.p, newPositions.p)
newGbest::(Real, d=>Real) = minby fst gbest (minimumby fst newPbests)
(keyNext,newGbest,newPbests,newPositions,newVelocities)
randInit1 keyI1 = randBounded keyI1 lb ub
randInit keyI = for p::10. randInit1 $ ixkey keyI p
(keyPos, keyVel, keyLoop) = splitKey3 key
initPositions::(10=>d=>Real) = randInit keyPos
initVelocities::(10=>d=>Real) = randInit keyVel
initPs::(10=>(Real, d=>Real)) = for p. (f initPositions.p, initPositions.p)
initG::(Real, d=>Real) = minimumby fst initPs
inits = (keyLoop,initG,initPs,initPositions,initVelocities)
res = optStep inits
(dc0,(finalGscore, finalGloc),dc1,dc2,dc3) = res
finalGloc
:p optimize 42 rosenbrock2 ([-3.0, -3.0],[3.0, 3.0]) (0.4,0.3,0.3)
' ---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment