java中调用matlab软件进行计算,返回结果
之所以要写这个,是因为我最近需要用这个;一开始想使用java的人很多,遇到这个问题,应该在网上可以找到满意的答案。 但通过搜索后,是有很多。 但仔细一看,都大同小异,而且有很多直接就是粘贴复制的嘛;结果没找到。偶然的看到了有用matlabcontrol-4.1.0.jar包来开发的一个文章。但也没有说个所以然,最后我针扎了一天,最后自己弄出来了。希望对大家有帮助。(查资料没有查到是在国内查的,没有翻墙。翻墙的话国外应该有,只是怪我查找不行没有找到吧)
一、首先说一下为什么要在java中调用matlab代码编程:
答: 当我们在编写java程序时,如果遇到大量的矩阵计算等一些数学计算很多的时候,如果我们使用java自己编写程序的话,代码量庞大,或者自己搞不出来,比如10个方程求解10个未知量时;而java又没有所有需要的库;这时我们就可以使用matlab这个工具了。这样大大的减少了代码量,提高了开发效率。
二、怎么用:
答:我看了网上有很多,大量的都是通过把matlab代码打包成jar的形式来使用。 本方法我也使用了,并折腾了一下午才打好一个包,调用的时候又出问题;为什么呢?因为他对软件版本一致性的要求很高,jdk必须要与从matlab中查看到的java版本一致才行。 而且运行时也是;我不知道运行时是不是严格要求一致,反正我是一致时,打包成功后去使用时报错而无法使用。所以我使用了matlabcontrol-4.1.0.jar这个工具,我的资源中有上传这个文件。
(下载地址:https://download.****.net/download/qq_27731689/10544548)
三、使用步骤:
1:确保电脑安装了matlab软件。我不知道对软包版本有没有要求,我(jdk1.8,matlab2016a)没有出问题。
2:新建一个java项目,导入这个jar包:
3:通过这样来调用:
我的demo.m(matlab代码是这样的):
function [f,x,favl,exitflag,output] = demo(p,Q,C,m,M,QQ,c)
f=C-p.*Q;
f=f';
intcon=1:6;
A=[C;-Q;ones(1,6);-ones(1,6);0,0,1,1,0,0,;0,0,-1,-1,0,0];
b=[c;-QQ;M;m;1;0];
lb=zeros(6,1);
ub=ones(6,1);
[x,favl,exitflag,output]=intlinprog(f,intcon,A,b,[],[],lb,ub);
end
切记:m文件一定要放在工作空间下,默认的工作空间是项目的空间,即把文件拷贝到项目的根目录下。
java代码:我先建了一个test测试单元:
public void xia() throws Exception {
MatlabProxyFactory factory = new MatlabProxyFactory();
MatlabProxy proxy = factory.getProxy();
double p=0.2;
double[] Q={13795,537,2000,3000,4000,7049};
double[] C={65,-50,100,300,600,1080};
double m=2;
double M=5;
double QQ=10000;
double c=10000;
//下面第一个参数是方法民,第二个为返回的参数的个数,后面依次为输入的参数
Object[] result = proxy.returningFeval("demo",5,p,Q,C,m,M,QQ,c);
//返回的结果,是一个数组形式,所以用数组接收,下面为我取得第一个返回的参数f的值。
double[] r=(double[]) result[0];
System.out.print("f:");
for (int i = 0; i < r.length; i++) {
System.out.print(r[i]);
}
// 但返回的数组中,可能会返回对象,比如这的output,最后一个参数,就这样接收
Object[] r4=(Object[]) result[4];
String[] key=(String[]) r4[0];
for (int i = 0; i < key.length; i++) {
System.out.println(key[i]);
}
//反正就是去看结果的结构,根据对象类型一级一级的取值
}
问题又来了: 我的是web项目,用这个计算每次都会启动matlab,就会很慢。所以我先建了一个Listener来代理;只要启动后,后面就无需在次启动,Listenerd代码如下:
public void contextInitialized(ServletContextEvent sce) {
File file = new File("F:\\javawebWorkspace\\matlabDemo");//知道m文件的路基,可以任意
MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
.setProxyTimeout(300000L)
.setMatlabStartingDirectory(file)//设置MATLAB的开始目录。
.setHidden(false)
.build();
MatlabProxyFactory factory = new MatlabProxyFactory(options);
MatlabProxy proxy = null;
try {
proxy = factory.getProxy();
}catch (MatlabConnectionException e) {
e.printStackTrace();
}
sce.getServletContext().setAttribute("proxy", proxy);
System.out.println("matlab连接成功");
}
调用的地方是这样的:
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
try {
MatlabProxy proxy=(MatlabProxy) req.getServletContext().getAttribute("proxy");
double p=0.2;
double[] Q={13795,537,2000,3000,4000,7049};
double[] C={65,-50,100,300,600,1080};
double m=2;
double M=5;
double QQ=10000;
double c=10000;
Object[] result = proxy.returningFeval("demo",5,p,Q,C,m,M,QQ,c);
double[] r=(double[]) result[0];
System.out.print("f:");
for (int i = 0; i < r.length; i++) {
System.out.print(r[i]);
}
double[] x=(double[]) result[1];
System.out.println();
System.out.print("x:");
for (int i = 0; i < x.length; i++) {
System.out.print(x[i]);
}
} catch (Exception e) {
// TODO: handle exception
}
}
这就是我的方法,有不对或者需改进的,希望大家给我指出,共同进步。 谢谢。
下面是结果: