找到函数的所有局部最大值
Finding all local maxima of a function
我已经编写代码使用模拟退火算法找到函数的全局最小值 — 下面 — 但如何使用相同的算法 找到函数的所有局部最大值?
我用于查找函数局部最小值的代码,请注意,我对函数一无所知我正在向 interactor 询问 f(x)
在 [=13] =] 即函数在特定点的成本。
#include <bits/stdc++.h>
using namespace std;
double myRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
int main()
{
cout.flush();
double x,fx,xMin;
double fMin;
cout << "? "<<fixed << setprecision(6) << -1<<endl;
cin>>fMin;
for(double T = 1000; T>1; T*=.995)
{
x=myRand(-100,100);
cout << "? "<<fixed << setprecision(6) << x <<endl;
cin>>fx;
if (fx<fMin)
{
fMin=fx;
xMin = x;
}
else
{
double P=exp((fMin-fx)/T);
if (P>myRand(1,100))
{
fMin=fx;
xMin=x;
}
}
}
cout << "! "<<fixed << setprecision(6)<<xMin<<endl;
return 0;
}
我寻找局部最大值的尝试是
#include <bits/stdc++.h>
using namespace std;
double myRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
int main()
{
cout.flush();
double x,fx,xMax;
double fMax;
int n;
double a,b;
cin>>n>>a>>b;
double answer[n];
for(int i=0; i<n; i++)
{
cout << "? "<<fixed << setprecision(6) << a+i/5 <<endl;
cin>>fMax;
for(double T = 1000; T>1; T*=.995)
{
x=myRand(a,b);
// i am avoiding to get the same local max twice
while(i>0&&answer[i-1]==x)
x=myRand(a,b);
cout << "? "<<fixed << setprecision(6) << x <<endl;
cin>>fx;
if (fx>fMax)
{
fMax=fx;
xMax = x;
}
else
{
double P=exp((fMax-fx)/T);
if (P<myRand(0,1))
{
fMax=fx;
xMax=x;
}
}
}
answer[i]=xMax;
}
cout << "!";
for(int i=0; i<n; i++)
{
cout<<" "<<fixed << setprecision(6)<<answer[i];
}
return 0;
}
将算法放在一个函数中:
double my_unknown_function(double x)
{
cout << "? " << fixed << setprecision(6) << x << endl;
cin >> fx;
return fx;
}
using function = double(double);
double minimum(function func)
{
double x, fx, xMin;
/* ... */
for(double T = 1000; T>1; T*=.995)
{
x = myRand(-100,100);
fx = func(x);
/* ... */
}
return xMin;
}
这样就可以简单的得到多个局部极小值:
std::vector<double> lm;
for (int i(0); i < 100; ++i)
lm.push_back(minimum(my_unknown_function));
如评论中所述,模拟退火是一种优化启发式算法。它不是详尽搜索并且没有找到所有最小值。
无论如何,多次调用 minimum
会得到不同的结果,因为它是随机的。预计,如果 重启次数足够多 ,任何局部搜索方法总有一天会为您提供实际的全局最小值。
不要重写最大化任务的算法:你可能会引入错误并且测试更难。
取你函数的反义词:
double my_unknown_function(double x)
{
cout << "? " << fixed << setprecision(6) << x << endl;
cin >> fx;
return -fx;
}
同时考虑:
- C++: "std::endl" vs "\n"
- Why is "using namespace std;" considered bad practice?
我已经编写代码使用模拟退火算法找到函数的全局最小值 — 下面 — 但如何使用相同的算法 找到函数的所有局部最大值?
我用于查找函数局部最小值的代码,请注意,我对函数一无所知我正在向 interactor 询问 f(x)
在 [=13] =] 即函数在特定点的成本。
#include <bits/stdc++.h>
using namespace std;
double myRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
int main()
{
cout.flush();
double x,fx,xMin;
double fMin;
cout << "? "<<fixed << setprecision(6) << -1<<endl;
cin>>fMin;
for(double T = 1000; T>1; T*=.995)
{
x=myRand(-100,100);
cout << "? "<<fixed << setprecision(6) << x <<endl;
cin>>fx;
if (fx<fMin)
{
fMin=fx;
xMin = x;
}
else
{
double P=exp((fMin-fx)/T);
if (P>myRand(1,100))
{
fMin=fx;
xMin=x;
}
}
}
cout << "! "<<fixed << setprecision(6)<<xMin<<endl;
return 0;
}
我寻找局部最大值的尝试是
#include <bits/stdc++.h>
using namespace std;
double myRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
int main()
{
cout.flush();
double x,fx,xMax;
double fMax;
int n;
double a,b;
cin>>n>>a>>b;
double answer[n];
for(int i=0; i<n; i++)
{
cout << "? "<<fixed << setprecision(6) << a+i/5 <<endl;
cin>>fMax;
for(double T = 1000; T>1; T*=.995)
{
x=myRand(a,b);
// i am avoiding to get the same local max twice
while(i>0&&answer[i-1]==x)
x=myRand(a,b);
cout << "? "<<fixed << setprecision(6) << x <<endl;
cin>>fx;
if (fx>fMax)
{
fMax=fx;
xMax = x;
}
else
{
double P=exp((fMax-fx)/T);
if (P<myRand(0,1))
{
fMax=fx;
xMax=x;
}
}
}
answer[i]=xMax;
}
cout << "!";
for(int i=0; i<n; i++)
{
cout<<" "<<fixed << setprecision(6)<<answer[i];
}
return 0;
}
将算法放在一个函数中:
double my_unknown_function(double x) { cout << "? " << fixed << setprecision(6) << x << endl; cin >> fx; return fx; } using function = double(double); double minimum(function func) { double x, fx, xMin; /* ... */ for(double T = 1000; T>1; T*=.995) { x = myRand(-100,100); fx = func(x); /* ... */ } return xMin; }
这样就可以简单的得到多个局部极小值:
std::vector<double> lm; for (int i(0); i < 100; ++i) lm.push_back(minimum(my_unknown_function));
如评论中所述,模拟退火是一种优化启发式算法。它不是详尽搜索并且没有找到所有最小值。
无论如何,多次调用
minimum
会得到不同的结果,因为它是随机的。预计,如果 重启次数足够多 ,任何局部搜索方法总有一天会为您提供实际的全局最小值。不要重写最大化任务的算法:你可能会引入错误并且测试更难。
取你函数的反义词:
double my_unknown_function(double x) { cout << "? " << fixed << setprecision(6) << x << endl; cin >> fx; return -fx; }
同时考虑:
- C++: "std::endl" vs "\n"
- Why is "using namespace std;" considered bad practice?