*本文主要记录和分享学习到的知识,算不上原创

*参考文献见链接

这篇文章主要记录一些Cplex的Callback的使用方法,采用Java语言。

https://www.ibm.com/support/knowledgecenter/SSSA5P_12.7.0/ilog.odms.cplex.help/CPLEX/UsrMan/topics/progr_adv/callbacks_basic/01_cb_title_synopsis.html

目录

  什么是Callback

  第一种:Informational Callback

  第二种:Query Callback

  第三种:Control Callback

什么是Callback

Callbacks allow you to monitor closely and to guide the behavior of CPLEX  optimizers. In particular, callbacks (either optimization or tuning callbacks) allow user code to be executed regularly during an optimization or during a tuning session. To use callbacks with CPLEX, you must first write the callback function, and then pass it to CPLEX.

This essay concentrates on optimization callbacks.

There are three types of optimization callbacks:

  • informational callbacks,

  • query callbacks,

  • control callbacks

第一种:Informational Callback

What is Informational Callback?

An informational callback is a user-written routine that enables your application to access information about the current mixed integer programming (MIP) optimization without sacrificing performance and without interfering in the search of the solution space. The algorithms call an informational callback when the algorithm finds it appropriate; for some algorithms, an informational callback is called at every node; for other algorithms, an informational callback is called at convenient points in the progress of the algorithm.

An informational callback can also enable your application to abort (that is, to terminate) optimization.

When to call?

Callback Interface

In the Java API, an informational callback is an instance of MIPInfoCallback or one of these derived subclasses:

IloCplex.DisjunctiveCutInfoCallback
IloCplex.FlowMIRCutInfoCallback
IloCplex.FractionalCutInfoCallback
IloCplex.ProbingInfoCallback

An informational callback is installed in a Java application by the method IloCplex.use().

Examples

(1)informational callback 01:  Spend at least timeLimit seconds on optimization, but once this limit is reached, quit as soon as the solution is acceptable.

 public class MIPex4 {
static void usage() {
System.out.println("usage: MIPex4 <filename> <option>");
System.out.println(" t to use the time-limit-gap callback");
System.out.println(" l to use the logging callback");
System.out.println(" a to use the aborter");
} public static void main(String[] args) throws IloException {
if ( args.length != 2 ) {
usage();
return;
}
IloCplex cplex=new IloCplex();
/*
* Aborter terminates the solve and tuning methods of CPLEX
*/
Aborter aborter=new Aborter();
boolean useLoggingCallback = false;
boolean useTimeLimitCallback = false;
boolean useAborter = false;
switch ( args[1].charAt(0) ) {
case 't':
useTimeLimitCallback = true;
break;
case 'l':
useLoggingCallback = true;
break;
case 'a':
useAborter = true;
break;
default:
usage();
return;
}
cplex.importModel(args[0]);
IloLPMatrix lp=(IloLPMatrix)cplex.LPMatrixIterator().next();
/*
* cplex.getObjective(): returns the IObjective object of the active model,
* or null if no IObjective object is currently in the active model
*/
IloObjective obj=cplex.getObjective();//
if(useTimeLimitCallback){
cplex.use(new TimeLimitCallback(false, cplex.getCplexTime(), 1.0, 0.1));
}else if(useLoggingCallback){
cplex.setParam(IloCplex.Param.MIP.Limits.Nodes, 5000);
/*
* IloObjectiveSense:
* Maximize
* Minimize
*/
double lastObjVal = (obj.getSense() == IloObjectiveSense.Minimize ) ?
Double.MAX_VALUE : -Double.MAX_VALUE;
cplex.use(new LogCallback(lp.getNumVars(), 0, lastObjVal));
cplex.setParam(IloCplex.Param.MIP.Display, 0);//turn off logging
}else if(useAborter){
cplex.use(aborter);
}
if(cplex.solve()){
System.out.println("Solution status = " + cplex.getStatus());
System.out.println("CPLEX status = " + cplex.getCplexStatus());
}
cplex.end();
} /*
* informational callback 01:
* Spend at least timeLimit seconds on optimization, but once this limit is reached,
* quit as soon as the solution is acceptable
*/
static class TimeLimitCallback extends MIPInfoCallback{
boolean aborted;
double timeLimit;
double timeStart;
double acceptableGap;
public TimeLimitCallback(boolean aborted,double timeStart,double timeLimit,double acceptableGap) {
// TODO Auto-generated constructor stub
this.aborted=aborted;
this.timeLimit=timeLimit;
this.timeStart=timeStart;
this.acceptableGap=acceptableGap;
}
@Override
protected void main() throws IloException {
// TODO Auto-generated method stub
/*
* hasIncumbent(): returns true if an incumbent solution has been found when the callback is called.
*/
if(! aborted && hasIncumbent()){
double gap=getMIPRelativeGap();
double timeUsed=getCplexTime()-timeStart;
if(timeUsed>timeLimit && gap<acceptableGap){
System.out.println("Good enough solution at "
+ timeUsed + " sec., gap = "
+ gap + "%, quitting.");
aborted=true;
abort();//terminate
}
}
}
}
}

