Libs/Optimize/Function/DualVectorFunction.h
Namespaces
| Name | 
|---|
| shapeworks  User usage reporting (telemetry)  | 
Classes
| Name | |
|---|---|
| class | shapeworks::DualVectorFunction | 
Source code
#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;
  typedef DualVectorFunction Self;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;
  typedef VectorFunction Superclass;
  itkTypeMacro(DualVectorFunction, VectorFunction);
  typedef typename Superclass::VectorType VectorType;
  itkNewMacro(Self);
  itkStaticConstMacro(Dimension, unsigned int, VDimension);
  virtual VectorType Evaluate(unsigned int idx, unsigned int d, const ParticleSystem* system,
                              double& maxmove) const {
    double maxA, maxB, maxC;
    maxA = 0;
    maxB = 0;
    maxC = 0;
    VectorType ansA;
    ansA.fill(0.0);
    VectorType ansB;
    ansB.fill(0.0);
    VectorType ansC;
    ansC.fill(0.0);
    const_cast<DualVectorFunction*>(this)->m_Counter = m_Counter + 1.0;
    // evaluate individual functions: A = surface energy, B = correspondence
    if (m_AOn == true) {
      ansA = m_FunctionA->Evaluate(idx, d, system, maxA);
      const_cast<DualVectorFunction*>(this)->m_AverageGradMagA = m_AverageGradMagA + ansA.magnitude();
    }
    if (m_BOn == true) {
      ansB = m_FunctionB->Evaluate(idx, d, system, maxB);
      const_cast<DualVectorFunction*>(this)->m_AverageGradMagB = m_AverageGradMagB + ansB.magnitude();
    }
    if (m_RelativeGradientScaling == 0.0) {
      ansB.fill(0.0);
      maxB = 0.0;
    }
    // get maxmove and predicted move for current configuration
    VectorType predictedMove;
    predictedMove.fill(0.0);
    if (m_BOn == true) {
      if (m_AOn == true)  // both A and B are active
      {
        if (maxB > maxA) {
          maxmove = maxB;
        } else {
          maxmove = maxA;
        }
        maxmove = maxA;  // always driven by the sampling to decrease the senstivity to covariance regularization
        predictedMove = ansA + m_RelativeGradientScaling * ansB;
        return (predictedMove);
      } else  // B is active, A is not active
      {
        maxmove = maxB;
        predictedMove = ansB;
        return (predictedMove);
      }
    } else  // only A is active
    {
      maxmove = maxA;
      return ansA;
    }
    maxmove = 0.0;
    return ansA;
  }
  virtual double EnergyA(unsigned int idx, unsigned int d, const ParticleSystem* system) const {
    m_FunctionA->BeforeEvaluate(idx, d, system);
    double ansA = 0.0;
    if (m_AOn == true) {
      ansA = m_FunctionA->Energy(idx, d, system);
    }
    return ansA;
  }
  virtual double EnergyB(unsigned int idx, unsigned int d, const ParticleSystem* system) const {
    m_FunctionB->BeforeEvaluate(idx, d, system);
    double ansB = 0.0;
    if (m_BOn == true) {
      ansB = m_FunctionB->Energy(idx, d, system);
    }
    ansB *= m_RelativeEnergyScaling;
    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 (m_AOn == true) {
      ansA = m_FunctionA->Energy(idx, d, system);
    }
    if (m_BOn == true) {
      ansB = m_FunctionB->Energy(idx, d, system);
    }
    if (m_RelativeEnergyScaling == 0) {
      ansB = 0.0;
    }
    // compute final energy for current configuration
    if (m_BOn == true) {
      if (m_AOn == true)  // both A and B are active
      {
        finalEnergy = ansA + m_RelativeEnergyScaling * 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)->m_Counter = m_Counter + 1.0;
    // evaluate individual functions: A = surface energy, B = correspondence
    if (m_AOn == true) {
      ansA = m_FunctionA->Evaluate(idx, d, system, maxA, energyA);
      const_cast<DualVectorFunction*>(this)->m_AverageGradMagA = m_AverageGradMagA + ansA.magnitude();
      const_cast<DualVectorFunction*>(this)->m_AverageEnergyA = m_AverageEnergyA + energyA;
    }
    if (m_BOn == true) {
      ansB = m_FunctionB->Evaluate(idx, d, system, maxB, energyB);
      const_cast<DualVectorFunction*>(this)->m_AverageGradMagB = m_AverageGradMagB + ansB.magnitude();
      const_cast<DualVectorFunction*>(this)->m_AverageEnergyB = m_AverageEnergyB + energyB;
    }
    if (m_RelativeEnergyScaling == 0.0) {
      energyB = 0.0;
      ansB.fill(0.0);
    }
    if (m_RelativeGradientScaling == 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 (m_BOn == true) {
      if (m_AOn == true)  // both A and B are active
      {
        if (maxB > maxA) {
          maxmove = maxB;
        } else {
          maxmove = maxA;
        }
        energy = energyA + m_RelativeEnergyScaling * energyB;
        maxmove = maxA;  // always driven by the sampling to decrease the senstivity to covariance regularization
        predictedMove = ansA + m_RelativeGradientScaling * 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 BeforeEvaluate(unsigned int idx, unsigned int d, const ParticleSystem* system) {
    if (m_AOn == true) {
      m_FunctionA->BeforeEvaluate(idx, d, system);
    }
    if (m_BOn == true) {
      m_FunctionB->BeforeEvaluate(idx, d, system);
    }
  }
  virtual void AfterIteration() {
    if (m_AOn) m_FunctionA->AfterIteration();
    if (m_BOn) {
      m_FunctionB->AfterIteration();
    }
  }
  virtual void BeforeIteration() {
    if (m_AOn) m_FunctionA->BeforeIteration();
    if (m_BOn) {
      m_FunctionB->BeforeIteration();
    }
    m_AverageGradMagA = 0.0;
    m_AverageGradMagB = 0.0;
    m_AverageEnergyA = 0.0;
    m_Counter = 0.0;
  }
  virtual void SetParticleSystem(ParticleSystem* p) {
    Superclass::SetParticleSystem(p);
    if (m_FunctionA.GetPointer() != 0) m_FunctionA->SetParticleSystem(p);
    if (m_FunctionB.GetPointer() != 0) m_FunctionB->SetParticleSystem(p);
  }
  void SetDomainNumber(unsigned int i) {
    Superclass::SetDomainNumber(i);
    if (m_FunctionA.GetPointer() != 0) m_FunctionA->SetDomainNumber(i);
    if (m_FunctionB.GetPointer() != 0) m_FunctionB->SetDomainNumber(i);
  }
  void SetFunctionA(VectorFunction* o) {
    m_FunctionA = o;
    m_FunctionA->SetDomainNumber(this->GetDomainNumber());
    m_FunctionA->SetParticleSystem(this->GetParticleSystem());
  }
  VectorFunction* GetFunctionA() { return m_FunctionA.GetPointer(); }
  VectorFunction* GetFunctionB() { return m_FunctionB.GetPointer(); }
  void SetFunctionB(VectorFunction* o) {
    m_FunctionB = o;
    m_FunctionB->SetDomainNumber(this->GetDomainNumber());
    m_FunctionB->SetParticleSystem(this->GetParticleSystem());
  }
  void SetAOn() { m_AOn = true; }
  void SetAOff() { m_AOn = false; }
  void SetAOn(bool s) { m_AOn = s; }
  bool GetAOn() const { return m_AOn; }
  void SetBOn() { m_BOn = true; }
  void SetBOff() { m_BOn = false; }
  void SetBOn(bool s) { m_BOn = s; }
  bool GetBOn() const { return m_BOn; }
  void SetRelativeEnergyScaling(double r) override { m_RelativeEnergyScaling = r; }
  double GetRelativeEnergyScaling() const override { return m_RelativeEnergyScaling; }
  void SetRelativeGradientScaling(double r) { m_RelativeGradientScaling = r; }
  double GetRelativeGradientScaling() const { return m_RelativeGradientScaling; }
  double GetAverageGradMagA() const {
    if (m_Counter != 0.0)
      return m_AverageGradMagA / m_Counter;
    else
      return 0.0;
  }
  double GetAverageGradMagB() const {
    if (m_Counter != 0.0)
      return m_AverageGradMagB / m_Counter;
    else
      return 0.0;
  }
  double GetAverageEnergyA() const {
    if (m_Counter != 0.0)
      return m_AverageEnergyA / m_Counter;
    else
      return 0.0;
  }
  double GetAverageEnergyB() const {
    if (m_Counter != 0.0)
      return m_AverageEnergyB / m_Counter;
    else
      return 0.0;
  }
  virtual typename VectorFunction::Pointer Clone() {
    typename DualVectorFunction::Pointer copy = DualVectorFunction::New();
    copy->m_AOn = this->m_AOn;
    copy->m_BOn = this->m_BOn;
    copy->m_RelativeGradientScaling = this->m_RelativeGradientScaling;
    copy->m_RelativeEnergyScaling = this->m_RelativeEnergyScaling;
    copy->m_AverageGradMagA = this->m_AverageGradMagA;
    copy->m_AverageGradMagB = this->m_AverageGradMagB;
    copy->m_AverageEnergyA = this->m_AverageEnergyA;
    copy->m_AverageEnergyB = this->m_AverageEnergyB;
    copy->m_Counter = this->m_Counter;
    if (this->m_FunctionA) copy->m_FunctionA = this->m_FunctionA->Clone();
    if (this->m_FunctionB) copy->m_FunctionB = this->m_FunctionB->Clone();
    if (!copy->m_FunctionA) copy->m_AOn = false;
    if (!copy->m_FunctionB) copy->m_BOn = false;
    copy->m_DomainNumber = this->m_DomainNumber;
    copy->m_ParticleSystem = this->m_ParticleSystem;
    return (VectorFunction::Pointer)copy;
  }
 protected:
  DualVectorFunction()
      : m_AOn(true), m_BOn(false), m_RelativeGradientScaling(1.0), m_RelativeEnergyScaling(1.0) {}
  virtual ~DualVectorFunction() {}
  void operator=(const DualVectorFunction&);
  DualVectorFunction(const DualVectorFunction&);
  bool m_AOn;
  bool m_BOn;
  double m_RelativeGradientScaling;
  double m_RelativeEnergyScaling;
  double m_AverageGradMagA;
  double m_AverageGradMagB;
  double m_AverageEnergyA;
  double m_AverageEnergyB;
  double m_Counter;
  VectorFunction::Pointer m_FunctionA;
  VectorFunction::Pointer m_FunctionB;
};
}  // namespace shapeworks
Updated on 2024-03-17 at 12:58:44 -0600