opl studio 3.7 component libraries user’s manual

112
ILOG OPL Studio 3.7 Component Libraries User’s Manual September 2003 Copyright © 1987-2003, by ILOG S.A. All rights reserved. ILOG, the ILOG design, CPLEX, and all other logos and product and service names of ILOG are registered trademarks or trademarks of ILOG in France, the U.S. and/or other countries. Java TM and all Java-based marks are either trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Microsoft, Windows, and Windows NT are either trademarks or registered trademarks of Microsoft Corporation in the U.S. and other countries. All other brand, product and company names are trademarks or registered trademarks of their respective holders.

Upload: oldecop

Post on 04-Jan-2016

99 views

Category:

Documents


4 download

DESCRIPTION

OPL studio 3.7 Component Libraries User’s Manual

TRANSCRIPT

Page 1: OPL studio 3.7 Component Libraries User’s Manual

ILOG OPL Studio 3.7

Component Libraries User’s Manual

September 2003

Copyright © 1987-2003, by ILOG S.A. All rights reserved.

ILOG, the ILOG design, CPLEX, and all other logos and product and service names of ILOG are registered trademarks or trademarks of ILOG in France, the U.S. and/or other countries.

JavaTM and all Java-based marks are either trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Microsoft, Windows, and Windows NT are either trademarks or registered trademarks of Microsoft Corporation in the U.S. and other countries.

All other brand, product and company names are trademarks or registered trademarks of their respective holders.

Page 2: OPL studio 3.7 Component Libraries User’s Manual
Page 3: OPL studio 3.7 Component Libraries User’s Manual

C O N T E N T S

Contents

Component Libraries User’s Manual

Preface Before You Begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

What You Need to Know . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7

Manual Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8

Notation Used in This Manual. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8

Related Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9

Licensing Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10

Chapter 1 Architecture of the OPL Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Location of Component Libraries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13

Chapter 2 Interfacing with OPL from Visual Basic via the COM API. . . . . . . . . . . . . . . . . . 15

The Bridge Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16

Creating a Visual Basic Project that Refers to the OPL Component . . . . . . . . . . . . . . . . . . . . .16

Examining the Bridge Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21

The Complete Bridge Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25

The Multiproduction Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27

Examining the Multiproduction Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27

The Complete Multiproduction Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .30

Chapter 3 Interfacing with OPL from C++ via the COM API . . . . . . . . . . . . . . . . . . . . . . . . . 31

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 3

Page 4: OPL studio 3.7 Component Libraries User’s Manual

C O N T E N T S

Chapter 4 Interfacing with OPL from Scripting Languages . . . . . . . . . . . . . . . . . . . . . . . . . 35

Calling the OPL Solver Component from Scripting Languages . . . . . . . . . . . . . . . . . . . . .36

Examining the JScript Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38

Examining the VBScript Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Instantiating from HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .39

Calling the OPL Solver from an ASP Script on the Server Side . . . . . . . . . . . . . . . . . . . . .40

Examining the ASP Script Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .44

Chapter 5 Interfacing with OPL from Excel VBA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Generating a Compiled Model File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .46

Solving the Model with Excel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .46

Examining the VBA Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48

Chapter 6 Interfacing with OPL from C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

The Bridge Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .52

Solving the Bridge Problem with OPL from a C++ Application . . . . . . . . . . . . . . . . . . . . . . . . .52

Examining the Bridge Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .52

The Complete Bridge Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .56

Output for the Bridge Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .57

The Multiproduction Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59

Examining the Multiproduction Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .59

The Complete Multiproduction Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62

Chapter 7 Interfacing with OPL from Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

Interfacing with OPL from the Java Native Interface API . . . . . . . . . . . . . . . . . . . . . . . . . . .66

Running an Example On UNIX Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .66

Running the Example On Windows Platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .66

Examining the Java Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67

