这个想法基于近期的一个练手项目,这个项目需要将JSHOP2规划器封装在系统中,并于系统的其他模块(如数据库,可视化结果等)对接。前前后后琢磨有一两周,终于成功实现从Java端直接对JSHOP2规划器进行调用,包括从Java端实现对JSHOP2的输入与输出。
综上,本文主要解决的问题如下:
需要提前配置JSHOP环境和Java运行环境。
由于domain文件涉及方法的分解,需要较多的
在生成Problem文件之前,需要根据用户输入,当前数据库信息等数据自动生成JSHOP2格式的代码。这一部分主要涉及字符串的处理,网上已有大量详细的文章介绍,故不再作阐述。自动生成的可由JSHOP2调用的格式为“文件格式”,生成的方式与txt文件生成的方式类似,不指定新建文件类型即可。
// 输入 path:Problem文件的生成地点 content:Problem文件的内容
public static void writefile(String path, String content) throws IOException {
try {
File file = new File(path); // 不指定新建文件类型,即可生成“文件”类型给JSHOP2调用。
OutputStream out = new FileOutputStream(file);
BufferedWriter rd = new BufferedWriter(new OutputStreamWriter(out, "utf-8"));
rd.write(content);
rd.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
上次介绍到我们调用JSHOP2的方法主要通过cmd,所以需要提前写好bat文件,调用指定位置的Problem和domain文件,并一同输入到JSHOP2规划器中进行求解。根据这一思路,写了如下方法:
// 输入 cmdpath:bat文件的路径 cmd:bat文件名称
// 输出 JSHOP2的规划结果,若失败则返回null。
// e.g. String outputString = runCmd("D:\\JSHOP2\\Workspace\\transresource", "main");
public static String runCmd(String cmdpath, String cmd) {
String result = "";
File dir = new File(cmdpath);
try {
Process ps = Runtime.getRuntime().exec("cmd /c " + cmd, null, dir);
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream(), Charset.forName("GBK")));
String line = null;
while ((line = br.readLine()) != null) {
// System.out.println(line);
result += line + "\n";
}
br.close();
ps.waitFor();
return result;
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("error");
return null;
}
至此,我们获得了JSHOP2的规划结果,对其进行字符串处理,如使用split()、replace()等String类下的方法,网上已有大量的教程,不再做过多阐述。
Java端调用JSHOP2规划器有诸多好处,也有丰富的实际应用场景。从实际应用的角度,调用JSHOP2规划器解决实际问题时,Problem文件的数据往往是时时更新的,是用户根据态势输入的,且JSHOP2的规划结果可读性较差,对用户十分不友好。在此场景下,自动生成Problem文件、调用JSHOP2规划器并将结果返回Java端进行处理甚至进一步可视化分析就显得十分必要。从科研的角度,基于自动生成Problem文件与调用规划器并返回规划的结果,我们可以便捷地实现基于规划结果判定是否需要进行重规划。 若需要重规划,可对自动对下次规划的Problem文件进行调整与修改,使得下次规划结果更加满意。
然而,笔者在实现的过程中也发现了此种方法的一些弊端。其一,这一方法较繁琐。自动生成Problem文件需要读取大量的数据库数据,而JSHOP2不支持中文格式(至少笔者尚未发现,如果有小伙伴知道请请与我分享),这其中就涉及中英文的转换,且转换的变量名不能有丝毫的偏差,对数据库的集成程度要求较高。其二,这一方法耗费时间长。JSHOP2本身规划时间是毫秒级别的,然而这一过程涉及自动生成Problem文件,调用bat文件从而调用JSHOP2规划器,并传回规划结果等多个阶段,使得规划一次问题的时间大大增加。 就笔者测试来说,若多次生成的Problem文件,多次调用规划器的情况下,可能耗费几十秒,这与使用HTN规划方法的初衷是背离的。其三,java代码过长无法编译。这也算是JSHOP2较SHOP2的一项弊端,就是当domain和problem文件太大时(自动生成的现实问题数据往往是庞大的),导致JSHOP2生成的类无法在使用Java进行编译(jdk规定方法编译后的字节码不能超过64KB大小)。解决的办法只能是拆分domain和problem文件,进行多次调用并组合结果。