gctl_optimization/example/ex2.cpp
2025-04-08 08:37:45 +08:00

179 lines
4.4 KiB
C++

/********************************************************
* ██████╗ ██████╗████████╗██╗
* ██╔════╝ ██╔════╝╚══██╔══╝██║
* ██║ ███╗██║ ██║ ██║
* ██║ ██║██║ ██║ ██║
* ╚██████╔╝╚██████╗ ██║ ███████╗
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
* Geophysical Computational Tools & Library (GCTL)
*
* Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn)
*
* GCTL is distributed under a dual licensing scheme. You can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 2
* of the License, or (at your option) any later version. You should have
* received a copy of the GNU Lesser General Public License along with this
* program. If not, see <http://www.gnu.org/licenses/>.
*
* If the terms and conditions of the LGPL v.2. would prevent you from using
* the GCTL, please consider the option to obtain a commercial license for a
* fee. These licenses are offered by the GCTL's original author. As a rule,
* licenses are provided "as-is", unlimited in time for a one time fee. Please
* send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget
* to include some description of your company and the realm of its activities.
* Also add information on how to contact you by electronic and paper mail.
******************************************************/
#include "../lib/optimization.h"
#define M 90
#define N 100
// get random floating points
double random_double(double l, double t)
{
return (t-l)*rand()*1.0/RAND_MAX + l;
}
// get random integral numbers
int random_int(int small, int big)
{
return (rand() % (big - small)) + small;
}
class ex2 : public gctl::lgd_solver
{
protected:
gctl::matrix<double> kernel;
gctl::array<double> obs, tmp;
protected:
double LGD_Evaluate(const gctl::array<double> &x, gctl::array<double> &g);
public:
ex2();
virtual ~ex2(){}
void CalObs(const gctl::array<double> &x);
};
ex2::ex2()
{
kernel.resize(M, N);
tmp.resize(M);
obs.resize(M);
srand(time(0));
// 添加一些大数
int tmp_id, tmp_size;
double tmp_val;
for (int i = 0; i < M; i++)
{
tmp_size = random_int(25, 35);
for (int j = 0; j < tmp_size; j++)
{
tmp_id = random_int(0, N);
tmp_val = random_double(-10, 10);
kernel[i][tmp_id] = tmp_val;
}
}
}
double ex2::LGD_Evaluate(const gctl::array<double> &x, gctl::array<double> &g)
{
for (int i = 0; i < M; i++)
{
tmp[i] = 0.0;
for (int j = 0; j < N; j++)
{
tmp[i] += kernel[i][j] * x[j];
}
tmp[i] -= obs[i];
//tmp[i] /= 1e-1;
}
for (int j = 0; j < N; j++)
{
g[j] = 0.0;
for (int i = 0; i < M; i++)
{
g[j] += kernel[i][j]*tmp[i];
}
g[j] *= 2.0/M;
}
double sum = 0.0;
for (int i = 0; i < M; i++)
{
sum += tmp[i]*tmp[i];
}
return sum/M;
}
void ex2::CalObs(const gctl::array<double> &x)
{
// 计算正演值
for (int i = 0; i < M; i++)
{
obs[i] = 0.0;
for (int j = 0; j < N; j++)
{
obs[i] += kernel[i][j]*x[j];
}
// 添加噪声
obs[i] += random_double(-1e-3, 1e-3);
}
}
int main(int argc, char const *argv[])
{
gctl::array<double> m(N, 0.0), mean_m(N, 0.0), stddev_m(N, 0.0), low(N), hig(N);
// 生成一组正演解 包含一些大值和一些小值
gctl::array<double> fm(N);
int N2 = (int) N/2;
srand(time(0));
for (int i = 0; i < N2; i++)
{
fm[i] = random_double(5, 10);
//fm[i] = 10.0;
}
for (int i = N2; i < N; i++)
{
fm[i] = random_double(1, 2);
//fm[i] = 1.0;
}
for (int i = 0; i < N2; i++)
{
low[i] = 4.0; // 对解的范围进行约束
hig[i] = 11.0;
}
for (int i = N2; i < N; i++)
{
low[i] = 0.0;
hig[i] = 3.0;
}
ex2 e;
e.CalObs(fm);
gctl::lgd_para my_para = e.default_lgd_para();
my_para.flight_times = 20000;
my_para.batch = 100;
my_para.fmt = 0.5;
my_para.smt = 0.05;
e.set_lgd_para(my_para);
e.LGD_Minimize(m, mean_m, stddev_m, low, hig);
for (int i = 0; i < N; i++)
{
std::cout << fm[i] << " " << m[i] << " " << mean_m[i] << " " << stddev_m[i] << " " << fabs(mean_m[i] - fm[i]) << std::endl;
}
return 0;
}