Saturday, March 19, 2005

 

Some notes on Matlab/Mathematica and C++/DotNet

I.
发信人: observer (笑看人生), 信区: Science
标 题: mathematica 和 C/C++的混合编程 -observer
发信站: Unknown Space - 未名空间 (Thu May 27 14:49:38 2004), 转信

网上已经有matlab 和 c的混合编程,

我就来写个mathematica 和 C/C++的混合编程吧,只图方便

- observer

mathematica的数学运算在有些方面比 matlab 要全一些,symbolic computing就不
用说了,

比如我感兴趣的 non-square的矩阵求逆, mathematica可以直接做,

matlab还要自己调svd,剔除无效singular value,再算逆矩阵,

还有spherical harmonics,mathematica 可以直接求

当然matlab和mathematica 我两个都用,

我比较喜欢的是用mathematica和matlab完成那些公式函数太多的运算,

调函数的方式在matlab和mathematica下效率是优化过的,所以不慢

而剩下的“苦”活就由我用c/c++来写好了

以下基于mathematica 5.0 的 mathlink 和 VC6,

mathlink支持很多接口,包括tcp/ip, 也就是装mathematica的机器可以不在本地

mathematica 好象没有做成 matlab那样,可以直接调用dll

而是用一个 mathlink的c/c++ 接口,即你的程序只和mathlink建立连接,

由mathlink启动mathematica kernal并将结果返回给你。

也就是说当你调用mathmatic函数时,mathematica主程序是单独运行的

(1) 先配置vc 的ide

把mathematica 为 vc写的include, lib, bin 目录加到 vc->tools->directories
, 怎么加不用说了吧

mathematica 的这些目录缺省在

C:\Program Files\Wolfram Research\Mathematica\5.0\AddOns\MathLink\Develo
perKit\Windows\CompilerAdditions\MLDev32

(2) 在你的vc project->settings->link->library modules下加入mathematica 的
lib文件"ML32I2M.LIB"

否则link你的程序时那些接口函数会找不到地

别的编译器也有mathematica提供的类似的lib文件,就不多说了

至于dll文件在你装mathematica时就设置好了,不用操心

(3) 在你的接口程序中 include mathlink的头文件"mathlink.h"

下面来分两种情况说混合编程

1. C/C++ 中调用mathematica

例子是从 help doc里面改出来的,运行通过

唯一要说明的是当建立mathlink时提示要找的exe是mathematica的keneral

而不是你自己程序编译出来的exe

如果参数用

-linkname "mathematica 的 kernal程序的完整路径"

可以省却每次都去找路径的麻烦

/* To run this program use the command-line below:

* Unix: quotient -linkname "math -mathlink"

* Mac or Windows: quotient -linkmode launch

*/

#include

#include

#include "mathlink.h"

extern int mlmactty_init( char*** argvp);

static void init_and_openlink( int argc, char* argv[]);

MLENV ep = (MLENV)0;

MLINK lp = (MLINK)0;

int main( int argc, char* argv[])

{

int pkt, m, n, q;

init_and_openlink( argc, argv);



MLActivate(lp);

// printf( "Two integers m/n: ");

// if( scanf( "%d/%d", &m, &n) != 2 && scanf( "%d %d", &m, &n) != 2)

// exit(-1);

m = 4;

n = 2;

/* Send EvaluatePacket[ Quotient[ m, n]] */

MLPutFunction( lp, "EvaluatePacket", 1L);

MLPutFunction( lp, "Quotient", 2L);

MLPutInteger( lp, m);

MLPutInteger( lp, n);

MLEndPacket( lp);



/* skip any packets before the first ReturnPacket */

while( (pkt = MLNextPacket( lp), pkt) && pkt != RETURNPKT)

MLNewPacket( lp);



/* inside the ReturnPacket we expect an integer */

MLGetInteger( lp, &q);



printf( "quotient = %d\n", q);



/* quit Mathematica */

MLPutFunction( lp, "Exit", 0);

return 0;

}

static void deinit( void)

{

if( ep) MLDeinitialize( ep);

}

static void closelink( void)

{

if( lp) MLClose( lp);

}

static void init_and_openlink( int argc, char* argv[])

