Skip to content

Commit 60214fc

Browse files
authored
Merge pull request #2 from vlkong/master
Added new sample showing how to use JdbcCustomDataSource in .dat
2 parents 97187cf + 7845980 commit 60214fc

File tree

15 files changed

+297
-14
lines changed

15 files changed

+297
-14
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# bin dirs
33
bin/
44
build/
5-
lib/
65

76
# This is not distributed, but contain libs for local deps management
87
external_libs/

README.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,21 @@ OPL custom data source API to import data from a JDBC data source into an OPL mo
66
This sample illustrates the [Subclassing IloCustomOplDataSoource](https://www.ibm.com/support/knowledgecenter/en/SSSA5P_12.8.0/ilog.odms.ide.help/OPL_Studio/opllanguser/topics/opl_languser_extfunc_datasubcl.html) section from the OPL User's manual.
77
This sample shows how to read and write tuplesets to/from a database with Java. It also enables you to read a database and generate .dat files to be used in the IDE to prototype your optimization model.
88

9-
While this sample uses MySQL as data storage, it can be easily adapted to
10-
any database that has JDBC drivers.
9+
One [variation](examples/ilo_opl_call_java) of this sample shows how to read and write tuplesets to/from a database involving only some scripting in your .dat
10+
11+
This sample comes with example connection configurations to DB2, MySQL and MS SQL Server. It can
12+
be easily adapted to any database that has JDBC drivers.
1113
This example will work with any 12.x OPL version, even if it is configured to run with 12.8.0 version.
1214

1315

1416
## Table of Contents
1517
- [Prerequisites](#prerequisites)
16-
- [Build and run the sample](#build-and-run-the-sample)
18+
- [Build and run the sample from java](#build-and-run-the-sample-from-java)
1719
- [Build the sample](#build-the-sample)
1820
- [Run sample with DB2](#run-sample-with-db2)
1921
- [Run sample with MySQL](#run-sample-with-mysql)
20-
- [Run sample with MS SQL Server](#run-sample-with-ms-sql-server)
22+
- [Run sample with MS SQL Server](#run-sample-with-ms-sql-server)
23+
- [Run the sample from OPL](#run-the-sample-from-opl)
2124
- [Export plain dat files](#export-plain-dat-files)
2225
- [Run with a previous OPL version](#run-with-a-previous-opl-version)
2326
- [License](#license)
@@ -41,7 +44,10 @@ This example will work with any 12.x OPL version, even if it is configured to ru
4144
MySQL Comunity Server, but is compatible with minimal changes with other JDBC
4245
compatible databases.
4346

44-
## Build and run the sample
47+
## Build and run the sample from java
48+
49+
The default sample uses model and data from [examples/oil](examples/oil)
50+
4551
### Build the sample
4652

4753
Before you build the sample, you must edit `build.properties` for the appropriate path locations:
@@ -203,6 +209,14 @@ $ ant run_mssql
203209

204210

205211

212+
### Run the sample from OPL
213+
214+
Sample in [examples/ilo_opl_call_java](examples/ilo_opl_call_java) shows how to
215+
use the jdbc custom data source as a library, without having the need to
216+
invoke OPL runtime from java. You can use this method to access database
217+
using a jdbc-custom-data-source from `oplrun` or OPL Studio.
218+
219+
206220
### Reusing the sample with other databases
207221
As the sample is build on JDBC, it's possible to reuse <code>JdbcCustomDataSource</code> with minimal changes:
208222

build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Example for MySQL:
44
mysql.jdbc.connector.path=external_libs/mysql-connector-java-5.1.40-bin.jar
55
# Example for DB2:
6-
db2.jdbc.connector.path=C:/Program Files/IBM/SQLLIB/java/db2jcc4.jar
6+
db2.jdbc.connector.path=external_libs/db2jcc4.jar
77
# MS SQL server
88
sqlserver.jdbc.connector.path=external_libs/mssql-jdbc-7.2.2.jre8.jar
99

build.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,19 @@
7272

7373
<target name="run_db2" depends="compile">
7474
<antcall target="run">
75-
<param name="cmd" value="-properties data/db_db2.xml data/oil.mod data/oil.dat"/>
75+
<param name="cmd" value="-properties data/db_db2.xml examples/oil/oil.mod examples/oil/oil.dat"/>
7676
</antcall>
7777
</target>
7878

7979
<target name="run_mysql" depends="compile">
8080
<antcall target="run">
81-
<param name="cmd" value="-properties data/db_mysql.xml data/oil.mod data/oil.dat"/>
81+
<param name="cmd" value="-properties data/db_mysql.xml examples/oil/oil.mod examples/oil/oil.dat"/>
8282
</antcall>
8383
</target>
8484

8585
<target name="run_mssql" depends="compile">
8686
<antcall target="run">
87-
<param name="cmd" value="-properties data/db_mssql.xml data/oil.mod data/oil.dat"/>
87+
<param name="cmd" value="-properties data/db_mssql.xml examples/oil/oil.mod examples/oil/oil.dat"/>
8888
</antcall>
8989
</target>
9090

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Example using IloOplCallJava
2+
3+
This sample is basically the same as [oil](../oil).
4+
5+
The difference is that it does not involve writing code in Java, and can be used
6+
in a .dat/.mod from OPL Studio.
7+
8+
# Setup
9+
10+
Before you run the sample, you will need to edit [oil.dat](oil.dat), and configure
11+
paths. In particular, you want to add the JDBC connector jar, for instance:
12+
13+
```
14+
// Update this to point to your jdbc driver.
15+
// For instance mssql-jdbc-7.2.2.jre8.jar for mssql
16+
IloOplImportJava("../../external_libs/mssql-jdbc-7.2.2.jre8.jar")
17+
```
18+
19+
And you want to specify the configuration file for your database connection:
20+
21+
```
22+
// This is the configuration file for accessing your database.
23+
var jdbcConfigXml = "../../data/db_mssql.xml";
24+
```
25+
26+
Lastly, you want to point to the jdbc custom data source jar.
27+
It is distributed as binaries in the [lib](../../lib) directory:
28+
29+
```
30+
// The jar containing the jdbc custom data source
31+
IloOplImportJava("../../lib/jdbc-custom-data-source.jar");
32+
```
33+
# Running the sample
34+
35+
To run the sample, invoke the `run.bat` script:
36+
37+
38+
```
39+
C:\> run
40+
Buildfile: C:\opl\OPL-jdbc-custom-data-source\examples\ilo_opl_call_java\build.xml
41+
42+
platform:
43+
44+
run:
45+
[exec]
46+
[exec] <<< setup
47+
[exec]
48+
[exec] Reading elements from database
49+
[exec] Reading Gasolines using "SELECT NAME FROM GASDATA"
50+
[exec] Reading OilData using "SELECT * FROM OILDATA"
51+
[exec] Reading Oils using "SELECT NAME FROM OILDATA"
52+
[exec] Reading GasData using "SELECT * FROM GASDATA"
53+
[exec] Done
54+
[exec]
55+
[exec] <<< generate
56+
[exec]
57+
[exec] Tried aggregator 1 time.
58+
[exec] LP Presolve eliminated 1 rows and 0 columns.
59+
[exec] Reduced LP has 12 rows, 12 columns, and 43 nonzeros.
60+
[exec] Presolve time = 0.00 sec. (0.01 ticks)
61+
[exec]
62+
[exec] Iteration log . . .
63+
[exec] Iteration: 1 Scaled dual infeas = 0.000000
64+
[exec] Iteration: 2 Dual objective = 434000.000000
65+
[exec]
66+
[exec] <<< solve
67+
[exec]
68+
[exec]
69+
[exec] OBJECTIVE: 287750
70+
[exec] Result = {<"Crude1" "Diesel" 800 0> <"Crude1" "Regular" 2111.1 750>
71+
72+
[exec] <"Crude1" "Super" 2088.9 0> <"Crude2" "Diesel" 0 0>
73+
[exec] <"Crude2" "Regular" 4222.2 750> <"Crude2" "Super" 777.78 0>
74+
[exec] <"Crude3" "Diesel" 200 0> <"Crude3" "Regular" 3166.7 750>
75+
[exec] <"Crude3" "Super" 133.33 0>}
76+
[exec]
77+
[exec] <<< post process
78+
[exec]
79+
[exec]
80+
[exec] <<< done
81+
[exec]
82+
83+
BUILD SUCCESSFUL
84+
Total time: 1 second
85+
Press any key to continue . . .
86+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<project name="externaldataread" default="run">
2+
<property environment="env"/>
3+
4+
<condition property="example.home" value="${env.CPLEX_STUDIO_DIR128}/opl">
5+
<isset property="env.CPLEX_STUDIO_DIR128"/>
6+
</condition>
7+
<property name="example.home" value="${opl.home}">
8+
</property>
9+
10+
11+
<import file="${example.home}/examples/opl_interfaces/java/build_common.xml"/>
12+
<condition property="oplrun.binary" value="oplrunjava">
13+
<os family="unix"/>
14+
</condition>
15+
<property name="oplrun.binary" value="oplrun"/>
16+
17+
<target name="run" depends="platform">
18+
<exec executable="${example.home}/bin/${example.platform}/${oplrun.binary}">
19+
<arg value="oil.mod"/>
20+
<arg value="oil.dat"/>
21+
<env key="ODMS_JAVA_ARGS" value='-classpath "${example.home}/lib/oplall.jar"' />
22+
<env key="PATH" path="${example.home}/bin/${example.platform}${platform.separator}${env.PATH}"/>
23+
<env key="Path" path="${example.home}/bin/${example.platform}${platform.separator}${env.Path}"/>
24+
<env key="LD_LIBRARY_PATH" path="${example.home}/bin/${example.platform}${platform.separator}${env.JAVA_HOME}/jre/bin${platform.separator}${env.JAVA_HOME}/jre/bin/j9vm${platform.separator}${env.JAVA_HOME}/jre/bin/classic"/>
25+
<env key="LIBPATH" path="${example.home}/bin/${example.platform}${platform.separator}${env.JAVA_HOME}/jre/bin${platform.separator}${env.JAVA_HOME}/jre/bin/j9vm${platform.separator}${env.JAVA_HOME}/jre/bin/classic"/>
26+
<env key="DYLD_LIBRARY_PATH" path="${example.home}/bin/${example.platform}${platform.separator}${env.DYLD_LIBRARY_PATH}"/>
27+
<env key="LD_PRELOAD_64" path="${preload_64}"/>
28+
</exec>
29+
</target>
30+
31+
</project>

examples/ilo_opl_call_java/oil.dat

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
prepare {
2+
// Update this to point to your jdbc driver.
3+
// For instance mssql-jdbc-7.2.2.jre8.jar for mssql
4+
IloOplImportJava("../../external_libs/mssql-jdbc-7.2.2.jre8.jar")
5+
6+
// This is the configuration file for accessing your database.
7+
var jdbcConfigXml = "../../data/db_mssql.xml";
8+
9+
// The jar containing the jdbc custom data source
10+
IloOplImportJava("../../lib/jdbc-custom-data-source.jar");
11+
12+
IloOplCallJava("com.ibm.opl.customdatasource.JdbcCustomDataSource",
13+
"addDataSource", "", jdbcConfigXml, thisOplModel);
14+
}
15+
16+
MaxProduction = 14000;
17+
ProdCost = 4;

examples/ilo_opl_call_java/oil.mod

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// --------------------------------------------------------------------------
2+
// Licensed Materials - Property of IBM
3+
//
4+
// 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55
5+
// Copyright IBM Corporation 1998, 2013. All Rights Reserved.
6+
//
7+
// Note to U.S. Government Users Restricted Rights:
8+
// Use, duplication or disclosure restricted by GSA ADP Schedule
9+
// Contract with IBM Corp.
10+
// --------------------------------------------------------------------------
11+
12+
13+
{string} Gasolines = ...;
14+
{string} Oils = ...;
15+
tuple gasType {
16+
string name;
17+
float demand;
18+
float price;
19+
float octane;
20+
float lead;
21+
}
22+
23+
tuple oilType {
24+
string name;
25+
float capacity;
26+
float price;
27+
float octane;
28+
float lead;
29+
}
30+
{gasType} GasData = ...;
31+
{oilType} OilData = ...;
32+
gasType Gas[Gasolines] = [ g.name : g | g in GasData ];
33+
oilType Oil[Oils] = [ o.name : o | o in OilData ];
34+
35+
float MaxProduction = ...;
36+
float ProdCost = ...;
37+
38+
39+
dvar float+ a[Gasolines];
40+
dvar float+ Blend[Oils][Gasolines];
41+
42+
43+
maximize
44+
sum( g in Gasolines , o in Oils )
45+
(Gas[g].price - Oil[o].price - ProdCost) * Blend[o][g]
46+
- sum( g in Gasolines ) a[g];
47+
48+
subject to {
49+
50+
ctDemand: forall( g in Gasolines )
51+
sum( o in Oils )
52+
Blend[o][g] == Gas[g].demand + 10 * a[g];
53+
54+
ctCapacity: forall( o in Oils )
55+
sum( g in Gasolines )
56+
Blend[o][g] <= Oil[o].capacity;
57+
58+
ctMaxProd: sum( o in Oils , g in Gasolines )
59+
Blend[o][g] <= MaxProduction;
60+
61+
ctOctane: forall( g in Gasolines )
62+
sum( o in Oils )
63+
(Oil[o].octane - Gas[g].octane) * Blend[o][g] >= 0;
64+
ctLead: forall( g in Gasolines )
65+
sum( o in Oils )
66+
(Oil[o].lead - Gas[g].lead) * Blend[o][g] <= 0;
67+
}
68+
tuple result {
69+
string oil;
70+
string gas;
71+
float blend;
72+
float a;
73+
}
74+
75+
{result} Result =
76+
{ <o,g,Blend[o][g],a[g]> | o in Oils, g in Gasolines };
77+
78+
execute DISPLAY_RESULT{
79+
writeln("Result = ",Result)
80+
}

examples/ilo_opl_call_java/run.bat

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@echo off
2+
rem Run the example
3+
4+
rem If CPLEX_STUDIO_DIR128 is not already defined, add the following line :
5+
rem CPLEX_STUDIO_DIR128=%~dp0\..\..\..\..\..
6+
7+
cd %~dp0
8+
9+
set "arg="
10+
:Loop
11+
IF "%1"=="" GOTO Continue
12+
set "arg=%arg% %1"
13+
SHIFT
14+
GOTO Loop
15+
:Continue
16+
17+
call "%CPLEX_STUDIO_DIR128%\opl\ant\bin\ant" -Dexample.arg.line="%arg%" run
18+
19+
pause

examples/oil/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Maximizing the profit of an oil company
2+
3+
## Describe the business problem
4+
5+
* An oil company manufactures different types of gasoline and diesel. Each type of gasoline is produced by blending different types of crude oils that must be purchased. The company must decide how much crude oil to buy in order to maximize its profit while respecting processing capacities and quality levels as well as satisfying customer demand.
6+
* Blending problems are a typical industry application of Linear Programming (LP). LP represents real life problems mathematically using an objective function to represent the goal that is to be minimized or maximized, together with a set of linear constraints which define the conditions to be satisfied and the limitations of the real life problem. The function and constraints are expressed in terms of decision variables and the solution, obtained from optimization engines such as IBM® ILOG® CPLEX®, provides the best values for these variables so that the objective function is optimized.
7+
* The oil-blending problem consists of calculating different blends of gasoline according to specific quality criteria.
8+
* Three types of gasoline are manufactured: super, regular, and diesel.
9+
* Each type of gasoline is produced by blending three types of crude oil: crude1, crude2, and crude3.
10+
* The gasoline must satisfy some quality criteria with respect to their lead content and their octane ratings, thus constraining the possible blendings.
11+
* The company must also satisfy its customer demand, which is 3,000 barrels a day of super, 2,000 of regular, and 1,000 of diesel.
12+
* The company can purchase 5,000 barrels of each type of crude oil per day and can process at most 14,000 barrels a day.
13+
* In addition, the company has the option of advertising a gasoline, in which case the demand for this type of gasoline increases by ten barrels for every dollar spent.
14+
* Finally, it costs four dollars to transform a barrel of oil into a barrel of gasoline.
15+
16+
## Files
17+
18+
`oil.mod` contains the OPL Model.
19+
20+
`oil.dat` contains part of the input data. Mostly parameters for the problem, like max production and production cost. The missing input data sets (OilData and GasData are read from the database at run time using the sql queries defined in the database connection xml configuration file)

0 commit comments

Comments
 (0)