以下是引用zhixl在2007-11-14 13:04:11的发言:
你用的是哪个版本的matlab?
这决定你选择什么方式的matlab/c混合编程
我用的是matlab 7.0.1,上午用共轭梯度法代码试了一下混编,好像有问题。
共轭梯度的M文件为:
function x=ctcg(A,x0,y,n,tol)
% 线性方程为y=Ax
% 参数说明:
% A——线性方程系数
% x0——初值
% y——已知数据
% n——线性方程未知数个数
% tol——迭代终止误差
% 线性方程可以化为正定二次矩阵函数f=x'*Q*x/2+b'*x+c
% 其中,Q=2*A'*A,b=-2*A'*y,c=y'*y
% 函数梯度为 gradf=Q*x+b
Q=2*A'*A;
b=-2*A'*y;
% 求初始梯度
gradf0=Q*x0+b;
k=0; % 计数器
% 若初始值已满足,则返回结果
if (norm(gradf0)<=tol)
x=x0;
return;
end
p0=-gradf0; % 初始搜索方向
lamda=-gradf0'*p0/(p0'*Q*p0); % 初始步长
xk=x0+lamda*p0; % 求第二个值
gradfk=Q*xk+b; % 求第二个值对应的梯度
k=1;
% 进入迭代运算
while (norm(gradfk)>tol)
if (k==n) % 若计数到n,则以xn为新初始值开始新一轮共轭梯度迭代
k=0; % 计数器清零
x0=xk;
gradf0=Q*x0+b;
if (norm(gradf0)<=tol)
x=x0;
return;
end
p0=-gradf0;
else
% F-R共轭梯度法
beta=norm(gradfk)*norm(gradfk)/(norm(gradf0)*norm(gradf0));
pk=-gradfk+beta*p0;
x0=xk;
gradf0=gradfk;
p0=pk;
end
lamda=-gradf0'*p0/(p0'*Q*p0); % 新的步长
xk=x0+lamda*p0; % 新的值
gradfk=Q*xk+b; % 新的梯度
k=k+1;
end
x=xk;
return;
这个代码经过线性方程组测试可以解出来解。然后mbuild和mex配置编译器,再用
mcc -B csglsharedlib:cg ctcg
来编译,这是《精通Matlab7》给的方法。编译完成后生成了dll,然后配置VC,将这个dll及其头文件和库拷贝到VC工程目录下,给一个按钮,在按钮函数中编写如下代码:
mxArray* A=NULL;
mxArray* x0=NULL;
mxArray* y=NULL;
mxArray* n=NULL;
mxArray* tol=NULL;
mxArray* x=NULL;
cgInitialize();
double da[16];
da[0] = 1.0000;
da[1] = 0.5000;
da[2] = 0.3333;
da[3] = 0.2500;
da[4] = 0.5000;
da[5] = 0.3333;
da[6] = 0.2500;
da[7] = 0.2000;
da[8] = 0.3333;
da[9] = 0.2500;
da[10] = 0.2000;
da[11] = 0.1667;
da[12] = 0.2500;
da[13] = 0.2000;
da[14] = 0.1667;
da[15] = 0.1429;
double dx0[4];
dx0[0] = 1;
dx0[1] = 1;
dx0[2] = 1;
dx0[3] = 1;
double dy[4];
dy[0] = 0.5;
dy[1] = 1;
dy[2] = 2;
dy[3] = 0;
double dn = 4;
double dtol = 0.000001;
A = mxCreateDoubleMatrix(4, 4, mxREAL);
x0 = mxCreateDoubleMatrix(4, 1, mxREAL);
y = mxCreateDoubleMatrix(4, 1, mxREAL);
n = mxCreateDoubleMatrix(1, 1, mxREAL);
tol = mxCreateDoubleMatrix(1, 1, mxREAL);
x = mxCreateDoubleMatrix(4, 1, mxREAL);
memcpy(mxGetPr(A), da, 16*sizeof(double));
memcpy(mxGetPr(x0), dx0, 4*sizeof(double));
memcpy(mxGetPr(y), dy, 4*sizeof(double));
memcpy(mxGetPr(n), &dn, sizeof(double));
memcpy(mxGetPr(tol), &dtol, sizeof(double));
mlfCtcg(1, &x, A, x0, y, n, tol);
double dx[4];
memcpy(dx, mxGetPr(x), 4*sizeof(double));
mxDestroyArray(A);
mxDestroyArray(x0);
mxDestroyArray(y);
mxDestroyArray(n);
mxDestroyArray(tol);
mxDestroyArray(x);
cgTerminate();
CString str;
str.Format("x1=%lf, x2=%lf, x3=%lf, x4=%lf", dx[0], dx[1], dx[2], dx[3]);
AfxMessageBox(str);
假设测试的线性方程组为:
x1+0.5*x2+0.3333*x3+0.25*x4=0.5
0.5*x1+0.3333*x2+0.25*x3+0.2*x4=1
0.3333*x1+0.25*x2+0.2*x3+0.1667*x4=2
0.25*x1+0.2*x2+0.1667*x3+0.1429*x4=0
最后,完成运算给出的解是:
x1=0.000000, x2=0.000000, x3=0.000000, x4=0.000000
不是我要的解。我不知道程序错在哪里……