bin: using Mosel's binary format
Topics covered in this section:
The bin driver implements a structured, architecture-independent binary format that can handle cross platform files and supports the full set of data structures that may be contained in initializations blocks. It can be used for exchanging data between Mosel models or between a Mosel model and a host application, particularly in the context of distributed applications using the Mosel remote invocation library XPRD (see the program examples in Part `V. Remote invocation of Mosel' of the `Xpress Mosel User Guide'). The bindrv library that provides the binary reading and writing functionality on the library level is independent of Mosel and can be used with any C or Java program. It comes with a documentation of its own, the `bindrv Library Reference Manual'.
Mosel code like the following expects input and output data from files in binary format.
initialisations from "bin:burgdatabin" [VALUE, WEIGHT] as "BurgData" end-initialisations ... initialisations to "bin:resdatabin" SOLTAKE as "SolTake" evaluation of getobjval as "Objective" end-initialisations
The file binary file burgdatabin has the same structure as the text file burglar.dat that we have seen in Section Example problem.
BurgData: [(camera) [ 15 2] (necklace) [100 20] ... (brick) [ 1 10] ]
The following C code produces the corresponding file burgdatabin in bindrv binary format. Notice the use of controls (label, open and close a list, open and close an index) through which we represent the structure of the file.
#include "bindrv.h" /**** Input data ****/ static double vdata[]={15,100,90,60,40,15,10, 1}; /* VALUE */ static double wdata[]={ 2, 20,20,30,40,30,60,10}; /* WEIGHT */ static char *ind[]={"camera", "necklace", "vase", "picture", "tv", "video", "chest", "brick" }; /* Index names */ int datasize=8; /**** Create a BinDrv data file ****/ static void writeburgbin(void) { FILE *f; s_bindrvctx bdrv; int i; f=fopen("burgdatabin","w"); bdrv=bindrv_newwriter((size_t (*)(const void *,size_t,size_t,void*))fwrite,f); bindrv_putctrl(bdrv,BINDRV_CTRL_LABEL); bindrv_putstring(bdrv,"BurgData"); bindrv_putctrl(bdrv,BINDRV_CTRL_OPENLST); /* [ */ for(i=0;i<datasize;i++) { bindrv_putctrl(bdrv,BINDRV_CTRL_OPENNDX); /* ( */ bindrv_putstring(bdrv,ind[i]); /* index */ bindrv_putctrl(bdrv,BINDRV_CTRL_CLOSENDX); /* ) */ bindrv_putctrl(bdrv,BINDRV_CTRL_OPENLST); /* [ */ bindrv_putreal(bdrv,vdata[i]); /* val1 */ bindrv_putreal(bdrv,wdata[i]); /* val2 */ bindrv_putctrl(bdrv,BINDRV_CTRL_CLOSELST); /* ] */ } bindrv_putctrl(bdrv,BINDRV_CTRL_CLOSELST); /* ] */ bindrv_delete(bdrv); fclose(f); }
The structure of the binary result file resdatabin corresponds to this text file:
'SolTake': [('camera') 1 ('necklace') 1 ('vase') 1 ('picture') 1 ('tv') 0 ('video') 1 ('chest') 0 ('brick') 0] 'Objective': 280
The binary file can be read and displayed with the following C code—the routines bindrv_get* follow the same logic as the bindrv_put* routines we have seen in the writing function, decoding the file structure via controls for labels, square and round brackets (for lists and indices respectively). For clarity's sake, we have implemented only a limited amount of checks whether the detected structure and data types correspond to the expected format.
static void readburgbin(void) { FILE *f; s_bindrvctx bdrv; union { int i; double r; char b; char *str; BINDRV_LONG l;} val; f=fopen("resdatabin","r"); bdrv=bindrv_newreader((size_t (*)(void *,size_t,size_t,void*))fread,f); bindrv_getctrl(bdrv,&(val.i)); if(val.i==BINDRV_CTRL_LABEL) { while(bindrv_nexttoken(bdrv)>=0) { bindrv_getstring(bdrv,&(val.str)); /* label: */ if(strcmp(val.str,"SolTake")==0) { free(val.str); printf("Solution values:\n"); bindrv_getctrl(bdrv,&(val.i)); /* [ */ while(bindrv_nexttoken(bdrv)>=0) { bindrv_getctrl(bdrv,&(val.i)); if(val.i== BINDRV_CTRL_LABEL) break; switch(val.i) { case BINDRV_CTRL_OPENNDX: /* ( */ printf(" take("); bindrv_getstring(bdrv,&(val.str)); /* index */ printf("%s",val.str); bindrv_getctrl(bdrv,&(val.i)); /* ) */ printf(")="); bindrv_getreal(bdrv,&(val.r)); /* value */ printf(" %g\n",val.r); break; case BINDRV_CTRL_CLOSELST: /* ] */ printf("\n"); break; default: printf("Unexpected token %d\n", val.i); exit(1); } } } else if(strcmp(val.str,"Objective")==0) { free(val.str); bindrv_getreal(bdrv,&(val.r)); printf("Objective value = %g\n", val.r); } else { printf("Unexpected label '%s'\n", val.str); free(val.str); exit(1); } } } else { printf("Unexpected token '%d'\n", val.i); exit(1); } bindrv_delete(bdrv); fclose(f); }
Java version of the example
The same binary files can be written and read with the Java version of the Bindrv library. The code producing the binary file burgdatabin looks as follows with Java—some of the calls to methods bdrv.put* have been combined for improved readability of our Java code (this does not impact the generated output).
/**** Input data ****/ static final double[] vdata={15,100,90,60,40,15,10, 1}; // VALUE static final double[] wdata={ 2, 20,20,30,40,30,60,10}; // WEIGHT static final String[] ind={"camera", "necklace", "vase", "picture", "tv", "video", "chest", "brick" }; // Index names static final int datasize=8; /**** Create a BinDrv data file ****/ static void writeBurgBin() throws IOException { BinDrvWriter bdrv; FileOutputStream f; f=new FileOutputStream("burgdatabin"); bdrv=new BinDrvWriter(f); bdrv.putControl(bdrv.CTRL_LABEL).put("BurgData"); // label: bdrv.putControl(bdrv.CTRL_OPENLST); // [ for(int i=0;i<datasize;i++) { // (index) bdrv.putControl(bdrv.CTRL_OPENNDX).put(ind[i]).putControl(bdrv.CTRL_CLOSENDX); bdrv.putControl(bdrv.CTRL_OPENLST).put(vdata[i]).put(wdata[i]); bdrv.putControl(bdrv.CTRL_CLOSELST); // [val1 val2] } bdrv.putControl(bdrv.CTRL_CLOSELST); // ] f.close(); }
The Java code for reading the binary results file resdatabin has the same structure as the C version that we have seen in the previous section. Again, we have implemented only a limited number of tests whether the data read corresponds to the expected format.
static void readBurgBin() throws IOException { BinDrvReader bdrv; FileInputStream f; int c; f=new FileInputStream("resdatabin"); bdrv=new BinDrvReader(f); if(bdrv.getControl()==BinDrvReader.CTRL_LABEL) { while(bdrv.nextToken()>=0) { String s=bdrv.getString(); // label: if(s.equals("SolTake")) { System.out.println("Solution values:"); bdrv.getControl(); while(bdrv.nextToken()>=0) { c=bdrv.getControl(); // [ if(c==BinDrvReader.CTRL_LABEL) break; switch(c) { case BinDrvReader.CTRL_OPENNDX: // ( System.out.print(" take("+bdrv.getString()+")="); // index bdrv.getControl(); // ) System.out.println(bdrv.getReal()); // value break; case BinDrvReader.CTRL_CLOSELST: // ] System.out.println(""); break; default: System.out.println("Unexpected Control"); System.exit(0); } } } else if(s.equals("Objective")) System.out.println("Objective value = "+bdrv.getReal()); else { System.out.println("Unexpected label "+s); System.exit(0); } } } else { System.out.println("Unexpected token"); System.exit(1); } f.close(); }
mmjobs version of the example
A model with an mmjobs version of the application program has already been shown in Section mmjobs version of the example. From multiple models running on the same Mosel instance, we now move one step further, namely, running the submodel on a remote Mosel instance. Before compiling the submodel, we connect to another Mosel instance. This instance is used for compiling to model, the source of which is located on our local machine running the main model. Remote access to a file is achieved via the rmt driver (equally defined by module mmjobs). In our example, data is exchanged via shared memory (shmem) accessed from a remote Mosel instance (rmt, optionally followed by a node number in square brackets) using binary format (bin), resulting in extended file names that combine several driver prefixes, for example, bin:rmt:[-1]shmem:burgdata to access binary data held in shared memory of the parent node.
model "Run model burglar remotely IO" uses "mmjobs", "mmsystem" declarations modBurg: Model ! Submodel moselInst: Mosel ! Mosel instance ISet,SSet: set of string ! Index set for data arrays V,W: array(ISet) of real ! Data arrays SolTake: array(SSet) of real ! Solution values end-declarations V:: (["camera","necklace","vase","picture","tv","video","chest","brick"]) [15, 100, 90, 60, 40, 15, 10, 1] W:: (["camera","necklace","vase","picture","tv","video","chest","brick"]) [ 2, 20, 20, 30, 40, 30, 60, 10] !!! Select the (remote) machines to be used: !!! Use names, IP addresses, or empty string for the node running this model MOSINST:= "" ! Connect to a remote instance if connect(moselInst, MOSINST)<>0 then exit(1); end-if ! Compile the model remotely if compile(moselInst, "", "rmt:"+expandpath("burglar2m.mos"), "shmem:burglar.bim")<>0 then exit(2); end-if load(moselInst, modBurg, "shmem:burglar.bim") ! Load the bim file fdelete("rmt:["+getnode(moselInst)+"]shmem:burglar.bim") ! bim file is no longer needed setdefstream(modBurg, F_OUTPUT, "null:") ! Disable output from submodel ! Save data in shared memory on local host initializations to "bin:shmem:burgdata" V as "VALUE" W as "WEIGHT" end-initializations ! Start model execution, setting parameters run(modBurg, "DATA='bin:rmt:[-1]shmem:burgdata',SOL='bin:rmt:[-1]shmem:burgsol'") wait ! Wait for model termination dropnextevent ! Ignore termination event message ! Retrieve solution from shared memory initializations from "bin:shmem:burgsol" SolTake end-initializations forall(i in SSet) writeln(" take(", i, "): ", SolTake(i)) end-model
© 2001-2025 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.