ling0 发表于 2007-10-12 17:54

如何定义1000个符号变量x1,x2,...,x1000?

举个例子:现有一个函数:f(x)=exp(x1)+exp(x2)+...+exp(x1000) ,想要求这个函数的梯度:g(x)=(diff(f(x),x1),diff(f(x),x2),...,diff(f(x),x1000));
这个例子用Matlab如可实现?

花如月 发表于 2007-10-12 18:22

最低限度用循环应该可以解决

心灯 发表于 2007-10-12 19:07

采用循环生成字符串,然后eval是比较好的方法。

gx_str=[];
for ii=1:1000
    gx_str=;
end

eval(['gx = [' gx_str '];']);

[ 本帖最后由 心灯 于 2007-10-12 19:10 编辑 ]

ling0 发表于 2007-10-12 19:10

谢谢!我试试

ling0 发表于 2007-10-12 20:49

我试了,还是无法得到想要的结果,因为x1,...,x1000没有定义,会报错

心灯 发表于 2007-10-12 21:13

回复 #5 ling0 的帖子

我只是给你个提示,里面的fx换成你的函数,里面的x1,x2... 等你给赋初值去。 怎么能不分析代码呢?

ling0 发表于 2007-10-12 21:18

做了一个晚上,终于得到一个调试通过的程序如下(运行速度较慢,因为求函数f(x)的形式时耗的时间较长):
n=1000;%定义变量个数
x=sym(ones(1,n));%给符号变量赋初值
for ii=1:n
    x(ii)=['x' num2str(ii)];%定义符号变量的形式为x1,...,xn
end
fx=sum(exp(x)-x);%定义函数f(x)的形式
for ii=1:n
    gx(ii)=diff(fx,x(ii));%求f(x)对各变量的偏导数
end
%输出f(x)的梯度
gx

谢谢楼上两位为我提供了思路。

花如月 发表于 2007-10-12 21:27

3楼的方法不错啊,学习了:@D 发现你们同门用eval都比较顺手啊:victory:

jimin 发表于 2007-10-12 22:27

比较常见的还有个Feval函数 下面的东东可以参考一下
求由字符串给定的函数值
函数feval与eval类似,但在用法上有更多的限制。feval(' fun ',x)求由字符串' fun '给定的函数值,其输入参量是变量x。即feval(' fun ',x)等价于求fun(x)值。
函数eval,feval的基本用途限在用户创建的函数内。一般地,feval可求出有大量输入参量的函数值
利用feval统一函数的调用方式
先看看这两个函数
function y = testfun1(x)
y = x + 1;

function y = testfun2(x,b)
y = x + b;

一般情况下,输入相应的自变量和参数值,就可以得到函数值
x = 1; y = testfun1(x);
x = 1; b = 2; y = testfun2(x,b);
也可以使用feval函数来执行。
x = 1; y = feval(@testfun1, x);
x = 1; b = 2; y = feval(@testfun2, x, b);

然而,有的时候需要用feval函数把这两个函数的执行方式统一起来。
就会遇到这样的问题:这两个函数一个是带参数的,另外一个是不带参数的,或者有可能会出现函数所带的参数数目不一样的情况,如何统一呢?

定义一个cell型的args参数,可以解决这个问题。

第一种情况: args={}; x = 1; y = feval(@testfun1, x, args{:});
注意:写成这样是不行的 :x = 1; y = feval(@testfun1, x, {});或者y = feval(@testfun1, x, {:});

第二种情况: args={2}; x = 1; y = feval(@testfun1, x, args{:});

当然,也可以采用下面这种比较笨的方法:
if(function==@testfun1)
    y = feval(@testfun1, x);
else
y = feval(@testfun2, x, b);
end

当可选函数较多,或者需要反复执行时,这样的调用方式显然是低效的。

这种通过feval将函数的执行方式统一起来的做法,特别适合于在主程序中调用某一类函数。比如在Matlab gads工具箱中,stepGA函数需要调用尺度变换函数,然而有的尺度变换函数是需要指定参数的,有些则不需要。