(2)informational callback 02: Log new incumbents if they are at better than the old by a relative tolerance of 1e-5; also log progress info every 100 nodes.

 public class MIPex4 {
static void usage() {
System.out.println("usage: MIPex4 <filename> <option>");
System.out.println(" t to use the time-limit-gap callback");
System.out.println(" l to use the logging callback");
System.out.println(" a to use the aborter");
} public static void main(String[] args) throws IloException {
if ( args.length != 2 ) {
usage();
return;
}
IloCplex cplex=new IloCplex();
/*
* Aborter terminates the solve and tuning methods of CPLEX
*/
Aborter aborter=new Aborter();
boolean useLoggingCallback = false;
boolean useTimeLimitCallback = false;
boolean useAborter = false;
switch ( args[1].charAt(0) ) {
case 't':
useTimeLimitCallback = true;
break;
case 'l':
useLoggingCallback = true;
break;
case 'a':
useAborter = true;
break;
default:
usage();
return;
}
cplex.importModel(args[0]);
IloLPMatrix lp=(IloLPMatrix)cplex.LPMatrixIterator().next();
/*
* cplex.getObjective(): returns the IObjective object of the active model,
* or null if no IObjective object is currently in the active model
*/
IloObjective obj=cplex.getObjective();//
if(useTimeLimitCallback){
cplex.use(new TimeLimitCallback(false, cplex.getCplexTime(), 1.0, 0.1));
}else if(useLoggingCallback){
cplex.setParam(IloCplex.Param.MIP.Limits.Nodes, 5000);
/*
* IloObjectiveSense:
* Maximize
* Minimize
*/
double lastObjVal = (obj.getSense() == IloObjectiveSense.Minimize ) ?
Double.MAX_VALUE : -Double.MAX_VALUE;
cplex.use(new LogCallback(lp.getNumVars(), 0, lastObjVal));
cplex.setParam(IloCplex.Param.MIP.Display, 0);//turn off logging
}else if(useAborter){
cplex.use(aborter);
}
if(cplex.solve()){
System.out.println("Solution status = " + cplex.getStatus());
System.out.println("CPLEX status = " + cplex.getCplexStatus());
}
cplex.end();
}   static class LogCallback extends MIPInfoCallback{
IloNumVar[] var;
long lastLog;
double lastIncumbent;
public LogCallback(IloNumVar[] var, int lastLog, double lastIncumbent) {
// TODO Auto-generated constructor stub
this.var=var;
this.lastLog=lastLog;
this.lastIncumbent=lastIncumbent;
}
@Override
protected void main() throws IloException {
// TODO Auto-generated method stub
boolean newIncumbent=false;
/*
* getNnodes64(): returns the number of nodes processed so far in the active branch-and-cut search
*/
long nodes=getNnodes64();
if(hasIncumbent() &&
//integer value: Math.abs(lastIncumbent-getIncumbentObjValue())>1e-5*(1+Math.abs(getIncumbentObjValue()))
//numeric value: Math.abs(lastIncumbent-getIncumbentObjValue())>1e-5*(1e-10+Math.abs(getIncumbentObjValue()))
Math.abs(lastIncumbent-getIncumbentObjValue())>1e-5*(1+Math.abs(getIncumbentObjValue()))){
lastIncumbent=getIncumbentObjValue();
newIncumbent=true;
}
if(nodes >=lastLog+100 || newIncumbent){
if(!newIncumbent){
lastLog=nodes;
/*
* getBestObjValue() returns a bound on the optimal solution value of the active problem at the moment the callback is called.
*/
System.out.println("Nodes = " + nodes
+ "(" + getNremainingNodes64() + ")"
+ " Best objective = " + getBestObjValue());
}
if ( hasIncumbent() ) {
System.out.println (" Incumbent objective = " +
getIncumbentObjValue());
}else {
System.out.println("");
}
if ( newIncumbent ) {
System.out.println("New incumbent values: ");
int n = var.length;
double[] x = getIncumbentValues(var, 0, n);
for (int i = 0; i < n; i++) {
System.out.println("x[" + i + "] = " + x[i]);
}
}
}
} }
}