Calling from JavaServer Pages (JSP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71

Examining the JSP Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .75

Chapter 8 OPL and .NET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

Interfacing with OPL from Visual Basic .NET via the COM/ActiveX API. . . . . . . . . . . . . . .78

4 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 5: OPL studio 3.7 Component Libraries User’s Manual

C O N T E N T S

Example for abridge.mod. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79

Interfacing with OPL from Visual C# .NET via the COM/ActiveX API . . . . . . . . . . . . . . . . .79

Example for queens8.mod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .80

Chapter 9 Customizing an OPL Model using Business Rules. . . . . . . . . . . . . . . . . . . . . . . 81

Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .82

The Warehouse Sample. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .82

OPL Formulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83

Business Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .84

Business Rule Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88

Integration with OPL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .89

Running the Sample from the ILOG Rule Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .92

Deployment in the Finished Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .93

Chapter 10 Interfacing with OPLScript from C++, COM, and Java . . . . . . . . . . . . . . . . . . . . 95

Chapter 11 Database Connectivity from the OPL Component Libraries . . . . . . . . . . . . . . . 97

Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98

Specific RDBMS Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100

The Environment Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100

Troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .101

List of Code Samples. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 5

Page 6: OPL studio 3.7 Component Libraries User’s Manual

C O N T E N T S

6 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 7: OPL studio 3.7 Component Libraries User’s Manual

P R E F A C E

Before You Begin

This manual explains how to use the examples of the ILOG OPL Component Libraries delivered with the standard distribution, and how to create your own applications that will provide access to the OPL engine.

Examples are given in Microsoft Visual Basic, C++, and Java.

What You Need to Know

This manual assumes that you are familiar with the Windows or UNIX environment in which you are going to use the ILOG OPL Component Libraries.

You should also be familiar with the programming language from which you access the OPL engine, i.e., Microsoft’s Visual Basic, C++, or Java.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 7

Page 8: OPL studio 3.7 Component Libraries User’s Manual

M A N U A L O R G A N I Z A T I O N

Manual Organization

◆ Chapter 1, Architecture of the OPL Components, contains a diagram showing how the OPL engine can be accessed from an application.

◆ Chapter 2, Interfacing with OPL from Visual Basic via the COM API, describes how to access the OPL engine from a Visual Basic application, via the COM/ActiveX API.

◆ Chapter 3, Interfacing with OPL from C++ via the COM API, provides an example of how to use the COM/ActiveX component from a C++ application.

◆ Chapter 4, Interfacing with OPL from Scripting Languages, describes how to access the OPL engine from languages such as VBscript and JavaScript.

◆ Chapter 5, Interfacing with OPL from Excel VBA, explains how OPL can interact with Excel.

◆ Chapter 6, Interfacing with OPL from C++, describes how to access the OPL engine from a C++ application, via the C++ API.

◆ Chapter 7, Interfacing with OPL from Java, describes how to access the OPL engine from the Java language, via the Java Native Interface.

◆ Chapter 8, OPL and .NET, describes how to access the OPL engine from Visual Basic.NET or Visual C#.NET, via the COM/ActiveX API.

◆ Chapter 9, Customizing an OPL Model using Business Rules, explains how to integrate an OPL model into an ILOG JRules-based application.

◆ Chapter 10, Interfacing with OPLScript from C++, COM, and Java, explains how OPLScript can be accessed from an application.

◆ Chapter 11, Database Connectivity from the OPL Component Libraries, describes the architecture of ILOG DB Link, gives specific RDBMS settings, and provides help with troubleshooting.

Notation Used in This Manual

The following typographic conventions apply throughout this manual:

◆ Code samples and file names are written in this typeface

◆ Commands appear as File>Open

◆ Important terms are emphasized like this.

8 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 9: OPL studio 3.7 Component Libraries User’s Manual

R E L A T E D D O C U M E N T A T I O N

Related Documentation

◆ ILOG OPL Component Libraries Reference Manual

This document describes the various APIs that allow you to access the OPL solving engine, including the Microsoft COM/ActiveX API, a native C++ API and a Java API. Microsoft’s Component Object Model (COM) allows Windows users to access OPL from within languages such as Visual Basic.

◆ ILOG OPL Studio Language Manual

This book provides a description of the OPL and OPLScript languages. It is based on The OPL Optimization Programming Language by Pascal Van Hentenryck, published by The MIT Press, 1999, Cambridge, Massachusetts.

◆ ILOG OPL Studio User’s Manual

This manual describes the graphical user interface for the OPL modeling language. All development effort is supported through the various modules accessible via ILOG OPL Studio.

Where to Get More Information

For technical support of the ILOG OPL Component Libraries, contact your local distributor, or, if you are a direct ILOG customer, contact:

We encourage you to use e-mail for faster, better service.

Region E-mail Telephone Fax

France [email protected] 0 800 09 27 91(numéro vert)+33 (0)1 49 08 35 62

+33 (0)1 49 08 35 10

Germany [email protected] +49 6172 40 60 33 +49 6172 40 60 10

Spain [email protected] +34 91 710 2480 +34 91 372 9976

United Kingdom

[email protected] +44 (0)1344 661 630 +44 (0)1344 661 601

Rest of Europe [email protected] +33 (0)1 49 08 35 62 +33 (0)1 49 08 35 10

Japan [email protected] +81 3 5211 5770 +81 3 5211 5771

Singapore oplstudio-support @ilog.com.sg +65 6773 06 26 +65 6773 04 39

North America [email protected] 1-877-ILOG-TECH1-877-8456-4832(toll free) or1-650-567-8080

+1 650 567 8001

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 9

Page 10: OPL studio 3.7 Component Libraries User’s Manual

W H E R E T O G E T M O R E I N F O R M A T I O N

Users’ Mailing List

The electronic mailing list [email protected] is available for you to share your development experience with other OPL users. This list is not moderated, but subscription is subject to an on-going maintenance contract. To subscribe to oplstudio-list, send an e-mail without any subject to [email protected], with the following contents:

subscribe oplstudio-list

your e-mail address if different from the From field

first name, last name

your location (company and country)

maintenance contract number

maintenance contract owner’s last name

Web Site

On our web sites, you will find a wealth of information about constraint programming in a range of articles and conference papers explaining the theoretical background and technical features of ILOG OPL Component Libraries and other ILOG products.

In addition to those freely accessible pages, there are also technical support pages on our web sites. They contain FAQ (Frequently Asked/Answered Questions) and the latest patches for some of our products. Changes are posted in the product mailing list. Access to these pages is restricted to owners of an on-going maintenance contract. The maintenance contract number and the name of the person this contract is sent to in your company will be needed for access, as explained on the login page.

All three of these sites contain the same information, but access is localized, so we recommend that you connect to the site corresponding to your location, and select the “Tech Support Web” page from the home page.

Americas: http://www.ilog.com

Asia and Pacific Nations: http://www.ilog.com.sg

Europe, Africa, and Middle East: http://www.ilog.fr

10 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 11: OPL studio 3.7 Component Libraries User’s Manual

L I C E N S I N G R E Q U I R E M E N T S

Licensing Requirements

The keys required for the ILOG OPL Component Libraries depend on the features you wish to use. The following table indicates which ILOG keys you will need.

When deploying, you can register the runtime licenses through specific register methods so that the end user does not need an access.ilm file on his computer.

See the following classes in the ILOG OPL Component Libraries Reference Manual:

◆ OPLsolver (C++ and Java) or IOPLsolver (COM/ActiveX)

◆ OPLscriptSolver (C++ and Java) or IOPLscriptSolver (COM/ActiveX).

To use compiled models (.opl files) generated by OPL Studio

To use interpreted models (.mod files)

To use interpreted scripts (.osc files)

COM, C++, or Java APIs

Keys for the underlying libraries (Solver 5, Scheduler 5 or CPLEX 8), as required by the model

◆ Key OPLinterpreter 3 orOPLStudio 3

◆ Keys for the underlyinglibraries (Solver 5,Scheduler 5 or CPLEX 8),as required by the model

◆ Key OPLinterpreter 3 orOPLStudio 3

◆ Keys for the underlyinglibraries (Solver 5,Scheduler 5 or CPLEX 8),as required by the model

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 11

Page 12: OPL studio 3.7 Component Libraries User’s Manual

L I C E N S I N G R E Q U I R E M E N T S

12 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 13: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Arch

itecture o

f the

OP

L C

om

po

nen

ts

1

Architecture of the OPL Components

◆ The OPL Studio engine is available as an independent component via three APIs:

● a COM/ActiveX API, provided through COM (Microsoft Component Object Model) wrappers

● a C++ API, which is a native C++ library enabling you to access the underlying algorithmic library objects

● a Java API, provided through JNI (Java Native Interface) wrappers.

◆ The OPL Component Library provides two main objects:

● OPLsolver solves a single OPL model and provides accessors to interfaces on the problem objects and the solution.

● OPLscriptSolver runs OPLScript, which handles multiple models.

◆ The OPL Studio IDE is itself statically linked to the OPL C++ library.

Figure 1 shows how the OPL engine can be integrated from your application, outside the OPL Studio environment.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 11

Page 14: OPL studio 3.7 Component Libraries User’s Manual

Figure 1.1

Figure 1.1 Architecture of the OPL Component Libraries

12 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 15: OPL studio 3.7 Component Libraries User’s Manual

L O C A T I O N O F C O M P O N E N T L I B R A R I E S

Arch

itecture o

f the

OP

L C

om

po

nen

ts

Location of Component Libraries

The table below indicates the location for the various OPL component libraries. Each path name should be preceded by <installation-directory>, representing the directory in which you have installed OPL Studio.

Table 1.1 OPL Component Libraries and their Locations

C++ API Java API COM/ActiveX API

C++ Static Libraryopl

C++ Dynamic Library for JNIopljni

C++ Dynamic Library for COMoplServer

Windows32 lib/msvc6/stat_mda/opl.liblib/x86_.net2003_7.1/stat_mda

lib/msvc6/dll_mda/opljni.dll bin/oplServer.dll

Windows64 ia64_.net2003_7.1/stat_mda Not Applicable Not Applicable

Solaris lib/ultrasparc32_8_6.2/static_pic_mt/libopl.a

lib/ultrasparc32_8_6.2/shared_mt/libopljni.so

Not Applicable

Linux lib/i86_linux2_glibc2.3_gcc3.2/static_pic_mt/libopl.a

lib/i86_linux2_glibc2.3_gcc3.2/shared_mt/libopljni.so

Not Applicable

You need to link with Solver, Scheduler, CPLEX, Concert, Hybrid and DB Link.On Windows you also need the the cplex .dll file.

The Java wrappers are located in classes/opljni.jarOn Windows you also need the the cplex .dll file.

You also need the cplex .dll file, which is located in the bin directory.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 13

Page 16: OPL studio 3.7 Component Libraries User’s Manual

L O C A T I O N O F C O M P O N E N T L I B R A R I E S

14 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 17: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith O

PL

fro

m V

isual B

asic

2

Interfacing with OPL from Visual Basic viathe COM API

This chapter illustrates how to use the OPL COM component from an application developed with Microsoft Visual Basic 6.0. It explains some of the Visual Basic examples that are part of the distribution, and shows how you can create your own Visual Basic application that has access to the OPL engine.

A working knowledge of Microsoft Visual Basic 6.0 is a prerequisite.

◆ In the first example (bridge.vbp) you will see how to:

● Set a reference to the OPLServer type library in your Visual Basic project

● Interact, from your Visual Basic project, with the OPL engine in order to load and solve models, obtain computation results and access OPL data structures

● Handle errors that may occur during the interaction with the OPL engine.

◆ In the second example (mulprod.vbp) you will see how to:

● Solve several instances of a model

● Modify instance data inside a loaded OPL model.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 15

Page 18: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

The Bridge Example

This example involves finding a schedule that minimizes the time needed to build a five-segment bridge.

The problem contains a set of 46 tasks and a set of constraints within these tasks. Most tasks require a resource (e.g. a crane), and tasks requiring the same resource cannot overlap in time. In addition, several other constraints must be satisfied, as explained in detail in the ILOG OPL Studio: Language Manual, Section 15.3.2.

If you are not already familiar with the bridge example, you can access it from OPL Studio, as a preliminary step, by launching the project bridge.prj located in the installation directory (here called <OPLDIR>:

<OPLDIR>\examples\opl\scheduler

Now you can create a simple Visual Basic application that will:

◆ solve the bridge problem

◆ output the objective value together with the computed schedule

◆ catch errors that may occur during the interaction with the OPL engine.

You can also look at the complete Visual Basic project bridge.vbp delivered with your distribution, and located in the directory:

<OPLDIR>\OPLSt37\examples\component\com\vb

Start the project by double-clicking on the file bridge.vbp in Windows Explorer.

Creating a Visual Basic Project that Refers to the OPL Component

Take the following steps to create a Visual Basic project and set a reference to the OPL component in the project.

1. Start Visual Basic and choose the Standard EXE option.

2. In Form1, draw a command button and a text box. In the Properties panel, set their properties as follows:

Object Command1

Name: ClickMe

Caption: Click Me

16 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 19: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E B R I D G E E X A M P L E

Object Text1

Your form should look like this:

Name: Output

Text: (leave blank)

ScrollBars: 2 - Vertical

MultiLine: True

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 17

Page 20: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

3. Since you want to use the OPL component, you need to set a reference to it within Visual Basic. Select Project>References from the Visual Basic menu, then select the appropriate OPLServer type library and press OK.

Information on the compatible versions of the OPLServer type library is given in the file component.txt, distributed with OPL Studio. This file can be found in the installation directory <OPLDIR>\examples\component.

18 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 21: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E B R I D G E E X A M P L E

4. At any moment you can visualize the COM interface exposed by the OPL component, by using the Object Browser within Visual Basic (launch it either from the View menu or by pressing the F2 key).

From the Object Browser choose OPLCOMLib, then click, for instance, on the class COPLSolver in order to see its members.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 19

Page 22: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

5. Double-click the command button on the form you created and enter the code of the example in the code entry box. The complete bridge example can be found on page 25.

To avoid typing the example, you can copy the code displayed when you double-click on the project bridge.vbp, and then make the following changes:

● delete the lines concerning error reporting

Dim reporter As MyReporterSet reporter = New MyReporterCall solver.setErrorReporter(reporter)

● for theModel and theData arguments, adjust the path name in the strings to your own installation.

6. Save the form and the project with the name of your choice.

7. Run the application by clicking on the start button in the tool bar. Then click on the Click Me button in the frame.

The text box in Form1 should look like this:

20 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 23: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E B R I D G E E X A M P L E

Examining the Bridge Example

Here we look more closely at the example, highlighting particular points of interest, to explain in detail how to use the OPL component. You can also consult the complete bridge example on page 25.

Creating a COPLsolver Instance

In order to interact with the OPL engine, first allocate and instantiate a reference to COPLsolver:

Dim solver As COPLsolverSet solver = New COPLsolver

Loading a Model and its Data

Another interesting instruction is:

Call solver.loadInterpretedModelFileAndDataFile(theModel, theData, 1)

where:

◆ the argument theModel is a character string that provides the name of the file containing the OPL model for the bridge problem. For a typical installation, this string is:

"C:\Ilog\OPLSt37\examples\opl\scheduler\bridge.mod"

◆ the argument theData is a character string that provides the name of the file containing the data for the bridge model. For a typical installation, this string is:

"C:\Ilog\OPLSt37\examples\opl\scheduler\bridge.dat"

◆ the integer constant 1, as third argument, indicates that the model is loaded in edit mode.

The subsequent method calls on the object solver will refer to the loaded model.

Solving the Model and Obtaining the Optimal Objective

The model is solved to optimality by calling the member function solve of the object solver:

Dim result As Longresult = solver.solve

Next, we use the member function getObjectiveValueInt to obtain the value of the objective:

If result = 1 Then Dim obj As Long obj = solver.getObjectiveValueInt

Note: You can create several instances of COPLsolver in the same application.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 21

Page 24: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Printing the Solution

To print out the computed optimal schedule, we need to access the start time and the duration of each activity in the bridge project. Remember that in the OPL model the activities are grouped in an array called a, indexed by the enumeration Task which provides the names of the activities:

enum Task ...;..Activity a[t in Task](duration[t]);

In order to access each activity we will iterate, from the Visual Basic code, over the elements of the OPL enumeration Task and then use these elements as indexes in the array of activities.

Referring to an Array in the OPL Model

We continue by creating the object activities of the class IOPLarray which will later allow us to refer to the OPL array a from the Visual Basic code. This object is obtained by calling the member function getArray on the object solver:

Dim activities As IOPLarraySet activities = solver.getArray("a")

Referring to an OPL Enumeration

The object task of the class IOPLenum refers to the OPL enumeration Task. This object is obtained by calling the member function getEnum on the object solver.

Dim task As IOPLenumSet task = solver.getEnum("Task")

The number of elements in the enumeration is provided by the member function getCard on the object task:

Dim nbTasks As LongnbTasks = task.getCard

Iterating Over an OPL Enumeration

◆ To determine the elements of the OPL enumeration Task, we create an iterator object, ite, of the class IOPLenumIterator:

Dim ite As IOPLenumIteratorSet ite = task.getIterator

◆ Once the iterator has been created, we can use it to loop over the elements of the enumeration and hence access each activity. An OPL activity is referred to from Visual Basic as an object of the class IOPLactivity.

With ite, we perform a loop as long as the iterator does not point "past the end" of the enumeration:

22 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 25: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E B R I D G E E X A M P L E

Do While .ok = 1

◆ Obtain a reference c to the enumeration element currently pointed to by the iterator:

Dim c As IOPLenumValueSet c = .get

◆ Obtain a reference to the activity of index c:

Dim act As IOPLactivitySet act = activities.getActivity(c)

◆ Access the start time and the duration of the current activity. The activity’s name is provided by the name of the current enumeration element referred to by c:

out = out & "Activity '" & c.getName & "'"out = out & " starts at " & act.getStartout = out & " with duration " & act.getDuration & vbCrLf

◆ Ensure that the memory referred to by the temporary index c is released:

Set c = Nothing

◆ Advance the iterator to the next element of the enumeration:

.Next Loop End With

Closing the COPLsolver Instance

At the end of the application you must ensure that a call is made to the member function Close on the object solver. This member function is responsible for releasing memory.

solver.Close

Handling Errors

Errors may occur during the interaction with the OPL engine. These errors are classified as follows:

◆ syntax errors occurring during the loading of an OPL model or data file

◆ semantic errors detected in the loaded model

◆ runtime errors detected while solving the loaded model, or accessing data items

◆ internal errors (if any).

You can handle these errors from the Visual Basic application. To do so, you must define a new class that implements the interface class IOPLerrorReporter.

In our project, we create a new class module (by selecting Add Class Module from the Project menu) whose Name property is MyReporter. This class implements the class

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 23

Page 26: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

IOPLerrorReporter by redefining the member functions notifyInternalError, notifyRuntimeError, notifySemanticError, and notifySyntaxError.

Each time an error is raised by the OPL engine we want a message box, containing the error message and the line number, to pop up:

Code Sample 2.1Implements IOPLerrorReporter

Private Sub IOPLerrorReporter_notifyInternalError(ByVal msg As String)MsgBox "Internal Error : " & msgScreen.MousePointer = vbNormalEnd Sub

Private Sub IOPLerrorReporter_notifyRuntimeError(ByVal line As Long, ByVal msg As String)MsgBox "Runtime Error : line " & line & " : " & msgScreen.MousePointer = vbNormalEnd Sub

Private Sub IOPLerrorReporter_notifySemanticError(ByVal line As Long, ByVal msg As String)MsgBox "Semantic Error : line " & line & " : " & msgScreen.MousePointer = vbNormalEnd Sub

Private Sub IOPLerrorReporter_notifySyntaxError(ByVal line As Long, ByVal msg As String)MsgBox "Syntax Error : line " & line & ": " & msgScreen.MousePointer = vbNormalEnd Sub

Code Sample 2.1 Implementing an Error Reporter in Visual Basic

Setting an Error Reporter

We can now modify the code of the application in order to take into account our specific error handling mechanism. For that, in the code associated with the ClickMe button you should:

◆ create a new object of the class MyReporter:

Dim reporter As MyReporterSet reporter = New MyReporter

◆ set the reporter on the solver object:

Call solver.setErrorReporter(reporter)

Insert the above three new lines of code after the creation of the solver object., i.e. after:

Set solver = New COPLsolver

To test the example, you can edit the bridge.mod file and provoke an error. For instance, replace, in line 7 of the model, the identifier Task with TaskX. The line now reads:

TaskX before;

24 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 27: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E B R I D G E E X A M P L E

Rerun the example and click on the Click Me button.

Upon error detection, the execution flow is transferred to the IOPLerrorReporter_notifySemanticError subroutine and a message box appears:

The Complete Bridge Example

Code Sample 2.2Private Sub ClickMe_Click()On Error GoTo ErrExitDim solver As COPLsolverSet solver = New COPLsolverDim reporter As MyReporterSet reporter = New MyReporterCall solver.setErrorReporter(reporter)Dim theModel As StringDim theData As String'Be sure to adjust the paths below to your actual installationtheModel = "../../../../examples/opl/scheduler/bridge.mod"theData = "../../../../examples/opl/scheduler/bridge.dat"Dim out As StringWith solver Call .loadInterpretedModelFileAndDataFile(theModel, theData, 1) Dim result As Long result = .solve If result = 1 Then Dim obj As Long obj = .getObjectiveValueInt out = out & "Objective: " & obj & vbCrLf Dim activities As IOPLarray Set activities = .getArray("a") Dim task As IOPLenum Set task = .getEnum("Task") Dim nbTasks As Long nbTasks = task.getCard out = out & "Number of activities: " & nbTasks & vbCrLf Dim ite As IOPLenumIterator Set ite = task.getIterator out = out & vbCrLf With ite

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 25

Page 28: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Do While .ok = 1 Dim c As IOPLenumValue Set c = .get Dim act As IOPLactivity Set act = activities.getActivity(c) out = out & "Activity '" & c.getName & "'" out = out & " starts at " & act.getStart out = out & " with duration " & act.getDuration & vbCrLf Set c = Nothing .Next Loop End With Else out = out & "No solution" End IfEnd WithOutput.Text = out & vbCrLf & "Done"solver.CloseExit SubErrExit: MsgBox "Oops..." Screen.MousePointer = vbNormalEnd Sub

Code Sample 2.2 Complete Bridge Example in Visual Basic

26 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 29: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E M U L T I P R O D U C T I O N E X A M P L E

The Multiproduction Example

The Visual Basic example mulprod.vbp illustrates how you can solve several instances of a model. By following this example you will see how to modify instance data inside a loaded OPL model. This functionality is valuable when performing various forms of sensitivity analyses or executing "what-if" scenarios on a model.

This example works with the linear model:

<OPLDIR>\OPLSt37\examples\opl\scripts\mulprod.mod

which solves a multi-period production planning problem.

The Visual Basic code solves various instances of this model. In each instance the capacity of one of the resources is different. The basic idea is to increase the capacity of the resource flour and to determine the effect on the objective function.

This application is very similar in functionality to the distributed OPL script mulprod.osc explained in the ILOG OPL Studio: Language Manual, Section 16.2. If you are not already familiar with this OPL script, as a preliminary step you can launch it from OPL Studio by accessing the file:

<OPLDIR>\OPLSt37\examples\opl\scripts\mulprod.osc

You can now start the Visual Basic project from Windows Explorer by double-clicking on the file mulprod.vbp. As the example is using Debug.Print instructions, make sure that the Immediate Window is visible in VB and reasonably sized.

Examining the Multiproduction Example

Once the VB project has started, look at the code associated with the ClickMe button. (You can also consult the complete multiproduction example on page 30.)

Creating a COPLsolver Instance

First, a new instance of COPLsolver is created and an error reporter is associated with it (see the bridge example on page 21 for a complete explanation):

Dim solver As COPLsolverSet solver = New COPLsolverDim reporter As MyReporterSet reporter = New MyReporterCall solver.setErrorReporter(reporter)

Next, a local variable capFlourValue is declared to store the current quantity of the resource flour to be set in the model:

Dim capFlourValue As LongcapFlourValue = 20

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 27

Page 30: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

Loading a Model and its Data

The multiproduction model, together with its initial data, is loaded into the solver object:

Call solver.loadInterpretedModelFileAndDataFile ("../../../../examples/opl/scripts/mulprod.mod", "../../../../examples/opl/scripts/mulprod.dat", 1)

Declaring the Data

The OPL engine constructs and initializes the data structures of the previously loaded model by calling the member function declareData:

solver.declareData

At this point, no solving process is taking place. After calling declareData, we can access and modify data items inside the model.

The following For loop modifies the capacity of the resource flour four times, and each time solves the model for the particular value of the resource:

Debug.Print vbCrLf & "********* Doing four computations *********"For i = 1 To 4

Accessing the Data

In order to modify the capacity of the resource flour, we need to obtain a reference to it from the Visual Basic code. Remember that in the OPL model, the capacities of the resources are stored in an integer array capacity, indexed by the enumeration Resources:

enum Resources ...;..int+ capacity[Resources] = ...;

In fact the enumeration Resources, as given by the data file, contains two values:

Resources = {flour eggs};

The following code obtains, from the IOPLint object capFlour, a reference to the OPL data item capacity[flour]:

Dim capacity As IOPLarraySet capacity = solver.getArray("capacity")Dim resources As IOPLenumSet resources = solver.getEnum("Resources")Dim flour As IOPLenumValueSet flour = resources.getValue("flour")Dim capFlour As IOPLintSet capFlour = capacity.getInt(flour)

28 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 31: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m V

isual B

asicT H E M U L T I P R O D U C T I O N E X A M P L E

Modifying the Data

The member function IOPLint::setValue can then be used to set a new value for capFlour, thus modifying the value of the data item capacity[flour] inside the loaded OPL model:

Debug.Print "flour capacity set to: ", capFlourValueCall capFlour.setValue(capFlourValue)

Solving the Problem and Accessing the Result

Once the current capacity for the resource flour is set, we solve the problem to optimality:

solver.solve

then we obtain the objective value:

Dim obj As Doubleobj = solver.getObjectiveValueFloatDebug.Print "objective is: ", obj

We also access the number of simplex iterations needed to solve the linear program represented by the multi-production model:

Debug.Print "iterations: ", solver.getNumberOfIterations

Resetting the Model

The call:

solver.Reset

re-initializes the loaded model, thus preparing it for the next access / modification / solve loop, with the flour capacity increased by one.

capFlourValue = capFlourValue + 1Next i

Closing the COPLsolver Instance

Finally, the solver object must be closed, in order to ensure proper memory release.

solver.CloseEnd Sub

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 29

Page 32: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

The Complete Multiproduction Example

Code Sample 2.3Private Sub ClickMe_Click()Dim solver As COPLsolverSet solver = New COPLsolverDim reporter As MyReporterSet reporter = New MyReporterCall solver.setErrorReporter(reporter)Dim capFlourValue As LongcapFlourValue = 20Call solver.loadInterpretedModelFileAndDataFile ("../../../../examples/opl/scripts/mulprod.mod", "../../../../examples/opl/scripts/mulprod.dat", 1)solver.declareDataDebug.Print vbCrLf & "********* Doing four computations *********"For i = 1 To 4 Dim capacity As IOPLarray Set capacity = solver.getArray("capacity") Dim resources As IOPLenum Set resources = solver.getEnum("Resources") Dim flour As IOPLenumValue Set flour = resources.getValue("flour") Dim capFlour As IOPLint Set capFlour = capacity.getInt(flour) Debug.Print "flour capacity set to: ", capFlourValue Call capFlour.setValue(capFlourValue) solver.solve Dim obj As Double obj = solver.getObjectiveValueFloat Debug.Print "objective is: ", obj Debug.Print "iterations: ", solver.getNumberOfIterations solver.Reset capFlourValue = capFlourValue + 1Next isolver.CloseEnd Sub

Code Sample 2.3 Complete Multiproduction Example in Visual Basic

30 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 33: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith O

PL

fro

m C

++ via CO

M

3

Interfacing with OPL from C++ via the COMAPI

Here we provide an example of how to use the COM component from a C++ application.

Nevertheless, we suggest that you use the native C++ API, rather than this COM API, as it is simpler and gives you more flexibility (for example, the generic C++ API allows access to the underlying libraries). For information on the generic API, see Chapter 6, Interfacing with OPL from C++.

The COM/ActiveX example can be found in:

<OPLDIR>\examples\component\com\c++\bridge.cpp

Note: You can build this example outside the Visual Studio environment, by typing a DOS shell:

cl \GX \I..\..\..\..\include bridge.cpp ole32.lib user32.lib

You do not need to link with the opl.lib file.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 31

Page 34: OPL studio 3.7 Component Libraries User’s Manual

#include <stdio.h>#include <windows.h>// Include IDL-generated header files:#include <ilopl/oplitf.h>#include <ilopl/oplitf_i.c>#include <assert.h>

class MyErrorReporter : public IOPLerrorReporter { long _count; // COM works with reference countingpublic: MyErrorReporter() : IOPLerrorReporter(), _count(0) {}

// IOPLerrorReporter methods virtual STDMETHODIMP notifyInternalError (BSTR msg) { MessageBox(0, bstrToChar(msg), "bridge internal error", MB_OK); return S_OK; } virtual STDMETHODIMP notifyRuntimeError (int line, BSTR msg) { MessageBox(0, bstrToChar(msg), "bridge runtime error", MB_OK); return S_OK; } virtual STDMETHODIMP notifySemanticError (int line, BSTR msg) { MessageBox(0, bstrToChar(msg), "bridge semantic error", MB_OK); return S_OK; } virtual STDMETHODIMP notifySyntaxError (int line, BSTR msg) { MessageBox(0, bstrToChar(msg), "bridge syntax error", MB_OK); return S_OK; }

// IUnknown methods virtual STDMETHODIMP_(ULONG) AddRef (void); virtual STDMETHODIMP_(ULONG) Release (void); virtual STDMETHODIMP QueryInterface(REFIID riid, void **ppv);

private: virtual ~MyErrorReporter() {} // protected to ensure that no client can delete it directly char* bstrToChar(BSTR msg) { const wchar_t* str = msg; int reqSize = wcslen(str); char* cstr = new char[reqSize+1]; if (cstr) { wcstombs(cstr,str,reqSize+1); } return cstr; }};

32 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 35: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m C

++ via CO

M

// Implementation of IUnknown:STDMETHODIMP_(ULONG) MyErrorReporter::AddRef (void) { return InterlockedIncrement(&_count); // instead of ++_count because of multithtreading concerns}

STDMETHODIMP_(ULONG) MyErrorReporter::Release (void){ LONG res = InterlockedDecrement(&_count); // instead of --_count because of multithtreading concerns if (res == 0) delete this; return res;}

STDMETHODIMP MyErrorReporter::QueryInterface(REFIID riid, void **ppv){ assert(ppv != 0); if (riid == IID_IOPLerrorReporter) // this value is defined in oplitf_i.c *ppv = static_cast<IOPLerrorReporter*>(this); else { // unsupported interface *ppv = 0; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK;}

int main(){ IOPLsolver* solver = 0; HRESULT hr = CoInitialize(0); if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_COPLsolver,0,CLSCTX_ALL, IID_IOPLsolver,(void **)&solver); if (SUCCEEDED(hr) && solver) { MyErrorReporter* errorReporter = new MyErrorReporter; IOPLerrorReporter* ierrorReporter = 0; hr = errorReporter->QueryInterface(IID_IOPLerrorReporter, reinterpret_cast<void**>(&ierrorReporter)); if (SUCCEEDED(hr)) { solver->setErrorReporter(ierrorReporter); hr = solver->loadInterpretedModelFileAndDataFile( L"..\\..\\..\\opl\\scheduler\\bridge.mod", L"..\\..\\..\\opl\\scheduler\\bridge.dat", 0); if (SUCCEEDED(hr)) { int solutionFound = 0; hr = solver->solve(&solutionFound); if (SUCCEEDED(hr) && solutionFound) { int objectiveValue = 0; hr = solver->getObjectiveValueInt(&objectiveValue); if (SUCCEEDED(hr)) { char message[1024]; sprintf(message, "Objective = %d", objectiveValue); MessageBox(0, message, "bridge", MB_OK); }

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 33

Page 36: OPL studio 3.7 Component Libraries User’s Manual

} } ierrorReporter->Release(); } solver->close(); solver->Release(); } CoUninitialize(); } return !(SUCCEEDED(hr));}

34 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 37: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g fro

m

Scrip

ting

Lan

gu

ages

4

Interfacing with OPL from ScriptingLanguages

This chapter provides examples of interfacing with the OPL engine from:

◆ VBScript

◆ Microsoft JScript

◆ HTML

◆ Active Server Pages (ASP)

The first example, generic.html, shows the interaction between OPL ActiveX and scripting languages such as VBScript and JScript. This example works offline (locally), in Internet Explorer. Note that this example is for pedagogical purposes only, for the case where you do not have a web server available. For deployment of your application, you should consider the genericServer.html example, which uses OPL ActiveX in a centralized web server.

The second example, using the files genericServer.html and genericServer.asp, shows how to integrate OPL ActiveX into a web server. The server is on Windows, and the client can be any machine running any browser.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 35

Page 38: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G T H E O P L S O L V E R C O M P O N E N T F R O M S C R I P T I N G L A N G U A G E S

Calling the OPL Solver Component from Scripting Languages

The generic sample shows you how to call the COM/ActiveX component from scripting languages such as VBScript and JScript in a web browser on the client side. To run the sample you need the key OPLStudio or OPLinterpreter, the Solver key and the Microsoft browser Internet Explorer.

For this example to work, the OPL ActiveX must be registered in the Windows registry. This is done automatically by InstallShield on the machine on which OPL Studio is installed.

To use OPL ActiveX on another machine:

◆ Type the command regsvr32 /s oplServer.dll in a DOS window to register the oplServer.dll on the new machine.

◆ Copy the CPLEX .dll file to the new machine and update the PATH variable so that it references this file.

◆ Ensure that you have the right licenses (see Licensing Requirements in the Preface).

Note: The PATH variable on the new machine must contain the paths to oplServer.dll and the CPLEX .dll file.

36 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 39: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g fro

m

Scrip

ting

Lan

gu

ages

C A L L I N G T H E O P L S O L V E R C O M P O N E N T F R O M S C R I P T I N G L A N G U A G E S

Proceed as follows:

1. Open MS Internet Explorer and click Open File. Select the file: <OPLDIR>\examples\component\com\script\generic.html

2. Click on Solve through JavaScript.

3. If a dialog box advises you not to run ActiveX, click Yes to force the use of ActiveX.

4. You will obtain the following result:

5. You can also click on Solve through VBScript to obtain the same result.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 37

Page 40: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G T H E O P L S O L V E R C O M P O N E N T F R O M S C R I P T I N G L A N G U A G E S

Examining the JScript Code

In MS Internet Explorer, select View>Source. In the HTML code, look first at the following section:

<!-- JScript example -->

<script language=JavaScript> function errorHandler(message, url, line) { alert(message); return true; }

function solveModel() { // install the global error-handler window.onerror = errorHandler;

var theModel = document.MODEL.MODEL_BUFFER.value;

var solver = new ActiveXObject("COPLsolver.solverMeta.7");

solver.loadInterpretedModelBuff(theModel,1); var result = solver.solve(); if (result) document.RESULT.RESULT_BUFFER.value = "Solving through JavaScript:\n" + solver.display(); else document.RESULT.RESULT_BUFFER.value = "Error: no solution found"; } </script>

As you can see the variables are totally untyped.

You instantiate a COPLsolver object by calling a new ActiveXObject("COPLsolver.solverMeta.7").

The last number refers to the minor version. The result is stored in the solver variable.

You can then call the methods on the instance.

To load the content of the buffer in which the model has been typed, call:

solver.loadInterpretedBuff(theModel,1);

where theModel is a string containing the model.

Note: The ActiveXObject keyword is accessible from JScript the MS implementation of JavaScript. This code may not work on a Netscape browser without plug-ins.

38 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 41: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g fro

m

Scrip

ting

Lan

gu

ages

I N S T A N T I A T I N G F R O M H T M L

To solve the model, call the solve method:

var result = solver.solve();

To display the result in a generic way, call solver.display() and put the result in the result buffer.

Examining the VBScript Code

In the HTML code, look at the following section:

</script>

<!-- VBScript example --> <script language = "VBScript"> Sub SolveVBScript_OnClick() Dim solverVBS Set solverVBS = CreateObject("COPLsolver.solverMeta.7") Dim buffer Call solverVBS.loadInterpretedModelBuff(MODEL.MODEL_BUFFER.value,1) solverVBS.solve() RESULT.RESULT_BUFFER.value = "Solving through VBScript:" & vbCrLf & solverVBS.display() End Sub </script>

Note the difference with the Visual Basic code shown in Chapter 2, Interfacing with OPL from Visual Basic via the COM API.

Dim solverVBS Set solverVBS = CreateObject("COPLsolver.solverMeta.7")

The variable declared is totally untyped. You instantiate the COPLsolver object through the CreateObject call, passing a string as parameter. The last number refers to the minor version.

Instantiating from HTML

You can instantiate the object from HTML and manipulate it in JScript afterwards.

<OBJECT ID="solver" CLASSID="Clsid:ba54d0f8-6dde-11d4-a9d1-00c04f68a8a8"> </OBJECT>

A solver variable is created. This variable contains an instance of the COPLsolver object corresponding to a class identifier (CLSID) that is a globally unique id referring to the current version of the COPLsolver component.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 39

Page 42: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G T H E O P L S O L V E R F R O M A N A S P S C R I P T O N T H E S E R V E R S I D E

Calling the OPL Solver from an ASP Script on the Server Side

You can easily embed the OPL COM Component in an Active Server Page on a Microsoft Web Server. See the example given in:

<OPLDIR>\examples\component\com\script\genericServer.html

and:

<OPLDIR>\examples\component\com\script\genericServer.asp

You need a Microsoft Web Server, such as the MS Internet Information Server (MS IIS), to run the example.

With the Windows 2000 Professional Edition, you can also install MS IIS. If it is not yet installed on your Windows 2000 Professional Edition, you must open the Control Panel, double-click on Add/Remove Programs and then click on Add/Remove Components. In the dialog window, check the Microsoft IIS box.

With the Windows NT 4 Workstation system you can install the Windows NT Option Pack 4.0 to run tests (limited to 10 connections).

1. Make sure the OPL COM component is registered in the registry of your server. It is automatically registered if you used the InstallShield archive on your server, otherwise copy the file <OPLDIR>\bin\oplServer.dll to your server disk and type in the following command on a DOS prompt:

regsvr32 /s oplServer.dll

(You must copy all the dynamic libraries provided in <OPLDIR>\bin to the directory in which you installed oplServer.dll).

2. Create a new MS IIS virtual directory that points to the example location:

OPLDIR>\examples\component\com\script

This physical directory contains the genericServer.html and genericServer.asp files. In this example we assume that you call your virtual directory myVirtualDirectory.

3. Install the file access.ilm on your server hard disk in:

c:\ilog\ilm\access.ilm

With this file, install the following NODE or EVAL type keys:

● OPLStudio key for development

● OPLinterpreter key for deployment (This is because, for this specific example, you use the interpreted model APIs, i.e the methods beginning with loadInterpretedXXX. You don't need this key with compiled model APIs, i.e. the methods beginning with loadCompiledXXX). You can use the

40 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 43: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g fro

m

Scrip

ting

Lan

gu

ages

C A L L I N G T H E O P L S O L V E R F R O M A N A S P S C R I P T O N T H E S E R V E R S I D E

registerOplLicense method in the OPLsolver object for this purpose when deploying, and thus avoid the need for an access.ilm file.

● Library keys required by your model. (Here Solver is enough.)

4. Run your web server

With the Windows 2000 Professional Edition: open the Control Panel inside the Administrative Tools category and double-click on Computer Management. In the window, expand the item Services and Applications, then expand Internet Information Server, and finally expand Default Web Server. Right-click on myVirtualDirectory and select the Properties menu item.

Make sure that the Read box is checked. Select Default Web Server from the tree, and click on the Start Item button in the tool bar.

On Windows NT 4.0: use the commands Start Menu>Programs>Windows NT 4.0 Option Pack>Microsoft Personal Web Server>Internet Service Manager.

Warning: Do not install TOKEN type keys because you need multithread safety on a Web Server, and the ILOG License Manager (ILM) is not multithread safe when dealing with TOKEN keys.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 41

Page 44: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G T H E O P L S O L V E R F R O M A N A S P S C R I P T O N T H E S E R V E R S I D E

The Management Console opens. Select Internet Information Server from the tree structure and expand <Your machine name>/Default Web Site. Right-click on the myVirtualDirectory item and select the properties menu item. Ensure that the Read box is checked. Select Default Web Server from the tree, and click on the Start Item button in the tool bar.

If you use your own machine as both server and client you can access the genericServer.html file at the following location:

http://localhost/myVirtualDirectory/genericServer.html

In the following screen capture, the machine name is aragon and the virtual directory is renoir.

Click on the Solve (ASP Script) button. A new HTML page is generated dynamically by the genericServer.asp page, which is executed on the server side. It contains the following result:

42 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 45: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g fro

m

Scrip

ting

Lan

gu

ages

C A L L I N G T H E O P L S O L V E R F R O M A N A S P S C R I P T O N T H E S E R V E R S I D E

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 43

Page 46: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G T H E O P L S O L V E R F R O M A N A S P S C R I P T O N T H E S E R V E R S I D E

Examining the ASP Script Code

<%@ Language=VBScript %>

<!-- genericServer.asp This sample shows the usage of the OPL COM Component on the server side, using the Microsoft ASP Scripting Technology. It solves a generic problem on the server and dynamically generates an HTML page on the client. The Active Server Page instantiates the OPL COM component on the server side. You need a Web Server such as Microsoft IIS to use ASP, and the OPL COM Component must be registered on the Windows Server. --> <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="Mozilla/4.75 [en] (WinNT; U) [Netscape]"> </head> <%@ LANGUAGE = "VBScript" %> <% MODELGENERIC = Request.Form("modelgeneric") %> <% DATA = Request.Form("Data") %> <body> <img SRC="opl.gif" ALT="OPL icon"><img SRC="com.gif" ALT="COM icon"> <b>GENERIC SOLVER SAMPLE</b> <br>&nbsp; <CENTER><P><B><FONT COLOR="#FF9933">Here, the result:</FONT></B></P></CENTER> <% Dim solver %> <% Set solver = Server.CreateObject("COPLsolver.solverMeta.7")%> <% Call solver.loadInterpretedModelBuffAndDataBuff(MODELGENERIC,DATA,1) %> <% IF solver.solve() THEN %> <center><table BORDER COLS=300 WIDTH=150 HEIGHT=30> <tr><td> <TEXTAREA COLS=40 ROWS=8 WIDTH=200 HEIGHT=25><%Response.Write(solver.display())%> </TEXTAREA></TD> </TR></TABLE></CENTER> <% ELSE%> <TEXTAREA COLS=60 ROWS=16 HEIGHT=25 > <%Response.Write("No solution found")%></TEXTAREA> <% END IF %> <% Call solver.close() %>

The main difference with the previous example is that you use predefined Microsoft objects called Request, Server and Response to do the job. These objects are instantiated for you by the web server.

44 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 47: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith O

PL

from

Excel V

BA

5

Interfacing with OPL from Excel VBA

You can install the OPL ActiveX from the Excel scripting language, Visual Basic for Applications (VBA). OPL can also read and write an Excel spreadsheet via the keywords SheetConnection, SheetRead, and SheetWrite. For that purpose, OPL uses a Microsoft ActiveX. You must have Excel 1997 or Excel 2000 installed on your computer.

In this chapter you will learn how OPL interacts with Excel. You’ll need a CPLEX key when using the VBA sample.

The sample calls the OPL ActiveX from Excel and the OPL ActiveX calls back the Excel sheet to read the data. The Excel VBA code obtains the result by using accessors on the OPL ActiveX.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 45

Page 48: OPL studio 3.7 Component Libraries User’s Manual

G E N E R A T I N G A C O M P I L E D M O D E L F I L E

Generating a Compiled Model File

1. Open the following model file in OPL Studio:

examples\component\com\vb\transport.mod

2. In the code of the model, adapt the Excel file location to your installation.

3. Select the OPL Studio command Run to execute the model. The objective value is 6600.

4. Generate a compiled model file, transport.opl, using the OPL Studio commands:

File>Generate Compiled Model File.

5. Quit OPL Studio.

Solving the Model with Excel

1. Open the Excel file, transport.xls, by double-clicking on it from Windows Explorer.

2. Select the option “Enable Macros”. The following Excel sheet is displayed:

46 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 49: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

from

Excel V

BA

S O L V I N G T H E M O D E L W I T H E X C E L

3. In the Excel sheet:

● adapt the path of the transport.opl file to your installation

● save the Excel file

● click on the button “Solve with OPL ActiveX”.

The objective value is now 6600.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 47

Page 50: OPL studio 3.7 Component Libraries User’s Manual

E X A M I N I N G T H E V B A C O D E

Examining the VBA Code

In the Excel sheet, select from the command menu:

Tools>Macro>Visual Basic Editor

The VBA code in transport.xls is displayed. You will see how the COPLsolver object is created and how the compiled model file is loaded. You will also see how the cells of the spreadsheet are filled with the result.

Code Sample 5.1Public Sub OPLsolverMacro()'' Example of use the OPL ActiveX from Excel' using VBA' On Error GoTo theEnd Application.ScreenUpdating = False ActiveWorkbook.Save Application.ScreenUpdating = True Range("B10", "E12").Clear ' Get the path to OPL file, ' assuming it is in the same directory as the Excel file Dim path As String path = ActiveWorkbook.path ' Get the Character Set of " Dim doublequote doublequote = String(1, 34) Dim dataBuff As String dataBuff = "location = " & doublequote & path & "\transport.xls" & doublequote & ";"

Dim opl As COPLsolver Set opl = New COPLsolver Call opl.loadCompiledModelFileAndDataBuff(path & "/transport.opl", dataBuff, 1)

Dim result As Long result = opl.solve If result = 1 Then Dim trans As IOPLarray Set trans = opl.getArray("trans") Dim Warehouses As IOPLenum Set Warehouses = opl.getEnum("Warehouses") Dim Customers As IOPLenum Set Customers = opl.getEnum("Customers") Dim itw As IOPLenumIterator Set itw = Warehouses.getIterator Dim itc As IOPLenumIterator Set itc = Customers.getIterator

48 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 51: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

from

Excel V

BA

E X A M I N I N G T H E V B A C O D E

Dim w As IOPLenumValue Dim c As IOPLenumValue Dim col As Long Dim row As Long Dim transC As IOPLarray Dim transVar As IOPLfloatVar For row = 10 To 12 Set w = itw.get() Set transC = trans.getArray(w) Call itc.Reset For col = 2 To 5 Set c = itc.get() Set transVar = transC.getFloatVar(c) Cells(row, col).Value = transVar.getValue() Call itc.Next Next Call itw.Next Next Cells(16, 2).Value = opl.getTime Else MsgBox "No Solution found!", vbCritical End If Call opl.Close Exit SubtheEnd: MsgBox "An error occured!", vbCriticalEnd Sub

Code Sample 5.1 The VBA Code for the Transport Model

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 49

Page 52: OPL studio 3.7 Component Libraries User’s Manual

E X A M I N I N G T H E V B A C O D E

50 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 53: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith O

PL

fro

m C

++

6

Interfacing with OPL from C++

This chapter presents examples that illustrate how to use the C++ interface, provided by the OPL component, from a C++ application.

A working knowledge of C++ on Windows or UNIX platforms is a prerequisite.

◆ In the first example (bridge.cpp) you will see how to:

● Interact, from your C++ application, with the OPL engine in order to load and solve models, obtain computation results and access OPL data structures

● Handle errors that may occur during the interaction with the OPL engine.

◆ In the second example (mulprod.cpp) you will see how to:

● Solve several instances of a model

● Modify instance data inside a loaded OPL model.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 51

Page 54: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

The Bridge Example

This example involves finding a schedule that minimizes the time needed to build a five-segment bridge.

The problem contains a set of 46 tasks and a set of constraints within these tasks. Most tasks require a resource (e.g. a crane), and tasks requiring the same resource cannot overlap in time. In addition, several other constraints must be satisfied, as explained in detail in the ILOG OPL Studio: Language Manual, Section 15.3.2.

If you are not already familiar with this example, as a preliminary step you can access it from OPL Studio by launching the OPL project bridge.prj located in the directory:

<OPLDIR>/OPLSt37/examples/opl/scheduler

Solving the Bridge Problem with OPL from a C++ Application

The example below is based on the C++ source file bridge.cpp delivered with your distribution and located in the directory:

<OPLDIR>OPLSt37/examples/component/c++/src

By following this example you will see how to:

◆ solve the bridge problem from a C++ application

◆ output the objective value together with the computed schedule

◆ catch possible errors occurring during the interaction with the OPL engine.

Examining the Bridge Example

The complete example can be found on page 56. This example contains typical steps that enable you to use the OPL component in a C++ application.

Creating an OPLsolver Instance

In order to interact with the OPL engine, first create an object of the class OPLsolver:

OPLsolver solver;

Setting an Error Reporter

Error handling is ensured by creating a new object, called error reporter, of the class MyReporter, and by setting this object on the OPLsolver instance:

MyReporter reporter;solver.setErrorReporter(&reporter);

The class MyReporter is a user-defined class which inherits from the class OPLerrorReporter, as explained later in this example.

52 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 55: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

Loading a Model and its Data

Another interesting instruction is:

solver.loadInterpretedModelFileAndDataFile ("../../../../opl/scheduler/bridge.mod", "../../../../opl/scheduler/bridge.dat", 1);

where:

◆ the first argument is a character string that provides the name of the file containing the OPL model for the bridge problem

◆ the second argument is a character string that provides the name of the file containing the data for the bridge model

◆ the integer constant 1, as third argument, indicates that the model is loaded in edit mode.

The subsequent method calls on the object solver will refer to the loaded model.

Solving the Model and Obtaining the Optimal Objective

The model is solved to optimality by calling the member function solve of the object solver:

if(solver.solve()){

Next, we use the member function getObjectiveValueInt to obtain the value of the objective:

int obj = solver.getObjectiveValueInt();cout << "\nObjective: " << obj << endl;

The amount of time elapsed since the creation of the OPLsolver instance is obtained by calling the method getTime on the object solver:

double time = solver.getTime();cout << "Time: " << time << endl << endl;

Printing the Solution

To print out the computed optimal schedule, we need to access the start time and the duration of each activity in the bridge project. Remember that in the OPL model the activities are grouped in an array called a, indexed by the enumeration Task which provides the names of the activities:

enum Task ...;..Activity a[t in Task](duration[t]);

In order to access each activity we will iterate, from the C++ code, over the elements of the OPL enumeration Task and then use these elements as indexes in the array of activities.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 53

Page 56: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Referring to an Array in the OPL Model

We continue by creating the object activities of the class OPLarray which will later allow us to refer to the OPL array a from the C++ code. This object is obtained by calling the member function getArray on the object solver:

OPLarray activities = solver.getArray("a");

Referring to an OPL Enumeration

The object task of the class OPLenum makes a reference to the OPL enumeration Task. This object is obtained by calling the member function getEnum on the object solver.

OPLenum task = solver.getEnum("Task");

The number of elements in the enumeration is provided by the member function getCard on the object task:

int nbTasks = task.getCard();

Iterating over an OPL Enumeration

◆ To determine the elements of the OPL enumeration Task, we create an iterator object, ite, of the class OPLenumIterator:

OPLenumIterator ite = task.getIterator();

◆ Once the iterator has been created, we can use it to loop over the elements of the enumeration and hence access each activity.

We perform a loop, as long as the iterator does not point "past the end" of the enumeration. The member function next advances the iterator to the next element of the enumeration:

for(; ite.ok() == 1; ite.next()) {

◆ Obtain a reference c to the enumeration element currently pointed to by the iterator:

OPLenumValue c = ite.get();

◆ Obtain a reference to the activity of index c. An OPL activity is referred to from C++ as an object of the class OPLactivity.

OPLactivity act = activities.getActivity(c);

◆ Access the start time and the duration of the current activity. The activity’s name is provided by the name of the current enumeration element referred to by c.

cout << "Activity '" << c.getName() << "'";cout << " starts at " << act.getStart();cout << " with duration " << act.getDuration() << endl;

54 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 57: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

Closing the OPLsolver Instance

At the end of the application you must ensure that a call is made to the member function Close on the object solver. This member function is responsible for releasing memory.

solver.close();

Handling Errors

Errors may occur during the interaction with the OPL engine. These errors are classified as follows:

◆ syntax errors occurring during the loading of an OPL model or data file

◆ semantic errors detected in the loaded model

◆ runtime errors detected while solving the loaded model, or accessing data items

◆ internal errors (if any).

To handle these errors from the C++ application, you must define a new class that derives from the class OPLerrorReporter.

In our example this class is called MyReporter. It redefines the member functions notifyInternalError, notifyRuntimeError, notifySemanticError and notifySyntaxError. The error reporter created at the beginning of the example is an instance of this class.

Each time an error is raised by the OPL engine, an error message, together with the line number, is sent to the standard output:

Code Sample 6.1class MyReporter : public OPLerrorReporter { void notifySyntaxError(const OPLsyntaxError& err){ cout << "OPL syntax error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifySemanticError(const OPLsemanticError& err){ cout << "OPL semantic error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyRuntimeError(const OPLruntimeError& err){ cout << "OPL runtime error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyInternalError(const OPLinternalError& err){ cout << "OPL internal error : " << err.getMessage() << endl; }};

Code Sample 6.1 Implementing an Error Reporter in C++

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 55

Page 58: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

To test the example, you can edit the bridge.mod file and introduce an error. For instance, replace, in line 7, the identifier Task with TaskX. This line now reads:

TaskX before;

Rerun the example.

Upon error detection, the execution flow is transferred to the member function MyReporter::notifySemanticError and an error message is printed on the standard output device.

The Complete Bridge Example

Code Sample 6.2#include <ilsolver/ilcint.h>#ifdef ILUSESTL#include <iostream>#else#include <iostream.h>#endif#include <ilopl/oplcomponent.h>#include <ilopl/oplerror.h>

ILCSTLBEGIN

class MyReporter : public OPLerrorReporter { void notifySyntaxError(const OPLsyntaxError& err){ cout << "OPL syntax error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifySemanticError(const OPLsemanticError& err){ cout << "OPL semantic error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyRuntimeError(const OPLruntimeError& err){ cout << "OPL runtime error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyInternalError(const OPLinternalError& err){ cout << "OPL internal error : " << err.getMessage() << endl; }};

int main(){ int status = 0; OPLsolver solver; MyReporter reporter; solver.setErrorReporter(&reporter);

try{ solver.loadInterpretedModelFileAndDataFile ("../../../../opl/scheduler/bridge.mod", "../../../../opl/scheduler/bridge.dat", 1);

56 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 59: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

if(solver.solve()){ int obj = solver.getObjectiveValueInt(); double time = solver.getTime(); cout << "\nObjective: " << obj << endl; cout << "Time: " << time << endl << endl; OPLenum task = solver.getEnum("Task"); int nbTasks = task.getCard(); OPLarray activities = solver.getArray("a"); OPLenumIterator ite = task.getIterator(); for(; ite.ok() == 1; ite.next()) { OPLenumValue c = ite.get(); OPLactivity act = activities.getActivity(c); cout << "Activity '" << c.getName() << "'"; cout << " starts at " << act.getStart(); cout << " with duration " << act.getDuration() << endl; } }else { cout << "No solution found" << endl; } } catch(...){ cout << "An error occurred" << endl; status = -1; }

solver.close(); return status;}

Code Sample 6.2 Complete Bridge Example in C++

Output for the Bridge Example

Code Sample 6.3Objective: 104Time: 0.1600

Activity 'start' starts at 0 with duration 0Activity 'a1' starts at 4 with duration 4Activity 'a2' starts at 2 with duration 2Activity 'a3' starts at 8 with duration 2Activity 'a4' starts at 0 with duration 2Activity 'a5' starts at 13 with duration 2Activity 'a6' starts at 35 with duration 5Activity 'p1' starts at 19 with duration 20Activity 'p2' starts at 6 with duration 13Activity 'ue' starts at 0 with duration 10Activity 's1' starts at 10 with duration 8Activity 's2' starts at 6 with duration 4Activity 's3' starts at 39 with duration 4Activity 's4' starts at 22 with duration 4Activity 's5' starts at 18 with duration 4Activity 's6' starts at 43 with duration 10Activity 'b1' starts at 18 with duration 1Activity 'b2' starts at 10 with duration 1Activity 'b3' starts at 43 with duration 1Activity 'b4' starts at 26 with duration 1Activity 'b5' starts at 22 with duration 1

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 57

Page 60: OPL studio 3.7 Component Libraries User’s Manual

T H E B R I D G E E X A M P L E

Activity 'b6' starts at 53 with duration 1Activity 'ab1' starts at 19 with duration 1Activity 'ab2' starts at 11 with duration 1Activity 'ab3' starts at 44 with duration 1Activity 'ab4' starts at 27 with duration 1Activity 'ab5' starts at 23 with duration 1Activity 'ab6' starts at 54 with duration 1Activity 'm1' starts at 20 with duration 16Activity 'm2' starts at 12 with duration 8Activity 'm3' starts at 52 with duration 8Activity 'm4' starts at 44 with duration 8Activity 'm5' starts at 36 with duration 8Activity 'm6' starts at 60 with duration 20Activity 'l' starts at 30 with duration 2Activity 't1' starts at 36 with duration 12Activity 't2' starts at 92 with duration 12Activity 't3' starts at 64 with duration 12Activity 't4' starts at 52 with duration 12Activity 't5' starts at 80 with duration 12Activity 'ua' starts at 78 with duration 10Activity 'v1' starts at 48 with duration 15Activity 'v2' starts at 92 with duration 10Activity 'k1' starts at 39 with duration 0Activity 'k2' starts at 80 with duration 0Activity 'stop' starts at 104 with duration 0

Code Sample 6.3 Output for the Bridge Example

58 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 61: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

The Multiproduction Example

The C++ example mulprod.cpp, located in:

<OPLDIR>/OPLSt37/examples/component/c++/src

illustrates how you can solve several instances of a model. By following this example you will see how to modify instance data inside a loaded OPL model. This functionality is valuable when performing various forms of sensitivity analyses or executing "what-if" scenarios on a model.

This example works with the linear model:

<OPLDIR>/OPLSt37/examples/opl/scripts/mulprod.mod

which solves a multi-period production planning problem.

The C++ code solves various instances of this model. In each instance, the capacity of one of the resources is different. The basic idea is to increase the capacity of the resource flour and to determine the effect on the objective function.

This application is very similar in functionality to the distributed OPL script mulprod.osc explained in the ILOG OPL Studio: Language Manual, Section 16.2. If you are not already familiar with this OPL script, you can launch it from OPL Studio, as a preliminary step, by accessing the file:

<OPLDIR>/OPLSt37/examples/opl/scripts/mulprod.osc

Examining the Multiproduction Example

Here we will highlight interesting aspects of the code. The complete multiproduction example can be found on page 62.

Creating an OPLsolver Instance

First, a new instance of OPLsolver is created and an error reporter is associated with it (see the bridge example for a complete explanation).

int main(){ int status = 0; OPLsolver solver; MyReporter reporter; solver.setErrorReporter(&reporter);

Next, an automatic variable capFlourValue is declared, in order to store the current quantity of the resource flour we want to set in the model:

int capFlourValue = 20;

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 59

Page 62: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

Loading a Model and its Data

The multiproduction model, together with its initial data, is loaded into the solver object:

solver.loadInterpretedModelFileAndDataFile ("../../../../opl/scripts/mulprod.mod", "../../../../opl/scripts/mulprod.dat", 1);

Declaring the Data

The OPL engine constructs and initializes the data structures of the previously loaded model by calling the member function declareData:

solver.declareData();

At this point, no solving process is taking place. After calling declareData, we can access and modify data items inside the model.

The following for loop modifies the capacity of the resource flour four times, and each time solves the model for the particular value of the resource:

cout << "********* Doing four computations ************ " << endl;for(int i = 0; i < 4; i++){

Accessing the Data

In order to modify the capacity of the resource flour, we need to obtain a reference to it from the C++ code. Remember that in the OPL model the capacities of the resources are stored in an integer array, capacity, indexed by the enumeration Resources:

enum Resources ...;..int+ capacity[Resources] = ...;

In fact, the enumeration Resources, as given by the data file, contains two values:

Resources = {flour eggs};

The following code obtains, from the OPLint object capFlour, a reference to the OPL data item capacity[flour]:

OPLarray capacity = solver.getArray("capacity");OPLenum resources = solver.getEnum("Resources");OPLenumValue flour = resources.getValue("flour");OPLint capFlour = capacity.getInt(flour);

Modifying the Data

The member function OPLint::setValue can then be used to set a new value for capFlour, thus modifying the value of the data item capacity[flour] inside the loaded OPL model:

cout << "flour capacity set to: " << capFlourValue << endl;capFlour.setValue(capFlourValue);

60 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 63: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

Solving the Problem and Accessing the Result

Once the current capacity for the resource flour is set, we solve the problem to optimality:

solver.solve();

then we obtain the objective value:

double obj = solver.getObjectiveValueFloat();cout << "objective is: " << obj << endl;

together with the number of simplex iterations needed to solve the linear program represented by the multi-production model:

cout << "iterations: "<< solver.getNumberOfIterations() << endl << endl;

Resetting the Model

The call:

solver.reset();

re-initializes the loaded model, thus preparing it for the next access / modification / solve loop, with the flour capacity increased by one:

capFlourValue++;}

Closing the OPLsolver Instance

Finally, the solver object must be closed, in order to ensure proper memory release.

solver.close();return status;}

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 61

Page 64: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

The Complete Multiproduction Example

Code Sample 6.4#include <ilsolver/ilcint.h>#ifdef ILUSESTL#include <iostream>#else#include <iostream.h>#endif#include <ilopl/oplcomponent.h>#include <ilopl/oplerror.h>ILCSTLBEGINclass MyReporter : public OPLerrorReporter { void notifySyntaxError(const OPLsyntaxError& err){ cout << "OPL syntax error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifySemanticError(const OPLsemanticError& err){ cout << "OPL semantic error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyRuntimeError(const OPLruntimeError& err){ cout << "OPL runtime error near line " << err.getLine() << " : " << err.getMessage() << endl; } void notifyInternalError(const OPLinternalError& err){ cout << "OPL internal error : " << err.getMessage() << endl; }};

int main(){ int status = 0; OPLsolver solver; MyReporter reporter; solver.setErrorReporter(&reporter);

try {

int capFlourValue = 20; solver.loadInterpretedModelFileAndDataFile ("../../../../opl/scripts/mulprod.mod", "../../../../opl/scripts/mulprod.dat", 1); solver.declareData();

62 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 65: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

Interfacin

g w

ith O

PL

fro

m C

++

cout << "********* Doing four computations ********* " << endl; for(int i = 0; i < 4; i++){ OPLarray capacity = solver.getArray("capacity"); OPLenum resources = solver.getEnum("Resources"); OPLenumValue flour = resources.getValue("flour"); OPLint capFlour = capacity.getInt(flour); cout << "flour capacity set to: " << capFlourValue << endl; capFlour.setValue(capFlourValue); solver.solve(); double obj = solver.getObjectiveValueFloat(); cout << "objective is: " << obj << endl; cout << "iterations: " << solver.getNumberOfIterations() << endl << endl; solver.reset(); capFlourValue++; } } catch(...){ cout << "An error occurred" << endl; status = -1; } solver.close(); return status;}

Code Sample 6.4 Complete Multiproduction Example in C++

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 63

Page 66: OPL studio 3.7 Component Libraries User’s Manual

T H E M U L T I P R O D U C T I O N E X A M P L E

64 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 67: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith O

PL

fro

m Java

7

Interfacing with OPL from Java

You can access the OPL C++ API from Java code, relying upon the Java Native Interface (JNI). The API is available on all platforms on which Java and OPL are available, and the entire API is assembled in the package ilog.opl.engine. You can then use the JavaServer Pages on a Java Web Server.

Before running the Java example, prepare the environment as follows:

◆ On Solaris and Linux Platforms

Set your LD_LIBRARY_PATH variable so that the OPL JNI dynamic library can be found. The file libopljni.so is located in:

<OPLDIR>/lib/<MACHINE>/shared -mt

◆ On HP Platforms

Set your SHLIB_PATH variable so that the OPL JNI dynamic library can be found. The file libopljni.sh is located in:

<OPLDIR>/lib/hp32_3.15/shared

◆ On Windows Platforms

Set your PATH variable so that the OPL JNI dynamic library can be found. The file opljni.dll is located in:

<OPLDIR>\lib\msvc6\dll_mda

Install the CPLEX.dll file in the same directory as opljni.dll.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 65

Page 68: OPL studio 3.7 Component Libraries User’s Manual

I N T E R F A C I N G W I T H O P L F R O M T H E J A V A N A T I V E I N T E R F A C E A P I

Interfacing with OPL from the Java Native Interface API

This section explains how to run an example on UNIX and Windows platforms and then examines the Java code, highlighting important aspects.

Running an Example On UNIX Platforms

The example MyJNIsample.java can be found in the directory:

<OPLDIR>/examples/component/jni

In order to use this example you must have a Java Development Kit (JDK) installed. The JNI wrappers for the example were generated with Sun's JDK 1.2.2.

1. Go the directory <OPLDIR>/examples/component/jni.

2. Set your PATH environment variable so that the system will find your Java Compiler, and at runtime your Java virtual machine.

Add the libopljni.so location (<OPLDIR>/lib/<MACHINE>/<PORT>) to your LD_LIBRARY_PATH on Linux and Solaris or to your SHLIB_PATH on HP.

3. Compile the example:

javac -classpath /usr/ilog/OPLSt37/classes/opljni.jar MyJNIsample.java

4. Run the example:

java -classpath /usr/ilog/OPLSt37/classes/opljni.jar:. MyJNIsample

Running the Example On Windows Platforms

The example MyJNIsample.java can be found in the directory:

<OPLDIR>\examples\component\jni

In order to use this example you must have a Java Development Kit (JDK) installed. The JNI wrappers for the example were generated with Sun's JDK 1.2.2 and should work with the 1.1 version upward.

1. Go the directory <OPLDIR>\examples\component\jni.

2. Set your PATH environment variable so that the system will find your Java Compiler, and at runtime your Java virtual machine.

Add the opljni.dll location to your PATH. Typically in a DOS shell:

set PATH=c:\ilog\OPLSt37\lib\msvc6\dll_mda;c:\jdk1.2.2\bin;%PATH%

Note: Linux users must use JDK 1.3 for Linux, to avoid the risk of deadlocks.

66 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 69: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m Java

I N T E R F A C I N G W I T H O P L F R O M T H E J A V A N A T I V E I N T E R F A C E A P I

(assuming that you have installed Sun's JDK in c:\jdk1.2.2)

3. Compile the example:

javac -classpath "c:\ILOG\OPLSt37\classes\opljni.jar;." MyJNIsample.java

4. Run the example:

java -classpath "c:\ILOG\OPLSt37\classes\opljni.jar;." MyJNIsample

Examining the Java Code

import java.lang.*;import ilog.opl.engine.*;

/** * This sample shows how to use the JNI encapsulation of the OPL C++ Component library. * It shows the use of the OPLsolver class. * Please, read the component.txt file on Windows and the README file on UNIX for explanations. */

class MyJNIsample { class MyOPLerrorReporter extends OPLerrorReporter { public void notifySyntaxError(String msg, String file, int line) throws OPLexception { throw new OPLexception ("syntax error: line "+ line +": " + msg); } public void notifySemanticError(String msg, String file, int line) throws OPLexception { throw new OPLexception ("semantic error: line "+ line +": "+ msg); } public void notifyRuntimeError(String msg, String file, int line) throws OPLexception{ throw new OPLexception ("runtime error: line "+ line +": "+ msg); } public void notifyInternalError(String msg) throws OPLexception{ throw new OPLexception ("internal error: " + msg); } }

public void run() { System.out.println("Intiantiating the OPLsolver engine..."); OPLsolver solver = new OPLsolver(); System.out.println("Intiantiating the error reporter..."); MyOPLerrorReporter reporter = new MyOPLerrorReporter();

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 67

Page 70: OPL studio 3.7 Component Libraries User’s Manual

I N T E R F A C I N G W I T H O P L F R O M T H E J A V A N A T I V E I N T E R F A C E A P I

try { System.out.println("Setting the error reporter..."); solver.setErrorReporter(reporter); System.out.println("Loading the queens8.mod file..."); solver.loadInterpretedModelFile("../../opl/queens8.mod",1); System.out.println("Solving the model..."); solver.solve(); System.out.println("Displaying the solution generically..."); System.out.println(solver.display()); System.out.println("Browsing the solution specifically..."); OPLarray queensArray = solver.getArray("queens"); int low = queensArray.getLow(); int high = queensArray.getHigh(); System.out.println("queens:"); for(int i = low; i <= high; ++i) { OPLintVar v = queensArray.eltIntVar(i); System.out.println(v.getValue()); } } catch (OPLexception e) { System.out.println(e.getMessage()); } System.out.println("Deleting the error reporter and the OPLsolver engine..."); reporter.end(); solver.close(); } public static void main(String[] args) { MyJNIsample sample = new MyJNIsample(); sample.run(); }}

Creating an OPLsolver InstanceOPLsolver solver = new OPLsolver();

Setting an Error Reporter

The error reporter is a nested class inside the MyJNIsample class.

MyOPLerrorReporter reporter = new MyOPLerrorReporter();solver.setErrorReporter(reporter);

Loading a Modelsolver.loadInterpretedModelFile("../../../../opl/queens8.mod",1);

Solving the Modelsolver.solve();

68 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 71: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m Java

I N T E R F A C I N G W I T H O P L F R O M T H E J A V A N A T I V E I N T E R F A C E A P I

Printing the Solution

We show how to display the solution (generically) for all models:

System.out.println(solver.display());

We show how to iterate on a specific model solution (here the queens8 model).

ilog.opl.engine.OPLarray queensArray = solver.getArray("queens");

int low = queensArray.getLow();

int high = queensArray.getHigh();

System.out.println("queens:");

for(int i = low; i <= high; ++i) {

OPLintVar v = queensArray.eltIntVar(i);

System.out.println(v.getValue());

}

Handling Errors

Errors may occur during the interaction with the OPL engine. These errors are classified as follows:

◆ syntax errors occurring during the loading of an OPL model or data file

◆ semantic errors detected in the loaded model

◆ runtime errors detected while solving the loaded model, or accessing data items

◆ internal errors.

You can handle these errors from the Java application. To do so, you must define a new class that implements the interface class OPLerrorReporter.

In our example this class is called MyOPLerrorReporter and is defined as a class nested inside the class MyJNISample. It implements the interface class OPLerrorReporter by redefining the methods notifyInternalError, notifyRuntimeError, notifySemanticError and notifySyntaxError.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 69

Page 72: OPL studio 3.7 Component Libraries User’s Manual

I N T E R F A C I N G W I T H O P L F R O M T H E J A V A N A T I V E I N T E R F A C E A P I

Each time an error is raised by the OPL engine we want the error message, together with the line number, to be printed in the bottom text area of the frame:

class MyReporter implements OPLerrorReporter { public void notifySemanticError(int line, String msg) { throw new OPLexception ("semantic error: line " + line + ":" + msg); } public void notifyRuntimeError(int line, String msg) { throw new OPLexception ("runtime error: line " + line + ":" + msg); } public void notifyInternalError(String msg) { throw new OPLexception ("internal error: line " + line + ":" + msg); } public void notifySyntaxError(int line, String msg) { throw new OPLexception ("syntax error: line " + line + ":" + msg); }};

70 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 73: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m Java

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

Calling from JavaServer Pages (JSP)

If you plan to embed the OPL component library in a web server supporting Java Servlets and JavaServer Pages, read the following example.

The example is provided with the distribution in:

<OPLDIR>\examples\component\jni\genericServer.html

and

<OPLDIR>\examples\component\jni\genericServer.jsp

You need a web server supporting Java Servlets and JavaServer Pages, such as Sun's Java Web Server or Apache.

◆ Sun's Java Web Server can be downloaded from:

http://java.sun.com/products

◆ Apache can be downloaded from:

http://www.apache.org/dist/

Installation instructions can be found at:

http://www.apache.org/docs/install.html

Here we use the Tomcat JavaServer Pages Reference Implementation, from the Jakarta project (http://jakarta.apache.org/), which will be used in the Apache Web Server as well as in other web servers and development tools in the future. You can download it from http://jakarta.apache.org/tomcat/.

Here the installation root directory of the server is referred to as $<Your_Tomcat_Home>.

1. Create a directory in $<Your_Tomcat_Home>/webapps called, for example, opljni.

Copy the files:

<OPLDIR>/examples/component/jni/genericServer.html

<OPLDIR>/examples/component/jni/genericServer.jsp

<OPLDIR>/examples/component/jni/*.gif files

to $<Your_Tomcat_Home>/webapps/opljni.

2. In the directory $<Your_Tomcat_Home>/webapps/opljni, create the subdirectories WEB-INF/lib.

3. Copy the file:

<OPLDIR>/classes/opljni.jar

to $<Your_Tomcat_Home>/webapps/opljni/WEB-INF/lib.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 71

Page 74: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

4. The dynamic library is located in <OPLDIR>/lib/<PLATFORM>/<SHARED_FORMAT>.

Put this location in:

● the LD_LIBRARY_PATH variable on Solaris and Linux

● the SHLIB_PATH variable on HP

● the PATH variable on Windows. Also on Windows, copy the file:

<OPLDIR>\bin\cplex80.dll to the above directory.

(If you intend to use database connectivity for your own application, please refer to the OPL Studio README for additional environment settings).

5. Install the ILOG License Manager file, access.ilm., or use your runtime keys via the methods registerOplLicense, registerSolverLicense, registerSchedulerLicense, registerCplexLicense. These methods are described in the ILOG OPL Component Libraries Reference Manual.

The file access.ilm is installed:

● On Windows, on your server hard disk in:

c:\ilog\ilm\access.ilm

● On UNIX, in

/usr/ilog/ilm/access.ilm.

With the access.ilm file, install the following NODE or EVAL type keys:

● OPLStudio key for development

● OPLinterpreter key for deployment (This is because, for this specific example, you use the interpreted model APIs, i.e the methods beginning with loadInterpretedXXX. You don't require this key with compiled model APIs, i.e. the methods beginning with loadCompiledXXX).

● Library keys needed by your model. (Here Solver is enough.)

Warning: Do not install TOKEN type keys because you need multithread safety on a Web Server, and the ILOG License Manager (ILM) is not multithread safe when dealing with TOKEN keys.

72 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 75: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m Java

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

6. Run your web server

If you use your own machine as both server and client you can access the genericServer.html file at:

http://localhost:8080/opljni/genericServer.html

In the following screen dump, the machine name is aragon:

7. Click on the Solve (JSP Script) button. A new HTML page is generated dynamically by the genericServer.jsp page, which is executed on the server side. This page contains the result.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 73

Page 76: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

74 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 77: OPL studio 3.7 Component Libraries User’s Manual

Interfacin

g w

ith O

PL

fro

m Java

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

Examining the JSP Code

<!-- genericServer.jsp --> <!doctype html public "-//w3c//dtd html 4.0 transitional//en"><html><head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="Mozilla/4.75 [en] (WinNT; U) [Netscape]"></head>

<%@ page language="java"%> <%@ page import="ilog.opl.engine.*" %> <!-- Error Reporter Definition --><% class MyOPLerrorReporter extends OPLerrorReporter { public void notifySyntaxError(String msg, String file, int line) throws OPLexception { throw new OPLexception ("syntax error: line " + line + ": " + msg); } public void notifySemanticError(String msg, String file, int line) throws OPLexception { throw new OPLexception ("semantic error: line " + line + ": " + msg); } public void notifyRuntimeError(String msg, String file, int line) throws OPLexception{ throw new OPLexception ("runtime error: line " + line + ": " + msg); } public void notifyInternalError(String msg) throws OPLexception{ throw new OPLexception ("internal error: " + msg); } } OPLsolver solver = new OPLsolver(); MyOPLerrorReporter reporter = new MyOPLerrorReporter(); try { solver.setErrorReporter(reporter); String MODELGENERIC; String DATA; MODELGENERIC = request.getParameter("modelgeneric"); DATA = request.getParameter("Data"); solver.loadInterpretedModelBuffAndDataBuff(MODELGENERIC,DATA,1);%> <img SRC="opl.gif" ALT="OPL icon" > <img SRC="javaserver.gif" height=136 width=134> <b>GENERIC SOLVER SAMPLE </b> <br>&nbsp;<%

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 75

Page 78: OPL studio 3.7 Component Libraries User’s Manual

C A L L I N G F R O M J A V A S E R V E R P A G E S ( J S P )

if (solver.solve()!=0){ %> <CENTER><P><B><FONT COLOR="#FF9935">Here, the result:</FONT> </B></P></CENTER> <center><table BORDER COLS=300 WIDTH=130 HEIGHT=30> <tr><td><TEXTAREA COLS=40 ROWS=8 WIDTH=200 HEIGHT=25 ><% out.println(solver.display());%> </TEXTAREA></TD></TR></TABLE></CENTER><% } else{%> <center><table BORDER COLS=300 WIDTH=130 HEIGHT=30> <tr><td><TEXTAREA COLS=40 ROWS=8 WIDTH=200 HEIGHT=25><% out.println("No Solution Found ");%> </TEXTAREA></TD></TR></TABLE></CENTER><% }; } catch (OPLexception e) { %> <CENTER><P><B><FONT COLOR=red>Error !!!:</FONT></B></P></CENTER> <center><table BORDER COLS=300 WIDTH=130 HEIGHT=30> <tr><td><TEXTAREA COLS=40 ROWS=8 WIDTH=200 HEIGHT=25 ><% out.println(e.getMessage());%> </TEXTAREA></TD></TR></TABLE></CENTER><% } reporter.end(); solver.close();%>

76 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 79: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

OP

L an

d .N

ET

8

OPL and .NET

You can call ILOG CPLEX, ILOG Solver or ILOG Scheduler from any .NET language via OPL by using .NET wrappers around the ILOG OPL COM component.

The easiest way to generate the .NET wrappers is to use Visual Studio .NET (alternatively you can use the tlbimp.exe command line utility provided in the .NET platform SDK).

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 77

Page 80: OPL studio 3.7 Component Libraries User’s Manual

I N T E R F A C I N G W I T H O P L F R O M V I S U A L B A S I C . N E T V I A T H E C O M / A C T I V E XA P I

Interfacing with OPL from Visual Basic .NET via the COM/ActiveX API

If you have not installed OPL with InstallShield you must register the OPL COM component on your machine. To do this:

◆ Go to the OPL Studio bin directory and call from the command line

regsvr32 oplServer.dll

◆ Start Visual Studio .NET.

◆ Create a new Visual Basic project (Windows application).

◆ Select the menu items Project>Add Reference.

◆ Select the COM tab.

◆ Select the OPL Server type library from the list and click on the Select button.

◆ Click on OK.

◆ Add a button to the form (View>ToolBox, then drag and drop a button onto your form).

◆ Double-click on the button and add the code indicated in steps 1 and 2.

1. Import the OPLCOMLib namespace at the beginning of the file:

Imports OPLCOMLib

2. Add the button handler code. (This is an example for an ILOG CPLEX model.)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim solver As New OPLCOMLib.COPLsolver() solver.loadInterpretedModelFileAndDataFile ("C:/ilog/OPLSt37/examples/opl/gas.mod", "C:/ilog/OPLSt37/examples/opl/gas.dat", 1) solver.solve() MsgBox("Result=" & solver.display()) solver.close()End Sub

◆ Make accessible the CPLEX .dll file located in the OPLSt37/bin directory.

78 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 81: OPL studio 3.7 Component Libraries User’s Manual

OP

L an

d .N

ET

I N T E R F A C I N G W I T H O P L F R O M V I S U A L C # . N E T V I A T H E C O M / A C T I V E X A P I

Example for abridge.mod

This is an ILOG Scheduler model with Microsoft Access connectivity. It can be found in <OPLDIR>/examples/opl/database.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim solver As New OPLCOMLib.COPLsolver() solver.loadInterpretedModelFile ("C:/ilog/OPLSt37/examples/opl/database/abridge.mod", 1) While (solver.nextSolution() = 1) End While solver.restore() MsgBox("Result=" & solver.display()) solver.close() End Sub

Make sure that the abridge.mdb file is defined as an ODBC user data source on your system.

Interfacing with OPL from Visual C# .NET via the COM/ActiveX API

If you have not installed OPL with InstallShield you must register the OPL COM component on your machine. To do this:

◆ Go to the OPL Studio bin directory and call from the command line

regsvr32 oplServer.dll

◆ Start Visual Studio .NET.

◆ Create a new Visual C# project (Console application).

◆ Select the menu item Project>Add Reference.

◆ Select the COM tab.

◆ Select the OPL Server type library from the list and click on the Select button.

◆ Click on OK.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 79

Page 82: OPL studio 3.7 Component Libraries User’s Manual

I N T E R F A C I N G W I T H O P L F R O M V I S U A L C # . N E T V I A T H E C O M / A C T I V E X A P I

Example for queens8.mod

This is an ILOG Solver example.

using System;using OPLCOMLib;

namespace ConsoleApplication1{ /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { // // TODO: Add code to start application here // OPLCOMLib.IOPLsolver s = new OPLCOMLib.COPLsolver(); s.loadInterpretedModelFile ("C:\\ILOG\\OPLSt37\\examples\\opl\\queens8.mod", 1); s.solve(); Console.Out.WriteLine(s.display()); s.close(); }}

◆ Make accessible the CPLEX .dll file located in the OPLSt37/bin directory.

◆ If you use database connectivity, make sure that the DB Link drivers located in OPLSt37/bin are accessible and that the ODBC data source is defined on your system.

80 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 83: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

OP

L M

od

el with

B

usin

ess Ru

les

9

Customizing an OPL Model using BusinessRules

You can control the agility of an OPL model using business rules expressed in natural language. In order to do so, you need ILOG OPL Studio and ILOG JRules 4.5 or above.

In this chapter you will learn how to integrate an OPL model into an ILOG JRules-based application. The OPL model warehouserules.mod is located in the directory examples/opl. The JRules repository and additional material are provided in the file examples/rules/warehouserules.zip. Extract the contents of this file to the directory examples/rules.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 81

Page 84: OPL studio 3.7 Component Libraries User’s Manual

A R C H I T E C T U R E

Architecture

The principle underlying this example is to feed, at runtime, the OPL component with an OPL model developed with OPL Studio and OPL data prepared by business rules. The OPL model iterates over sets filled by the business layer to post additional business constraints to a core model.

Figure 9.1

Figure 9.1 Principle of Integration of OPL and ILOG JRules

The model can be encrypted using the OPL Studio menu item File> Generate Compiled Model File. This enables an optimization expert to retain the intellectual property on a model. These compiled models have the .opl extension.

The Warehouse Sample

◆ OPL Formulation

◆ Business Logic

◆ Business Rule Translation

◆ Integration with OPL

◆ Running the Sample from the ILOG Rule Builder

◆ Deployment in the Finished Application

82 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 85: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

OPL Formulation

Open the project warehousefules.prj in OPL Studio. As in the warehouse.prj project, the company in this project is considering a number of locations for building warehouses to supply existing stores. The author of the optimization model wants a business user to be able to customize the core model with additional constraints that rely on business rules. For example, it should be possible to specify incompatible warehouses or to force two stores to be supplied by the same warehouse based upon business conditions. For this purpose, the optimization modeler creates additional set parameters, as shown in Code Sample 9.1.

Code Sample 9.1

Code Sample 9.1 Declarations in warehouserules.mod

The sets are iterated over in the constraint part of the model. If no business rules have been applied, these sets can be empty, thus omitting the corresponding constraints. In this example, the author of the optimization model linearizes the constraints to use the underlying mathematical programming optimizer (ILOG CPLEX). The author could also have used a constraint programming formulation that would use ILOG Solver or a hybrid formulation. Refer to the projects wlocation.prj and wareboth.prj for examples of these.

// Core daterange Boolean 0..1;int fixed = ...;enum Warehouses ...’int nbStores = ...;range Stores 0..nbStores-1;int capacity[Warehouses[ = ...;int supplyCost[Stores,Warehouses] = ...;

// Decision variablesvar Boolean open[Warehouses];var Boolean supply[Stores,Warehouses];

// Definition of two types of requirement:struct CommonSupplier { Stores store1; Stores store2;};struct IncompatibleWarehouses { Warehouses warehouse1; Warehouses warehouse2;};

// Sets of requirements filled in by business rules// using ILOG JRules 4.5 or later{CommonSupplier} commonSupplier = ...;{IncompatibleWarehouses} incompatibleWarehouses = ...;

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 83

Page 86: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

Code Sample 9.2

Code Sample 9.2 Constraints in warehouserules.mod

Business Logic

To examine the business object model and business rules used in this example:

1. Unzip the examples/rules/warehouserules.zip file to the examples/rules directory.

2. Set your PATH variable on Windows or your LD_LIBRARY_PATH variable on UNIX so that it contains the opljni dynamic library location, typically lib/<platform>/<dynamic format>.

3. Launch the ILOG Rule Builder and open the rulesRepository located in the examples/rules/warehouse directory.

4. Expand the RulePackage item and open the RuleFlow.

minimize sum(w in Warehouses) fixed * open[w] + sum(w in Warehouses, s in Stores) supplyCost[s,w] * supply[s,w]subject to { /**** Core model ****/ forall(s in Stores) sum(w in Warehouses) supply[s,w] = 1; forall(w in Warehouses, s in Stores) supply[s,w] <= open[w]; forall(w in Warehouses) sum(s in Stores) supply[s,w] <= capacity[w];

/**** Cusomization by business rules ****/ //Common provider for selected pairs of stores forall(c in commonSupplier) forall(w in Warehouses) supply[c.store1,w] = supply[c.store2,w]; // Incompatible warehouses forall(i in incompatibleWarehouses) open[i.warehouse1] + open[i.warehouse2] <= 1;};

84 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 87: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

Figure 9.2

Figure 9.2 Rule Flow and Global Parameters in the ILOG Rule Builder

The Function Task Initialization is responsible for creating and asserting objects in the Working Memory of JRules. A Rule Task called Business Policy customizes the optimization problem and a second Rule Task, Postprocessing, post processes the results. These two tasks use the Rete pattern matching algorithm of ILOG JRules. A Function Task called Solving with OPL is responsible for data adaptation, loading solving and putting the result back in the object model. This task relies heavily on the OPL Component Java API and calls an optimization engine, in this case ILOG CPLEX (it could alternatively be ILOG Solver or ILOG Scheduler). Several global parameters are defined to pass information between tasks. Note that the commonSupplierRequirements and the incompatibleWarehousesRequirements parameters are ordinary Java Set instances.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 85

Page 88: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

Figure 9.3

Figure 9.3 Object Model

Business rules are applied on a business object model, which is a view of an existing Java object model. You can find the sources of the Java object model used in the sample in examples/rules/warehouse/src. To define the pieces of natural language usable by the business policy manager, you can specify an alternate string on each method of the object model. Figure 9.4 shows an example of an alternate string on the method forceCommonSupplier.

86 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 89: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

Figure 9.4

Figure 9.4 alternate String on the forceCommonSupplier Method

Figure 9.5

Figure 9.5 Common Supplier Rule for Stores from the Same Country

Figure 9.5 shows an example of a business rule that forces any two stores in the same country to be supplied by the same warehouse. The action on the right hand side of the rule fills in a set of pairs of stores using the Java class OPLrequirement.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 87

Page 90: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

Figure 9.6

Figure 9.6 Incompatible Warehouses Rule

Figure 9.6 shows an example of a business rule that prevents the solution of the optimization problem from containing two open warehouses in the same country. The action on the right hand side of the rule fills a set of pairs of incompatible warehouses using the Java class OPLsymmetricRequirement.

Business Rule Translation

To view how the underlying IRL (ILOG Rule Language) expresses the common supplier rule, switch from the syntactic view to the IRL view:

Figure 9.7

Figure 9.7 IRL View of the Common Supplier Rule

In Figure 9.7, you can see that the right hand side has been translated to a method call that adds a new instance of the class OPLrequirement to a HashSet called commonSupplierRequirements, which is a global parameter of the rule package.

Open the BOM view and select the method forceCommonSupplier on the class Requirements. The method returns void, so it is considered a possible action by JRules and is available in the syntactic editor on the right hand side of the business rules, as shown in Figure 9.8. The property sheet in Figure 9.4 shows the alternate string that will be visible in the syntactic editor to the business user and the translation to the IRL formulation. Note

88 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 91: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

that here the class Requirements and the method forceCommonSupplier have no Java counterpart. They are artificial methods and classes relying on the translation mechanism.

Figure 9.8

Figure 9.8 The Alternate Strings for the Method Requirements.forceCommonSupplier

Integration with OPL

The function task Solving with OPL contains IRL syntax and can be divided into three parts:

◆ translating Java data structures to OPL syntax

◆ loading model and data and solving

◆ updating the object model with the result

Translating Java Objects to OPL Data

The Java data structures populated by business rules must be translated to a java.lang.String. This step is greatly simplified by helper methods in the OPL Component Java API.

Code Sample 9.3

Code Sample 9.3 IRL Code Calling OPL Adaptors

bind dataBuffer = new StringBuffer();ilog.opl.engine.OPLadaptor.formatAsInt(dataBuffer, "fixed", warehouse.Costs.FIXED);// generates: fixed = 30;

ilog.opl.engine.OPLadaptor.format(dataBuffer, "Warehouses", warehouses,false);// generates: Warehouses = (Bonn,Bordeaux,London,Paris,Rome);

ilog.opl.engine.OPLadaptor.format(dataBuffer,"commonSupplier", ?context.?commonSupplierRequirements,false);

// generates: commonSupplier={< 9,6 >,< 5,8 >,< 4,2 >};

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 89

Page 92: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

There are two ways to perform the translation of a Java Object to an OPL struct or enum:

◆ relying on reflection

◆ implementing the OPLadaptable interface

Two ways are provided to control the transformation:

◆ relying on a predefined mapping between Java and OPL (method format)

◆ forcing the result to be of OPL type T (method formatAsT)

As showed in Code Sample 9.4, the Warehouse class implements the OPLadaptable interface which consists in implementing a formatToOPL method.

Code Sample 9.4

Code Sample 9.4 Implementing the OPLadaptable Interface in Java

You can use the OPLadaptor.format API without specifying any accessor methods. This method takes a java.lang.Object as argument. It uses the conventions for the translation showed in Table 9.1.

public class Warehouse implements OPLadaptable { // Data String name; String country; int capacity; int id; // Result of optimization computed by OPL boolean mustOpen = false; ............. public void formatToOPL(StringBuffer buffer) { buffer.append(this.name); }}

90 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 93: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

(*) formatToOPL is called if the values are instances of OPLadaptable, otherwise toString() is called.

(**) Depends on the argument doubleQuotes

Relying on reflection is less efficient but provides more flexibility. You specify an array of accessor methods and the adaptor uses them to perform the translation. If there is more than one accessor method, the Objects will be translated into structs.

Note that if you have created a JRules IlrDefaultCollector, you can use the OPLrulesAdaptor class to convert it to an OPL set, enum, or array.

Refer to the OPL Studio Component Libraries Reference Manual for more information.

Loading Model and Data, Solving

As usual when integrating with the OPL component, an instance of OPLsolver loads the model and the data and then solves the problem. Refer to Chapter 7, Interfacing with OPL from Java for more details about this. In this example, you use the method loadCompiledModelFileAndDataBuff.

This method expects the compiled model file location and the values of data in a java.lang.String respecting the OPL data syntax.

Code Sample 9.5

Code Sample 9.5 Loading an OPL Model and Data Buffer and Solving the Optimization Problem

Table 9.1 Translation of Java Types to OPL Data Types

Java OPL

java.util.collection set (*)

java.lang.Object[] [] (*)

java.util.Map [] (*)

int[] int[]

double[] float[]

java.lang.Int int

java.lang.Double float

java.lang.Boolean int 0/1

java.lang.String string or enumerated value (**)

solver.loadInterpretedModelFileAndDataBuff(OPLModelLocation, dataBuffer.toString(),1);solver.solve();

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 91

Page 94: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

Updating the Object Model with the Result of the Optimization

As shown in Code Sample 9.6, you feed the result back to the Java object model using the OPL component API. See Chapter 7, Interfacing with OPL from Java, and the OPL Studio Component Libraries Reference Manual for more details on this API.

Code Sample 9.6

Code Sample 9.6 Returning the Result of Optimization to the Object Model

Once you have returned the result to the object model, you can apply other business rules for postprocessing. The Postprocessing rule task in the sample just displays the advice given by the optimization engine about opening or not a warehouse. See Code Sample 9.7.

Running the Sample from the ILOG Rule Builder

Right click on the RulePackage item in the Project tab and select the Execute menu item. The execution stops at the beginning of the rule flow. Click on the Continue button. The following result is displayed:

Code Sample 9.7

Code Sample 9.7 Result Displayed in the ILOG Rule Builder Console

// Using the OPL Java Component API to query the result// and update the Java object modelbind open = solver.getArray("open");bind iterator = warehouses.iterator();while(iterator.hasNext()) { bind warehouse = (warehouse.Warehouse)iterator.next(); bind index = solver.getEnumValue(warehouse.getName()); if (open.getIntVar(index).getValue() == 1) { warehouse.setOpen(true); } else { warehouse.setOpen(false); }}

total cost = 421advisor: warehouse Rome should open. Stores to supply = { MontpellierVenice Napoli }advisor: warehouse Bonn should open. Stores to supply = { Berlin }advisor: warehouse Bordeaux should open. Stores to supply = { MadridAmsterdam Barcelona Rotterdam }advisor: warehouse Paris should not open.advisor: warehouse London should open. Stores to supply = { SouthamptonOslo }Execution completed.

92 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 95: OPL studio 3.7 Component Libraries User’s Manual

OP

L M

od

el with

B

usin

ess Ru

lesT H E W A R E H O U S E S A M P L E

Deployment in the Finished Application

You can integrate the example in the finished application using the Rule Service publishing feature of JRules. There are three targets to choose from:

◆ J2SE (Java Standard Edition, typically for desktop applications)

◆ J2EE (Java Enterprise Edition, typically for EJB integration)

◆ Web Service

For details, refer to the ILOG JRules documentation.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 93

Page 96: OPL studio 3.7 Component Libraries User’s Manual

T H E W A R E H O U S E S A M P L E

94 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 97: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Interfacin

g w

ith

OP

LS

cript

10

Interfacing with OPLScript from C++, COM,and Java

You can run an OPLScript file (.osc) from the OPL Component Libraries using the object OPLscriptSolver.

In order to do this, you need to execute the following steps:

1. Create an OPLscriptSolver object (or COPLscriptSolver object for the COM API).

2. Create your own error reporter, derived from the class OPLerrorReporter.

For COM, your own error reporter class must implement the interface IOPLerrorReporter. VBScript, JavaScript and VBA are exceptions because of a limitation of the language, so in those cases use the default error reporter which is implicitly created by the COPLscriptsolver instance.

3. Set the OPLerrorReporter on the OPLscriptSolver object (otherwise the default error reporter will be triggered).

4. Register the runtime licenses, if any, by calling the methods registerOplLicense and registerCplexLicense, or registerSolverLicense, or registerSchedulerLicense.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 95

Page 98: OPL studio 3.7 Component Libraries User’s Manual

5. Call the method run, passing the .osc file location as parameter.

It is the responsibility of the .osc code to store the result either in a file or in a database, or send it to the standard output (stdout).

6. Call the method close on OPLscriptSolver to release the memory.

After calling the close method, you can no longer use the instance of OPLscriptSolver.

7. For the C++ API, delete the objects OPLscriptSolver and OPLerrorReporter.

For the COM/ActiveX API, release the references to the objects IOPLscriptSolver and IOPLerrorReporter.

For the Java API, call the end method on OPLerrorReporter.

More information is provided in the ILOG OPL Component Libraries Reference Manual.

You can also consult the following distributed examples:

C++ API:

examples/component/c++/src/oplbatch.cpp

COM/ActiveX API:

examples/component/com/vb/mulprodscript.vbp

Java API:

examples/component/jni/MyJNIscriptSample.java

Note: OPLScriptsolver cannot run a script file twice. If you need to run more than one script file, create an instance of OPLScriptsolver for each script file.

Note: This is done automatically by Visual Basic. You need to call the Release() method when using COM from C++.

96 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 99: OPL studio 3.7 Component Libraries User’s Manual

C H A P T E R

Datab

ase C

on

nectivity

11

Database Connectivity from the OPLComponent Libraries

The ILOG OPL 3.7 Component Libraries use ILOG DB Link 5.0 for connectivity with relational databases. The ILOG DB Link 5.0 libraries are supplied with the ILOG OPL 3.7 archive. A DB Link key is never required when using ILOG DB Link via the ILOG OPL Component.

If there are last-minute changes to the database connections supported, they will be mentioned in the README file distributed with OPL Studio.

Consult the README file on UNIX and the readme.txt and component.txt files on Windows for the most up-to-date information.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 97

Page 100: OPL studio 3.7 Component Libraries User’s Manual

A R C H I T E C T U R E

Architecture

The ILOG DB Link product consists of two parts, the DB Link kernel and the DB Link drivers specific to each database.

◆ The DB Link kernel

● Windows dynamic libraries

dbkernel.dll + dblnkdyn.dll + ilog.dll

● UNIX dynamic libraries

libdbkernel.so + libdblnkdyn.so + libilog.so (or .sl on HP)

◆ The DB Link drivers specific to each RDBMS

Here we provide a few examples. See the README files for the complete list of databases supported on Windows and UNIX platforms.

● Some Windows examples are:

Informix 9.1: dbinf9.dll

ODBC: dbodbc.dll

Oracle 7.3: dbora73.dll

Oracle 8.0: dbora8.dll

Oracle 8.1: dbora81.dll

Oracle 9i: dbora9.dll

SQLBase: dbsqlbas.dll

Sybase: ctsyb.dll

MS SQL: dbmssql.dll

IBM DB2: dbdb2.dll

● Some UNIX examples are:

Solaris

Oracle 8.1: libdbora81.so

Linux

Oracle 8.1: libdbora81.so

HP

Oracle 8.1: libdbora81.sl

IBM RS6000

Oracle 8.1: libdbora81.a

98 I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 101: OPL studio 3.7 Component Libraries User’s Manual

Datab

ase C

on

nectivity

A R C H I T E C T U R E

The DB Link driver calls the corresponding database client.

◆ For instance, on Windows, when accessing an MS SQL database from the OPL ActiveX, the following calls occur:

◆ For instance, on Solaris, when accessing the Oracle 8.1 database from the OPL C++ static library, the following calls occur:

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 99

Page 102: OPL studio 3.7 Component Libraries User’s Manual

S P E C I F I C R D B M S S E T T I N G S

Specific RDBMS Settings

Ensure that you have installed the database client and that it is correctly configured.

For instance, on Windows, if you want to use MS SQL you must install the MS SQL client on your machine. On Windows, the installer of your database client should configure your environment.

With ODBC you must select a Data Source Name from Start>Settings>Control Panel>ODBC, so that you can refer to your database. This is explained in the ILOG OPL Studio User’s Manual, in the chapter Working with a Database.

The Environment Variable

◆ On UNIX systems

When integrating with your application you should make the LD_LIBRARY_PATH (or SHLIB_PATH or LIBPATH) environment variable point to the database driver location and to the ILOG DB Link driver directory.

The DB Link drivers are provided in directories of the type:

<OPLDIR>/lib/<platform>/<shared_format>

Details are provided in the README file.

ILOG OPL 3.7 is in theory independent of ILOG DB Link, since it comes with all the DB Link dynamic link libraries. In certain cases, however, DB Link drivers need to be relinked for the platform and database release that OPL needs to connect to. Please consult the ILOG DB Link documentation that explains how to rebuild the DB Link drivers.

In these specific cases:

● Install ILOG DB Link 5.0 and patches if necessary.

● Relink the DB Link drivers for the platform and RDBMS in question.

● Type the name of the ILOG DB Link dynamic library directory at the beginning of your LD_LIBRARY_PATH (or SHLIB_PATH or LIBPATH).

◆ On Windows XP, Windows 2000, Windows NT 4, and Windows 98

● To use database connectivity on Windows from the GUI, you do not need to set paths. The dblink.ini file is in the bin directory containing the oplst.exe file and calls the libraries in the directory lib/msvc6/dll_mda.

● To use database connectivity on Windows from an application that integrates the OPL library, you need to check that the dynamic link libraries required by DB Link can be

100I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 103: OPL studio 3.7 Component Libraries User’s Manual

Datab

ase C

on

nectivity

S P E C I F I C R D B M S S E T T I N G S

found in the PATH variable. (Example for msvc6/stat_mda, COM or JNI applications: set PATH=c:\ilog\OPLSt37\lib\msvc6\dll_mda;%PATH%)

Dynamic link libraries are provided with OPL Studio 3.7. These dll files are for msvc6/stat_mda, COM/ActiveX and Java. They can be found in <OPLDIR>\lib\msvc6\dll_mda. For the other ports, you need to install ILOG DB Link 5.0.

● In the case of deployment on another machine, make sure that the PATH variable of the target machine indicates where the dynamic drivers are located.

Consult the README file for details.

Troubleshooting

Here we give troubleshooting recommendations for the following cases:

◆ An ILOG DB Link Driver is not Found

◆ A Database Client Dynamic Library is not Found

◆ An Undefined Symbol Exists at Runtime or Crash.

An ILOG DB Link Driver is not Found

The symptom is the message:

DBconnection: Dynamic library not found.

On Windows

First make sure that your PATH variable contains the directory in which the ILOG DB Link drivers are located.

◆ For Java and COM/ActiveX

<OPLDIR>\lib\msvc6\dll_mda

◆ For C++

The dll DB drivers for msvc6/stat_mda can be found in <OPLDIR>\lib\msvc6\dll_mda. For the other ports, you need to install ILOG DB Link 5.0 and its latest patch.

You cannot connect to a database through the single threaded ports.

If the symptom persists, make sure that you have not defined an ILDHOME environment variable. If an ILDHOME environment variable exists, ILOG DB Link will read the specified dblink.ini file to select the right DB Link driver. Check that the dblink.ini file specified in ILDHOME is equivalent to the dblink.ini file located in the directory <OPLDIR>/bin.

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 101

Page 104: OPL studio 3.7 Component Libraries User’s Manual

S P E C I F I C R D B M S S E T T I N G S

If you have a dblink.ini file in your %WINDIR% directory, make sure that it is equivalent to the dblink.ini file located in the <OPLDIR>/bin directory.

On UNIX

First make sure that your LD_LIBRARY_PATH variable (or SHLIB_PATH on HP, or LIBPATH on RS6000) contains the directory in which the DB Link drivers are located.

◆ For Java

<OPLDIR>/lib/rs6000_4.3_5.0/shared_mt

or <OPLDIR>/lib/sparc_5_5.0/shared_mt

or <OPLDIR>/lib/ultrasparc_5_5.0/shared_mt:<OPLDIR>/lib/sparc_5_5.0/shared_mt (ensure that you keep this order)or <OPLDIR>/lib/i86_linux2_glibc2.2_gcc3.0/shared_mt

or <OPLDIR>/lib/hp32_11_3.15/shared

NOTE: On ultrasparc, the path must first specify <OPLDIR>/lib/ultrasparc_5_5.0/shared_mt in order to find the OPL dynamic library, and then <OPLDIR>/lib/sparc_5_5.0/shared_mt in order to find the DB Link drivers.

◆ For C++

<OPLDIR>/lib/rs6000_4.3_5.0/shared_mt

or <OPLDIR>lib/sparc_5_5.0/shared_mt

or <OPLDIR>/lib/i86_linux2_glibc2.2_gcc3.0/shared_mt

or <OPLDIR>/lib/hp32_11_3.15/shared

If the symptom persists, make sure you have not defined an ILDHOME environment variable. If an ILDHOME environment variable exists, ILOG DB Link will read the specified dblink.ini file to select the right DB Link driver. With DB Link 5.0 the dblink.ini file is no longer mandatory, so just remove it.

A Database Client Dynamic Library is not Found

Make sure you that you have installed the database client and it is correctly configured. Check that your environment variables are correct (see the README file).

An Undefined Symbol Exists at Runtime or Crash

ILOG OPL 3.7 is, in theory, independent of ILOG DB Link, since it comes with all the ILOG DB Link dynamic link libraries. In certain cases, on UNIX platforms, however, the ILOG DB Link drivers have to be relinked for the platform and database release that OPL needs to connect to. Please consult the ILOG DB Link documentation that explains how to rebuild the DB Link drivers.

102I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 105: OPL studio 3.7 Component Libraries User’s Manual

Datab

ase C

on

nectivity

S P E C I F I C R D B M S S E T T I N G S

In this specific case:

1. Install ILOG DB Link 5.0 and its latest patches.

2. Relink the DB Link drivers for the platform and RDBMS in question.

3. Add the ILOG DB Link 5.0 dynamic library directory at the beginning of your LD_LIBRARY_PATH (or SHLIB_PATH on HP, or the LIBPATH environment variable on RS6000).

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 103

Page 106: OPL studio 3.7 Component Libraries User’s Manual

S P E C I F I C R D B M S S E T T I N G S

104I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 107: OPL studio 3.7 Component Libraries User’s Manual

S A M P L E S

List of Code Samples

2.1 Implementing an Error Reporter in Visual Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.2 Complete Bridge Example in Visual Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2.3 Complete Multiproduction Example in Visual Basic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

5.1 The VBA Code for the Transport Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

6.1 Implementing an Error Reporter in C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

6.2 Complete Bridge Example in C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

6.3 Output for the Bridge Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

6.4 Complete Multiproduction Example in C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

9.1 Declarations in warehouserules.mod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

9.2 Constraints in warehouserules.mod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

9.3 IRL Code Calling OPL Adaptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

9.4 Implementing the OPLadaptable Interface in Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

9.5 Loading an OPL Model and Data Buffer and Solving the Optimization Problem . . . . . . . . . . . . . . . . . . . 91

9.6 Returning the Result of Optimization to the Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

9.7 Result Displayed in the ILOG Rule Builder Console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 105

Page 108: OPL studio 3.7 Component Libraries User’s Manual

C O D E S A M P L E S

106I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 109: OPL studio 3.7 Component Libraries User’s Manual

I N D E X

Index

A

accessing datafrom C++ 60from VB 28

accessing the OPL enginefrom C++ 52from Java 66from VB 21

Apache web server 71architecture of component libraries 11array in an OPL model

C++ 54VB 22

ASP Script 40, 44

B

bridge exampleC++ 51, 52VB 15, 16

business constraints 82business object model 84, 86business rules 81, 82, 83, 84, 89

C

C++ examplesbridge.cpp 51, 52mulprod.cpp 51, 59

closing the OPLsolver instance (C++) 55, 61code entry (Visual Basic) 20COM interface in C+ 31COM interface in Visual Basic 19component libraries architecture 11component libraries, location 13COPLsolver instance

closing in VB 23, 29creating in JScript 38creating in VB 21, 27

creating a project in Visual Basic 16creating an OPLsolver instance

C++ 52, 59Java 68

customizing an OPL model 83

D

data accessC++ 60VB 28

data declarationC++ 60VB 28

data loadingC++ 53VB 21

data modificationC++ 59, 60VB 27, 29

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 107

Page 110: OPL studio 3.7 Component Libraries User’s Manual

I N D E X

databaseconnectivity 97connectivity troubleshooting 101settings 100

DB Linkarchitecture 98key 97libraries 97

displaying the solution in JScript 39

E

embedding the Java library in a web server 71entering code (Visual Basic) 20error handling

C++ 55Java 69VB 23

error reporterC++ 52Java 68VB 24

errors in DB connectivity 101examples

C++ 51, 52, 59Excel VBA 45Java 67JavaServer Pages 71, 75Visual Basic 15, 16, 20, 27Visual Basic .NET 79Visual C# .NET 80

Excel VBA example 45

H

handling errorsC++ 55Java 69VB 23

HTML, instantiating the solver object 39

I

ILM (ILOG License Manager)Java 72

scripting languages 40initializing data

C++ 60VB 28

instance dataC++ 59VB 27

instances of a modelC++ 59VB 27

integrate an OPL model into JRules 81integrating the OPL engine 11interacting with the OPL engine

from C++ 52from VB 21

interfacing with Excel via VBA 45interfacing with OPL

from ASP Script 40from C++ 51from Excel 45from Java 66from JavaServer Pages 71from VBScript 37from Visual Basic 15from Visual Basic .NET 78from Visual C# .NET 79

interfacing with OPLscript 95IOPLerrorReporter instance 95IRL (ILOG Rule Language) 88, 89iterating over an OPL enumeration

C++ 53, 54VB 22

J

Java exampleon UNIX 66on Windows 66the code 67

Java Native Interface (JNI) 65, 66JavaServer Pages (JSP) 65JRules 81, 85JScript code 38JSP example

code 75

108I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L

Page 111: OPL studio 3.7 Component Libraries User’s Manual

I N D E X

location 71

K

keys required 10java 72OPLScript 95scripting languages 36, 40

L

library location 13licenses required 10

Java 72OPLScript 95scripting languages 40

loading a model and dataC++ 53Java 68JScript 38VB 21

location of component libraries 13

M

model instancesC++ 59VB 27

model loading 68C++ 53JScript 38VB 21

model solvingC++ 53, 59Java 68JScript 39VB 21, 27

modifying dataC++ 59, 60VB 27, 29

multiproduction exampleC++ 51, 59VB 15, 27

O

OPL component, referenced from VB 18OPL engine

access from C++ 52access from VB 21

OPL enumerationreferenced from C++ 54referenced from VB 22

OPLCOMLib (Visual Basic) 19OPLerrorReporter instance 95OPLscript 95OPLscriptSolver instance 95OPLServer type library, selecting in VB 18OPLsolver instance

C++ 52, 55, 59, 61Java 68

optimal objectiveC++ 53VB 21

P

printing the solutionC++ 53Java 69JScript 39VB 22

R

referencing an array in the OPL modelC++ 54VB 22

referencing an OPL enumerationC++ 54VB 22

referencing COPLsolver (VB) 21referencing the OPL component from VB 18resetting the model

C++ 61VB 29

I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L 109

Page 112: OPL studio 3.7 Component Libraries User’s Manual

I N D E X

S

scripting languagesASP Script 40, 44JScript 38VBScript 37, 39

setting an error reporterC++ 52VB 24

solving a modelC++ 53Java 68JScript 39VB 21

solving several instances of a modelC++ 59VB 27

Sun Java Web Server 71

T

Tomcat JavaServer Pages 71troubleshooting DB connectivity 101

V

VBScript 37, 39Visual Basic .NET example

abridge.mod 79Visual Basic examples

bridge.vbp 15, 16mulprod.vbp 15, 27

Visual C# examplequeens8.mod 80

visualizing the COM interface in Visual Basic 19

W

warehouse project 83web server

Apache 71Sun Java Web Server 71

110I L O G O P L S T U D I O 3 . 7 — C O M P O N E N T L I B R A R I E S U S E R ’ S M A N U A L