Skip to content

Commit 401b745

Browse files
authored
Upgrade to ensmallen 1.14.1 (#9)
* Citation tweaks. * Add scripts to build ignore. * Upgrade ensmallen to 1.14.1 * Bump version information * Update NEWS and ChangeLog for Ensmallen 1.14.1 * Add new line to DE header
1 parent c327405 commit 401b745

File tree

14 files changed

+376
-115
lines changed

14 files changed

+376
-115
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
^\.Rproj\.user$
44
^\.travis\.yml$
55
^cran-comments\.md$
6+
^inst/scripts/.*$

ChangeLog

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
2019-03-09 James Balamuta <[email protected]>
2+
3+
* DESCRIPTION (Version, Date): Release 1.14.1
4+
5+
* NEWS.md: Update for Ensmallen release 1.14.1
6+
7+
* inst/include/ensmallen_bits: Upgraded to Ensmallen 1.14.1
8+
* inst/include/ensmallen.hpp: ditto
9+
110
2019-01-20 James Balamuta <[email protected]>
211

312
* DESCRIPTION (Version, Date): Release 1.13.0

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: RcppEnsmallen
22
Title: Header-Only C++ Mathematical Optimization Library for 'Armadillo'
3-
Version: 0.1.13.0.1
3+
Version: 0.1.14.1.1
44
Authors@R: c(
55
person("James Joseph", "Balamuta", email = "[email protected]",
66
role = c("aut", "cre", "cph"),

NEWS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# RcppEnsmallen 0.1.14.1.1
2+
3+
- Upgraded to ensmallen release 1.14.1 "Difficult Crimp" (2019-03-09)
4+
- Fixes for SPSA (#87).
5+
- Optimized CNE and DE (#90). Changed initial population generation
6+
in CNE to be a normal distribution about the given starting point,
7+
which should accelerate convergence.
8+
- Add DE optimizer (#77).
9+
- Fix for Cholesky decomposition in CMAES (#83).
10+
111
# RcppEnsmallen 0.1.13.0.1
212

313
- Upgraded to ensmallen release 1.13.0 "Coronavirus Invasion" (2019-01-14)

inst/CITATION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
citHeader("To cite 'RcppEnsmallen' in publications use:")
1+
citHeader("To cite the 'RcppEnsmallen' R package and 'Ensmallen' libray in publications, please use:")
22

33
citEntry(entry = "Manual",
44
title = "{RcppEnsmallen: Header-Only C++ Mathematical Optimization Library for 'Armadillo'}",
55
author = personList(as.person("James Joseph Balamuta"),
66
as.person("Dirk Eddelbuettel")
77
),
88
year = 2018,
9-
textVersion = paste("James Joseph Balamuta and Dirk Eddelbuettel (2018)",
9+
textVersion = paste("Balamuta, J.J. and Eddelbuettel, D. (2018)",
1010
"RcppEnsmallen: Header-Only C++ Mathematical Optimization Library for 'Armadillo'.",
1111
"URL https://cran.r-project.org/package=RcppEnsmallen.")
1212
)
@@ -21,7 +21,7 @@ citEntry(entry = "Article",
2121
journal = "Workshop on Systems for ML and Open Source Software at NIPS",
2222
year = "2018",
2323
month = "dec",
24-
textVersion = paste("S. Bhardwaj, R. Curtin, M. Edel, Y. Mentekidis, C. Sanderson (2018).",
24+
textVersion = paste("S. Bhardwaj, R. Curtin, M. Edel, Y. Mentekidis, and C. Sanderson (2018).",
2525
"ensmallen: a flexible C++ library for efficient function optimization.",
2626
"Workshop on Systems for ML and Open Source Software at NIPS 2018.",
2727
"URL http://www.ensmallen.org/files/ensmallen_2018.pdf.")

inst/include/ensmallen.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include "ensmallen_bits/bigbatch_sgd/bigbatch_sgd.hpp"
6969
#include "ensmallen_bits/cmaes/cmaes.hpp"
7070
#include "ensmallen_bits/cne/cne.hpp"
71+
#include "ensmallen_bits/de/de.hpp"
7172
#include "ensmallen_bits/eve/eve.hpp"
7273
#include "ensmallen_bits/ftml/ftml.hpp"
7374

inst/include/ensmallen_bits/cmaes/cmaes_impl.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ double CMAES<SelectionPolicyType>::Optimize(
128128
const size_t idx0 = (i - 1) % 2;
129129
const size_t idx1 = i % 2;
130130

131-
const arma::mat covLower = arma::chol(C.slice(idx0), "lower");
131+
// Perform Cholesky decomposition. If the matrix is not positive definite,
132+
// add a small value and try again
133+
arma::mat covLower;
134+
while (!arma::chol(covLower, C.slice(idx0), "lower"))
135+
C.slice(idx0).diag() += 1e-16;
132136

133137
for (size_t j = 0; j < lambda; ++j)
134138
{

inst/include/ensmallen_bits/cne/cne.hpp

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,13 @@ class CNE
8787
* the next generation.
8888
* @param tolerance The final value of the objective function for termination.
8989
* If set to negative value, tolerance is not considered.
90-
* @param objectiveChange Minimum change in best fitness values between two
91-
* consecutive generations should be greater than threshold. If set to
92-
* negative value, objectiveChange is not considered.
9390
*/
9491
CNE(const size_t populationSize = 500,
9592
const size_t maxGenerations = 5000,
9693
const double mutationProb = 0.1,
9794
const double mutationSize = 0.02,
9895
const double selectPercent = 0.2,
99-
const double tolerance = 1e-5,
100-
const double objectiveChange = 1e-5);
96+
const double tolerance = 1e-5);
10197

10298
/**
10399
* Optimize the given function using CNE. The given
@@ -137,16 +133,11 @@ class CNE
137133
//! Modify the selection percentage.
138134
double& SelectionPercentage() { return selectPercent; }
139135

140-
//! Get the final objective value.
136+
//! Get the tolerance.
141137
double Tolerance() const { return tolerance; }
142-
//! Modify the final objective value.
138+
//! Modify the tolerance.
143139
double& Tolerance() { return tolerance; }
144140

145-
//! Get the change in fitness history between generations.
146-
double ObjectiveChange() const { return objectiveChange; }
147-
//! Modify the termination criteria of change in fitness value.
148-
double& ObjectiveChange() { return objectiveChange; }
149-
150141
private:
151142
//! Reproduce candidates to create the next generation.
152143
void Reproduce();
@@ -198,9 +189,6 @@ class CNE
198189
//! The final value of the objective function.
199190
double tolerance;
200191

201-
//! Minimum change in best fitness values between two generations.
202-
double objectiveChange;
203-
204192
//! Number of candidates to become parent for the next generation.
205193
size_t numElite;
206194

inst/include/ensmallen_bits/cne/cne_impl.hpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ inline CNE::CNE(const size_t populationSize,
2525
const double mutationProb,
2626
const double mutationSize,
2727
const double selectPercent,
28-
const double tolerance,
29-
const double objectiveChange) :
28+
const double tolerance) :
3029
populationSize(populationSize),
3130
maxGenerations(maxGenerations),
3231
mutationProb(mutationProb),
3332
mutationSize(mutationSize),
3433
selectPercent(selectPercent),
3534
tolerance(tolerance),
36-
objectiveChange(objectiveChange),
3735
numElite(0),
3836
elements(0)
3937
{ /* Nothing to do here. */ }
@@ -70,8 +68,10 @@ double CNE::Optimize(DecomposableFunctionType& function, arma::mat& iterate)
7068
"children. Increase population size.");
7169
}
7270

73-
// Set the population size and fill random values [0,1].
74-
population = arma::randu(iterate.n_rows, iterate.n_cols, populationSize);
71+
// Generate the population based on a Gaussian distribution around the given
72+
// starting point.
73+
population = arma::randn(iterate.n_rows, iterate.n_cols, populationSize);
74+
population.each_slice() += iterate;
7575

7676
// Store the number of elements in a cube slice or a matrix column.
7777
elements = population.n_rows * population.n_cols;
@@ -105,19 +105,10 @@ double CNE::Optimize(DecomposableFunctionType& function, arma::mat& iterate)
105105
Reproduce();
106106

107107
// Check for termination criteria.
108-
if (tolerance >= fitnessValues.min())
108+
if (std::abs(lastBestFitness - fitnessValues.min()) < tolerance)
109109
{
110-
Info << "CNE::Optimize(): terminating. Given fitness criteria "
111-
<< tolerance << " > " << fitnessValues.min() << "." << std::endl;
112-
break;
113-
}
114-
115-
// Check for termination criteria.
116-
if (lastBestFitness - fitnessValues.min() < objectiveChange)
117-
{
118-
Info << "CNE::Optimize(): terminating. Fitness history change "
119-
<< (lastBestFitness - fitnessValues.min())
120-
<< " < " << objectiveChange << "." << std::endl;
110+
Info << "CNE: minimized within tolerance " << tolerance << "; "
111+
<< "terminating optimization." << std::endl;
121112
break;
122113
}
123114

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/**
2+
* @file de.hpp
3+
* @author Rahul Ganesh Prabhu
4+
*
5+
* Differential Evolution is a method used for global optimization of arbitrary
6+
* functions that optimizes a problem by iteratively trying to improve a
7+
* candidate solution.
8+
*
9+
* ensmallen is free software; you may redistribute it and/or modify it under
10+
* the terms of the 3-clause BSD license. You should have received a copy of
11+
* the 3-clause BSD license along with ensmallen. If not, see
12+
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
13+
*/
14+
15+
#ifndef ENSMALLEN_DE_DE_HPP
16+
#define ENSMALLEN_DE_DE_HPP
17+
18+
namespace ens {
19+
20+
/**
21+
* Differential evolution is a stochastic evolutionary algorithm used for global
22+
* optimization. This class implements the best/1/bin strategy of differential
23+
* evolution to converge a given function to minima.
24+
*
25+
* The algorithm works by generating a fixed number of candidates from the
26+
* given starting point. At each pass through the population, the algorithm
27+
* mutates each candidate solution to create a trial solution. If the trial
28+
* solution is better than the candidate, it is replaced in the
29+
* population.
30+
*
31+
* The evolution takes place in two steps:
32+
* - Mutation
33+
* - Crossover
34+
*
35+
* Mutation is done by generating a new candidate solution from the best
36+
* candidate of the previous solution and two random other candidates.
37+
*
38+
* Crossover is done by mixing the parameters of the candidate solution and the
39+
* mutant solution. This is done only if a randomly generated number between 0
40+
* and 1 is greater than the crossover rate.
41+
*
42+
* The final value and the parameters are returned by the Optimize() method.
43+
*
44+
* For more information, see the following:
45+
*
46+
* @techreport{storn1995,
47+
* title = {Differential Evolution—a simple and efficient adaptive scheme
48+
* for global optimization over continuous spaces},
49+
* author = {Storn, Rainer and Price, Kenneth},
50+
* year = 1995
51+
* }
52+
*
53+
* DE can optimize arbitrary functions. For more details, see the
54+
* documentation on function types included with this distribution or on the
55+
* ensmallen website.
56+
*/
57+
class DE
58+
{
59+
public:
60+
/**
61+
* Constructor for the DE optimizer
62+
*
63+
* The default values provided over here are not necessarily suitable for a
64+
* given function. Therefore it is highly recommended to adjust the
65+
* parameters according to the problem.
66+
*
67+
* @param populationSize The number of candidates in the population.
68+
* This should be at least 3 in size.
69+
* @param maxGenerations The maximum number of generations allowed for CNE.
70+
* @param crossoverRate The probability that a crossover will occur.
71+
* @param differentialWeight A parameter used in the mutation of candidate
72+
* solutions controls amplification factor of the differentiation.
73+
* @param tolerance The final value of the objective function for termination.
74+
*/
75+
DE(const size_t populationSize = 100,
76+
const size_t maxGenerations = 2000,
77+
const double crossoverRate = 0.6,
78+
const double differentialWeight = 0.8,
79+
const double tolerance = 1e-5);
80+
81+
/**
82+
* Optimize the given function using DE. The given
83+
* starting point will be modified to store the finishing point of the
84+
* algorithm, and the final objective value is returned.
85+
*
86+
* @tparam DecomposableFunctionType Type of the function to be optimized.
87+
* @param function Function to optimize.
88+
* @param iterate Starting point (will be modified).
89+
* @return Objective value of the final point.
90+
*/
91+
template<typename DecomposableFunctionType>
92+
double Optimize(DecomposableFunctionType& function, arma::mat& iterate);
93+
94+
//! Get the population size.
95+
size_t PopulationSize() const { return populationSize; }
96+
//! Modify the population size.
97+
size_t& PopulationSize() { return populationSize; }
98+
99+
//! Get maximum number of generations.
100+
size_t MaxGenerations() const { return maxGenerations; }
101+
//! Modify maximum number of generations.
102+
size_t& MaxGenerations() { return maxGenerations; }
103+
104+
//! Get crossover rate.
105+
double CrossoverRate() const { return crossoverRate; }
106+
//! Modify crossover rate.
107+
double& CrossoverRate() { return crossoverRate; }
108+
109+
//! Get differential weight.
110+
double DifferentialWeight() const {return differentialWeight; }
111+
//! Modify differential weight.
112+
double& DifferentialWeight() { return differentialWeight; }
113+
114+
//! Get the tolerance.
115+
double Tolerance() const { return tolerance; }
116+
//! Modify the tolerance.
117+
double& Tolerance() { return tolerance; }
118+
119+
private:
120+
//! Population matrix. Each column is a candidate.
121+
arma::cube population;
122+
123+
//! Vector of fitness values corresponding to each candidate.
124+
arma::vec fitnessValues;
125+
126+
//! The number of candidates in the population.
127+
size_t populationSize;
128+
129+
//! Maximum number of generations before termination criteria is met.
130+
size_t maxGenerations;
131+
132+
//! Probability that crossover will occur.
133+
double crossoverRate;
134+
135+
//! Amplification factor for differentiation.
136+
double differentialWeight;
137+
138+
//! The tolerance for termination.
139+
double tolerance;
140+
};
141+
142+
} // namespace ens
143+
144+
// Include implementation.
145+
#include "de_impl.hpp"
146+
147+
#endif

0 commit comments

Comments
 (0)