Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/torch/optim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'cmaes.lua')
-rw-r--r--cmaes.lua62
1 files changed, 31 insertions, 31 deletions
diff --git a/cmaes.lua b/cmaes.lua
index 1045a48..74cd58a 100644
--- a/cmaes.lua
+++ b/cmaes.lua
@@ -1,16 +1,16 @@
require 'torch'
require 'math'
-local BestSolution = {}
---[[ An implementation of `CMAES` (Covariance Matrix Adaptation Evolution Strategy),
+local BestSolution = {}
+--[[ An implementation of `CMAES` (Covariance Matrix Adaptation Evolution Strategy),
ported from https://www.lri.fr/~hansen/barecmaes2.html.
-
+
Parameters
----------
ARGS:
-- `opfunc` : a function that takes a single input (X), the point of
- evaluation, and returns f(X) and df/dX. Note that df/dX is not used
+- `opfunc` : a function that takes a single input (X), the point of
+ evaluation, and returns f(X) and df/dX. Note that df/dX is not used
- `x` : the initial point
- `state.sigma`
float, initial step-size (standard deviation in each
@@ -20,16 +20,16 @@ ARGS:
- `state.ftarget`
float, target function value
- `state.popsize`
- population size. If this is left empty,
+ population size. If this is left empty,
4 + int(3 * log(|x|)) will be used
-- `state.ftarget`
+- `state.ftarget`
stop if fitness < ftarget
- `state.verb_disp`
int, display on console every verb_disp iteration, 0 for never
RETURN:
- `x*` : the new `x` vector, at the optimal point
-- `f` : a table of all function values:
+- `f` : a table of all function values:
`f[1]` is the value of the function before any optimization and
`f[#f]` is the final fully optimized value, at `x*`
--]]
@@ -50,13 +50,13 @@ function optim.cmaes(opfunc, x, config, state)
local min_iterations = state.min_iterations or 1
local lambda = state.popsize -- population size, offspring number
- -- Strategy parameter setting: Selection
+ -- Strategy parameter setting: Selection
if state.popsize == nil then
lambda = 4 + math.floor(3 * math.log(N))
end
local mu = lambda / 2 -- number of parents/points for recombination
- local weights = torch.range(0,mu-1):apply(function(i)
+ local weights = torch.range(0,mu-1):apply(function(i)
return math.log(mu+0.5) - math.log(i+1) end) -- recombination weights
weights:div(weights:sum()) -- normalize recombination weights array
local mueff = weights:sum()^2 / torch.pow(weights,2):sum() -- variance-effectiveness of sum w_i x_i
@@ -69,18 +69,18 @@ function optim.cmaes(opfunc, x, config, state)
local cmu = math.min(1 - c1, 2 * (mueff - 2 + 1/mueff) / ((N + 2)^2 + mueff)) -- and for rank-mu update
local damps = 2 * mueff/lambda + 0.3 + cs -- damping for sigma, usually close to 1
- -- Initialize dynamic (internal) state variables
+ -- Initialize dynamic (internal) state variables
local pc = torch.Tensor(N):zero():typeAs(x) -- evolution paths for C
local ps = torch.Tensor(N):zero():typeAs(x) -- evolution paths for sigma
- local B = torch.eye(N):typeAs(x) -- B defines the coordinate system
+ local B = torch.eye(N):typeAs(x) -- B defines the coordinate system
local D = torch.Tensor(N):fill(1):typeAs(x) -- diagonal D defines the scaling
- local C = torch.eye(N):typeAs(x) -- covariance matrix
+ local C = torch.eye(N):typeAs(x) -- covariance matrix
if not pcall(function () torch.symeig(C,'V') end) then -- if error occurs trying to use symeig
- error('torch.symeig not available for ' .. x:type() ..
+ error('torch.symeig not available for ' .. x:type() ..
" please use Float- or DoubleTensor for x")
end
local candidates = torch.Tensor(lambda,N):typeAs(x)
- local invsqrtC = torch.eye(N):typeAs(x) -- C^-1/2
+ local invsqrtC = torch.eye(N):typeAs(x) -- C^-1/2
local eigeneval = 0 -- tracking the update of B and D
local counteval = 0
local f_hist = {[1]=opfunc(x)} -- for bookkeeping output and termination
@@ -90,7 +90,7 @@ function optim.cmaes(opfunc, x, config, state)
local function ask()
- --[[return a list of lambda candidate solutions according to
+ --[[return a list of lambda candidate solutions according to
m + sig * Normal(0,C) = m + sig * B * D * Normal(0,I)
--]]
-- Eigendecomposition: first update B, D and invsqrtC from C
@@ -117,9 +117,9 @@ function optim.cmaes(opfunc, x, config, state)
Parameters
----------
- `arx`
+ `arx`
a list of solutions, presumably from `ask()`
- `fitvals`
+ `fitvals`
the corresponding objective function values --]]
-- bookkeeping, preparation
counteval = counteval + lambda -- slightly artificial to do here
@@ -142,7 +142,7 @@ function optim.cmaes(opfunc, x, config, state)
local c = (cs * (2-cs) * mueff)^0.5 / sigma
ps = ps - ps * cs + z * c -- exponential decay on ps
- local hsig = (torch.sum(torch.pow(ps,2)) /
+ local hsig = (torch.sum(torch.pow(ps,2)) /
(1-(1-cs)^(2*counteval/lambda)) / N < 2 + 4./(N+1))
hsig = hsig and 1.0 or 0.0 --use binary numbers
@@ -155,23 +155,23 @@ function optim.cmaes(opfunc, x, config, state)
for i=1,N do
for j=1,N do
local r = torch.range(1,mu)
- r:apply(function(k)
+ r:apply(function(k)
return weights[k] * (arx[k][i]-xold[i]) * (arx[k][j]-xold[j]) end)
local Cmuij = torch.sum(r) / sigma^2 -- rank-mu update
- C[i][j] = C[i][j] + ((-c1a - cmu) * C[i][j] +
+ C[i][j] = C[i][j] + ((-c1a - cmu) * C[i][j] +
c1 * pc[i]*pc[j] + cmu * Cmuij)
end
end
-- Adapt step-size sigma with factor <= exp(0.6) \approx 1.82
- sigma = sigma * math.exp(math.min(0.6,
+ sigma = sigma * math.exp(math.min(0.6,
(cs / damps) * (torch.sum(torch.pow(ps,2))/N - 1)/2))
end
- local function stop()
- --[[return satisfied termination conditions in a table like
- {'termination reason':value, ...}, for example {'tolfun':1e-12},
- or the empty table {}--]]
+ local function stop()
+ --[[return satisfied termination conditions in a table like
+ {'termination reason':value, ...}, for example {'tolfun':1e-12},
+ or the empty table {}--]]
local res = {}
if counteval > 0 then
if counteval >= maxEval then
@@ -184,7 +184,7 @@ function optim.cmaes(opfunc, x, config, state)
res['condition'] = 1e7
end
if fitvals:nElement() > 1 and fitvals[fitvals:nElement()] - fitvals[1] < 1e-12 then
- res['tolfun'] = 1e-12
+ res['tolfun'] = 1e-12
end
if sigma * torch.max(D) < 1e-11 then
-- remark: max(D) >= max(diag(C))^0.5
@@ -206,8 +206,8 @@ function optim.cmaes(opfunc, x, config, state)
end
if iteration <= 2 or iteration % verb_modulo == 0 then
local max_std = math.sqrt(torch.max(torch.diag(C)))
- print(tostring(counteval).. ': ' ..
- string.format(' %6.1f %8.1e ', torch.max(D) / torch.min(D), sigma * max_std)
+ print(tostring(counteval).. ': ' ..
+ string.format(' %6.1f %8.1e ', torch.max(D) / torch.min(D), sigma * max_std)
.. tostring(fitvals[1]))
end
@@ -224,7 +224,7 @@ function optim.cmaes(opfunc, x, config, state)
fitvals[i] = objfunc(candidate)
end
- tell(X)
+ tell(X)
disp(verb_disp)
end
@@ -245,7 +245,7 @@ end
-BestSolution.__index = BestSolution
+BestSolution.__index = BestSolution
function BestSolution.new(x, f, evals)
local self = setmetatable({}, BestSolution)
self.x = x