34 struct QuinticRbfKernel {
35 double operator()(
double r)
const {
36 return std::pow(r, 5);
40 struct MultiquadricRbfKernel {
42 MultiquadricRbfKernel(
double eps = 1.0) : epsilon(eps) {}
43 double operator()(
double r)
const {
44 return std::sqrt(1.0 + (epsilon * r) * (epsilon * r));
48 struct InverseMultiquadricRbfKernel {
50 InverseMultiquadricRbfKernel(
double eps = 1.0) : epsilon(eps) {}
51 double operator()(
double r)
const {
52 return 1.0 / std::sqrt(1.0 + (epsilon * r) * (epsilon * r));
56 struct InverseQuadraticRbfKernel {
58 InverseQuadraticRbfKernel(
double eps = 1.0) : epsilon(eps) {}
59 double operator()(
double r)
const {
60 return 1.0 / (1.0 + (epsilon * r) * (epsilon * r));
64 std::function<double(
const double)> getKernelFunction(
const std::string& kernelType,
double epsilon)
66 if (kernelType ==
"gaussian")
68 return mathtoolbox::GaussianRbfKernel(epsilon);
70 else if (kernelType ==
"linear")
72 return mathtoolbox::LinearRbfKernel();
74 else if (kernelType ==
"cubic")
76 return mathtoolbox::CubicRbfKernel();
78 else if (kernelType ==
"quintic")
80 return QuinticRbfKernel();
82 else if (kernelType ==
"multiquadric")
84 return MultiquadricRbfKernel(epsilon);
86 else if (kernelType ==
"inverse_multiquadric")
88 return InverseMultiquadricRbfKernel(epsilon);
90 else if (kernelType ==
"inverse_quadratic")
92 return InverseQuadraticRbfKernel(epsilon);
94 else if (kernelType ==
"thin_plate_spline")
96 return mathtoolbox::ThinPlateSplineRbfKernel();
101 <<
"Unknown kernel type: " << kernelType
102 <<
". Valid options are: gaussian, linear, cubic, quintic, multiquadric, "
103 <<
"inverse_multiquadric, inverse_quadratic, thin_plate_spline"
104 << Foam::exit(Foam::FatalError);
105 return mathtoolbox::GaussianRbfKernel(1.0);
110mtbRBF::mtbRBF(
const Foam::word& kernelType,
bool usePolynomialTerm,
bool useRegularization, Foam::scalar lambda,
bool normalize)
111: kernelType_(kernelType),
112 useRegularization_(useRegularization),
113 usePolynomialTerm_(usePolynomialTerm),
115 normalize_(normalize)
117 auto kernel = getKernelFunction(kernelType_, 1.0);
118 impl_ = std::make_unique<mathtoolbox::RbfInterpolator>(kernel, usePolynomialTerm_);
121mtbRBF::mtbRBF(
const Foam::dictionary& dict)
123 kernelType_ = dict.lookupOrDefault<Foam::word>(
"kernel",
"gaussian");
124 usePolynomialTerm_ = dict.lookupOrDefault<
bool>(
"polynomial",
true);
125 useRegularization_ = dict.lookupOrDefault<
bool>(
"regularization",
true);
126 lambda_ = dict.lookupOrDefault<Foam::scalar>(
"lambda", 0.001);
127 normalize_ = dict.lookupOrDefault<
bool>(
"normalize",
true);
128 epsilon_ = dict.lookupOrDefault<Foam::scalar>(
"epsilon", 1.0);
130 auto kernel = getKernelFunction(kernelType_, epsilon_);
131 impl_ = std::make_unique<mathtoolbox::RbfInterpolator>(kernel, usePolynomialTerm_);
134mtbRBF::~mtbRBF() =
default;
136void mtbRBF::fit(
const Eigen::MatrixXd& X,
const Eigen::VectorXd& y)
141 xMean_ = X.rowwise().mean();
144 Eigen::MatrixXd centered = X.colwise() - xMean_;
145 xStd_ = (centered.array().square().rowwise().sum() / (X.cols() - 1)).sqrt();
149 xStd_ = Eigen::VectorXd::Ones(X.rows());
152 for(
int i=0; i<xStd_.size(); ++i) {
153 if(xStd_(i) < 1e-16) xStd_(i) = 1.0;
156 Eigen::MatrixXd X_norm = (X.colwise() - xMean_).array().colwise() / xStd_.array();
162 Eigen::VectorXd yCentered = y.array() - yMean_;
163 yStd_ = std::sqrt(yCentered.array().square().sum() / (y.size() - 1));
170 if(yStd_ < 1e-16) yStd_ = 1.0;
172 Eigen::VectorXd y_norm = (y.array() - yMean_) / yStd_;
174 impl_->SetData(X_norm, y_norm);
178 impl_->SetData(X, y);
180 impl_->CalcWeights(useRegularization_, lambda_);
183Foam::scalar mtbRBF::predict(
const Eigen::VectorXd& x)
187 Eigen::VectorXd x_norm = (x - xMean_).array() / xStd_.array();
188 Foam::scalar y_pred_norm = impl_->CalcValue(x_norm);
189 return y_pred_norm * yStd_ + yMean_;
191 return impl_->CalcValue(x);
194Eigen::VectorXd mtbRBF::predict(
const Eigen::MatrixXd& X)
198 Eigen::MatrixXd X_norm = (X.colwise() - xMean_).array().colwise() / xStd_.array();
200 Eigen::VectorXd result(X.cols());
201 for (
int i = 0; i < X.cols(); ++i)
203 result(i) = impl_->CalcValue(X_norm.col(i));
205 return result.array() * yStd_ + yMean_;
208 Eigen::VectorXd result(X.cols());
209 for (
int i = 0; i < X.cols(); ++i)
211 result(i) = impl_->CalcValue(X.col(i));
216void mtbRBF::printInfo()
218 Foam::Info <<
"mtbRBF Model Info:" << Foam::endl;
219 Foam::Info <<
"\t useKernel: " << kernelType_ << Foam::endl;
220 Foam::Info <<
"\t usePolynomialTerm: " << (usePolynomialTerm_ ?
"true" :
"false") << Foam::endl;
221 Foam::Info <<
"\t useRegularization: " << (useRegularization_ ?
"true" :
"false") << Foam::endl;
222 Foam::Info <<
"\t lambda: " << lambda_ << Foam::endl;
223 Foam::Info <<
"\t normalize: " << (normalize_ ?
"true" :
"false") << Foam::endl;