查找具有N个变量的函数的最小值

时间:2018-09-23 12:38:21

标签: c c99 minimum repeat

我正在尝试对一种算法进行编码,以查找可能具有N个变量的Rosenbrock function的最小值。当N = 2时,我可以很容易地弄清楚。我用于N = 2的代码如下:

double y,z,x, aux1, aux2;
double menor = INT_MAX;
y = INT_MIN;
x = INT_MIN;


while(x < INT_MAX)
{
    while(y < INT_MAX)
    {
        z = (1-x)*(1-x) + 100*(y - (x*x))*(y - (x*x));
        if(menor > z)
        {
            menor = z;
            aux1 = x;
            aux2 = y;
        }   

        y = y + 0.1;    

    }
    y = 0.1;
    x = x + 0.1;
}

printf("(x,y) : (%.2lf, %.2lf) Minimum value of z: %.2lf\n", aux1, aux2, menor);

这段代码可以正常工作,我将y和x乘以0.1只是因为我已经知道该函数的最小值(它在(1,1)上)。运行需要一些时间,但可以。我的问题是N变量。当我想到这一点时,我想到我将需要N个重复结构。这是现在的代码。它不起作用,但是可能会给我一些想法:

//Calculates the value of the Rosenbrock function given n(the number of variables)
double rosen(double *x, int n){

double y;

for(int i = 0; i < n-1; i++)
{
    y = y + 100*((x[i+1] - x[i]*x[i])*(x[i+1] - x[i]*x[i])) + (1 - x[i])*(1 - x[i]);
}   

return y;
}

int main(void){
double *x;
//n is the number of variables and it may change
int n = 3;

x = (double*)malloc(n * sizeof(double));
double rosen(double *x, int n);

for(int i = 0; i < n; i++)
{
    x[i] = INT_MIN;
}
//That's the part where I can't figure out how to compute all the possibilities, changing the value of the last variable between INT_MIN AND INT_MAX. Then this variable gets the value of INT_MIN again and I will sum 0.1 to the variable antecedent, and then do all the process again to the last variable. And so on for all the N variables.
for(int i = n - 1; i >= 0; i--)
{
    while(x[i] < INT_MAX)
    {
        x[i] = x[i] + 0.1;
    }       
    x[i] = INT_MIN;
}

上面的代码可能包含一些错误。但是,我唯一需要帮助的是更改N个变量的所有值。因此,我想做的是获取最后一个变量,并在INT_MIN和INT_MAX之间改变其值,总和为0.1(我知道这确实很漫长)。此后,此变量将再次接收INT_MIN值,并且前一个变量将变化+0.1。然后,最后一个变量将再次从INT_MIN更改为INT_MAX。所有N个变量都会发生这种情况。

这是我要解决的问题,以蛮力地使函数的值最小。如果你们对我有一些提示或可能有用的图书馆,我将非常感激。

1 个答案:

答案 0 :(得分:0)

您可以具有如下所示的递归函数(粗略C):

void rosenMin(int maxDims, int currDim, double[] values, double* currMin)
{
    if (currDims == maxDims) {
        double rosenVal = rosen(values); // You need to implement this
        if (rosenVal < *currMax) {
            *currMin = rosenVal;
        }
    } else {
        for (double c = INT_MIN; c <= INT_MAX; c += 0.1) {
            values[currDim + 1] = c;
            rosenMin(maxDim, currDim + 1, values, currMin);
        }
    }
}

double[] values = new double[N] { 0 }; // Check with C syntax how this'll look!
double min = INT_MAX
rosenMin(N, 1, values, &min);