C++ 一种寻找物体漂浮状态的优化方法

C++ 一种寻找物体漂浮状态的优化方法,c++,algorithm,math,mathematical-optimization,nonlinear-optimization,C++,Algorithm,Math,Mathematical Optimization,Nonlinear Optimization,要解决的问题是,根据浮体的重量和重心,确定浮体的浮态 我使用的函数计算给定下陷、后跟和纵倾时身体的位移体积和膨胀中心。 其中下沉量为长度单位,后跟/纵倾角度限制为-90到90之间的值 当位移体积等于重量且重心与浮力中心在一条垂直线上时,会发现浮力状态 我把它实现为一个非线性牛顿-拉斐逊寻根问题,有3个变量(下沉、纵倾、横倾)和3个方程。 此方法可行,但需要良好的初始猜测。所以我希望找到一个更好的方法,或者一个好的方法来找到初始值 下面是用于牛顿-拉斐逊迭代的牛顿和雅可比算法的代码。功能体积采用

要解决的问题是,根据浮体的重量和重心,确定浮体的浮态

我使用的函数计算给定下陷、后跟和纵倾时身体的位移体积和膨胀中心。 其中下沉量为长度单位,后跟/纵倾角度限制为-90到90之间的值

当位移体积等于重量且重心与浮力中心在一条垂直线上时,会发现浮力状态

我把它实现为一个非线性牛顿-拉斐逊寻根问题,有3个变量(下沉、纵倾、横倾)和3个方程。 此方法可行,但需要良好的初始猜测。所以我希望找到一个更好的方法,或者一个好的方法来找到初始值

下面是用于牛顿-拉斐逊迭代的牛顿和雅可比算法的代码。功能体积采用参数下沉、后跟和纵倾。并返回体积和浮力中心的坐标

我还包括了maxabs和GSolve2算法,我相信这些都是从数值公式中得到的

void jacobian(float x[], float weight, float vcg, float tcg, float lcg, float jac[][3], float f0[]) {
    float h = 0.0001f;
    float temp;
    float j_volume, j_vcb, j_lcb, j_tcb;
    float f1[3];

    volume(x[0], x[1], x[2], j_volume, j_lcb, j_vcb, j_tcb);
    f0[0] = j_volume-weight;
    f0[1] = j_tcb-tcg;
    f0[2] = j_lcb-lcg;

    for (int i=0;i<3;i++) {
        temp = x[i];
        x[i] = temp + h;
        volume(x[0], x[1], x[2], j_volume, j_lcb, j_vcb, j_tcb);

        f1[0] = j_volume-weight;
        f1[1] = j_tcb-tcg;
        f1[2] = j_lcb-lcg;
        x[i] = temp;

        jac[0][i] = (f1[0]-f0[0])/h;
        jac[1][i] = (f1[1]-f0[1])/h;
        jac[2][i] = (f1[2]-f0[2])/h;
    }
}


void newton(float weight, float vcg, float tcg, float lcg, float &sinkage, float &heel, float &trim) {
    float x[3] = {10,1,1};

    float accuracy = 0.000001f;
    int ntryes = 30;
    int i = 0;
    float jac[3][3];
    float max;
    float f0[3];
    float gauss_f0[3];

    while (i < ntryes) {
        jacobian(x, weight, vcg, tcg, lcg, jac, f0);

        if (sqrt((f0[0]*f0[0]+f0[1]*f0[1]+f0[2]*f0[2])/2) < accuracy) {
            break;
        }

        gauss_f0[0] = -f0[0];
        gauss_f0[1] = -f0[1];
        gauss_f0[2] = -f0[2];

        GSolve2(jac, 3, gauss_f0);

        x[0] = x[0]+gauss_f0[0];
        x[1] = x[1]+gauss_f0[1];
        x[2] = x[2]+gauss_f0[2];

        // absmax(x) - Return absolute max value from an array
        max = absmax(x);
        if (max < 1) max = 1;

        if (sqrt((gauss_f0[0]*gauss_f0[0]+gauss_f0[1]*gauss_f0[1]+gauss_f0[2]*gauss_f0[2])) < accuracy*max) {
            x[0]=x2[0];
            x[1]=x2[1];
            x[2]=x2[2];
            break;
        }

        i++;
    }

    sinkage = x[0];
    heel = x[1];
    trim = x[2];
}

