Enforce positive value

96 views
Skip to first unread message

Alex Pander

unread,
Mar 7, 2023, 11:23:01 AM3/7/23
to gtsam...@googlegroups.com
Hey all,

just a quickly question: is there a way to ensure a variable to be positive? Or to control the delta update?

Best regards

Alex Pander

unread,
Mar 21, 2023, 11:26:32 AM3/21/23
to gtsam users
After working my way through the GTSAM code, I now think I have to implement a custom value with type traits.

Dellaert, Frank

unread,
Mar 21, 2023, 12:34:00 PM3/21/23
to Alex Pander, gtsam users

Yes. Another way is to use expressions and put your positively constrained scalar through an exponential, which is a common approach in deep learning.

--
You received this message because you are subscribed to the Google Groups "gtsam users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gtsam-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gtsam-users/13a26243-0227-4f73-a38a-d1d78842a604n%40googlegroups.com.

Alex Pander

unread,
Mar 23, 2023, 12:43:46 PM3/23/23
to gtsam users
Thanks a lot! For future visitors, this is how I did it. Of main interest is here the custom retract() function:

#pragma once

#include <iostream>

#include <gtsam/base/VectorSpace.h>

namespace gtsam
{

struct ScalarExpDelta
{
ScalarExpDelta(double value) : value_(value) {}
ScalarExpDelta(const ScalarExpDelta& other) : value_(other.value_) {}

template<typename T>
T operator*(const T& other) const { return value_*other; }

double val() const { return value_; }

friend std::ostream& operator<<(std::ostream& os, const ScalarExpDelta& s)
{
os << s.value_;
return os;
}

enum {
dimension = 1
};

[[nodiscard]] inline size_t dim() const {
return dimension;
}

/// Retract delta to manifold
[[nodiscard]] ScalarExpDelta retract(const Vector &v) const {
return { value_ * exp(v[0])};
}

/// Compute the coordinates in the tangent space
[[nodiscard]] Vector localCoordinates(const ScalarExpDelta &other) const {
return Vector1(other.value_ - value_);
}

/// The print function
void print(const std::string &str = std::string()) const {
gtsam::print(value_, str);
}

/// The equals function with tolerance
[[nodiscard]] bool equals(const ScalarExpDelta &s, double tol = 1e-9) const {
return std::abs(value_ - s.value_) < tol;
}

private:
double value_;
};

template<>
struct traits<ScalarExpDelta> : public internal::Manifold<ScalarExpDelta> {};

template<>
struct traits<const ScalarExpDelta> : public internal::Manifold<ScalarExpDelta> {};

}


Dellaert, Frank

unread,
Mar 23, 2023, 8:50:12 PM3/23/23
to Alex Pander, gtsam users

Mike Bosse

unread,
Mar 29, 2023, 2:53:17 PM3/29/23
to Dellaert, Frank, Alex Pander, gtsam users
Alex, I’m not sure you’ve really implemented what Frank was suggesting.  Ideally the retract and localCoordinates functions should be inverses of one another.  You may have better results if you were to modify your implementation of localCoordinates to return something like:
  log(other.value_) - log(this->value_)

Or you could fold the log into the constructor and which could also make sure values were always positive to start with.

Cheers,
-Mike

--
Mike Bosse / Senior Staff Software Engineer / Perception

Alex Pander

unread,
Mar 31, 2023, 9:21:20 PM3/31/23
to Mike Bosse, Dellaert, Frank, gtsam users
Hey Mike,

I was already wondering if localCoordinates is relevant during optimisation as well. My value never went below 0.0 since implementing it like this. So I was fine with it. But it is also not converging to the results I would like to see. Could be related to something else, but I will add your suggestions and see. 

Thanks anyway and best regards

Alex
Reply all
Reply to author
Forward
0 new messages