第二种:Query Callback

What is Query Callback?

Query or diagnostic callbacks allow you to monitor an ongoing optimization, and optionally to abort it (that is, to terminate it). Query callbacks access more detailed information about the current optimization than do informational callbacks. As a side effect, query or diagnostic callbacks may slow progress.

Furthermore, query or diagnostic callbacks make assumptions about the traversal of a conventional branch &  cut tree; those assumptions about a mixed integer program (MIP) may be incorrect during dynamic search or during deterministic search in parallel optimization.

When to call?

Callback Interface

Query or diagnostic callbacks are distinguished by the place where they are called during an optimization. There are nine such places where CPLEX calls a query or diagnostic callback:

The presolve query callback is called regularly during presolve.
  IloCplex.PresolveCallback in the Java API
The crossover query callback is called regularly during crossover from a barrier solution to a simplex basis.
  IloCplex.CrossoverCallback in the Java API
The network query callback is called regularly during the network simplex algorithm.
  IloCplex.NetworkCallback in the Java API
The barrier query callback is called at each iteration during the barrier algorithm.
  IloCplex.BarrierCallback or IloCplex.ContinuousCallback in the Java API
The simplex query callback is called at each iteration during the simplex algorithm.
  IloCplex.SimplexCallback or IloCplex.ContinuousCallback in the Java API
The MIP query callback is called regularly during the branch and cut search.
  IloCplex.MIPCallback in the Java API
The probing query callback is called regularly during probing.
  IloCplex.ProbingCallback in the Java API
The fractional cut query callback is called regularly during the generation of fractional cuts.
  IloCplex.FractionalCutCallback in the Java API
The disjunctive cut query callback is called regularly during the generation of disjunctive cuts.
  IloCplex.DisjunctiveCutCallback in the Java API
The flow and mixed integer rounding (MIR) cut query callback is called regularly during the generation of flow and MIR cuts.
  IloCplex.FlowMIRCutCallback in the Java API

In the Java API, a query callback is installed by the method IloCplex.use().

Examples

第三种:Control Callback

What is Control Callback?

Control callbacks allow you to control the branch & cut search during the optimization of MIP problems. Because control callbacks intervene in the search, the presence of a control callback in an application will cause CPLEX to turn off dynamic search.

As the reader is no doubt familiar, the process of solving a mixed integer programming problem involves exploring a tree of linear programming relaxations. CPLEX repeatedly selects a node from the tree, solves the LP relaxation at that node, attempts to generate cutting planes to cut off the current solution, invokes a heuristic to try to find an integer feasible solution “close” to the current relaxation solution, selects a branching variable (an integer variable whose value in the current relaxation is fractional), and finally places the two nodes that result from branching up or down on the branching variable back into the tree.

The user should be aware that the branch & cut process works with the presolved problem.

These callbacks allow sophisticated users to control the details of the branch & cut process. Specifically, users can choose the next node to explore, choose the branching variable, add their own cutting planes, place additional restrictions on integer solutions, or insert their own heuristic solutions.

How to implement callback?

(1)选择想要实现的Callback类,写一个子类;

(2)重写子类中的main()方法;

(3)然后用IloCplex.use()调用。

CallBack Interface

If you determine that your application needs to seize control, intervene in the search, and redirect the optimizer, then the following control callbacks are available to do so.

The node callback allows you to query and optionally overwrite the next node CPLEX will process during a branch & cut search.
  IloCplex.NodeCallback
in the Java API
The solve callback allows you to specify and configure the optimizer option to be used for solving the LP at each individual node.
  IloCplex.SolveCallback
in the Java API
The user cut callback allows you to add problem-specific user-defined cuts at each node.
  IloCplex.UserCutCallback
in the Java API
The lazy constraint callback allows you to add lazy constraints; that is, constraints that are not evaluated unless they are violated.
  IloCplex.LazyConstraintCallback
in the Java API
The heuristic callback allows you to implement a heuristic that tries to generate a new incumbent from the solution of the LP relaxation at each node.
  IloCplex.HeuristicCallback
in the Java API
The branch callback allows you to query and optionally overwrite the way CPLEX will branch at each node.
  IloCplex.BranchCallback
in the Java API
The incumbent callback allows you to check and optionally reject incumbents found by CPLEX during the search.
  IloCplex.IncumbentCallback
in the Java API

