FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Data output to text files, spreadsheets and databases, and to memory

Description

This example shows different ways of writing out data from a Mosel model, namely to

  1. differently formatted text files (example trio_out.mos described in the 'Mosel User Guide', Section 10.2 File output): using 'initializations to', free-format output with 'write'/'writeln', or 'diskdata' format,
  2. spreadsheets or databases (examples duo_out.mos, duosheet_out.mos, duooci_out.mos, duoexc_out.mos, and duodd_out.mos described in the Xpress Whitepaper 'Using ODBC and other database interfaces with Mosel'),
  3. the application (C/Java) executing the Mosel model (examples dataoutputc.mos and dataoutputj.mos



Accessing spreadsheets and databases

Using initializations to data is written to spreadsheets or databases through the ODBC connector in a similar way as text files are accessed; all necessary SQL commands are generated automatically. With the extended filename to "mmodbc.odbc:data.mdb" the data will be written to the MS Access database data.mdb and the string "mmodbc.odbc:DSN=mysql;DB=data" could be used to access a mysql database named data.

Instead of using an initializations block, we may write out data from a Mosel model directly with the corresponding SQL statements (this makes it possible, for example, to clear the data table before writing to it - this functionality is not available with spreadsheets)

 SQLconnect("data.sqlite")
 SQLexecute("delete from MyOutTable")
 SQLexecute(
  "insert into MyOutTable (Index1,Index2,AValue) values (?,?,?)", A)
 SQLdisconnect

When working with Excel spreadsheets it is recommended to use one of the dedicated spreadsheet drivers from the mmsheet module: with the excel driver, the spreadsheet may remain open while writing to it from a Mosel model, in this case the data written out to the spreadsheet does not get saved, making it possible to re-run the application with different data sets without causing any lasting modifications to your spreadsheet. All other spreadsheet drivers require the spreadsheet file to be closed. The xls/xlsx drivers do not require an installation of Excel and are available for certain non-Windows platforms.

The module mmoci (requires a separate license) defines a software-specific interface to Oracle databases that is used in a similar way as the ODBC connection provided through mmmodbc. With initializations to an extended filename will take a form like "mmoci.oci:debug;myname/mypassword@dbname" and it is equally possible to use PL/SQL statements directly.



Data output in memory using I/O drivers

Using initializations to it is also possible to send data from a Mosel model in memory to the calling application (C/C++, C# or Java). This is done using a combination of the I/O drivers mem (data held in memory) and raw driver (data in binary format) in C, drivers dotnet and dotnetraw in C# programs and drivers java and jraw in Java programs.



Other options for data output

Other possibilities of outputting data from a Mosel model include

  • Use of the Mosel Libraries: information about the model objects is retrieved after the execution of the model is terminated. See the 'Mosel User Guide', Part III Working with the Mosel Libraries and the example dataafterexec.c.
  • Redirection of the output and error streams: to a file or to the calling application with the help of a callback function (I/O driver cb).
  • Static modules: data exchange between the calling application and a model via custom functions, using the Mosel Native Interface. See the example datainout.c.
  • Custom formats/custom data sources: the Mosel Native Interface allows the user to implement his own I/O drivers (to be used with initializations blocks and all other Mosel functionality involving file access, such as matrix export or model compilation). Possible uses of such user-written drivers include encoding/decoding of data on the fly or compression/decompression of data. See the Xpress Whitepaper 'Generalized file handling in Mosel' for the complete code and documentation of an example implementing a compression driver with the zip library.

    Furthermore, the Mosel I/O driver pipe may be used to channel the output of a Mosel model to an external program. See the section on I/O drivers in the 'Mosel Libraries Reference Manual' for more information.



Further explanation of this example: Whitepapers 'Using ODBC and other database interfaces with Mosel' and 'Generalized file handling in Mosel'


Source Files

Data Files





datainout.c

/*******************************************************
   Mosel Example Problems
   ====================== 

   file datainout.c
   ````````````````
   Exchanging data between model and host application
   through a static module.
   - Sparse data format -
   
   (c) 2008 Fair Isaac Corporation
       author: S.Heipcke, Mar. 2006
********************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "xprm_mc.h"
#include "xprm_ni.h"

typedef struct
{                                 /* Initial values for array 'data': */
 int index_i,index_j;             /*   index names */
 double value;                    /*   data value */
} s_mydata;

static s_mydata data[]={{1,1,12.5}, {2,3,5.6}, {10,9,-7.1}, {3,2,1}};

s_mydata dataout[9];


/* Initialization function of the module 'datainout' */
static int datainout_init(XPRMnifct nifct, int *interver,int *libver,
		XPRMdsointer **interf);

/*****************/
/* Main function */
/*****************/
int main()
{
 XPRMmodel mod;
 int result;
 char params[120];

 if(XPRMinit())                   /* Initialize Mosel */
  return 1;

 /* Register 'datainout' as a static module (=stored in the program) */
 if(XPRMregstatdso("datainout",datainout_init))
  return 2;

 /* Parameters: the address of the data tables and their size */
 sprintf(params,"INDATA='%p',INSIZE=%d,OUTDATA='%p',OUTSIZE=%d", 
         data,sizeof(data)/sizeof(s_mydata), 
	 dataout,sizeof(dataout)/sizeof(s_mydata));

 if(XPRMexecmod(NULL, "datainout.mos", params, &result, &mod))
  return 3;                       /* Execute the model file */

 return result;
}

/************************* Body of the module 'datainout' ******************/

static int dt_readdata(XPRMcontext ctx,void *libctx);
static int dt_writedata(XPRMcontext ctx,void *libctx);

static XPRMdsofct tabfct[]=
        {
         {"readdata",1000,XPRM_TYP_NOT,3,"AII.rsi",dt_readdata},
         {"writedata",1001,XPRM_TYP_NOT,3,"AII.rsi",dt_writedata}
        };

static XPRMdsointer dsointer=
        {
         0,NULL,
         sizeof(tabfct)/sizeof(XPRMdsofct),tabfct,
         0,NULL,
         0,NULL
        };

static XPRMnifct mm;             /* To store the mosel function table */

/*****************************************/
/* Initialization function of the module */
/*****************************************/
static int datainout_init(XPRMnifct nifct, int *interver,int *libver,
		XPRMdsointer **interf)
/* The following header is required to compile 'datainout' as a DSO file:
DSO_INIT datainout_init(XPRMnifct nifct, int *interver,int *libver,
		XPRMdsointer **interf)
*/
{
 mm=nifct;                      /* Save the table of functions */
 *interver=XPRM_NIVERS;         /* The interface version we are using */
 *libver=XPRM_MKVER(0,0,1);     /* The version of the module: 0.0.1 */
 *interf=&dsointer;             /* Our interface */

 return 0;
}

/*********************************************************/
/* Initialize an array with data in C:                   */
/*  readdata(array(range,range) of real,string,integer)  */
/*********************************************************/
static int dt_readdata(XPRMcontext ctx,void *libctx)
{
 XPRMarray arr;
 XPRMstring adr_s;
 s_mydata *adr;
 int indices[2],siz,i;

 arr=XPRM_POP_REF(ctx);             /* The array */
 adr_s=XPRM_POP_STRING(ctx);        /* Data location (as a string) */
 siz=XPRM_POP_INT(ctx);             /* Data size */
 sscanf(adr_s, "%p", &adr);         /* Get the address from the string */

 for(i=0;i<siz;i++)
 {
  indices[0]=adr[i].index_i;
  indices[1]=adr[i].index_j;
  mm->setarrvalreal(ctx, arr, indices, adr[i].value);
 }
 return XPRM_RT_OK;
}

/**********************************************************/
/* Initialize a C array with data from the model:         */
/*  writedata(array(range,range) of real,string,integer)  */
/**********************************************************/
static int dt_writedata(XPRMcontext ctx,void *libctx)
{
 XPRMarray arr;
 XPRMstring adr_s;
 XPRMset ndxset;
 s_mydata *adr;
 int indices[2],i,siz;

 arr=XPRM_POP_REF(ctx);             /* The array */
 adr_s=XPRM_POP_STRING(ctx);        /* Data location (as a string) */
 siz=XPRM_POP_INT(ctx);             /* Data size */
 sscanf(adr_s, "%p", &adr);         /* Get the address from the string */

 i=0;                               /* Print out values read from the model */
 if(!mm->getfirstarrtruentry(arr,indices))   /* Get first index tuple */
  do
  {                                 /* Get the array value */
   mm->getarrval(arr, indices, &(adr[i].value));
   adr[i].index_i=indices[0];       /* Get the indices */
   adr[i].index_j=indices[1];
   printf(" A(%d,%d): %g\n", adr[i].index_i, adr[i].index_j,
         adr[i].value);
   i++;	 
  } while(!mm->getnextarrtruentry(arr,indices) && i<siz);  /* Get next index */
 return XPRM_RT_OK;
}

Back to examples browserPrevious exampleNext example