175 lines
4.4 KiB
C++
175 lines
4.4 KiB
C++
|
/********************************************************
|
||
|
* ██████╗ ███████╗████████╗██╗
|
||
|
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||
|
* ██║ ███╗███████╗ ██║ ██║
|
||
|
* ██║ ██║╚════██║ ██║ ██║
|
||
|
* ╚██████╔╝███████║ ██║ ███████╗
|
||
|
* ╚═════╝ ╚══════╝ ╚═╝ ╚══════╝
|
||
|
* Generic Scientific Template Library
|
||
|
*
|
||
|
* Copyright (c) 2022 Yi Zhang (yizhang-geo@zju.edu.cn)
|
||
|
*
|
||
|
* The GSTL 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 (LGPL) 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 GSTL, please consider the option to obtain a commercial license for a
|
||
|
* fee. These licenses are offered by the GSTL'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 100
|
||
|
#define N 90
|
||
|
|
||
|
// 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;
|
||
|
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] = 9.0; // 对解的范围进行约束
|
||
|
hig[i] = 11.0;
|
||
|
}
|
||
|
|
||
|
for (int i = N2; i < N; i++)
|
||
|
{
|
||
|
low[i] = 0.0;
|
||
|
hig[i] = 2.0;
|
||
|
}
|
||
|
|
||
|
ex2 e;
|
||
|
e.CalObs(fm);
|
||
|
|
||
|
gctl::lgd_para my_para = e.default_lgd_para();
|
||
|
my_para.flight_times = 20000;
|
||
|
my_para.batch = 100;
|
||
|
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;
|
||
|
}
|