1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #ifndef INCLUDED_SCCOMP_SOURCE_DIFFERENTIALEVOLUTION_HXX
12 #define INCLUDED_SCCOMP_SOURCE_DIFFERENTIALEVOLUTION_HXX
20 std::vector
<double> mVariables
;
23 template <typename DataProvider
> class DifferentialEvolutionAlgorithm
25 static constexpr double mnDifferentialWeight
= 0.5; // [0, 2]
26 static constexpr double mnCrossoverProbability
= 0.9; // [0, 1]
28 static constexpr double constAcceptedPrecision
= 0.000000001;
30 DataProvider
& mrDataProvider
;
32 size_t const mnPopulationSize
;
33 std::vector
<Individual
> maPopulation
;
35 std::random_device maRandomDevice
;
36 std::mt19937 maGenerator
;
37 size_t const mnDimensionality
;
39 std::uniform_int_distribution
<> maRandomPopulation
;
40 std::uniform_int_distribution
<> maRandomDimensionality
;
41 std::uniform_real_distribution
<> maRandom01
;
43 Individual maBestCandidate
;
49 DifferentialEvolutionAlgorithm(DataProvider
& rDataProvider
, size_t nPopulationSize
)
50 : mrDataProvider(rDataProvider
)
51 , mnPopulationSize(nPopulationSize
)
52 , maGenerator(maRandomDevice())
53 , mnDimensionality(mrDataProvider
.getDimensionality())
54 , maRandomPopulation(0, mnPopulationSize
- 1)
55 , maRandomDimensionality(0, mnDimensionality
- 1)
56 , maRandom01(0.0, 1.0)
57 , mfBestFitness(std::numeric_limits
<double>::lowest())
63 std::vector
<double> const& getResult() { return maBestCandidate
.mVariables
; }
65 int getGeneration() { return mnGeneration
; }
67 int getLastChange() { return mnLastChange
; }
74 maBestCandidate
.mVariables
.clear();
76 // Initialize population with individuals that have been initialized with uniform random
78 // uniform noise means random value inside your search space
79 maPopulation
.reserve(mnPopulationSize
);
80 for (size_t i
= 0; i
< mnPopulationSize
; ++i
)
82 maPopulation
.emplace_back();
83 Individual
& rIndividual
= maPopulation
.back();
84 mrDataProvider
.initializeVariables(rIndividual
.mVariables
, maGenerator
);
88 // Calculate one generation
91 bool bBestChanged
= false;
93 for (size_t agentIndex
= 0; agentIndex
< mnPopulationSize
; ++agentIndex
)
95 // calculate new candidate solution
97 // pick random point from population
98 size_t x
= agentIndex
; // randomPopulation(generator);
101 // create a copy of chosen random agent in population
102 Individual
& rOriginal
= maPopulation
[x
];
103 Individual
aCandidate(rOriginal
);
105 // pick three different random points from population
108 a
= maRandomPopulation(maGenerator
);
113 b
= maRandomPopulation(maGenerator
);
114 } while (b
== x
|| b
== a
);
118 c
= maRandomPopulation(maGenerator
);
120 } while (c
== x
|| c
== a
|| c
== b
);
122 size_t randomIndex
= maRandomDimensionality(maGenerator
);
124 for (size_t index
= 0; index
< mnDimensionality
; ++index
)
126 double randomCrossoverProbability
= maRandom01(maGenerator
);
127 if (index
== randomIndex
|| randomCrossoverProbability
< mnCrossoverProbability
)
129 double fVarA
= maPopulation
[a
].mVariables
[index
];
130 double fVarB
= maPopulation
[b
].mVariables
[index
];
131 double fVarC
= maPopulation
[c
].mVariables
[index
];
133 double fNewValue
= fVarA
+ mnDifferentialWeight
* (fVarB
- fVarC
);
134 fNewValue
= mrDataProvider
.boundVariable(index
, fNewValue
);
135 aCandidate
.mVariables
[index
] = fNewValue
;
139 double fCandidateFitness
= mrDataProvider
.calculateFitness(aCandidate
.mVariables
);
141 // see if is better than original, if so replace
142 if (fCandidateFitness
> mrDataProvider
.calculateFitness(rOriginal
.mVariables
))
144 maPopulation
[x
] = aCandidate
;
146 if (fCandidateFitness
> mfBestFitness
)
148 if (std::abs(fCandidateFitness
- mfBestFitness
) > constAcceptedPrecision
)
151 mnLastChange
= mnGeneration
;
153 mfBestFitness
= fCandidateFitness
;
154 maBestCandidate
= maPopulation
[x
];
165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */