Skip to content

Commit 0699194

Browse files
authored
Merge pull request #5 from IBMDecisionOptimization/support20.1
Adding support for 20.1
2 parents 033b5c3 + 33111ca commit 0699194

4 files changed

Lines changed: 61 additions & 24 deletions

File tree

README.md

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ WML offers a Python and REST API to develop and execute DO models.
99
The code included in this repository provides two ways to use WML to solve DO models.
1010
1. the `ilog.cplex.*` and `ilog.cp.*` packages include classes to easily modify existing Java code so that the optimization will execute on WML.
1111
The Java code should include both the modeling and execution of the DO model, and **after just a single line change, execution will occur on WML**.
12-
2. the `com.ibm.ml.ilog*` package includes lower level classes to create **models** and **deployments** in WML, and then create and poll **jobs**.
12+
2. the `com.ibm.ml.ilog*` package includes lower level classes to create **models** and **deployments** in WML, and then create and poll **jobs**.
1313
With these classes, you can have detailed control on the execution and integration of DO in WML.
1414

1515
* The 1st packages are useful if you use CPLEX/CPO engines from Java and want to delegate the solve resources to Cloud.
@@ -34,7 +34,7 @@ You will need a CPLEX installation in order to compile and run this code.
3434

3535
You don't need an official commercial version of CPLEX to run this as the optimization will happen on WML.
3636

37-
The compilation and modeling can be done with the **Community Edition** of CPLEX that is freely available.
37+
The compilation and modeling can be done with the **Community Edition** of CPLEX that is freely available.
3838

3939
### WML instance and credentials
4040
In order to run on WML, you will need an instance with some credentials.
@@ -50,13 +50,13 @@ But you should be able to adapt to any Java environment that you prefer.
5050

5151
As always the important things to check are:
5252
* the dependencies on the Concert and CPLEX Java packages,
53-
* and the right setting of the path to the CPLEX native library.
54-
53+
* and the right setting of the path to the CPLEX native library.
54+
5555
* If you use a released version of this library, add it as a Java dependancy
5656
* If you use the project sources, then
5757
* add `src/main/java` as `Source Root`
5858
* add `src/main/resources` as `Resources Root`
59-
59+
6060
In any case, to run the examples, you need to:
6161
* add `src/test/java` as `Test Source Root`
6262
* add `src/test/resources` as `Test Resources Root`
@@ -86,7 +86,7 @@ In order to solve on WML, you just need to use the new class and provide some WM
8686
IloCplex cplex = new WmlCplex(credentials, runtime, size, numNodes);
8787
```
8888
where:
89-
* **Credentials** credentials: contains the list of your credentials. You can easily create one from a config file.
89+
* **Credentials** credentials: contains the list of your credentials. You can easily create one from a config file.
9090
See [`wml.cpd.conf`](src/test/resources/wml.cpd.conf) or [`wml.public.conf`](src/test/resources/wml.public.conf) for example.
9191
(Cloud Pak for Data public and private have small credentials inputs).
9292
you can specify your WML credentials, either by hard-coding them in those files or by overloading the environment variables.
@@ -96,11 +96,11 @@ you can specify your WML credentials, either by hard-coding them in those files
9696

9797
The new CPLEX class will behave exactly like the original one (see [supported API and limitations](#Supported-CPLEX-and-CPO-API-and-limitations)), you can call the solve, get the variables values, an so on.
9898

99-
The same applies to the IloCP class where
99+
The same applies to the IloCP class where
100100
```
101101
IloCP cp = new IloCP();
102102
```
103-
is replaced with
103+
is replaced with
104104
```
105105
IloCP cp = new WmlCP(credentials, runtime, size, numNodes);
106106
```
@@ -119,12 +119,12 @@ will create:
119119
* For a 12.10 version of DO
120120
* with a medium size
121121
* and 1 node
122-
122+
123123
### Supported CPLEX and CPO API and limitations
124124

125125
With both CPLEX and CPO, you can build any type of model as long as you don't use any callbacks, set parameters and delegate the solve to Cloud Pak for Data.
126126

127-
Both engines have unsupported methods.
127+
Both engines have unsupported methods.
128128
When such an unsupported method is called, an exception will be raised in most cases at execution time.
129129

130130
#### CPLEX Supported/Unsupported API
@@ -137,9 +137,9 @@ In few words, most CPLEX methods are supported except methods related to:
137137
* Asynchronous api
138138
* Conflicts
139139
* Tuning methods
140-
140+
141141
See [`Details about CPLEX`](CPLEX.md) for a detailed list of methods.
142-
142+
143143
#### CP Supported/Unsupported API
144144

145145
All model building methods are supported.
@@ -150,7 +150,7 @@ You can set parameters.
150150
You can query values for variables, interval variables, and get objective(s) value(s).
151151

152152

153-
* All methods related to callbacks (non-batch solving) are not supported.
153+
* All methods related to callbacks (non-batch solving) are not supported.
154154
* A number of additional methods like failure explanation or search information are not supported.
155155
* Others methods are not supported but a work-around can be used (for instance: `getValue(IloIntExpr expr)` can be replaced with: `getIntValue(IloIntVar idvar)` after adding an equality constraint binding the integer decision variable to the expression value).
156156

@@ -165,7 +165,7 @@ This package contains the classes you need to use to pilot a fine grained handli
165165
They might not be useful if you only use CPLEX/CPO jobs, but are relevant if you want to use Python-based jobs, or OPL-based jobs.
166166

167167
* If you are interested in the WML api, see the [`BrowseWML.java`](src/test/java/com/ibm/ml/BrowseWML.java) example.
168-
* If you are interested in delegating a Python/OPL based scenario, see the [`WMLSamples.java`](src/test/java/com/ibm/ml/WMLSamples.java) example.
168+
* If you are interested in delegating a Python/OPL based scenario, see the [`WMLSamples.java`](src/test/java/com/ibm/ml/WMLSamples.java) example.
169169

170170
Library execution can be controlled by the [`src/main/resources/resources.conf`](src/main/resources/resources.conf)file, where you can specify with hard coded values or environment variables various parameters such as:
171171
* the default time limit (If no time limit is provided by the engines, then by default, the WML job will be terminated after this time limit to avoid wasting resources).
@@ -197,11 +197,33 @@ Credentials.getCredentials(ConfigFactory.parseResources("wml.public.conf").resol
197197
```
198198
* or by providing the keys/values yourself.
199199

