Libs/Optimize/Function/DualVectorFunction.h
Namespaces
| Name |
|---|
| shapeworks User usage reporting (telemetry) |
Classes
| Name | |
|---|---|
| class | shapeworks::DualVectorFunction |
Source code
```cpp
pragma once
include "ParticleSystemEvaluation.h"
include "itkLightObject.h"
include "itkObjectFactory.h"
include "itkWeakPointer.h"
include "vnl/vnl_vector_fixed.h"
namespace shapeworks {
class DualVectorFunction : public VectorFunction { public: constexpr static int VDimension = 3; constexpr static unsigned int Dimension = VDimension;
using VectorType = VectorFunction::VectorType;
static std::shared_ptr
VectorType evaluate(unsigned int idx, unsigned int d, const ParticleSystem* system, double& maxmove) const override { double maxA = 0; double maxB = 0; VectorType ansA; ansA.fill(0.0); VectorType ansB; ansB.fill(0.0);
const_cast<DualVectorFunction*>(this)->counter_ = counter_ + 1.0;
// evaluate individual functions: A = surface energy, B = correspondence
if (a_on_) {
ansA = function_a_->evaluate(idx, d, system, maxA);
const_cast<DualVectorFunction*>(this)->average_grad_mag_a_ = average_grad_mag_a_ + ansA.magnitude();
}
if (b_on_) {
ansB = function_b_->evaluate(idx, d, system, maxB);
const_cast<DualVectorFunction*>(this)->average_grad_mag_b_ = average_grad_mag_b_ + ansB.magnitude();
}
if (relative_gradient_scaling_ == 0.0) {
ansB.fill(0.0);
maxB = 0.0;
}
// get maxmove and predicted move for current configuration
VectorType predictedMove;
predictedMove.fill(0.0);
// both A and B are active
if (a_on_ && b_on_) {
maxmove = maxA; // always driven by the sampling to decrease the sensitivity to covariance regularization
predictedMove = ansA + relative_gradient_scaling_ * ansB;
return predictedMove;
}
// B is active, A is not active
if (b_on_) {
maxmove = maxB;
predictedMove = ansB;
return predictedMove;
}
// else only A is active (or if both are off, 0 will be return)
maxmove = maxA;
return ansA;
}
double EnergyA(unsigned int idx, unsigned int d, const ParticleSystem* system) const { function_a_->before_evaluate(idx, d, system); double ansA = 0.0; if (a_on_) { ansA = function_a_->energy(idx, d, system); } return ansA; }
virtual double EnergyB(unsigned int idx, unsigned int d, const ParticleSystem system) const { function_b_->before_evaluate(idx, d, system); double ansB = 0.0; if (b_on_ == true) { ansB = function_b_->energy(idx, d, system); } ansB = relative_energy_scaling_; return ansB; }
virtual double energy(unsigned int idx, unsigned int d, const ParticleSystem* system) const { double ansA = 0.0; double ansB = 0.0; double ansC = 0.0; double finalEnergy = 0.0;
// evaluate individual functions: A = surface energy, B = correspondence
if (a_on_ == true) {
ansA = function_a_->energy(idx, d, system);
}
if (b_on_ == true) {
ansB = function_b_->energy(idx, d, system);
}
if (relative_energy_scaling_ == 0) {
ansB = 0.0;
}
// compute final energy for current configuration
if (b_on_ == true) {
if (a_on_ == true) // both A and B are active
{
finalEnergy = ansA + relative_energy_scaling_ * ansB;
return (finalEnergy);
} else // B is active, A is not active
{
finalEnergy = ansB;
return finalEnergy;
}
} else // only A is active
{
return ansA;
}
return 0.0;
}
virtual VectorType evaluate(unsigned int idx, unsigned int d, const ParticleSystem* system, double& maxmove, double& energy) const { double maxA = 0.0; double maxB = 0.0; double energyA = 0.0; double energyB = 0.0; VectorType ansA; ansA.fill(0.0); VectorType ansB; ansB.fill(0.0);
const_cast<DualVectorFunction*>(this)->counter_ = counter_ + 1.0;
// evaluate individual functions: A = surface energy, B = correspondence
if (a_on_ == true) {
ansA = function_a_->evaluate(idx, d, system, maxA, energyA);
const_cast<DualVectorFunction*>(this)->average_grad_mag_a_ = average_grad_mag_a_ + ansA.magnitude();
const_cast<DualVectorFunction*>(this)->average_energy_a_ = average_energy_a_ + energyA;
}
if (b_on_ == true) {
ansB = function_b_->evaluate(idx, d, system, maxB, energyB);
const_cast<DualVectorFunction*>(this)->average_grad_mag_b_ = average_grad_mag_b_ + ansB.magnitude();
const_cast<DualVectorFunction*>(this)->average_energy_b_ = average_energy_b_ + energyB;
}
if (relative_energy_scaling_ == 0.0) {
energyB = 0.0;
ansB.fill(0.0);
}
if (relative_gradient_scaling_ == 0.0) {
maxB = 0.0;
ansB.fill(0.0);
}
// compute final energy, maxmove and predicted move based on current configuration
VectorType predictedMove;
predictedMove.fill(0.0);
if (b_on_ == true) {
if (a_on_ == true) // both A and B are active
{
if (maxB > maxA) {
maxmove = maxB;
} else {
maxmove = maxA;
}
energy = energyA + relative_energy_scaling_ * energyB;
maxmove = maxA; // always driven by the sampling to decrease the senstivity to covariance regularization
predictedMove = ansA + relative_gradient_scaling_ * ansB;
return (predictedMove);
} else // only B is active, A is not active
{
maxmove = maxB;
energy = energyB;
predictedMove = ansB;
return (predictedMove);
}
} else // only A is active
{
maxmove = maxA;
energy = energyA;
return ansA;
}
maxmove = 0.0;
return ansA;
}
virtual void before_evaluate(unsigned int idx, unsigned int d, const ParticleSystem* system) { if (a_on_ == true) { function_a_->before_evaluate(idx, d, system); }
if (b_on_ == true) {
function_b_->before_evaluate(idx, d, system);
}
}
void after_iteration() override { if (a_on_) { function_a_->after_iteration(); } if (b_on_) { function_b_->after_iteration(); } }
void before_iteration() override { if (a_on_) { function_a_->before_iteration(); } if (b_on_) { function_b_->before_iteration(); } average_grad_mag_a_ = 0.0; average_grad_mag_b_ = 0.0; average_energy_a_ = 0.0; counter_ = 0.0; }
void set_particle_system(ParticleSystem* p) override { VectorFunction::set_particle_system(p); if (function_a_ != nullptr) { function_a_->set_particle_system(p); } if (function_b_ != nullptr) { function_b_->set_particle_system(p); } }
void set_domain_number(unsigned int i) override { VectorFunction::set_domain_number(i); if (function_a_ != nullptr) { function_a_->set_domain_number(i); } if (function_b_ != nullptr) { function_b_->set_domain_number(i); } }
void set_function_a(std::shared_ptr
std::shared_ptr
std::shared_ptr
void set_function_b(std::shared_ptr
void set_a_on() { a_on_ = true; } void set_a_off() { a_on_ = false; } void set_a_on(bool s) { a_on_ = s; } bool get_a_on() const { return a_on_; } void set_b_on() { b_on_ = true; } void set_b_off() { b_on_ = false; } void set_b_on(bool s) { b_on_ = s; } bool get_b_on() const { return b_on_; }
void set_relative_energy_scaling(double r) override { relative_energy_scaling_ = r; } double get_relative_energy_scaling() const override { return relative_energy_scaling_; }
void set_relative_gradient_scaling(double r) { relative_gradient_scaling_ = r; } double get_relative_gradient_scaling() const { return relative_gradient_scaling_; }
double get_average_grad_mag_a() const { if (counter_ != 0.0) { return average_grad_mag_a_ / counter_; } else { return 0.0; } } double get_average_grad_mag_b() const { if (counter_ != 0.0) { return average_grad_mag_b_ / counter_; } else { return 0.0; } }
double get_average_energy_a() const { if (counter_ != 0.0) { return average_energy_a_ / counter_; } else { return 0.0; } } double get_average_energy_b() const { if (counter_ != 0.0) { return average_energy_b_ / counter_; } else { return 0.0; } }
std::shared_ptr
copy->relative_gradient_scaling_ = this->relative_gradient_scaling_;
copy->relative_energy_scaling_ = this->relative_energy_scaling_;
copy->average_grad_mag_a_ = this->average_grad_mag_a_;
copy->average_grad_mag_b_ = this->average_grad_mag_b_;
copy->average_energy_a_ = this->average_energy_a_;
copy->average_energy_b_ = this->average_energy_b_;
copy->counter_ = this->counter_;
if (this->function_a_) {
copy->function_a_ = this->function_a_->clone();
}
if (this->function_b_) {
copy->function_b_ = this->function_b_->clone();
}
if (!copy->function_a_) {
copy->a_on_ = false;
}
if (!copy->function_b_) {
copy->b_on_ = false;
}
copy->domain_number_ = this->domain_number_;
copy->particle_system_ = this->particle_system_;
return copy;
}
DualVectorFunction() : a_on_(true), b_on_(false), relative_gradient_scaling_(1.0), relative_energy_scaling_(1.0) {}
~DualVectorFunction() override = default;
protected: DualVectorFunction(const DualVectorFunction&) = delete; DualVectorFunction& operator=(const DualVectorFunction&) = delete;
bool a_on_; bool b_on_; double relative_gradient_scaling_; double relative_energy_scaling_; double average_grad_mag_a_; double average_grad_mag_b_; double average_energy_a_; double average_energy_b_; double counter_;
std::shared_ptr
} // namespace shapeworks ```
Updated on 2026-03-31 at 16:02:11 +0000