| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 507 人关注过本帖
标题:用c对函数进行优化的问题
只看楼主 加入收藏
visow
Rank: 2
等 级:论坛游民
帖 子:36
专家分:24
注 册:2012-7-8
结帖率:50%
收藏
已结贴  问题点数:10 回复次数:5 
用c对函数进行优化的问题
有一个要求就是从键盘上输入一个表达式,然后通过程序中的优化函数得出优化结果。
比如
运行程序后
从键盘输入y=x[1]*x[1]+4*x[1]*x[2]+x[2]*x[2];
可以求出该函数的极小值。
其他的都可以解决。
但是如何将从键盘上输入的表达式变成可以运用的程序表达式,
或者说程序能识别这个表达式。
换一个说法,
double f(double *x)                 
{
    char y;
    y=(x[0]-2)*(x[0]-2)*(x[0]-2)*(x[0]-2)+(x[0]-2*x[1])*(x[0]-2*x[1]);

    //y=(x[0]-2)^4+(x[0]-2*x[1])^2;
    return y;
    }
这个函数中的y后面那一串表达式怎么变成从键盘输入


搜索更多相关主题的帖子: 运行程序 double return 表达式 键盘 
2014-02-23 21:49
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:10 
你告诉我其他都是怎么解决的,我就告诉你怎么输入那一串表达式

重剑无锋,大巧不工
2014-02-23 22:28
visow
Rank: 2
等 级:论坛游民
帖 子:36
专家分:24
注 册:2012-7-8
收藏
得分:0 
回复 2楼 beyondyf
通过进退法确定谷区间和黄金分割法求极小值然后求极小值,我现在将我的代码发给您看看。前段时间因为出了点事,所以拖到了现在,万分抱歉。
程序代码:
// 多维无约束优化软件设计
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double det=1e-5;     //计算精度
double det1=1e-3;    //梯度判断精度            
double ak=3e-3;      //搜索步长
double dx=1e-4;      //梯度计算步长 


/*目标函数(n维)
  入口参数:
  x       :n维数组,自变量 
  返回值  :函数值           */

double f(double *x)                
{
    double y;
    y=(x[0]-2)*(x[0]-2)*(x[0]-2)*(x[0]-2)+(x[0]-2*x[1])*(x[0]-2*x[1]);

    //y=(x[0]-2)^4+(x[0]-2*x[1])^2;
    return y;
    }

/*  计算X(k+1)=X(k)+a*S(k)
    入口参数:
    x_k  : n维数组,自变量
    s_k  : n维数组,方向向量
    a    : 方向步长
    n    : 维数
    出口参数:
    x_k1 : 转换后的n维数组*/

void fun(double *x_k1,double *x_k,double *s_k,double a,int n)    
{
    int i;
    for(i=0;i<n;i++)
        x_k1[i]=x_k[i]+a*s_k[i];
}

/*进退法求谷区间
  入口参数:
  n     :优化模型维数
  x_k   :n维数组,初始点坐标
  s_k   :n维数组,搜索方向向量  
  出口参数:
  a1     :搜索区间步长下限
  a3     :搜索区间步长上限*/

void Get_Search_area(int n,double *x_k,double *s_k,double *a1,double *a3)
{                                                                  
    double a=ak,s,f0,a2=0;
    double f1=0,f2=0,f3=0;
    double *x_k1;
    x_k1=(double*)malloc(sizeof(double)*n);
    f2=f(x_k);
    while(1)
    {
        *a1=a2+a;
        fun(x_k1,x_k,s_k,*a1,n);
        f1=f(x_k1);
        if(f1>f2)
        {
            if(a==ak)
            {
                *a3=*a1;
                f3=f1;
                a=-a;
                continue;
            }
            else if(*a1>*a3)
                {
                    s=*a1;
                    *a1=*a3;
                    *a3=s;
                    f0=f1;
                    f1=f3;
                    f3=f0;
                    break;
                }
            else break;
        }
        else
        {
            *a3=a2;
            a2=*a1;
            f3=f2;
            f2=f1;
            a=2*a;
            continue;
        }
    }
    free(x_k1);
}

/*黄金分割法求极小值*/
/*入口参数:
  n     :优化模型维数
  a1    :搜索区间步长下限
  a4    :索区间步长上限
  s_k   :n维数组,搜索方向向量           */
/*出口参数:
  x_k     :n维数组,极小点坐标 */

void Gold_division(int n,double a1,double a4,double *x_k,double *s_k)
{
    double a2,a3,f2,f3,a_star;
    double *x_k2,*x_k3;    int i;
    x_k2=(double*)malloc(sizeof(double)*n);
    x_k3=(double*)malloc(sizeof(double)*n);

    for(i=0;i<n;i++)
    {
        x_k2[i]=0;
        x_k3[i]=0;
    }
    a2=a1+0.382*(a4-a1);
    fun(x_k2,x_k,s_k,a2,n);
    f2=f(x_k2);
    a3=a1+0.618*(a4-a1);
    fun(x_k3,x_k,s_k,a3,n);
    f3=f(x_k3);   
    do
    {
        if(f2<=f3)
        {
            a4=a3;
            a3=a2;
            f3=f2;
            a2=a1+0.382*(a4-a1);
            fun(x_k2,x_k,s_k,a2,n);
            f2=f(x_k2);
        }
        else
        {
            a1=a2;
            a2=a3;
            f2=f3;
            a3=a1+0.618*(a4-a1);
            fun(x_k3,x_k,s_k,a3,n);
            f3=f(x_k3);
        }
    } while(fabs(a4-a1)>det);   
        a_star=(a1+a4)*0.5;
        fun(x_k,x_k,s_k,a_star,n);
    free(x_k2);
    free(x_k3);
}