200+
## How to run the examples.
201+
202+
The examples are using configuration files and environment variables to handle the various endpoints/credentials you need to provide to make them run.
203+
you need to either hardcode them in the config files or define the env vars.
204+
205+
Here is a list of the variables you need to setup to run them.
206+
To run the CP/CPLEX examples, you only need to provide the variables related to Watson Machine Learning.
207+
To run the WML workflow examples, you will need to provide the variables related to Cloud Object Storage also
208+
209+
**Watson Machine Learning related**
210+
* WML_HOST: defines the host, for example "https://us-south.ml.cloud.ibm.com".
211+
* WML_API_KEY: your api key.
212+
* WML_SPACE_ID: defines the space that will used to store/handle the various artefacts (model, deployment, ...).
213+
214+
215+
**Cloud Object Storage related**
216+
* COS_ENDPOINT: defines the COS endpoint, for example "https://control.cloud-object-storage.cloud.ibm.com/v2/endpoints".
217+
* COS_BUCKET: your bucket name.
218+
* COS_ACCESS_KEY: access key.
219+
* COS_SECRET_KEY: secret access key.
220+
221+
200222
## Note about the library and WML interactions.
201223

202224
Running a DO job in WML needs a WML Deployment job.
203225
The creation of a job takes approximately 20 seconds, so to avoid this delay, the library reuses deployments when a new job is triggered.
204-
Deployments can be created if not present: they will be created/reused with a name that is the combination of
226+
Deployments can be created if not present: they will be created/reused with a name that is the combination of
205227
* the engine
206228
* the runtime
207229
* the size

