@@ -97,7 +97,6 @@ typename MatType::elem_type NSGA2::Optimize(
9797 // Convenience typedefs.
9898 typedef typename MatType::elem_type ElemType;
9999 typedef typename MatTypeTraits<MatType>::BaseMatType BaseMatType;
100- typedef typename ForwardType<MatType>::bcol BaseColType;
101100 typedef typename ForwardType<CubeType>::bmat CubeBaseMatType;
102101
103102 BaseMatType& iterate = (BaseMatType&) iterateIn;
@@ -124,8 +123,9 @@ typename MatType::elem_type NSGA2::Optimize(
124123 numObjectives = sizeof ...(ArbitraryFunctionType);
125124 numVariables = iterate.n_rows ;
126125
127- // Cache calculated objectives.
128- std::vector<BaseColType> calculatedObjectives (populationSize);
126+ // Cache calculated objectives as a matrix: (numObjectives x populationSize).
127+ arma::Mat<ElemType> calculatedObjectives (numObjectives, populationSize,
128+ arma::fill::zeros);
129129
130130 // Population size reserved to 2 * populationSize + 1 to accommodate
131131 // for the size of intermediate candidate population.
@@ -175,22 +175,20 @@ typename MatType::elem_type NSGA2::Optimize(
175175 BinaryTournamentSelection (population, castedLowerBound, castedUpperBound);
176176
177177 // Evaluate the objectives for the new population.
178- calculatedObjectives.resize (population.size ());
179- std::fill (calculatedObjectives.begin (), calculatedObjectives.end (),
180- BaseColType (numObjectives, GetFillType<MatType>::zeros));
178+ calculatedObjectives.zeros (numObjectives, population.size ());
181179 EvaluateObjectives (population, objectives, calculatedObjectives);
182180
183181 // Perform fast non dominated sort on P_t ∪ G_t.
184182 ranks.resize (population.size ());
185- FastNonDominatedSort<BaseMatType> (fronts, ranks, calculatedObjectives);
183+ FastNonDominatedSort (fronts, ranks, calculatedObjectives);
186184
187185 // Perform crowding distance assignment.
188186 crowdingDistance.resize (population.size ());
189187 std::fill (crowdingDistance.begin (), crowdingDistance.end (), 0 .);
190188 for (size_t fNum = 0 ; fNum < fronts.size (); fNum ++)
191189 {
192- CrowdingDistanceAssignment<BaseMatType, BaseColType>(
193- fronts[ fNum ], calculatedObjectives, crowdingDistance);
190+ CrowdingDistanceAssignment (fronts[ fNum ], calculatedObjectives,
191+ crowdingDistance);
194192 }
195193
196194 // Sort based on crowding distance.
@@ -234,12 +232,11 @@ typename MatType::elem_type NSGA2::Optimize(
234232 }
235233
236234 // Set the candidates from the Pareto Front as the output.
237- paretoFrontIn.set_size (calculatedObjectives[0 ].n_rows ,
238- calculatedObjectives[0 ].n_cols , fronts[0 ].size ());
235+ paretoFrontIn.set_size (calculatedObjectives.n_rows , 1 , fronts[0 ].size ());
239236 for (size_t solutionIdx = 0 ; solutionIdx < fronts[0 ].size (); ++solutionIdx)
240237 {
241238 paretoFrontIn.slice (solutionIdx) = conv_to<CubeBaseMatType>::from (
242- calculatedObjectives[ fronts[0 ][solutionIdx]] );
239+ calculatedObjectives. col ( fronts[0 ][solutionIdx]) );
243240 }
244241
245242 // Assign iterate to first element of the Pareto Set.
@@ -249,45 +246,43 @@ typename MatType::elem_type NSGA2::Optimize(
249246
250247 ElemType performance = std::numeric_limits<ElemType>::max ();
251248
252- for (const BaseColType& objective: calculatedObjectives)
253- if (accu (objective) < performance)
254- performance = accu (objective);
249+ for (size_t i = 0 ; i < calculatedObjectives.n_cols ; ++i)
250+ performance = std::min (performance, arma::accu (calculatedObjectives.col (i)));
255251
256252 return performance;
257253}
258254
259255// ! No objectives to evaluate.
260256template <std::size_t I,
261- typename InputMatType ,
257+ typename MatType ,
262258 typename ObjectiveMatType,
263259 typename ...ArbitraryFunctionType>
264260typename std::enable_if<I == sizeof ...(ArbitraryFunctionType), void>::type
265261NSGA2::EvaluateObjectives(
266- std::vector<InputMatType >&,
262+ std::vector<MatType >&,
267263 std::tuple<ArbitraryFunctionType...>&,
268- std::vector< ObjectiveMatType> &)
264+ ObjectiveMatType&)
269265{
270266 // Nothing to do here.
271267}
272268
273269// ! Evaluate the objectives for the entire population.
274270template <std::size_t I,
275- typename InputMatType ,
271+ typename MatType ,
276272 typename ObjectiveMatType,
277273 typename ...ArbitraryFunctionType>
278274typename std::enable_if<I < sizeof ...(ArbitraryFunctionType), void>::type
279275NSGA2::EvaluateObjectives(
280- std::vector<InputMatType >& population,
276+ std::vector<MatType >& population,
281277 std::tuple<ArbitraryFunctionType...>& objectives,
282- std::vector< ObjectiveMatType> & calculatedObjectives)
278+ ObjectiveMatType& calculatedObjectives)
283279{
284280 for (size_t i = 0 ; i < populationSize; i++)
285281 {
286- calculatedObjectives[i](I) = std::get<I>(objectives).Evaluate (
287- population[i]);
288- EvaluateObjectives<
289- I + 1 , InputMatType, ObjectiveMatType, ArbitraryFunctionType...>(
290- population, objectives, calculatedObjectives);
282+ calculatedObjectives (I, i) =
283+ std::get<I>(objectives).Evaluate (population[i]);
284+ EvaluateObjectives<I + 1 , MatType, ObjectiveMatType,
285+ ArbitraryFunctionType...>(population, objectives, calculatedObjectives);
291286 }
292287}
293288
@@ -375,11 +370,11 @@ void NSGA2::Mutate(
375370}
376371
377372// ! Sort population into Pareto fronts.
378- template <typename InputMatType, typename ObjectiveMatType >
373+ template <typename MatType >
379374void NSGA2::FastNonDominatedSort (
380375 std::vector<std::vector<size_t > >& fronts,
381376 std::vector<size_t >& ranks,
382- std::vector<ObjectiveMatType> & calculatedObjectives)
377+ MatType & calculatedObjectives)
383378{
384379 std::map<size_t , size_t > dominationCount;
385380 std::map<size_t , std::set<size_t > > dominated;
@@ -395,9 +390,9 @@ void NSGA2::FastNonDominatedSort(
395390
396391 for (size_t q = 0 ; q < populationSize; q++)
397392 {
398- if (Dominates<InputMatType >(calculatedObjectives, p, q))
393+ if (Dominates<MatType >(calculatedObjectives, p, q))
399394 dominated[p].insert (q);
400- else if (Dominates<InputMatType >(calculatedObjectives, q, p))
395+ else if (Dominates<MatType >(calculatedObjectives, q, p))
401396 dominationCount[p] += 1 ;
402397 }
403398
@@ -436,43 +431,43 @@ void NSGA2::FastNonDominatedSort(
436431}
437432
438433// ! Check if a candidate Pareto dominates another candidate.
439- template <typename InputMatType, typename ObjectiveMatType >
440- bool NSGA2::Dominates (
441- std::vector<ObjectiveMatType> & calculatedObjectives,
434+ template <typename MatType >
435+ inline bool NSGA2::Dominates (
436+ MatType & calculatedObjectives,
442437 size_t candidateP,
443438 size_t candidateQ)
444439{
445440 bool allBetterOrEqual = true ;
446441 bool atleastOneBetter = false ;
447- size_t n_objectives = calculatedObjectives[ 0 ]. n_elem ;
442+ const size_t n_objectives = calculatedObjectives. n_rows ;
448443
449444 for (size_t i = 0 ; i < n_objectives; i++)
450445 {
451446 // P is worse than Q for the i-th objective function.
452- if (calculatedObjectives[candidateP](i ) >
453- calculatedObjectives[candidateQ](i ))
447+ if (calculatedObjectives (i, candidateP ) >
448+ calculatedObjectives (i, candidateQ ))
454449 allBetterOrEqual = false ;
455450
456451 // P is better than Q for the i-th objective function.
457- else if (calculatedObjectives[candidateP](i ) <
458- calculatedObjectives[candidateQ](i ))
452+ else if (calculatedObjectives (i, candidateP ) <
453+ calculatedObjectives (i, candidateQ ))
459454 atleastOneBetter = true ;
460455 }
461456
462457 return allBetterOrEqual && atleastOneBetter;
463458}
464459
465460// ! Assign crowding distance to the population.
466- template <typename InputMatType, typename ObjectiveMatType >
461+ template <typename MatType >
467462void NSGA2::CrowdingDistanceAssignment (
468463 const std::vector<size_t >& front,
469- std::vector<ObjectiveMatType> & calculatedObjectives,
470- std::vector<typename InputMatType ::elem_type>& crowdingDistance)
464+ MatType & calculatedObjectives,
465+ std::vector<typename MatType ::elem_type>& crowdingDistance)
471466{
472467 // Convenience typedefs.
473- typedef typename InputMatType ::elem_type ElemType;
474- typedef typename ForwardType<InputMatType >::uvec UVecType;
475- typedef typename ForwardType<ObjectiveMatType >::bcol BaseColType;
468+ typedef typename MatType ::elem_type ElemType;
469+ typedef typename ForwardType<MatType >::uvec UVecType;
470+ typedef typename ForwardType<MatType >::bcol BaseColType;
476471
477472 size_t fSize = front.size ();
478473 // Stores the sorted indices of the fronts.
@@ -482,11 +477,8 @@ void NSGA2::CrowdingDistanceAssignment(
482477 {
483478 // Cache fValues of individuals for current objective.
484479 BaseColType fValues (fSize );
485- for (size_t i = 0 ; i < front.size (); ++i)
486- {
487- size_t individual = front[i];
488- fValues [i] = calculatedObjectives[individual](m);
489- }
480+ for (size_t k = 0 ; k < fSize ; ++k)
481+ fValues (k) = calculatedObjectives (m, size_t (front[k]));
490482
491483 // Sort front indices by ascending fValues for current objective.
492484 sortedIdx = sort_index (fValues , " ascend" );
0 commit comments