当前位置: 首页 > 计算模拟 >1stopt 7参数拟合求助

1stopt 7参数拟合求助

作者 ckm0811
来源: 小木虫 550 11 举报帖子
+关注

需要根据两个式子(一个微分方程,一个代数方程)拟合7个未知参数fac(1)~fac(7),网上下载的软件有参数限制,想向有正版软件的朋友求助,帮忙拟合一下。写了两版,程序分别如下。完整程序和数据放在了文件里,不知为什么上传失败,只能贴一下网盘链接,麻烦大家了。
链接:https://pan.baidu.com/s/18yjg6HL9hhQ5hmjGdjFhEQ
提取码:8xmm

第一种:
//title "fit";
parameter fac(1:7);
variable t,lamb,pa,p,lambv;
odefunction lambv'=((1/3/fac(7))*(fac(1)*((lamb/lambv)^fac(2)-(lambv/lamb)^(0.5*fac(2)))+fac(3)*((lamb/lambv)^fac(4)-(lambv/lamb)^(0.5*fac(4)))+fac(5)*((lamb/lambv)^fac(6)-(lambv/lamb)^(0.5*fac(6)))));
p=(pa+fac(1)*((lamb/lambv)^fac(2)/lamb-(lambv/lamb)^(fac(2)*0.5)/lamb)+fac(3)*((lamb/lambv)^fac(4)/lamb-(lambv/lamb)^(fac(4)*0.5)/lamb)+fac(5)*((lamb/lambv).^fac(6)/lamb-(lambv/lamb)^(fac(6)*0.5)/lamb));


//根据上面两个式子拟合fac(1)~fac(7),共计7个参数。lambv为中间变量
data;
//t,lamb,pa,p

第二种:
//title "fit";
parameter fac(1:7);
variable t,lamb,pa,p;
conststr lambvdif=((1/3/fac(7))*(fac(1)*((lamb/lambv)^fac(2)-(lambv/lamb)^(0.5*fac(2)))+fac(3)*((lamb/lambv)^fac(4)-(lambv/lamb)^(0.5*fac(4)))+fac(5)*((lamb/lambv)^fac(6)-(lambv/lamb)^(0.5*fac(6)))));
function p=(pa+fac(1)*((lamb/lambv)^fac(2)/lamb-(lambv/lamb)^(fac(2)*0.5)/lamb)+fac(3)*((lamb/lambv)^fac(4)/lamb-(lambv/lamb)^(fac(4)*0.5)/lamb)+fac(5)*((lamb/lambv).^fac(6)/lamb-(lambv/lamb)^(fac(6)*0.5)/lamb));

//根据上面两个式子拟合fac(1)~fac(7),共计7个参数。lambv为中间变量
data;
//t,lamb,pa,p 返回小木虫查看更多