int GSolve2(float a[][3],int n,float b[]) {
    float x,sum,max,temp;
    int i,j,k,p,m,pos;

    int nn = n-1; 

    for (k=0;k<=n-1;k++)
    {
        /* pivot*/
        max=fabs(a[k][k]);
        pos=k;


        for (p=k;p<n;p++){
            if (max < fabs(a[p][k])){
                max=fabs(a[p][k]);
                pos=p;
            }
        }

        if (ABS(a[k][pos]) < EPS) {
            writeLog("Matrix is singular");
            break;
        }

        if (pos != k) {
            for(m=k;m<n;m++){
                temp=a[pos][m];
                a[pos][m]=a[k][m];
                a[k][m]=temp;
            }
        }

        /*   convert to upper triangular form */
        if ( fabs(a[k][k])>=1.e-6)
        {
            for (i=k+1;i<n;i++)
            {
            x = a[i][k]/a[k][k];
            for (j=k+1;j<n;j++) a[i][j] = a[i][j] -a[k][j]*x;
            b[i] = b[i] - b[k]*x;
            }
        }
        else
        {
            writeLog("zero pivot found in line:%d",k);
            return 0;
       }
     }

/*   back substitution */
     b[nn] = b[nn] / a[nn][nn];
     for (i=n-2;i>=0;i--)
     {
        sum = b[i];
         for (j=i+1;j<n;j++) 
           sum = sum - a[i][j]*b[j];
        b[i] = sum/a[i][i];
     }
     return 0;
}

float absmax(float x[]) {
    int i = 1;
    int n = sizeof(x);
    float max = x[0];
    while (i < n) {
        if (max < x[i]) {
            max = x[i];
        }
        i++;
    }
    return max;
}
void-jacobian(浮点数x[],浮点数,浮点数vcg,浮点数tcg,浮点数lcg,浮点数jac[][3],浮点数f0[]){
浮子h=0.0001f;
浮子温度;
浮动j_体积、j_vcb、j_lcb、j_tcb;
浮动f1[3];
卷(x[0],x[1],x[2],j_卷,j_lcb,j_vcb,j_tcb);
f0[0]=j_体积重量;
f0[1]=j_tcb-tcg;
f0[2]=j_lcb-lcg;

对于(int i=0;i您是否考虑过一些随机搜索方法来找到初始值,然后使用牛顿-拉斐逊(Newton-Raphson)进行微调?一种可能性是进化计算,您可以使用Inspyred软件包。对于在许多方面与您描述的物理问题类似的物理问题,请看以下示例:

使用阻尼版本如何牛顿方法的n?你可以很容易地修改你的实现来实现它。把牛顿方法看作是在寻找方向

d_k=f(x_k)/f'(x_k)

以及更新变量

x_k+1=x_k-L_k d_k

在通常的牛顿方法中,L_k总是1,但这可能会产生超调或欠调。因此,让你的方法选择L_k。假设你的方法通常超调。一种可能的策略是取集合{1,1/2,1/4,1/8,…L_min}中的最大L_k,这样条件


|f(x_k+1)|你有权使用KNITRO非线性优化求解器吗(你是学者吗)?它有一个multistart选项。您可以尝试一下,看看multistart在使用您自己的方法之前是如何工作的。我不是学术性的,所以不幸的是无法访问KNITRO.user978281-您没有提供足够的详细信息来回答您的问题。您能给出一些示例代码吗?如果我们能看到您的非线性NR方法,它会更清楚地了解如何实现优化。@user978281,支持Mike Vella的评论。特别是如果你对你的问题悬赏,你应该尽可能多地在问题中加入相关细节。用代码示例更新,希望这能提供一些额外的细节