Initializing help system before first use

cb: output to callback functions

Using the cb I/O driver a function is used as a file. Depending on the type of stream to manage (i.e. a general stream or a for an initializations block) a specific function type as to be provided. In the following example we define a callback function to receive the output stream. Our function simply prints all output lines preceeded by Mosel: .

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

/* Callback function to handle output */
long XPRM_RTC cbmsg(XPRMmodel model, void *info, char *buf, unsigned long size)
{
/* Note: 'model' is NULL if the stream is used outside of an execution */
 printf("Mosel: %.*s", (int)size, buf);
 return 0;
}

int main()
{
 XPRMmodel mod;
 int result;
 char outfile_name[40];           /* File name of output stream */

 XPRMinit();                      /* Initialize Mosel */

                                  /* Prepare file name for output stream   */
                                  /* using 'cb' driver:                    */
                                  /* "cb:function pointer[/callback data]" */
 sprintf(outfile_name, "cb:%p", cbmsg);

                                  /* Set default output stream to callback */
 XPRMsetdefstream(NULL, XPRM_F_WRITE, outfile_name);

                                  /* Execute = compile/load/run model file
                                               `burglar2.mos'
                                     Generates the BIM file `burglar2.bim' */
 XPRMexecmod(NULL, "burglar2.mos", NULL, &result, NULL);

 return 0;
}

The output produced by this program looks as follows:

Mosel: Solution:
Mosel:  Objective: 280
Mosel: [(`camera',1),(`necklace',1),(`vase',1),(`picture',1),(`tv',0),
(`video',1),(`chest',0),(`brick',0)] 

Callback functionality can also be used for data I/O in initializations blocks—see Chapters 13.4.3 and 14.1.7.3 (Exchanging data between an application and a model Dynamic data) of the `Mosel User Guide' for C and Java examples respectively.

Java version of the example

The stream redirections functions of the Mosel Java library expect objects of the type InputStream or OutputStream. The following Java program implements the same behavior as the C program above. With Java, we replace the cb driver by the Java memory driver java.

// OutputStream class to handle default output
 public static class MyOut extends OutputStream
 {
  public void flush()
  { System.out.flush(); }
  public void write(byte[] b)
  {
   System.out.print("Mosel: ");
   System.out.write(b, 0, b.length);
  }
  // The following methods are not used by Mosel:
  public void write(byte[] b, int off, int len) {}
  public void write(int b) {}
  public void close() {}
 }

 public static void main(String[] args) throws Exception
 {
  XPRM mosel;
  XPRMModel mod;
  MyOut cbmsg = new MyOut();            // Define output stream as "MyOut"

  mosel = new XPRM();                   // Initialize Mosel

  mosel.bind("mycb", cbmsg);    // Associate Java object with a name in Mosel
                                // Set default output stream to cbmsg
  mosel.setDefaultStream(XPRM.F_OUTPUT|XPRM.F_LINBUF, "java:mycb");

  mosel.compile("burglar2.mos");        // Compile, load & run the model
  mod = mosel.loadModel("burglar2.bim");
  mod.run();
 }

.NET version of the example

With the Mosel .NET libraries, the stream redirection functions accept the objects TextWriter and TextReader in addition to strings with Mosel file names. We therefore have several different implementation options for our example.

The following version of our example closely matches the structure of the Java program from the previous section—it makes use of the dotnet I/O driver for redirecting the model output to a custom TextWriter object:

 static void Main(string[] args) {
  // Initialize Mosel
  XPRM mosel = XPRM.Init();

  // Associate .NET object with a name in Mosel
  mosel.Bind("mycb", new MyOut());

  // Compile and load the Mosel model
  XPRMModel model = mosel.CompileAndLoad("burglar2.mos");

  // Redirect the model's output to our printing function 'cbmsg'
  model.SetDefaultStream(XPRMStreamType.F_OUTPUT_LINEBUF, "dotnet:mycb");

  // Run the model
  model.Run();
 }

Alternatively, we can simply use this form of our program (without employing any I/O driver):

 static void Main(string[] args) {
  // Initialize Mosel
  XPRM mosel = XPRM.Init();

  // Compile and load the Mosel model
  XPRMModel model = mosel.CompileAndLoad("burglar2.mos");

  // Redirect the model's output to a custom TextWriter
  MyOut modelOut = new MyOut();
  model.SetDefaultStream(XPRMStreamType.F_OUTPUT_LINEBUF, modelOut);

  // Run the model
  model.Run();
 }

In both cases, we work with the following definition for the class MyOut:

 public class MyOut: TextWriter
 {
  private bool atStartOfLine = true;
  public override void Write(char b)
  {
    if (atStartOfLine) {
     Console.Write("Mosel: ");
     atStartOfLine=false;
    }
    if (b=='\n') {
     Console.WriteLine();
     atStartOfLine=true;
    }
    else if (b=='\r') {
     // ignore
    }
    else {
     Console.Write(b);
    }
  }
  public override Encoding Encoding {
   get {
    return Encoding.UTF8;
   }
  }
 }