今日热帖
  • 精华评论
  • wlfc

    图形参考:https://blog.csdn.net/wlfc/article/details/119539076

  • wlfc

    使用 3楼、4楼 的公式进行求解。

    有两个难点:
    1、微分方程求解时要传递中间变量lamb, pa。
    2、lambv为未知中间变量,需要求解。
    第一个难点对Lu脚本来说不是问题,gsl支持的Lu扩展数学库中求解微分方程的函数gsl_ode中提供了该功能。
    进一步讨论:微分方程求解传递中间变量时,按时间t的改变量进行插值,可提高求解精度。例如,进行线性插值:lamb=lamb0+(lamb1-lamb0)*[(t-t0)/(t1-t0)], pa=pa0+(pa1-pa0)*[(t-t0)/(t1-t0)]。
    第二个难点若使用6楼的办法,当数据量大时似乎难以实现。故在这里使用幂级数逼近lambv,进行拟合的方法,需增加k0,k1,k2,k3四个拟合参数;当然拟合参数多时精度高,但耗时长。

    仍使用部分数据拟合,以减少时间。

    Lu脚本代码:

    !!!using["luopt","math"]; //使用命名空间
    f(t,p,dp, i : lamb,pa, A,w,lambdif,lambvdif,lambv: t_A, t_lamb, t_pa, fac1,fac2,fac3,fac4,fac5,fac6,fac7,k0,k1,k2,k3,k4) =
    {
        lamb=t_lamb+(t_lamb[i+1]-t_lamb)*[(t-t_A)/(t_A[i+1]-t_A)], pa=t_pa+(t_pa[i+1]-t_pa)*[(t-t_A)/(t_A[i+1]-t_A)], //线性插值计算lamb,pa
        lambv=k0+k1*lamb+k2*lamb*lamb+k3*lamb^3+k4*lamb^4, //lambv=f(lamb,k0,k1,k2,k3,k4),使用幂级数逼近
        A=0.02,w=2*pi*0.1,
        lambdif=A*w*cos(w*t),
        lambvdif=((1.0/3/fac7)*(fac1*((lamb/lambv)^fac2-(lambv/lamb)^(0.5*fac2))+fac3*((lamb/lambv)^fac4-(lambv/lamb)^(0.5*fac4))+fac5*((lamb/lambv)^fac6-(lambv/lamb)^(0.5*fac6)))),

        dp=pa+fac1*((fac2-1)*lamb^(fac2-2)*lambv^(-fac2)*lambdif-fac2*lamb^(fac2-1)*lambv^(-fac2-1)*lambvdif
            +(0.5*fac2+1)*lamb^(-0.5*fac2-2)*lambv^(0.5*fac2)*lambdif-0.5*fac2*lamb^(-0.5*fac2-1)*lambv^(0.5*fac2-1)*lambvdif)
            +fac3*((fac4-1)*lamb^(fac4-2)*lambv^(-fac4)*lambdif-fac4*lamb^(fac4-1)*lambv^(-fac4-1)*lambvdif+(0.5*fac4+1)*lamb^(-0.5*fac4-2)*lambv^(0.5*fac4)*lambdif
            -0.5*fac4*lamb^(-0.5*fac4-1)*lambv^(0.5*fac4-1)*lambvdif)+fac5*((fac6-1)*lamb^(fac6-2)*lambv^(-fac6)*lambdif
            -fac6*lamb^(fac6-1)*lambv^(-fac6-1)*lambvdif+(0.5*fac6+1)*lamb^(-0.5*fac6-2)*lambv^(0.5*fac6)*lambdif
            -0.5*fac6*lamb^(-0.5*fac6-1)*lambv^(0.5*fac6-1)*lambvdif),

        0 //必须返回0
    };
    目标函数(_fac1,_fac2,_fac3,_fac4,_fac5,_fac6,_fac7,_k0,_k1,_k2,_k3,_k4 : i,s,tf: t_A, t_p, fac1,fac2,fac3,fac4,fac5,fac6,fac7,k0,k1,k2,k3,k4)=
    {
        fac1=_fac1, fac2=_fac2, fac3=_fac3, fac4=_fac4, fac5=_fac5, fac6=_fac6, fac7=_fac7, k0=_k0, k1=_k1, k2=_k2, k3=_k3, k4=_k4, //传递优化变量
        //最后一个参数50表示gsl_ode函数在计算时,最多循环计算50次,这样可以提高速度
        tf=gsl_ode[@f, nil, nil, t_A, ra1(-0.060966222), 1e-6, 1e-6, gsl_rkf45, 1e-6,50],
        sum{[tf(all:1).reshape()-t_p].^2.0} //代码矢量化加速,特别适合大数据量
    };
    main(: tArray : t_A, t_lamb, t_pa, t_p)=
    {
        tArray=matrix{ //存放实验数据//t,lamb,pa,p
        "0 0.959926667 -0.218715994 -0.060966222
        0.25 0.963063333 -0.200840559 -0.046836278
        0.5 0.96612 -0.183553472 -0.035042256
        0.75 0.969016667 -0.167289626 -0.024438988
        1 0.97171 -0.152268899 -0.01706765
        1.25 0.97409 -0.139075651 -0.010939712
        1.5 0.976123333 -0.127862697 -0.006795087
        1.75 0.977786667 -0.118729759 -0.002919842
        2 0.979000001 -0.112089924 -0.001981819
        2.25 0.979743333 -0.108031322 -0.001163676
        2.5 0.98001 -0.106577018 -0.003491456
        2.75 0.979766667 -0.107904033 -0.009723697"
        },
        t_A=tArray(all:0).reshape(), t_lamb=tArray(all:1).reshape(), t_pa=tArray(all:2).reshape(), t_p=tArray(all:3).reshape(), //t_A等取矩阵的列,并转为一维数组
        Opt1[@目标函数, optwaysimdeep, optwayconfra] //Opt1函数全局优化
    };

    结果(fac1~fac7,k0,k1,k2,k3,k4,最小值):

    17.38947868627771 0.3416680168065553 -31901.02726305072 1.871542771429994e-004 2.297270203567084e-003 8.207606707403809 -41.52220237484659 -1.705988163594953 -0.3001058349255158 2.1410790976942 4.419612473682794 -4.029380465220802 2.405714024195563e-006

    绘图代码:

    !!!using["luopt","math","win"]; //使用命名空间
    f(t,p,dp, i : lamb,pa, A,w,lambdif,lambvdif,lambv: t_A, t_lamb, t_pa, fac1,fac2,fac3,fac4,fac5,fac6,fac7,k0,k1,k2,k3,k4) =
    {
        lamb=t_lamb+(t_lamb[i+1]-t_lamb)*[(t-t_A)/(t_A[i+1]-t_A)], pa=t_pa+(t_pa[i+1]-t_pa)*[(t-t_A)/(t_A[i+1]-t_A)], //线性插值计算lamb,pa
        lambv=k0+k1*lamb+k2*lamb*lamb+k3*lamb^3+k4*lamb^4, //lambv=f(lamb,k0,k1,k2,k3,k4),使用幂级数逼近
        A=0.02,w=2*pi*0.1,
        lambdif=A*w*cos(w*t),
        lambvdif=((1.0/3/fac7)*(fac1*((lamb/lambv)^fac2-(lambv/lamb)^(0.5*fac2))+fac3*((lamb/lambv)^fac4-(lambv/lamb)^(0.5*fac4))+fac5*((lamb/lambv)^fac6-(lambv/lamb)^(0.5*fac6)))),

        dp=pa+fac1*((fac2-1)*lamb^(fac2-2)*lambv^(-fac2)*lambdif-fac2*lamb^(fac2-1)*lambv^(-fac2-1)*lambvdif
            +(0.5*fac2+1)*lamb^(-0.5*fac2-2)*lambv^(0.5*fac2)*lambdif-0.5*fac2*lamb^(-0.5*fac2-1)*lambv^(0.5*fac2-1)*lambvdif)
            +fac3*((fac4-1)*lamb^(fac4-2)*lambv^(-fac4)*lambdif-fac4*lamb^(fac4-1)*lambv^(-fac4-1)*lambvdif+(0.5*fac4+1)*lamb^(-0.5*fac4-2)*lambv^(0.5*fac4)*lambdif
            -0.5*fac4*lamb^(-0.5*fac4-1)*lambv^(0.5*fac4-1)*lambvdif)+fac5*((fac6-1)*lamb^(fac6-2)*lambv^(-fac6)*lambdif
            -fac6*lamb^(fac6-1)*lambv^(-fac6-1)*lambvdif+(0.5*fac6+1)*lamb^(-0.5*fac6-2)*lambv^(0.5*fac6)*lambdif
            -0.5*fac6*lamb^(-0.5*fac6-1)*lambv^(0.5*fac6-1)*lambvdif),

        0 //必须返回0
    };
    set(_fac1,_fac2,_fac3,_fac4,_fac5,_fac6,_fac7,_k0,_k1,_k2,_k3,_k4 :: fac1,fac2,fac3,fac4,fac5,fac6,fac7,k0,k1,k2,k3,k4)=
    {
        fac1=_fac1, fac2=_fac2, fac3=_fac3, fac4=_fac4, fac5=_fac5, fac6=_fac6, fac7=_fac7, k0=_k0, k1=_k1, k2=_k2, k3=_k3, k4=_k4 //传递优化变量
    };
    init(init: tArray,t_lambv,i,tf,k,lamb : t_A, t_lamb, t_pa, t_p, max, fac1,fac2,fac3,fac4,fac5,fac6,fac7,k0,k1,k2,k3,k4)=
    {
        tArray=matrix{ //存放实验数据//t,lamb,pa,p
        "0 0.959926667 -0.218715994 -0.060966222
        ... ...  数据省略
        2.75 0.979766667 -0.107904033 -0.009723697"
        },
        len[tArray,0,&max], t_A=tArray(all:0).reshape(), t_lamb=tArray(all:1).reshape(), t_pa=tArray(all:2).reshape(), t_p=tArray(all:3).reshape(),

        set[17.38947868627771, 0.3416680168065553, -31901.02726305072, 1.871542771429994e-004, 2.297270203567084e-003, 8.207606707403809, -41.52220237484659, -1.705988163594953, -0.3001058349255158, 2.1410790976942, 4.419612473682794, -4.029380465220802 ],

        t_lambv=new[real_s,max],
        i=-1, while{++i<max, lamb=t_lamb, t_lambv=k0+k1*lamb+k2*lamb*lamb+k3*lamb^3+k4*lamb^4},
        tf=gsl_ode[@f, nil, nil, t_A, ra1(-0.060966222), 1e-6, 1e-6, gsl_rkf45, 1e-6,50],

        cwAttach[typeSplit], cwResizePlots(1,2,2), //左二右二分裂
        k=cwAddCurve{t_A, t_p, max, 0}, //给0子图添加曲线
        cwSetScatter(k,0),         //设置绘制点
        cwSetDataLineSize(5, k, 0),    //设置点的大小
        cwAddCurve{t_A, tf(all:1).reshape(), max, 0}, //给0子图添加曲线
        cwAddCurve{t_A, t_lamb, max, 1}, //给1子图添加曲线
        cwAddCurve{t_A, t_pa, max, 2},   //给2子图添加曲线
        cwAddCurve{t_A, t_lambv, max, 3} //给3子图添加曲线
    };
    ChartWnd[@init];

    图形:
    https://blog.csdn.net/wlfc/article/details/119607664

  • ckm0811

    引用回帖:
    10楼: Originally posted by wlfc at 2021-08-11 16:09:33
    使用 3楼、4楼 的公式进行求解。

    有两个难点:
    1、微分方程求解时要传递中间变量lamb, pa。
    2、lambv为未知中间变量,需要求解。
    第一个难点对Lu脚本来说不是问题,gsl支持的Lu扩展数学库中求解微分方程的函数 ...

    非常感谢,您博客里给出的图形拟合效果很好,我再仔细看一下您的答复

  • wlfc

    引用回帖:
    7楼: Originally posted by wlfc at 2021-08-09 08:09:41
    尝试用OpenLu(可从www.forcal.net下载)求解,与大家探讨。
    使用 1楼 给出的第一种公式。未知中间变量lambv用解方程法求解,但不知这种方法有没有问题?
    仍类似于 4楼 使用部分数据拟合,以减少运行时间。

    Lu ...

    7楼、8楼、9楼的回复,因理解有误,故重新解答。

    仍使用 1楼 给出的第一种公式。仍使用部分数据拟合。

    分析:需在微分方程求解中传递中间变量lamb,gsl支持的Lu扩展数学库中求解微分方程的函数gsl_ode提供了传递中间变量的功能。
    进一步讨论:微分方程求解传递中间变量时,按时间t的改变量进行插值,可提高求解精度。例如,进行线性插值:lamb=lamb0+(lamb1-lamb0)*[(t-t0)/(t1-t0)]。

    另外,微分方程初值lambv未知,将其追加为拟合变量lambv0。

    Lu代码:
    CODE:
    !!!using["luopt","math"]; //使用命名空间

    f(  t,lambv,dlambv,i
        : lamb
        : t_A, t_lamb, fac1,fac2,fac3,fac4,fac5,fac6,fac7) =
        lamb=t_lamb[i]+(t_lamb[i+1]-t_lamb[i])*[(t-t_A[i])/(t_A[i+1]-t_A[i])],
        dlambv=((1.0/3/fac7)*(fac1*((lamb/lambv)^fac2-(lambv/lamb)^(0.5*fac2))+fac3*((lamb/lambv)^fac4-(lambv/lamb)^(0.5*fac4))+fac5*((lamb/lambv)^fac6-(lambv/lamb)^(0.5*fac6)))),
        0;  //成功返回0

    目标函数(_fac1,_fac2,_fac3,_fac4,_fac5,_fac6,_fac7,lambv0
        : i,s,tf,pa,lamb,lambv
        : t_A, t_lamb, t_pa, t_p, max, fac1,fac2,fac3,fac4,fac5,fac6,fac7)=
    {
        fac1=_fac1, fac2=_fac2, fac3=_fac3, fac4=_fac4, fac5=_fac5, fac6=_fac6, fac7=_fac7,  //传递优化变量
        //最后一个参数50表示gsl_ode函数在计算时,最多循环计算50次,这样可以提高速度
        tf=gsl_ode[@f, nil, nil, t_A, ra1(lambv0),  1e-6, 1e-6, gsl_rkf45, 1e-6,50],
        i=-1, s=0, while{++i<max,
            pa=t_pa(i), lamb=t_lamb(i), lambv=tf(i,1),
            s=s+[(pa+fac1*((lamb/lambv)^fac2/lamb-(lambv/lamb)^(fac2*0.5)/lamb)+fac3*((lamb/lambv)^fac4/lamb-(lambv/lamb)^(fac4*0.5)/lamb)+fac5*((lamb/lambv)^fac6/lamb-(lambv/lamb)^(fac6*0.5)/lamb)) - t_p(i)]^2.0
        },
        s
    };

    main(: tArray : t_A, t_lamb, t_pa, t_p, max)=
    {
        tArray=matrix{ //存放实验数据//t,lamb,pa,p
            "0        0.959926667        -0.218715994        -0.060966222
    0.25        0.963063333        -0.200840559        -0.046836278
    0.5        0.96612        -0.183553472        -0.035042256
    0.75        0.969016667        -0.167289626        -0.024438988
    1        0.97171        -0.152268899        -0.01706765
    1.25        0.97409        -0.139075651        -0.010939712
    1.5        0.976123333        -0.127862697        -0.006795087
    1.75        0.977786667        -0.118729759        -0.002919842
    2        0.979000001        -0.112089924        -0.001981819
    2.25        0.979743333        -0.108031322        -0.001163676
    2.5        0.98001        -0.106577018        -0.003491456
    2.75        0.979766667        -0.107904033        -0.009723697"
        },
        len[tArray,0,&max], t_A=tArray(all:0).reshape(), t_lamb=tArray(all:1).reshape(), t_pa=tArray(all:2).reshape(), t_p=tArray(all:3).reshape(), //用len函数取矩阵的行数,t_A等取矩阵的列
        Opt1[@目标函数,  optwaysimdeep, optwayconfra] //Opt1函数全局优化
    };

    结果:

    7.148976005697928e-003    -14.5708961980305         -1.059296609366114        0.2342635320112431        -9.68049051324744e-005    -31.79361445870142        -2.026215042289879        1.184269268536115         3.55377979903292e-006

    绘图代码:
    CODE:
    !!!using["luopt","math","win"]; //使用命名空间

    f(  t,lambv,dlambv,i
        : lamb
        : t_A, t_lamb, fac1,fac2,fac3,fac4,fac5,fac6,fac7) =
        lamb=t_lamb[i]+(t_lamb[i+1]-t_lamb[i])*[(t-t_A[i])/(t_A[i+1]-t_A[i])],
        dlambv=((1.0/3/fac7)*(fac1*((lamb/lambv)^fac2-(lambv/lamb)^(0.5*fac2))+fac3*((lamb/lambv)^fac4-(lambv/lamb)^(0.5*fac4))+fac5*((lamb/lambv)^fac6-(lambv/lamb)^(0.5*fac6)))),
        0;  //成功返回0

    get(t_pp,t_lambv, _fac1,_fac2,_fac3,_fac4,_fac5,_fac6,_fac7,lambv0
        : i,tf,pa,lamb,lambv
        : t_A, t_lamb, t_pa, t_p, max, fac1,fac2,fac3,fac4,fac5,fac6,fac7)=
    {
        fac1=_fac1, fac2=_fac2, fac3=_fac3, fac4=_fac4, fac5=_fac5, fac6=_fac6, fac7=_fac7,  //传递优化变量
        //最后一个参数50表示gsl_ode函数在计算时,最多循环计算50次,这样可以提高速度
        tf=gsl_ode[@f, nil, nil, t_A, ra1(lambv0),  1e-6, 1e-6, gsl_rkf45, 1e-6,50],
        t_lambv.copy[tf(all,1)],
        i=-1, while{++i<max,
            pa=t_pa(i), lamb=t_lamb(i), lambv=t_lambv(i),
            t_pp[i]=(pa+fac1*((lamb/lambv)^fac2/lamb-(lambv/lamb)^(fac2*0.5)/lamb)+fac3*((lamb/lambv)^fac4/lamb-(lambv/lamb)^(fac4*0.5)/lamb)+fac5*((lamb/lambv)^fac6/lamb-(lambv/lamb)^(fac6*0.5)/lamb))
        }
    };

    init( main
        :  tArray, tf, i, k, t_pp,t_lambv
        : t_A, t_lamb, t_pa, t_p, max)=
    {
        tArray=matrix{ //存放实验数据//t,lamb,pa,p
            "0        0.959926667        -0.218715994        -0.060966222
    0.25        0.963063333        -0.200840559        -0.046836278
    0.5        0.96612        -0.183553472        -0.035042256
    0.75        0.969016667        -0.167289626        -0.024438988
    1        0.97171        -0.152268899        -0.01706765
    1.25        0.97409        -0.139075651        -0.010939712
    1.5        0.976123333        -0.127862697        -0.006795087
    1.75        0.977786667        -0.118729759        -0.002919842
    2        0.979000001        -0.112089924        -0.001981819
    2.25        0.979743333        -0.108031322        -0.001163676
    2.5        0.98001        -0.106577018        -0.003491456
    2.75        0.979766667        -0.107904033        -0.009723697"
        },
        len[tArray,0,&max], t_A=tArray(all:0).reshape(), t_lamb=tArray(all:1).reshape(), t_pa=tArray(all:2).reshape(), t_p=tArray(all:3).reshape(), //用len函数取矩阵的行数,t_A等取矩阵的列
        t_pp=new[real_s,max], t_lambv=new[real_s,max],

        get[t_pp, t_lambv, 7.148976005697928e-003  ,  -14.5708961980305     ,    -1.059296609366114    ,    0.2342635320112431    ,    -9.68049051324744e-005  ,  -31.79361445870142     ,   -2.026215042289879     ,   1.184269268536115  ],

        cwAttach[typeSplit], cwResizePlots(1,2,2), //左二右二分裂
        k=cwAddCurve{t_A, t_p, max, 0},    //给0子图添加曲线
        cwSetScatter(k,0),                 //设置绘制点
        cwSetDataLineSize(5, k, 0),        //设置点的大小
        cwAddCurve{t_A, t_pp, max, 0},     //给0子图添加曲线
        cwAddCurve{t_A, t_lamb, max, 1},   //给1子图添加曲线
        cwAddCurve{t_A, t_pa, max, 2},     //给2子图添加曲线
        cwAddCurve{t_A, t_lambv, max, 3}   //给3子图添加曲线
    };
    ChartWnd[@init];

    图形参考:https://blog.csdn.net/wlfc/article/details/119830682

猜你喜欢
下载小木虫APP
与700万科研达人随时交流
  • 二维码
  • IOS
  • 安卓