/*计算函数梯度
  入口参数:
  n     :优化模型维数
  dx    :梯度步长
  x_k   :n维数组,初始点坐标  
  出口参数:
  s_k   :梯度的负方向向量*/

void tidu(int n,double dx,double x[],double s_k[])   
{
    int i;
    double *x0;
    x0=(double*)malloc(sizeof(double)*n);
    for(i=0;i<n;i++)
        x0[i]=x[i];
    for(i=0;i<n;i++)
    {   
        x0[i]=x[i]+dx;
        s_k[i]=(f(x0)-f(x))/dx*(-1);
        x0[i]=x0[i]-dx;
    }
    free(x0);
}

/*计算梯度范数
  入口参数:
  n     :优化模型维数
  s_k   :梯度的负方向向量  
  返回值:梯度范数  */
double f_fanshu(int n,double s_k[])
{
    int i;
    double sum=0;
    for(i=0;i<n;i++)
        sum+=s_k[i]*s_k[i];
    return (sqrt(sum));
}
/*梯度法求最优函数值
/*入口参数:
  n     :优化模型维数
  x_k   :n维数组,极小点坐标       */
/*出口参数:
  f0    :函数极小值 */

void fun_tidu(int n,double *x_k,double *f0)
{
    double *s_k;
    double a1=0,a3=0;
    double *a_1,*a_3;
    a_1=&a1;
    a_3=&a3;
    s_k=(double*)malloc(sizeof(double)*n);
    while(1)   
    {   tidu(n,dx,x_k,s_k);
        if(f_fanshu(n,s_k)>det1)
        {
            Get_Search_area(n,x_k,s_k,a_1,a_3);   
            Gold_division(n,*a_1,*a_3,x_k,s_k);
           
        }
        else
            break;
    }
    *f0=f(x_k);
    free(s_k);
}

/* 主函数*/

int main()
{
    int n,i;
    double *x_k,*f;
    double f0=0;
    f=&f0;
   

    puts("原函数为f=(x[0]-2)*(x[0]-2)*(x[0]-2)*(x[0]-2)+(x[0]-2*x[1])*(x[0]-2*x[1]);\n");
    puts("请输入变量维数n:\n");
    scanf("%d",&n);    

    x_k=(double*)malloc(sizeof(double)*n);

    printf("输入起始坐标x_k:\n");
    for(i=0;i<n;i++)
    {
        scanf("%lf",&x_k[i]);
   
        fun_tidu(n,x_k,f);
    }

    puts("函数极小点坐标:\n");
    for(i=0;i<n;i++)
        printf("%lf;",x_k[i]);
    printf("\n");

    puts("函数最优值:\n");
    printf("%lf\n",*f);

    free(x_k);
    return 0;
}

2014-03-04 21:12
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
都快忘了这贴子了。你的代码也没测试过吧,变量f(一个double型指针)与函数f重名了都没注意到?

表达式的解析在学数据结构中就有讲。对于中缀表达式(就是我们平时写的表达式,如你代码中那个)通过两个栈来实现,一个数据栈,一个符号栈。这时运算符要预先设置优先级,而数据栈由于你是要随时变更数据,那么里面就不能用来存储实际数据,可以改成数据的索引。

如果你能接受逆波兰式那可以简化表达式的存储与执行,只需要数据栈即可。

三两句也不可能说清楚,我也不想大篇幅地重复书中的内容。有兴趣可以查有关资料学习自己实现,严蔚敏那本《数据结构》里就有讲。

或者准备10个百分贴并回答我下面的问题,我送你一段代码。

1、你希望在表达式里实现哪些运算?(加、减、乘除、指数、对数、三角?要具体)

2、你希望用哪种形式输入表达式?(前缀、中缀、后缀?)

3、你能保证你每次输入的表达式都是正确的么?需要容错检查么?

重剑无锋,大巧不工
2014-03-04 22:22
visow
Rank: 2
等 级:论坛游民
帖 子:36
专家分:24
注 册:2012-7-8
收藏
得分:0 
谢谢斑竹,我主要是学习,所以我先自己试试,不过希望不懂得地方斑竹多多指教哈
2014-03-08 20:27
pycansi
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:5
帖 子:418
专家分:1060
注 册:2012-7-26
收藏
得分:0 
逆波兰,Forth
这语言还是蛮有意思的


莫问前尘有愧,但求今生无悔
2014-03-09 00:51
快速回复:用c对函数进行优化的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.019746 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved