我已经阅读了https://eigen.tuxfamily.org/dox/structEigen_1_1NumTraits.html和https://eigen.tuxfamily.org/dox/TopicCustomizing_CustomScalar.html并写了我认为合适的代码,但显然不是。我试图使用glm :: vec2作为标量类型并解决线性最小二乘问题,但这是我当前的错误:
[1/4] Automatic MOC for target curves
Generating MOC predefs moc_predefs.h
[2/3] Building CXX object CMakeFiles/curves.dir/src/main.cpp.o
FAILED: CMakeFiles/curves.dir/src/main.cpp.o
/usr/bin/c++ -DGLM_FORCE_CXX14=1 -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I. -I../ -Icurves_autogen/include -I../glm -I../blaze -isystem /usr/include/qt -isystem /usr/include/qt/QtWidgets -isystem /usr/include/qt/QtGui -isystem /usr/include/qt/QtCore -isystem /usr/lib/qt/mkspecs/linux-g++ -fPIC -std=c++1z -MD -MT CMakeFiles/curves.dir/src/main.cpp.o -MF CMakeFiles/curves.dir/src/main.cpp.o.d -o CMakeFiles/curves.dir/src/main.cpp.o -c ../src/main.cpp
In file included from ../Eigen/SVD:37:0,
from ../Eigen/Dense:5,
from ../src/lls_solver.hpp:16,
from ../src/main.cpp:4:
../Eigen/src/SVD/JacobiSVD.h: In instantiation of ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>& Eigen::JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’:
../Eigen/src/SVD/JacobiSVD.h:548:14: required from ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>::JacobiSVD(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../Eigen/src/SVD/JacobiSVD.h:799:10: required from ‘Eigen::JacobiSVD<typename Eigen::DenseBase<Derived>::PlainObject> Eigen::MatrixBase<Derived>::jacobiSvd(unsigned int) const [with Derived = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; typename Eigen::DenseBase<Derived>::PlainObject = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../src/lls_solver.hpp:84:79: required from ‘vlw::control_points<PointT> vlw::lls_solver(const vlw::control_points<PointT>&, uint32_t, vlw::basis_function_set<PointT>*) [with PointT = glm::vec<2, float, (glm::qualifier)0>; uint32_t = unsigned int]’
../src/main.cpp:180:103: required from here
../Eigen/src/SVD/JacobiSVD.h:683:29: error: no match for ‘operator/’ (operand types are ‘const MatrixType {aka const Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>}’ and ‘Eigen::JacobiSVD<Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>, 2>::RealScalar {aka float}’)
m_scaledMatrix = matrix / scale;
~~~~~~~^~~~~~~
In file included from ../Eigen/Core:72:0,
from ../src/lls_solver.hpp:15,
from ../src/main.cpp:4:
../Eigen/src/Core/../plugins/CommonCwiseBinaryOps.h:69:40: note: candidate: template<class T> typename Eigen::internal::enable_if<true, const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<typename Eigen::internal::traits<T>::Scalar, typename Eigen::internal::promote_scalar_arg<typename Eigen::internal::traits<T>::Scalar, T, Eigen::internal::has_ReturnType<Eigen::ScalarBinaryOpTraits<typename Eigen::internal::traits<T>::Scalar, T, Eigen::internal::scalar_quotient_op<typename Eigen::internal::traits<T>::Scalar, T> > >::value>::type>, const Derived, const typename Eigen::internal::plain_constant_type<Derived, typename Eigen::internal::promote_scalar_arg<typename Eigen::internal::traits<T>::Scalar, T, Eigen::internal::has_ReturnType<Eigen::ScalarBinaryOpTraits<typename Eigen::internal::traits<T>::Scalar, T, Eigen::internal::scalar_quotient_op<typename Eigen::internal::traits<T>::Scalar, T> > >::value>::type>::type> >::type Eigen::MatrixBase<Derived>::operator/(const T&) const [with T = T; Derived = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]
EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT(operator/,quotient)
^
../Eigen/src/Core/util/Macros.h:941:4: note: in definition of macro ‘EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT’
(METHOD)(const T& scalar) const { \
^~~~~~
../Eigen/src/Core/../plugins/CommonCwiseBinaryOps.h:69:40: note: template argument deduction/substitution failed:
EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT(operator/,quotient)
^
../Eigen/src/Core/util/Macros.h:941:4: note: in definition of macro ‘EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT’
(METHOD)(const T& scalar) const { \
^~~~~~
../Eigen/src/Core/../plugins/CommonCwiseBinaryOps.h: In substitution of ‘template<class T> typename Eigen::internal::enable_if<true, const Eigen::CwiseBinaryOp<Eigen::internal::scalar_quotient_op<glm::vec<2, float, (glm::qualifier)0>, typename Eigen::internal::promote_scalar_arg<glm::vec<2, float, (glm::qualifier)0>, T, Eigen::internal::has_ReturnType<Eigen::ScalarBinaryOpTraits<glm::vec<2, float, (glm::qualifier)0>, T, Eigen::internal::scalar_quotient_op<glm::vec<2, float, (glm::qualifier)0>, T> > >::value>::type>, const Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>, const typename Eigen::internal::plain_constant_type<Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>, typename Eigen::internal::promote_scalar_arg<glm::vec<2, float, (glm::qualifier)0>, T, Eigen::internal::has_ReturnType<Eigen::ScalarBinaryOpTraits<glm::vec<2, float, (glm::qualifier)0>, T, Eigen::internal::scalar_quotient_op<glm::vec<2, float, (glm::qualifier)0>, T> > >::value>::type>::type> >::type Eigen::MatrixBase<Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1> >::operator/<T>(const T&) const [with T = float]’:
../Eigen/src/SVD/JacobiSVD.h:683:29: required from ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>& Eigen::JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../Eigen/src/SVD/JacobiSVD.h:548:14: required from ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>::JacobiSVD(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../Eigen/src/SVD/JacobiSVD.h:799:10: required from ‘Eigen::JacobiSVD<typename Eigen::DenseBase<Derived>::PlainObject> Eigen::MatrixBase<Derived>::jacobiSvd(unsigned int) const [with Derived = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; typename Eigen::DenseBase<Derived>::PlainObject = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../src/lls_solver.hpp:84:79: required from ‘vlw::control_points<PointT> vlw::lls_solver(const vlw::control_points<PointT>&, uint32_t, vlw::basis_function_set<PointT>*) [with PointT = glm::vec<2, float, (glm::qualifier)0>; uint32_t = unsigned int]’
../src/main.cpp:180:103: required from here
../Eigen/src/Core/../plugins/CommonCwiseBinaryOps.h:69:40: error: no type named ‘type’ in ‘struct Eigen::internal::promote_scalar_arg<glm::vec<2, float, (glm::qualifier)0>, float, false>’
EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT(operator/,quotient)
^
../Eigen/src/Core/util/Macros.h:941:4: note: in definition of macro ‘EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT’
(METHOD)(const T& scalar) const { \
^~~~~~
In file included from /usr/include/qt/QtCore/QMargins:1:0,
from /usr/include/qt/QtGui/qwindow.h:46,
from /usr/include/qt/QtGui/QWindow:1,
from ../src/openglwindow.h:51,
from ../src/main.cpp:5:
../Eigen/src/SVD/JacobiSVD.h: In instantiation of ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>& Eigen::JacobiSVD<MatrixType, QRPreconditioner>::compute(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’:
../Eigen/src/SVD/JacobiSVD.h:548:14: required from ‘Eigen::JacobiSVD<MatrixType, QRPreconditioner>::JacobiSVD(const MatrixType&, unsigned int) [with _MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; int QRPreconditioner = 2; Eigen::JacobiSVD<MatrixType, QRPreconditioner>::MatrixType = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../Eigen/src/SVD/JacobiSVD.h:799:10: required from ‘Eigen::JacobiSVD<typename Eigen::DenseBase<Derived>::PlainObject> Eigen::MatrixBase<Derived>::jacobiSvd(unsigned int) const [with Derived = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>; typename Eigen::DenseBase<Derived>::PlainObject = Eigen::Matrix<glm::vec<2, float, (glm::qualifier)0>, -1, -1, 1, -1, -1>]’
../src/lls_solver.hpp:84:79: required from ‘vlw::control_points<PointT> vlw::lls_solver(const vlw::control_points<PointT>&, uint32_t, vlw::basis_function_set<PointT>*) [with PointT = glm::vec<2, float, (glm::qualifier)0>; uint32_t = unsigned int]’
../src/main.cpp:180:103: required from here
这是代码:
#include "basis_function_set.hpp"
#include "control_points.hpp"
#include "knots.hpp"
#include "debug.hpp"
//#include <blaze/Math.h>
#include <cstdint>
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
namespace Eigen {
template<> struct NumTraits<glm::vec2>
: NumTraits<double> // permits to get the epsilon, dummy_precision, lowest, highest functions
{
typedef glm::vec2::value_type Real;
typedef glm::vec2::value_type NonInteger;
typedef glm::vec2 Literal;
typedef glm::vec2 Nested;
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 2,
AddCost = 2,
MulCost = 2
};
};
}
namespace glm {
inline const vec2& conj(const vec2& x) { return x; }
inline const vec2& real(const vec2& x) { return x; }
inline vec2 imag(const vec2&) { return vec2{0.}; }
inline vec2 abs(const vec2& x) { return vec2{fabs(x.x), fabs(x.y)}; }
inline vec2 abs2(const vec2& x) { return x*x; }
}
namespace vlw {
template <typename PointT>
vlw::control_points<PointT> lls_solver(
const vlw::control_points<PointT> &data,
uint32_t cp_size,
vlw::basis_function_set<PointT> *basis_set
) {
using MatrixVec2 = Eigen::Matrix<PointT, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using VectorVec2 = Eigen::Matrix<PointT, Eigen::Dynamic, 1>;
using ScalarT = typename PointT::value_type;
const auto N = cp_size;
const auto M = data.size();
auto t = uniform_knots<ScalarT>(
basis_set->get_open_knot_size(cp_size),
basis_set->get_open_knot_repeated_size(cp_size)
);
ScalarT knot_range = ((t[t.size()-1] - t[0])-0.00001);
MatrixVec2 A( N, M );
for (uint32_t m = 0; m < M; ++m) {
for (uint32_t i = 0; i < N; ++i) {
auto u = static_cast<ScalarT>(m) / (static_cast<ScalarT>(M-1)+0.00001);
u = (u * knot_range) + t[0];
auto n = basis_set->get(i)->evaluate(i, u, t);
PointT p;
for (uint32_t d = 0; d < PointT::length(); ++d) {
p[d] = n;
}
A(m, i) = p;
}
}
vlw::control_points<PointT> retval{cp_size, PointT{0.0}};
VectorVec2 b(M);
for (uint32_t j = 0; j < data.size(); ++j) {
b(j) = data[j];
}
VectorVec2 x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
//MatrixVec2 AtA = A.transpose() * A;
//VectorVec2 b = A.transpose() * y;
std::cout << A << std::endl;
std::cout << "--" << std::endl;
std::cout << b << std::endl;
VectorVec2 x = AtA.colPivHouseholderQr().solve(b);
//std::cout << "--" << std::endl;
//std::cout << x << std::endl;
return retval;
}
}; // end namespace vlw
答案 0 :(得分:0)
我在发布问题之前等了整整24个小时,然后设法在发布问题的几个小时内让它工作。这就是人生。以下解决方案略微与原始解决方案不同,因为我已经切换到求解正规方程,而不是使用jacobiSVD,但它可以工作。
#include "basis_function_set.hpp"
#include "control_points.hpp"
#include "knots.hpp"
#include "debug.hpp"
//#include <blaze/Math.h>
#include <cstdint>
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Dense>
namespace Eigen {
template<> struct NumTraits<glm::vec2> : GenericNumTraits<glm::vec2>
{
typedef glm::vec2 ReturnType;
typedef glm::vec2 Real;
typedef glm::vec2 NonInteger;
typedef glm::vec2 Literal;
typedef glm::vec2 Nested;
static inline glm::vec2 epsilon() {
return glm::vec2{
std::numeric_limits<glm::vec2::value_type>::epsilon(),
std::numeric_limits<glm::vec2::value_type>::epsilon()
};
}
static inline glm::vec2::value_type digits10() { return std::numeric_limits<glm::vec2::value_type>::digits10; }
static inline glm::vec2::value_type dummy_precision() { return 0.; }
static inline glm::vec2 lowest() {
return glm::vec2{
std::numeric_limits<glm::vec2::value_type>::min(),
std::numeric_limits<glm::vec2::value_type>::min()
};
}
static inline glm::vec2 highest() {
return glm::vec2{
std::numeric_limits<glm::vec2::value_type>::max(),
std::numeric_limits<glm::vec2::value_type>::max()
};
}
static inline glm::vec2 infinity() {
return glm::vec2{
std::numeric_limits<glm::vec2::value_type>::infinity(),
std::numeric_limits<glm::vec2::value_type>::infinity()
};
}
static inline glm::vec2 quiet_NaN() {
return glm::vec2{
std::numeric_limits<glm::vec2::value_type>::quiet_NaN(),
std::numeric_limits<glm::vec2::value_type>::quiet_NaN()
};
}
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned = 1,
RequireInitialization = 1,
ReadCost = 2,
AddCost = 2,
MulCost = 2
};
};
}
namespace glm {
inline const vec2& conj(const vec2& x) { return x; }
inline const vec2& real(const vec2& x) { return x; }
inline vec2::value_type imag(const vec2&) { return 0.; }
inline vec2::value_type abs2(const vec2 &x) { return length2(x)*length2(x); }
inline vec2 operator/(const vec2 &lhs, float x ) { return vec2{lhs.x/x, lhs.y/x}; }
inline bool operator<(const vec2 &lhs, const vec2 &rhs) { return length(lhs)<length(rhs); }
inline bool operator<=(const vec2 &lhs, const vec2 &rhs) { return length(lhs)<=length(rhs); }
inline bool operator>(const vec2 &lhs, const vec2 &rhs) { return length(lhs)>length(rhs); }
inline bool operator>= (const vec2 &lhs, const vec2 &rhs) { return length(lhs)>=length(rhs); }
inline vec2 operator* (long int x, const vec2 &rhs) { return static_cast<glm::vec2::value_type>(x) * rhs; }
}
namespace vlw {
template <typename PointT>
vlw::control_points<PointT> lls_solver(
const vlw::control_points<PointT> &data,
uint32_t cp_size,
vlw::basis_function_set<PointT> *basis_set
) {
using MatrixVec2 = Eigen::Matrix<PointT, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
using VectorVec2 = Eigen::Matrix<PointT, Eigen::Dynamic, 1>;
using ScalarT = typename PointT::value_type;
const auto N = cp_size;
const auto M = data.size();
auto t = uniform_knots<ScalarT>(
basis_set->get_open_knot_size(cp_size),
basis_set->get_open_knot_repeated_size(cp_size)
);
ScalarT knot_range = ((t[t.size() - 1] - t[0]) - 0.00001);
MatrixVec2 A(N, M);
for (uint32_t m = 0; m < M; ++m) {
for (uint32_t i = 0; i < N; ++i) {
auto u = static_cast<ScalarT>(m) / (static_cast<ScalarT>(M - 1) + 0.00001);
u = (u * knot_range) + t[0];
auto n = basis_set->get(i)->evaluate(i, u, t);
PointT p;
for (uint32_t d = 0; d < PointT::length(); ++d) {
p[d] = n;
}
A(m, i) = p;
}
}
vlw::control_points<PointT> retval{cp_size, PointT{0.0}};
VectorVec2 b(M);
for (uint32_t j = 0; j < data.size(); ++j) {
b(j) = data[j];
}
//VectorVec2 x = A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
MatrixVec2 AtA = A.transpose() * A;
b = A.transpose() * b;
// std::cout << A << std::endl;
// std::cout << "--" << std::endl;
// std::cout << b << std::endl;
VectorVec2 x = AtA.colPivHouseholderQr().solve(b);
for (uint32_t i = 0; i < x.size(); ++i) {
PointT cp;
for (uint32_t d = 0; d < PointT::length(); ++d) {
cp[d] = x[i][d];
}
retval[i] = cp;
}
return retval;
}
}; // end namespace vlw