In Java, there is no way of removing individual callbacks from yourIloCplexorCplexobject. Instead, you remove all callbacks by calling the methodIloCplex.clearCallbacksorCplexClearCallbacks.

Cplex: MIP Callback Interface的更多相关文章

  1. Cplex: MIP Control Callback

    *本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 之前,我们有简单提到Cplex中的MIP Callback Interface,包括了Informational callback, q ...

  2. Cplex: MIP Control Callback Methods

    *本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要归纳了Cplex的Control callback常用的方法. 目录 NodeCallback SolveCallback Us ...

  3. Android图形系统之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的联系

    1.Surface Surface extends Objectimplements Parcelable java.lang.Object    ↳ android.view.Surface Cla ...

  4. Android图形系统之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback开发实例

    原文:Android图形系统之Surface.SurfaceView.SurfaceHolder及SurfaceHolder.Callback之间的联系 Surface是原始图像缓冲区(raw buf ...

  5. JAVA 构造器, extends[继承], implements[实现], Interface[接口], reflect[反射], clone[克隆], final, static, abstrac

    记录一下: 构造器[构造函数]: 在java中如果用户编写类的时候没有提供构造函数,那么编译器会自动提供一个默认构造函数.它会把所有的实例字段设置为默认值:所有的数字变量初始化为0;所有的布尔变量设置 ...

  6. C++根据图片url下载图片

    需要使用到URLDownloadToFile()函数,该函数在头文件<urlmon.h>中声明. URLDownloadToFile()函数的定义如下: HRESULT URLDownlo ...

  7. Android源码分析之Handler

    接上一篇分析,正如Android doc所说,Handler主要有2方面用处: 1. delay执行同一线程中的某个操作,也就是schedule message.runnable在未来的某一时刻执行: ...

  8. Fragment间的通信

    在网上看到的一篇文章,总结的很好 为了重用Fragment的UI组件,创建的每个Fragment都应该是自包含的.有它自己的布局和行为的模块化组件.一旦你定义了这些可重用的Fragment,你就可以把 ...

  9. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->关于spring framework中的beans

    Spring framework中的beans 1.概述 bean其实就是各个类实例化后的对象,即objects spring framework的IOC容器所管理的基本单元就是bean spring ...

随机推荐

  1. HDU6440(费马小定理)

    其实我读题都懵逼--他给出一个素数p,让你设计一种加和乘的运算使得\[(m+n)^p = m^p+n^p\] 答案是设计成%p意义下的加法和乘法,这样:\[(m+n)^p\ \%\ p = m+n\] ...

  2. 安装linux时的分区问题,需要了解目录树及挂载知识

    Linux是目录树架构,如何结合目录树架构与磁盘内的数据→挂载. Linux先有目录,后有磁盘分区.数据(文件)依存于目录. 目录为挂载点,磁盘分区的数据放置在该目录下,进入该目录,就可以读取该分区. ...

  3. hdu4578Transformation(线段树多个lz标记)

    这里以3次方来举例讲一下这题的做法,其它维类似. 如果要求某一个值的3次方那么sum = t^3,设t = x+y.那也就是sum = (x+y)^3. 假如我让每个数都加z t = x+y+z,我可 ...

  4. JAVA 时间的使用

    今天老师又没有讲新课,不过讲了练习题,扩展了一下我们的思维. 今天就讲一下如何获取时间吧. 代码: import java.util.* public class Test{ public stati ...

  5. H5移动端图片裁剪(base64)

    在移动端开发的过程中,或许会遇到对图片裁剪的问题.当然遇到问题问题,不管你想什么方法都是要进行解决的,哪怕是丑点,难看点,都得去解决掉. 图片裁剪的jquery插件有很多,我也测试过很多,不过大多数都 ...

  6. java httpclient 跳过证书验证

    import java.io.IOException;import java.net.InetAddress;import java.net.Socket;import java.net.Unknow ...

  7. JAVA 配置

    JAVA 版本为jdk-7u25-windows-x64 Java 下载地址为: .CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.j ...

  8. vue 中 $set 的使用

    在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给数据赋值时,有时候并不会自动更新到视图上去: <!DOCTYPE html> <html> & ...

  9. 如何用node命令和webpack命令传递参数

    1. 比如在项目中我们的publicPath需要根据服务器环境的变化而变化,这时我们会写一个配置文件,在webpack.config.js中读取,可以 如何才能 取到变量呢? 这里介绍一种方法: 如果 ...

  10. ZOJ-1360 || POJ-1328——Radar Installation

    ZOJ地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=360 POJ地址:http://poj.org/problem?id ...