这种同一类函数参数个数不统一的状况也可以通过引入冗余参数来解决
function y = testfun1(x, b)
y = x + 1 ;

花如月 发表于 2007-10-12 22:33

回复 #9 jimin 的帖子

看了一遍,不过还是觉得这2个函数似乎用处不大呀:@L 。有没有哪种情况必须使用他们呢?

eight 发表于 2007-10-12 23:15

原帖由 花如月 于 2007-10-12 22:33 发表 http://www.chinavib.com/forum/images/common/back.gif
看了一遍,不过还是觉得这2个函数似乎用处不大呀:@L 。有没有哪种情况必须使用他们呢?

这两个函数的区别:
eval的第一个变量名必须是字符串,feval和eval的区别在于前者的第一个变量名不能是表达式,只能是函数名,且当两者可用的情况下,前者运行效率更高

至少以下两个场合用他们比较高效:
1. 把字符串作为命令执行
2. fevel 如果作用在函数名上,相当于c语言的函数指针

心灯 发表于 2007-10-13 00:19

eval函数我常用,配合 num2str(规则表达式),或者是cell变量(不规则的变量或表达式,把不同的地方放到cell中,后面调用)等命令, 主要是用于进行一系列的批处理操作,例如自动生成图的标注,批量保存fig文件,或者保存文本数据文件,或者是对struct变量进行一些操作,可以使程序代码简化很多。

ling0 发表于 2007-10-13 11:55

原帖由 心灯 于 2007-10-12 19:07 发表 http://www.chinavib.com/forum/images/common/back.gif
采用循环生成字符串,然后eval是比较好的方法。

gx_str=[];
for ii=1:1000
    gx_str=;
end

eval(['gx = [' gx_str '];']);

有兴趣的朋友可以按照这个思路完整地编程调试一下,我是没办法做出想要的结果。
主要是以下两个问题:
1.x1,...,x1000要定义成符号变量,否则应该无法求偏导。
2.字符串的位数最大只有63个,对于这1000以上的字符串,后面的部分都被截断了。

[ 本帖最后由 ling0 于 2007-10-13 11:58 编辑 ]

ling0 发表于 2007-10-13 18:28

Sorry ,我在13楼中所说的“字符串的位数最大只有63个,对于这1000以上的字符串,后面的部分都被截断了。”表述有误,应该是双击变量名后看到的位数不多,实际上,计算机内部存储的字符串是可以有1000位以上的。

心灯 发表于 2007-10-13 18:42

回复 #13 ling0 的帖子

哦,我只是给你一个提示,所以里面也是直接用f(x)代替的表达式,没有注意到这是个符号表达式运算,抱歉。
eval 是生成一个字符串命令,有时候可以提高效率,你这里有点体现不出来优势了,我就不那么写了,当然是可以实现的。感兴趣的可以尝试。
如果改成下面的第一种语句,在n很大的时候,效率可以提高不少。

%
clear all;clc
tic;
n=500;%定义变量个数
syms x
fx=sum(exp(x)-x);%定义函数f(x)的形式
gx_str = diff(fx,x);
for ii=1:n
    gx(ii)=subs(gx_str,'x',['x' num2str(ii)]);%求f(x)对各变量的偏导数
end
toc

clear all
tic
n=500;%定义变量个数
x=sym(ones(1,n));%给符号变量赋初值
for ii=1:n
    x(ii)=['x' num2str(ii)];%定义符号变量的形式为x1,...,xn
end
fx=sum(exp(x)-x);%定义函数f(x)的形式
for ii=1:n
    gx(ii)=diff(fx,x(ii));%求f(x)对各变量的偏导数
end
%输出f(x)的梯度
toc
return

Elapsed time is 2.588355 seconds.
Elapsed time is 13.490953 seconds.

[ 本帖最后由 心灯 于 2007-10-13 18:49 编辑 ]
页: [1] 2
查看完整版本: 如何定义1000个符号变量x1,x2,...,x1000?