Introduction
Topics covered in this chapter:
The Mosel language is extensible by the means of modules. A module may define
- constants
- subroutines
- types
- operators for the types defined by the module
- I/O drivers
- control parameters
Constants that are used by several Mosel programs could be defined by a module; a module may also publish constants that are to be used in combination with its types or subroutines.
Subroutines are probably the most common use of modules. These may be entirely new functions or procedures, or overload existing subroutines of Mosel.
Defining new types requires a little more work, but as a result the user defined types will be no different from Mosel's own types (like integer or mpvar). So user defined types can be used in complex data structures (arrays, sets), read from file in initializations sections, appear as parameters of subroutines, or have operators applied to them.
The Mosel distribution comes with a set of I/O drivers that provide interfaces to specific data sources (such as ODBC) or serve to exchange information between the application running the Mosel libraries and a Mosel model in a very direct way by providing various possibilities of passing data back and forth in memory. The user may define additional drivers, for instance to read/write compressed or encrypted files. For examples of the use and definition of I/O drivers the reader is refered to the Xpress Whitepaper `Generalized file handling in Mosel'.
Control parameters make little sense on their own. They may be used for directing the behavior of subroutines defined by a module (e.g. algorithmic settings) or obtaining status information from a module. The values of control parameters may be changed from within a Mosel program.
Depending on the purpose of the module, it needs to provide one or several of the following to Mosel
- a list of constants
- a list of subroutines
- a list of types
- a list of services
Services are functions that Mosel calls at predefined places to perform tasks that may be characterized as `administration' of the module: the definition of types makes a reset functionality necessary; control parameters are retrieved and enumerated through service functions; other service functions may be activated during the checking of the version number and when Mosel unloads the module. I/O drivers are also defined as services. A module that only defines constants or subroutines may not require any specific services.
Mosel expects the required information to be formatted correctly. In the following pages we shall see a few examples how this is to be done. The first example, in Chapter Defining constants, shows how different types of constants are defined in a module. The following chapter lists and comments the complete code of a module that implements a single subroutine. Chapters Creating external types and Creating external types: second example give examples of the implementation of new types. In Chapter Creating external types this is a structure grouping data items of various types and in Chapter Creating external types: second example a new numerical type is defined. Chapter Control parameters adds the definition of parameters to the module from Chapter Creating external types.
A specific set of NI functions and data structures are dedicated to the generation and handling of the matrix representation for LP/MIP solvers, Chapter Implementing an LP/MIP solver interface documents an example implementation for basic solver access functionality for Xpress Optimizer.
If the Mosel program that uses a module is compiled and executed from a C program, then the definition of the module can be included directly in this C program. Chapter Defining a static module gives an example of such a static module.
Prerequisites
To be able to write your own modules you have to be very familiar with the way Mosel works, specifically the Mosel libraries. The implementation of a module (especially for defining new types) requires a fair amount of programming and a good experience in C programming is recommended.
Standard elements of a module
The following may serve as a check list for writing modules and a quick reference as to where to find the corresponding examples and documentation in this user guide:
- Module initialization (always required):
- Mosel Native Interface header function: Structures for passing information, Implementing the new subroutine, Complete module example
- main interface structure
examples: Interface structure, Interface structure, Implementing the new subroutine, Interface structure, Interface structure, Complete module example; - structure with the list of NI functions
example: Initialization function, Implementing the new subroutine, Complete module example - initialization function
examples: Initialization function, Initialization function, Implementing the new subroutine, Initialization function, Initialization function; documentation: Module initialization - module context
examples: Module context, Module context, Improved memory management for external types, Module context
- Definition of constants:
- entry in the list of constants
examples: List of constants, List of parameters; documentation: List of constants
- entry in the list of constants
- Definition of subroutines:
- entry in the list of subroutines
examples: List of subroutines, List of subroutines, List of subroutines, List of subroutines, List of subroutines, List of subroutines; documentation: List of subroutines - implementation
examples: Implementing the new subroutine, Other library functions and operators, Functions for handling parameters, Complete module example, Solver library calls, Implementation of callback handling, Implementing the 'writeprob' subroutine
- entry in the list of subroutines
- Definition of types:
- entry in the list of types
example: List of types, List of types, List of types; documentation: List of types - entry in the list of services
example: List of services; documentation: List of services - implementation of service XPRM_SRV_RESET: Service function reset, Improved memory management for external types, Implementation of services
- implementation of type-related functions
documentation: List of types
required function create: Type-related functions, Improved memory management for external types, Handling optimization problems
optional functions delete, tostr, fromstr, copy: Type-related functions, Improved memory management for external types, Handling optimization problems
- operators (entries in the list of subroutines)
examples: Structures for passing information, List of subroutines; documentation: Overview on operators in Mosel - implementation of operators
examples: Other library functions and operators, Definition of operators
- entry in the list of types
- Definition of I/O drivers:
- for examples see the Xpress Whitepaper `Generalized file handling in Mosel'
- Definition of control parameters:
- required parameter information (no predefined structure)
examples: Module context, List of parameters; documentation: Parameters - entries in the list of services
examples: List of services, List of services; documentation: List of services - implementation of service functions
required service XPRM_SRV_PARAM: Services related to parameters, Implementation of services
optional service XPRM_SRV_PARLST: Services related to parameters, Implementation of services - entries in the list of subroutines
examples: List of subroutines, List of subroutines; documentation: List of subroutines - implementation of the subroutines setparam and getparam: Functions for handling parameters, Solver library calls
- required parameter information (no predefined structure)
- Definition of a MIP solver interface:
- MIP solver interface structure
example: Module context - implementation of matrix handling functions
examples: Implementation of MIP solver interface functions, Generating names for matrix entries
- MIP solver interface structure
Creating a DSO
From the operating system point of view, a module is a dynamic library (Dynamic Shared Object, DSO). The name of this DSO is the name of the module with the file extension .dso. For instance, assuming we have written a file test.c to implement the module testmodule, the DSO will be called testmodule.dso. To build this DSO, under Linux the following compilation command should be used:
gcc -shared -D_REENTRANT -I${MOSEL}/include test.c -o testmodule.dso
Similarly for Unix (Sun Solaris):
cc -G -D_REENTRANT -I${MOSEL}/include test.c -o testmodule.dso
The corresponding command under Windows:
cl -MD -LD -Fetestmodule.dso -I%MOSEL%\include test.c
Example makefiles are provided with the module examples in the Mosel distribution.
Mosel looks for the DSOs in the directory dso under the installation directory of Mosel (see Section 2.3.1 Directive uses of the Mosel Language Reference for further detail). If user-written DSOs are placed in a different directory, the environment variable MOSEL_DSO needs to be set to their location(s). The MOSEL_DSO is expected to be a list of paths conforming to the operating system conventions.
Modules vs. packages
Release 2.0 of Mosel introduced the possibility to write libraries for Mosel directly in the Mosel language, such a library is called a package. Packages are included into models with the uses statement for dynamic loading (the package BIM needs to be present for model execution), in the same way as this is the case for modules (DSO). Alternatively, packages can be loaded statically via imports in which case they get included in the model BIM file (this option is not available for modules that are always dynamic).
From the implementation and functionality points of view the two ways of writing Mosel libraries are not the same and the choice between packages and modules depends largely on the contents and intended use of the library. In some cases it may be convenient to split the implementation of a library into two parts, one as a module and the other as a package. If a module and a package on the specified DSO path have the same name, the package will be loaded by Mosel.
The following list summarizes the main differences between packages and modules.
- Definition
- Package
- library written in the Mosel language
- Module
- dynamic library written in C that obeys the conventions of the Mosel Native Interface
- Package
- Functionality
- Package
- define
- symbols
- subroutines
- types
- control parameters
- define
- Module
- extend the Mosel language with
- constant symbols
- subroutines
- operators
- types
- control parameters
- IO drivers
- extend the Mosel language with
- Package
- Efficiency
- Package
- like standard Mosel models
- Module
- faster execution speed
- higher development effort
- Package
- Use
- Package
- making parts of Mosel models re-usable
- deployment of Mosel code whilst protecting your intellectual property
- Module
- connection to external software
- time-critical tasks
- definition of new I/O drivers and operators for the Mosel language
- Package
With every module example in this manual we shall discuss the possibilities of implementing similar functionality as a package. For a detailed introduction to writing packages the reader is refered to the chapter 'Packages' of the Mosel User Guide.
© 2001-2024 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.