src/main/java/com/ibm/ml/ilog/Connector.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ static Connector getConnector(Credentials creds) throws IloException {
4343

4444
enum Runtime {
4545
DO_12_9("do_12.9"),
46-
DO_12_10("do_12.10");
46+
DO_12_10("do_12.10"),
47+
DO_20_1("do_20.1");
4748

4849
private final String shortName;
4950

@@ -69,7 +70,11 @@ enum ModelType {
6970
CPLEX_12_10("do-cplex_12.10"),
7071
CPO_12_10("do-cpo_12.10"),
7172
OPL_12_10("do-opl_12.10"),
72-
DOCPLEX_12_10("do-docplex_12.10");
73+
DOCPLEX_12_10("do-docplex_12.10"),
74+
CPLEX_20_1("do-cplex_20.1"),
75+
CPO_20_1("do-cpo_20.1"),
76+
OPL_20_1("do-opl_20.1"),
77+
DOCPLEX_20_1("do-docplex_20.1");
7378

7479
private final String shortName;
7580

@@ -93,6 +98,8 @@ static ModelType getCPLEXModelType(Runtime r) throws IloException {
9398
return ModelType.CPLEX_12_9;
9499
case DO_12_10:
95100
return ModelType.CPLEX_12_10;
101+
case DO_20_1:
102+
return ModelType.CPLEX_20_1;
96103
}
97104
throw new IloException("Runtime " + r + " is not supported currently");
98105
}
@@ -103,6 +110,8 @@ static ModelType getCPOModelType(Runtime r) throws IloException {
103110
return ModelType.CPO_12_9;
104111
case DO_12_10:
105112
return ModelType.CPO_12_10;
113+
case DO_20_1:
114+
return ModelType.CPO_20_1;
106115
}
107116
throw new IloException("Runtime " + r + " is not supported currently");
108117
}

src/main/java/com/ibm/ml/ilog/v4/Connector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public class Connector extends HttpUtils implements com.ibm.ml.ilog.Connector {
6262

6363
private final String COMPLETED = "completed";
6464
private final String FAILED = "failed";
65-
private final String[] status = {COMPLETED, "failed", "canceled", "deleted"};
65+
private final String[] status = {COMPLETED, FAILED, "canceled", "deleted"};
6666
private final Set<String> completedStatus = new java.util.HashSet<>(Arrays.asList(status));
6767

6868
private final int statusRefreshRate = config.getInt("wmlconnector.v4.status_rate");

src/main/java/ilog/cplex/ExternalCplex.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ private void addVariable(HashMap<String, IloNumVar> name2var, HashMap<IloNumVar,
4545

4646
if (!oldNames.containsKey(v)) {
4747
oldNames.put(v, name); // even if name == null!
48-
name = String.format("v%x", oldNames.size());
48+
name = String.format("vv%x", oldNames.size());
4949
v.setName(name);
5050
name2var.put(name, v);
5151
}
@@ -55,7 +55,7 @@ private void addRange(HashMap<String, IloRange> name2rng, HashMap<IloRange, Stri
5555
String name = v.getName();
5656
if (!oldNames.containsKey(v)) {
5757
oldNames.put(v, name); // even if name == null!
58-
name = String.format("c%x", oldNames.size());
58+
name = String.format("cc%x", oldNames.size());
5959
v.setName(name);
6060
name2rng.put(name, v);
6161
}
@@ -251,7 +251,11 @@ private void parse(InputStream solutionXml, Set<String> knownVariables, Set<Stri
251251
state = ParserState.VARIABLES;
252252
} else if (element.equals("linearConstraints")) {
253253
state = ParserState.LINEAR_CONSTRAINTS;
254-
} else {
254+
}
255+
else if (element.equals("indicatorConstraints")) {
256+
state = ParserState.LINEAR_CONSTRAINTS;
257+
}
258+
else {
255259
state = ParserState.UNKNOWN;
256260
unknownStack.add(element);
257261
}
@@ -275,8 +279,6 @@ private void parse(InputStream solutionXml, Set<String> knownVariables, Set<Stri
275279
}
276280
break;
277281
case LINEAR_CONSTRAINTS:
278-
if (!element.equals("constraint"))
279-
throw new IOException(MALFORMED_XML);
280282
attrs = getAttributes(reader, "name", "dual", "slack");
281283
if (attrs[0] != null) {
282284
if (attrs[1] == null) {
@@ -332,7 +334,11 @@ private void parse(InputStream solutionXml, Set<String> knownVariables, Set<Stri
332334
throw new IOException(MALFORMED_XML);
333335
break;
334336
case LINEAR_CONSTRAINTS:
335-
if (element.equals("constraint")) { /* nothing */ } else if (element.equals("linearConstraints")) {
337+
if (element.equals("constraint")) { /* nothing */ }
338+
else if (element.equals("linearConstraints")) {
339+
state = ParserState.SOLUTION;
340+
}
341+
else if (element.equals("indicatorConstraints")) {
336342
state = ParserState.SOLUTION;
337343
} else
338344
throw new IOException(MALFORMED_XML);

0 commit comments

Comments
 (0)