Particle swarm optimization: Difference between revisions

Content added Content deleted
(Added Wren)
Line 1,554: Line 1,554:
f(2.20, 1.57) : -1.801140718473825
f(2.20, 1.57) : -1.801140718473825
</pre>
</pre>

=={{header|Nim}}==
{{trans|Kotlin}}
<lang Nim>import math, random, sequtils, sugar

type

Func = seq[float] -> float

Parameters = tuple[omega, phip, phig: float]

State = object
iter: int
gbpos: seq[float]
gbval: float
min, max: seq[float]
parameters: Parameters
pos, vel, bpos: seq[seq[float]]
bval: seq[float]
nParticles, nDims: int


func initState(min, max: seq[float]; parameters: Parameters; nParticles: int): State =
let nDims = min.len
State(iter: 0,
gbpos: repeat(Inf, nDims),
gbval: Inf,
min: min,
max: max,
parameters: parameters,
pos: repeat(min, nParticles),
vel: newSeqWith(nParticles,
newSeq[float](nDims)),
bpos: repeat(min, nParticles),
bval: repeat(Inf, nParticles),
nParticles: nParticles,
nDims: nDims)


proc report(state: State; testFunc: string) =
echo "Test Function: ", testfunc
echo "Iterations: ", state.iter
echo "Global Best Position: ", state.gbpos
echo "Global Best Value: ", state.gbval


proc pso(fn: Func; y: State): State =
let p = y.parameters
var v = newSeq[float](y.nParticles)
var bpos = repeat(y.min, y.nParticles)
var bval = newSeq[float](y.nParticles)
var gbpos = newSeq[float](y.nDims)
var gbval = Inf

for j in 0..<y.nParticles:
# evaluate.
v[j] = fn(y.pos[j])
# update.
if v[j] < y.bval[j]:
bpos[j] = y.pos[j]
bval[j] = v[j]
else:
bpos[j] = y.bpos[j]
bval[j] = y.bval[j]
if bval[j] < gbval:
gbval = bval[j]
gbpos = bpos[j]

let rg = rand(1.0)
var pos = newSeqWith(y.nParticles, newSeq[float](y.nDims))
var vel = newSeqWith(y.nParticles, newSeq[float](y.nDims))
for j in 0..<y.nParticles:
# migrate.
let rp = rand(1.0)
var ok = true
for k in 0..<y.nDims:
vel[j][k] = p.omega * y.vel[j][k] +
p.phip * rp * (bpos[j][k] - y.pos[j][k]) +
p.phig * rg * (gbpos[k] - y.pos[j][k])
pos[j][k] = y.pos[j][k] + vel[j][k]
ok = ok and y.min[k] < pos[j][k] and y.max[k] > pos[j][k]
if not ok:
for k in 0..<y.nDims:
pos[j][k]= y.min[k] + (y.max[k] - y.min[k]) * rand(1.0)

result = State(iter: 1 + y.iter,
gbpos: gbpos,
gbval: gbval,
min: y.min,
max: y.max,
parameters: y.parameters,
pos: pos,
vel: vel,
bpos: bpos,
bval: bval,
nParticles: y.nParticles,
nDims: y.nDims)


proc iterate(fn: Func; n: int; y: State): State =
result = y
if n == int.high:
while true:
let old = result
result = pso(fn, result)
if result == old: break
else:
for _ in 1..n:
result = pso(fn, result)


func mccormick(x: seq[float]): float =
let a = x[0]
let b = x[1]
result = sin(a + b) + (a - b) * (a - b) + 1.0 + 2.5 * b - 1.5 * a


func michalewicz(x: seq[float]): float =
const M = 10
for i in 1..x.len:
let j = x[i - 1]
let k = sin(i.toFloat * j * j / PI)
result -= sin(j) * k^(2 * M)


randomize()

var state = initState(min = @[-1.5, -3],
max = @[4.0, 4.0],
parameters = (0.0, 0.6, 0.3),
nParticles = 100)

state = iterate(mccormick, 40, state)
state.report("McCormick")
echo "f(-.54719, -1.54719): ", mccormick(@[-0.54719, -1.54719])
echo()
state = initState(min = @[0.0, 0.0],
max = @[PI, PI],
parameters = (0.3, 0.3, 0.3),
nParticles = 1000)
state = iterate(michalewicz, 30, state)
state.report("Michalewicz (2D)")
echo "f(2.20, 1.57): ", michalewicz(@[2.2, 1.57])</lang>

{{out}}
<pre>Test Function: McCormick
Iterations: 40
Global Best Position: @[-0.5470347980396687, -1.547176688676891]
Global Best Value: -1.913222920248667
f(-.54719, -1.54719): -1.913222954882274

Test Function: Michalewicz (2D)
Iterations: 30
Global Best Position: @[2.202898715299719, 1.570804023976923]
Global Best Value: -1.801303406946448
f(2.20, 1.57): -1.801140718473825</pre>


=={{header|ooRexx}}==
=={{header|ooRexx}}==