mmquad



The mmquad module extends the Mosel language with a new type for representing quadratic expressions.To use this module, the following line must be included in the header of the Mosel model file:

 uses 'mmquad'

The first section presents the new functionality for the Mosel language that is provided by mmquad, namely the new type qexp and a set of subroutines that may be applied to objects of this type.

Via the inter-module communication interface, the module mmquad publishes several of its library functions. These are documented in the second section. By means of an example it is shown how the functions published by mmquad can be used in another module for accessing quadratic expressions and working with them.

New functionality for the Mosel language

The type qexp and its operators

The module mmquad defines the type qexp to represent quadratic expressions in the Mosel Language. As shown in the following example, mmquad also defines the standard arithmetic operations that are required for working with objects of this type. By and large, these are the same operations as for linear expressions (type linctr of the Mosel language) with in addition the possibility to multiply two decision variables or one variable with itself. For the latter, the exponential notation x^2 may be used (assuming that x is of type mpvar).

Example: using mmquad for Quadratic Programming

Quadratic expressions as defined with the help of mmquad may be used to define quadratic objective functions for Quadratic Programming (QP) or Mixed Integer Quadratic Programming (MIQP) problems. The Xpress-Optimizer module mmxprs for instance accepts expressions of type qexp as arguments for its optimization subroutines minimize and maximize, and for the procedure loadprob (see also the mmxprs Reference Manual). The following

model "Small MIQP example"
 uses "mmxprs", "mmquad"
  
 declarations
  x: array(1..4) of mpvar
  Obj: qexp
 end-declarations

! Define some linear constraints
 x(1) + 2*x(2) - 4*x(4) >= 0
 3*x(1) - 2*x(3) - x(4) <= 100
 x(1) + 3*x(2) + 3*x(3) - 2*x(4) => 10
 x(1) + 3*x(2) + 3*x(3) - 2*x(4) <= 30 

 2 <= x(1); x(1) <= 20
 x(2) is_integer; x(3) is_integer
 x(4) is_free

! The objective function is a quadratic expression
 Obj:= x(1) + x(1)^2 + 2*x(1)*x(2) + 2*x(2)^2 + x(4)^2

! Solve the problem and print its solution
 minimize(Obj)

 writeln("Solution: ", getobjval)
 forall(i in 1..4) writeln(getsol(x(i)))
end-model

Procedures and functions

The module mmquad overloads certain subroutines of the Mosel language, replacing an argument of type linctr by the type qexp.

exportprob
Export a quadratic problem to a file.
getsol
Get the solution value of a quadratic expression.

Published library functions

The module mmquad publishes some of its library functions via the service IMCI for use by other modules (see the Mosel Native Interface Reference Manual for more detail about services). The list of published functions is contained in the interface structure mmquad_imci that is defined in the module header file mmquad.h.

From another module, the context of mmquad and its communication interface can be obtained using functions of the Mosel Native Interface as shown in the following example.

static XPRMnifct mm;
XPRMcontext mmctx;
XPRMdsolib dso;
mmquad_imci mq;
void **quadctx;

dso=mm->finddso("mmquad");            /* Retrieve the mmquad module*/
quadctx=*(mm->getdsoctx(mmctx, dso, (void **)(&mq)));
                                      /* Get the module context and the
                                         communication interface of mmquad */

Typically, a module calling functions that are provided by mmquad will include this module into its list of dependencies in order to make sure that mmquad will be loaded by Mosel at the same time as the calling module. The ``dependency'' service of the Mosel Native Interface has to be used to set the list of module dependencies:

static const char *deplist[]={"mmquad",NULL};   /* Module dependency list */

static XPRMdsoserv tabserv[]=                   /* Table of services */
    {
     {XPRM_SRV_DEPLST, (void *)deplist}
    };

Complete module example

