37 #ifdef ENABLE_CPP_OPTLIB 38 #include "cppoptlib/solver/lbfgssolver.h" 56 std::vector<Individual> individuals;
61 std::vector<double> initial_guess;
62 std::vector<double> solution;
63 std::vector<double> temp_joint_variables;
64 double solution_fitness;
65 std::vector<Species> species;
66 std::vector<Individual> children;
67 std::vector<aligned_vector<Frame>> phenotypes, phenotypes2, phenotypes3;
68 std::vector<size_t> child_indices;
69 std::vector<double*> genotypes;
70 std::vector<Frame> phenotype;
71 std::vector<size_t> quaternion_genes;
80 #ifdef ENABLE_CPP_OPTLIB 81 struct OptlibProblem : cppoptlib::Problem<double>
88 double value(
const TVector& x)
90 const double* genes = x.data();
91 ik->model.computeApproximateMutations(1, &genes, ik->phenotypes);
92 return ik->computeCombinedFitnessActiveVariables(ik->phenotypes[0], genes);
95 typedef cppoptlib::LbfgsSolver<OptlibProblem> OptlibSolver;
96 std::shared_ptr<OptlibSolver> optlib_solver;
97 std::shared_ptr<OptlibProblem> optlib_problem;
98 typename OptlibSolver::TVector optlib_vector;
101 void genesToJointVariables(
const Individual& individual, std::vector<double>& variables)
103 auto& genes = individual.genes;
104 variables.resize(params.robot_model->getVariableCount());
105 for(
size_t i = 0; i < problem.active_variables.size(); i++)
106 variables[problem.active_variables[i]] = genes[i];
109 const std::vector<double>& getSolution()
const {
return solution; }
111 void initialize(
const Problem& problem)
113 BLOCKPROFILER(
"initialization");
115 IKBase::initialize(problem);
118 quaternion_genes.clear();
119 for(
size_t igene = 0; igene < problem.active_variables.size(); igene++)
121 size_t ivar = problem.active_variables[igene];
122 auto* joint_model = params.robot_model->getJointOfVariable(ivar);
123 if(joint_model->getFirstVariableIndex() + 3 != ivar)
continue;
124 if(joint_model->getType() != moveit::core::JointModel::FLOATING)
continue;
125 quaternion_genes.push_back(igene);
129 initial_guess = problem.initial_guess;
130 solution = initial_guess;
131 solution_fitness = computeFitness(solution);
134 temp_joint_variables = initial_guess;
137 size_t population_size = 2;
138 size_t child_count = 16;
142 for(
auto& s : species)
145 s.individuals.resize(population_size);
149 auto& v = s.individuals[0];
152 v.genes.resize(problem.active_variables.size());
158 for(
size_t i = 0; i < v.genes.size(); i++)
159 v.genes[i] = initial_guess[problem.active_variables[i]];
164 for(
size_t i = 0; i < v.genes.size(); i++)
165 v.genes[i] = random(modelInfo.getMin(problem.active_variables[i]), modelInfo.getMax(problem.active_variables[i]));
170 v.gradients.resize(problem.active_variables.size(), 0);
174 for(
size_t i = 1; i < s.individuals.size(); i++)
176 s.individuals[i].genes = s.individuals[0].genes;
177 s.individuals[i].gradients = s.individuals[0].gradients;
182 children.resize(population_size + child_count);
183 for(
auto& child : children)
185 child.genes.resize(problem.active_variables.size());
186 child.gradients.resize(problem.active_variables.size());
192 genes_min.resize(problem.active_variables.size());
193 genes_max.resize(problem.active_variables.size());
194 genes_span.resize(problem.active_variables.size());
195 for(
size_t i = 0; i < problem.active_variables.size(); i++)
197 genes_min[i] = modelInfo.getClipMin(problem.active_variables[i]);
198 genes_max[i] = modelInfo.getClipMax(problem.active_variables[i]);
199 genes_span[i] = modelInfo.getSpan(problem.active_variables[i]);
242 __attribute__((hot)) __attribute__((noinline))
246 reproduce(
const std::vector<Individual>& population)
248 const auto __attribute__((aligned(32)))* __restrict__ genes_span = this->genes_span.data();
249 const auto __attribute__((aligned(32)))* __restrict__ genes_min = this->genes_min.data();
250 const auto __attribute__((aligned(32)))* __restrict__ genes_max = this->genes_max.data();
252 auto gene_count = children[0].genes.size();
254 size_t s = (children.size() - population.size()) * gene_count + children.size() * 4 + 4;
256 auto* __restrict__ rr = fast_random_gauss_n(s);
257 rr = (
const double*)(((
size_t)rr + 3) / 4 * 4);
263 for(
size_t child_index = population.size(); child_index < children.size(); child_index++)
265 double mutation_rate = (1 << fast_random_index(16)) * (1.0 / (1 << 23));
266 auto& parent = population[0];
267 auto& parent2 = population[1];
268 double fmix = (child_index % 2 == 0) * 0.2;
269 double gradient_factor = child_index % 3;
271 auto __attribute__((aligned(32)))* __restrict__ parent_genes = parent.genes.data();
272 auto __attribute__((aligned(32)))* __restrict__ parent_gradients = parent.gradients.data();
274 auto __attribute__((aligned(32)))* __restrict__ parent2_genes = parent2.genes.data();
275 auto __attribute__((aligned(32)))* __restrict__ parent2_gradients = parent2.gradients.data();
277 auto& child = children[child_index];
279 auto __attribute__((aligned(32)))* __restrict__ child_genes = child.genes.data();
280 auto __attribute__((aligned(32)))* __restrict__ child_gradients = child.gradients.data();
282 #pragma omp simd aligned(genes_span : 32), aligned(genes_min : 32), aligned(genes_max : 32), aligned(parent_genes : 32), aligned(parent_gradients : 32), aligned(parent2_genes : 32), aligned(parent2_gradients : 32), aligned(child_genes : 32), aligned(child_gradients : 32) aligned(rr : 32) 284 for(
size_t gene_index = 0; gene_index < gene_count; gene_index++)
288 double r = rr[gene_index];
290 double f = mutation_rate * genes_span[gene_index];
291 double gene = parent_genes[gene_index];
292 double parent_gene = gene;
294 double parent_gradient = mix(parent_gradients[gene_index], parent2_gradients[gene_index], fmix);
295 double gradient = parent_gradient * gradient_factor;
297 gene = clamp(gene, genes_min[gene_index], genes_max[gene_index]);
298 child_genes[gene_index] = gene;
299 child_gradients[gene_index] = mix(parent_gradient, gene - parent_gene, 0.3);
301 rr += (gene_count + 3) / 4 * 4;
320 for(
auto quaternion_gene_index : quaternion_genes)
322 auto& qpos = (*(Quaternion*)&(children[child_index].genes[quaternion_gene_index]));
332 for(
size_t ispecies = 0; ispecies < species.size(); ispecies++)
334 auto& species = this->species[ispecies];
335 auto& population = species.individuals;
338 BLOCKPROFILER(
"evolution");
341 genesToJointVariables(species.individuals[0], temp_joint_variables);
344 model.applyConfiguration(temp_joint_variables);
345 model.initializeMutationApproximator(problem.active_variables);
349 size_t generation_count = 16;
350 if(memetic) generation_count = 8;
351 for(
size_t generation = 0; generation < generation_count; generation++)
359 BLOCKPROFILER(
"reproduction");
360 reproduce(population);
363 size_t child_count = children.size();
366 if(problem.secondary_goals.size())
368 BLOCKPROFILER(
"pre-selection");
369 child_count = random_index(children.size() - population.size() - 1) + 1 + population.size();
370 for(
size_t child_index = population.size(); child_index < children.size(); child_index++)
372 children[child_index].fitness = computeSecondaryFitnessActiveVariables(children[child_index].genes.data());
375 BLOCKPROFILER(
"pre-selection sort");
376 std::sort(children.begin() + population.size(), children.end(), [](
const Individual& a,
const Individual& b) {
return a.fitness < b.fitness; });
382 BLOCKPROFILER(
"keep alive");
383 for(
size_t i = 0; i < population.size(); i++)
385 children[i].genes = population[i].genes;
386 children[i].gradients = population[i].gradients;
392 BLOCKPROFILER(
"phenotype");
393 size_t gene_count = children[0].genes.size();
394 genotypes.resize(child_count);
395 for(
size_t i = 0; i < child_count; i++)
396 genotypes[i] = children[i].genes.data();
397 model.computeApproximateMutations(child_count, genotypes.data(), phenotypes);
402 BLOCKPROFILER(
"fitness");
403 for(
size_t child_index = 0; child_index < child_count; child_index++)
405 children[child_index].fitness = computeFitnessActiveVariables(phenotypes[child_index], genotypes[child_index]);
411 BLOCKPROFILER(
"selection");
412 child_indices.resize(child_count);
413 for(
size_t i = 0; i < child_count; i++)
414 child_indices[i] = i;
415 for(
size_t i = 0; i < population.size(); i++)
418 double fmin = children[child_indices[i]].fitness;
419 for(
size_t j = i + 1; j < child_count; j++)
421 double f = children[child_indices[j]].fitness;
422 if(f < fmin) jmin = j, fmin = f;
424 std::swap(child_indices[i], child_indices[jmin]);
426 for(
size_t i = 0; i < population.size(); i++)
428 std::swap(population[i].genes, children[child_indices[i]].genes);
429 std::swap(population[i].gradients, children[child_indices[i]].gradients);
437 BLOCKPROFILER(
"memetics");
439 if(memetic ==
'q' || memetic ==
'l')
443 auto& individual = population[0];
444 gradient.resize(problem.active_variables.size());
445 if(genotypes.empty()) genotypes.emplace_back();
446 phenotypes2.resize(1);
447 phenotypes3.resize(1);
450 double dp = 0.0000001;
451 if(fast_random() < 0.5) dp = -dp;
453 for(
size_t generation = 0; generation < 8; generation++)
460 temp = individual.genes;
461 genotypes[0] = temp.data();
462 model.computeApproximateMutations(1, genotypes.data(), phenotypes2);
463 double f2p = computeFitnessActiveVariables(phenotypes2[0], genotypes[0]);
464 double fa = f2p + computeSecondaryFitnessActiveVariables(genotypes[0]);
465 for(
size_t i = 0; i < problem.active_variables.size(); i++)
467 double* pp = &(genotypes[0][i]);
468 genotypes[0][i] = individual.genes[i] + dp;
469 model.computeApproximateMutation1(problem.active_variables[i], +dp, phenotypes2[0], phenotypes3[0]);
470 double fb = computeCombinedFitnessActiveVariables(phenotypes3[0], genotypes[0]);
471 genotypes[0][i] = individual.genes[i];
477 double sum = dp * dp;
478 for(
size_t i = 0; i < problem.active_variables.size(); i++)
479 sum += fabs(gradient[i]);
480 double f = 1.0 / sum * dp;
481 for(
size_t i = 0; i < problem.active_variables.size(); i++)
485 for(
size_t i = 0; i < problem.active_variables.size(); i++)
486 genotypes[0][i] = individual.genes[i] - gradient[i];
487 model.computeApproximateMutations(1, genotypes.data(), phenotypes3);
488 double f1 = computeCombinedFitnessActiveVariables(phenotypes3[0], genotypes[0]);
492 for(
size_t i = 0; i < problem.active_variables.size(); i++)
493 genotypes[0][i] = individual.genes[i] + gradient[i];
494 model.computeApproximateMutations(1, genotypes.data(), phenotypes3);
495 double f3 = computeCombinedFitnessActiveVariables(phenotypes3[0], genotypes[0]);
502 double v1 = (f2 - f1);
503 double v2 = (f3 - f2);
504 double v = (v1 + v2) * 0.5;
505 double a = (v1 - v2);
506 double step_size = v / a;
524 for(
size_t i = 0; i < problem.active_variables.size(); i++)
525 genotypes[0][i] = modelInfo.clip(individual.genes[i] + gradient[i] * step_size * f, problem.active_variables[i]);
526 model.computeApproximateMutations(1, genotypes.data(), phenotypes2);
527 double f4p = computeFitnessActiveVariables(phenotypes2[0], genotypes[0]);
532 individual.genes = temp;
549 double cost_diff = (f3 - f1) * 0.5;
550 double step_size = f2 / cost_diff;
553 for(
size_t i = 0; i < problem.active_variables.size(); i++)
554 temp[i] = modelInfo.clip(individual.genes[i] - gradient[i] * step_size, problem.active_variables[i]);
555 model.computeApproximateMutations(1, genotypes.data(), phenotypes2);
556 double f4p = computeFitnessActiveVariables(phenotypes2[0], genotypes[0]);
561 individual.genes = temp;
572 #ifdef ENABLE_CPP_OPTLIB 576 auto& individual = population[0];
581 optlib_solver = std::make_shared<OptlibSolver>();
582 cppoptlib::Criteria<double> crit;
584 optlib_solver->setStopCriteria(crit);
585 optlib_problem = std::make_shared<OptlibProblem>(
this);
589 optlib_vector.resize(problem.active_variables.size());
590 for(
size_t i = 0; i < problem.active_variables.size(); i++)
591 optlib_vector[i] = individual.genes[i];
594 optlib_solver->minimize(*optlib_problem, optlib_vector);
597 for(
size_t i = 0; i < problem.active_variables.size(); i++)
598 individual.genes[i] = modelInfo.clip(optlib_vector[i], problem.active_variables[i]);
605 BLOCKPROFILER(
"species");
608 for(
auto& species : this->species)
610 genesToJointVariables(species.individuals[0], temp_joint_variables);
611 double fitness = computeFitness(temp_joint_variables);
612 species.improved = (fitness != species.fitness);
613 species.fitness = fitness;
617 std::sort(species.begin(), species.end(), [](
const Species& a,
const Species& b) {
return a.fitness < b.fitness; });
620 for(
size_t species_index = 1; species_index < species.size(); species_index++)
622 if(fast_random() < 0.1 || !species[species_index].improved)
626 auto& individual = species[species_index].individuals[0];
628 for(
size_t i = 0; i < individual.genes.size(); i++)
629 individual.genes[i] = random(modelInfo.getMin(problem.active_variables[i]), modelInfo.getMax(problem.active_variables[i]));
631 for(
auto& v : individual.gradients)
634 for(
size_t i = 0; i < species[species_index].individuals.size(); i++)
635 species[species_index].individuals[i] = species[species_index].individuals[0];
640 if(species[0].fitness < solution_fitness)
642 genesToJointVariables(species[0].individuals[0], solution);
643 solution_fitness = species[0].fitness;
649 virtual size_t concurrency()
const {
return 4; }
656 #ifdef ENABLE_CPP_OPTLIB