{

long err;

#if MACINTOSH_MATHLINK

MLYieldFunctionObject yielder;

argc = mlmactty_init( &argv);

#endif

ep = MLInitialize( (MLParametersPointer)0);

if( ep == (MLENV)0) exit(1);

atexit( deinit);

#if MACINTOSH_MATHLINK

yielder = MLCreateYieldFunction( ep, NewMLYielderProc( MLDefaultYielder
), 0);

#endif

lp = MLOpenArgv( ep, argv, argv + argc, &err);

if(lp == (MLINK)0) exit(2);

atexit( closelink);



#if MACINTOSH_MATHLINK

MLSetYieldFunction( lp, yielder);

#endif

}

上面程序用几个接口函数将命令传给mathlink, 再从mathlink得到结果

命令具体格式和含义就看help 吧

(2) mathematica 调 c/c++

这个呢就比上面稍微麻烦一点

以mathematica 提供的例子 addtwo 为例

(缺省在C:\Program Files\Wolfram Research\Mathematica\5.0\AddOns\MathLin
k\DeveloperKit\Windows\MathLinkExamples"下可以找到)

值得注意的是为了调用c/c++写的函数,需要声明该函数在mathematica里面的接口


就是如文件addtwo.tm所示的东西

int addtwo P(( int, int));

: Begin:

: Function: addtwo

: Pattern: AddTwo[i_Integer, j_Integer]

: Arguments: { i, j }

: ArgumentTypes: { Integer, Integer }

: ReturnType: Integer

: End:

: Evaluate: AddTwo::usage = "AddTwo[x, y] gives the sum of two machine in
tegers x and y."

然后用 前面提到的 bin 目录下的MPREP.EXE生成接口申明的addtwotm.c文件,

和addtwo.c的源c文件一块编译

注意,生成addtwotm.c这一步可以用vc ide 的custom build 完成即

include addtwo.tm 到你的project中去

project->setting->custom build->

在左边文件列表中选addtwo.tm, 在右边的commands中填入

mprep addtwo.tm -o addtwotm.c

在右边的ouput中填入

$(OutDir)\addtwotm.c

第一次编译时就会在debug目录下输出addtwotm.c文件

include it 到你的project中,就可以编译通过了

运行时到mathematica中,

link = Install[LinkLaunch["AddTwo"]];

就会要你找到该外部命令的exe,也就是刚刚编译出来的exe

剩下的就是在mathematica中敲

AddTwo[2, 3]之类的运行该命令了

网上URL:

www.mathematica.com

http://documents.wolfram.com/v5/Add-onsLinks/MathLink/System-SpecificInf
ormation/Windows/index.html

上面的例子我都运行通过了,如果我有什么遗漏,欢迎指正

嗯,版权归observer所有

--
※ 来源:.Unknown Space - 未名空间 mitbbs.com.[FROM: 141.210.]

(按:呵呵,Mathematica Dos版是我上大学用的第一个数学计算软件,不过后来基本使用Matlab啦。存个目,以防万一吧)

2.
在.NET中应用MATLAB算法

作者:lihonggen0
出处:http://www.csdn.net

在科学研究和工程应用中,往往要进行大量的数学计算,其中包括矩阵运算。这些运算一般来说难以用手工精确和快捷地进行,而要借助计算机编制相应的程序做近似计算。目前流行用Basic、Fortran和c语言编制计算程序, 既需要对有关算法有深刻的了解,还需要熟练地掌握所用语言的语法及编程技巧。对多数科学工作者而言,同时具备这两方面技能有一定困难。通常,编制程序也是繁杂的,不仅消耗人力与物力,而且影响工作进程和效率。为克服上述困难,美国Mathwork公司于1967年推出了“Matrix Laboratory”(缩写为MATLAB)软件包,并不断更新和扩充。目前最新的6.x版本(windows环境)是一种功能强、效率高便于进行科学和工程计算的交互式软件包。其中包括:一般数值分析、矩阵运算、数字信号处理、建模和系统控制和优化等应用程序,并集应用程序和图形于一便于使用的集成环境中。在此环境下所解问题的MATLAB语言表述形式和其数学表达形式相同,不需要按传统的方法编程。不过,MATLAB作为一种新的计算机语言,要想运用自如,充分发挥它的威力,也需先系统地学习它。但由于使用MATLAB编程运算与人进行科学计算的思路和表达方式完全一致,所以不象学习其它高级语言--如Basic、Fortran和C等MATLAB的基础知识,在短短几个小时的使用中就能初步掌握它.从而使你能够进行高效率和富有创造性的计算。 MATLAB大大降低了对使用者的数学基础和计算机语言知识的要求,而且编程效率和计算效率极高,还可在计算机上直接输出结果和精美的图形拷贝,所以它的确为一高效的科研助手。自推出后即风行美国,流传世界。

MATLAB算法是一个优秀的算法,我们在软件开发过程中,尤其是数据库开发方面,要进行数据汇总、统计分析、然后根据汇总的数据产生图表(包括柱图、饼图、四分图、雷达图等),这种需求甚为普遍。

由于MATLAB算法具有强大的计算处理功能,所以在许多软件中已经用到它,比如作个销售预测,前提是基于以往的销售数据,可以用MATLAB算法对以往的销售数据进行处理(如函数、矩阵的一系列运算,或者采用一些运筹学的知识进行数据处理),再由MATLAB算法产生出相关数据的精美图形输出,得到一个具有科学理论依据的方案,把我们的管理思想融合到了计算机程序设计中,使软件解决方案不是简单的电算化工具,而是一个综合许多学科的智慧的结晶!

微软的.NET开发工具,结合数据库SQL SERVER,是开发数据库应用的最佳选择!我们可以把SQL SERVER里的数据用MATLAB算法进行处理,还可以将自己写的算法包装成COM,在.NET中引用就可以了。在使用的MATLAB算法时,图形输出的功能往往被人忽略,下面的例子,就是采用的MATLAB出的图形

首先在.NET中,引用matlab 的对象库(Matlab Application(version 6.5) Type Library),笔者采用的是MATLAB 6.5 版本,然后在窗体上加一个图片框PictureBox1,用于显示图片;

一个Button1用于调用MATLAB,并加载图形。

[code]
Dim strMatLab As String '定义matlab语句字符串

' 显示正弦图

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim MatLab As Object

'建立matlab应用

MatLab = CreateObject("matlab.application")

'最小化matlab命令窗口

MatLab.MinimizeCommandWindow()

'matlab语句

strMatLab = "t=2:0.2:4*pi;y=sin(t);plot(t,y)"

'执行matlab算法

matlab.Execute(strMatLab)

'生成一个JPG的图形c:\Test1.jpg

matlab.Execute("print( gcf, '-djpeg', 'c:\Test1')")

'退出matlab,释放资源

matlab.Quit()

MatLab = Nothing

'显示在图片框

PictureBox1.Image = New Bitmap("c:\Test1.jpg")

End Sub

' 显示饼图

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Dim matlab As Object

matlab = CreateObject("matlab.application")

strMatLab = "sale=[100 400 150 250 500];pie3(sale,[0 0 1 0 0],{'公司A','公司B','公司C','公司D','公司E'})"

matlab.Execute(strMatLab)

matlab.Execute("print( gcf, '-djpeg', 'c:\Test2')")

matlab.Quit()

matlab = Nothing

PictureBox1.Image = New Bitmap("c:\Test2.jpg")

End Sub

' 显示三维螺旋线图

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

Dim matlab As Object

matlab = CreateObject("matlab.application")

strMatLab = "t=0:0.2:4*pi;plot3(sin(t),cos(t),t)"

matlab.Execute(strMatLab)

matlab.Execute("print( gcf, '-djpeg', 'c:\Test3')")

matlab.Quit()

matlab = Nothing

PictureBox1.Image = New Bitmap("c:\Test3.jpg")

End Sub

' 显示立体波浪图

Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click

Dim matlab As Object

matlab = CreateObject("matlab.application")

strMatLab = "[X,Y,Z] = peaks(20);surfc(X,Y,Z);colormap hsv;axis ([-2 4 -6 8 -10 6])"

matlab.Execute(strMatLab)

matlab.Execute("print( gcf, '-djpeg', 'c:\Test5')")

matlab.Quit()

matlab = Nothing

PictureBox1.Image = New Bitmap("c:\Test5.jpg")

End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

End Sub
[/code]

总结:一般情况下,我们将自己的算法在MATLAB中生成dll,供VB.NET调用此算法,输入一组数据,输出一系列数据,而且MATLAB算法比较简单,一个命令就完成了许多功能,大大提高了开发效率!



<< Home

This page is powered by Blogger. Isn't yours?