If the Mosel procedures write / writeln are applied to a quadratic expression, they print the address of the expression and not its contents (just the same would happen for types mpvar or linctr). Especially for debugging purposes, it may be useful to be able to display some more detailed information. The module example printed below defines the procedure printqexp that displays all the terms of a quadratic expression (for simplicity's sake, we do not retrieve the model names for the variables but simply print their addresses).

model "Test printqexp module"
 uses "printqexp"

 declarations
  x: array(1..5) of mpvar
  q: qexp
 end-declarations
 
 printqexp(10+x(1)*x(2)-3*x(3)^2)

 q:= x(1)*(sum(i in 1..5) i*x(i))
 printqexp(q)
end-model

Note that in this model it is not necessary to load explicitly the mmquad module. This will be done by the printqexp module because mmquad appears in its dependency list.

#include <stdlib.h>
#include "xprm_ni.h"
#include "mmquad.h"

/**** Function prototypes ****/
static int printqexp(XPRMcontext ctx,void *libctx);

/**** Structures for passing info to Mosel ****/
/* Subroutines */
static XPRMdsofct tabfct[]=
    {
     {"printqexp", 1000, XPRM_TYP_NOT, 1, "|qexp|", printqexp}
    };

static const char *deplist[]={"mmquad",NULL};   /* Module dependency list */

/* Services */
static XPRMdsoserv tabserv[]=
    {
     {XPRM_SRV_DEPLST, (void *)deplist}
    };

/* Interface structure */
static XPRMdsointer dsointer= 
    { 
     0,NULL, sizeof(tabfct)/sizeof(XPRMdsofct),tabfct, 
     0,NULL, sizeof(tabserv)/sizeof(XPRMdsoserv),tabserv
    };

/**** Structures used by this module ****/
static XPRMnifct mm;         /* For storing Mosel NI function table */


/**** Initialize the module library just after loading it ****/
DSO_INIT printqexp_init(XPRMnifct nifct, int *interver,int *libver, XPRMdsointer **interf)
{
 mm=nifct;                  /* Save the table of Mosel NI functions */
 *interver=MM_NIVERS;       /* Mosel NI version */
 *libver=MM_MKVER(0,0,1);   /* Module version */
 *interf=&dsointer;         /* Pass info about module contents to Mosel */

 return 0;
}

/**** Implementation of "printqexp" ****/
static int printqexp(XPRMcontext ctx, void *libctx)
{
 XPRMdsolib dso;
 mmquad_imci mq;
 mmquad_qexp q;
 void **quadctx;
 void *prev;
 XPRMmpvar v1,v2;
 double coeff;
 int nlin,i;
 
 dso=mm->finddso("mmquad");    /* Retrieve reference to the mmquad module*/
 quadctx=*(mm->getdsoctx(ctx, dso, (void **)(&mq)));
                               /* Get the module context and the
                                  communication interface of mmquad */

 q = XPRM_POP_REF(ctx);        /* Get the quadratic expression from the stack */
 
                               /* Get the number of linear terms */ 
 mq->getqexpstat(ctx, quadctx, q, &nlin, NULL, NULL, NULL);
                               /* Get the first term (constant) */
 prev=mq->getqexpnextterm(ctx, quadctx, q, NULL, &v1, &v2, &coeff);
 if(coeff!=0) mm->printf(ctx, "%g ", coeff);                           
 for(i=0;i<nlin;i++)           /* Print all linear terms */
 {
  prev=mq->getqexpnextterm(ctx, quadctx, q, prev, &v1, &v2, &coeff);
  mm->printf(ctx,"%+g %p ", coeff, v2); 
 }
 while(prev!=NULL)             /* Print all quadratic terms */
 {
  prev=mq->getqexpnextterm(ctx, quadctx, q, prev, &v1, &v2, &coeff);
  mm->printf(ctx,"%+g %p * %p ", coeff, v1, v2);
 }
 mm->printf(ctx,"\n");

 return XPRM_RT_OK; 
}

Description of the library functions

clearqexpstat
Free the memory allocated by getqexpstat.
getqexpnextterm
Enumerate the terms of a quadratic expression.
getqexpsol
Evaluate a quadratic expression.
getqexpstat
Get information about a quadratic expression.


If you have any comments or suggestions about these pages, please send mail to docs@dashoptimization.com.