7.8 MOSEK OptServer

MOSEK provides an easy way to offload optimization problem to a remote server. This section demonstrates related functionalities from the client side, i.e. sending optimization tasks to the remote server and retrieving solutions.

Setting up and configuring the remote server is described in a separate manual for the OptServer.

The URL of the remote server required in all client-side calls should be a string of the form http://host:port or https://host:port.

7.8.1 Synchronous Remote Optimization

In synchronous mode the client sends an optimization problem to the server and blocks, waiting for the optimization to end. Once the result has been received, the program can continue. This is the simplest mode all it takes is to provide the address of the server before starting optimization. The rest of the code remains untouched.

Note that it is impossible to recover the job in case of a broken connection.

Source code example

Listing 7.7 Using the OptServer in synchronous mode. Click here to download.
extern crate mosek;

use mosek::{Task,Streamtype,Sparam};
use std::env;

enum FileOrText {
    File(String),
    Text(String)
}
fn main() -> Result<(),String> {
    let mut args = env::args();
    if args.len() < 3 {
        println!("Missing argument, syntax is:");
        println!("  opt_server_sync inputfile http[s]://HOSTNAME:PORT [certfile]");
        return Err("Missing arguments".to_string())
    }
    let _ = args.next();
    opt_server_sync(FileOrText::File(args.next().unwrap()),
                    args.next().unwrap(),
                    args.next())
}

fn opt_server_sync(inputfile : FileOrText, addr : String, cert : Option<String>) -> Result<(),String> {
    let mut task = Task::new().unwrap().with_callbacks();
    task.put_stream_callback(Streamtype::LOG, |msg| print!("{}",msg))?;

    // Load some data into the task
    match inputfile {
        FileOrText::File(filename) => task.read_data(filename.as_str())?,
        FileOrText::Text(data) => task.read_ptf_string(data.as_str())?
    }

    // Set OptServer URL
    task.put_optserver_host(addr.as_str())?;

    // Path to certificate, if any
    if let Some(cert) = cert {
        task.put_str_param(Sparam::REMOTE_TLS_CERT_PATH, cert.as_str())?;
    }

    // Optimize remotely, no access token
    let _trm = task.optimize()?;

    task.solution_summary(Streamtype::LOG)?;

    Ok(())
}

7.8.2 Asynchronous Remote Optimization

In asynchronous mode the client sends a job to the remote server and the execution of the client code continues. In particular, it is the client’s responsibility to periodically check the optimization status and, when ready, fetch the results. The client can also interrupt optimization. The most relevant methods are:

Source code example

In the example below the program enters in a polling loop that regularly checks whether the result of the optimization is available.

Listing 7.8 Using the OptServer in asynchronous mode. Click here to download.
extern crate mosek;

use mosek::{Task,Streamtype,Sparam};
use std::env;
use std::time::Duration;
use std::thread::sleep;

#[derive(Debug)]
enum FileOrText {
    File(String),
    Text(String)
}
fn main() {
    let mut args = env::args();
    if args.len() < 3 {
        println!("Missing argument, syntax is:");
        println!("  opt_server_async inputfile http[s]://HOSTNAME:PORT numpolls [certfile]");
        panic!("Missing arguments");
    }
    let _ = args.next();
    opt_server_async(FileOrText::File(args.next().unwrap()),
                     args.next().unwrap(),
                     args.next().unwrap().parse().unwrap(),
                     args.next()).unwrap();
}
fn opt_server_async(inputfile : FileOrText, addr : String, numpolls : usize, cert : Option<String>) -> Result<(),String> {
    // Path to certificate, if any

    let token = {
        Task::new().unwrap()
            .with_stream_callback(
                Streamtype::LOG,
                &mut |msg| print!("{}",msg),
                |task| {
                    match inputfile {
                        FileOrText::File(ref filename) => task.read_data(filename.as_str()).unwrap(),
                        FileOrText::Text(ref data)     => task.read_ptf_string(data.as_str()).unwrap()
                    }
                    if let Some(ref cert) = cert {
                        task.put_str_param(Sparam::REMOTE_TLS_CERT_PATH,cert.as_str())?;
                    }
                    task.async_optimize(addr.as_str(),"")
                }).expect("Failed to submit async optimization")
    };

    println!("Task token = '{}'", token);


    println!("Setting log stream...");
    Task::new().unwrap().with_stream_callback(
        Streamtype::LOG,
        & mut |msg| print!("{}",msg),
        |task| task.with_callback(
            &mut|caller| { println!("caller = {}",caller); false },
            |task| {
                println!("Reading input file '{:?}'...",inputfile);
                match inputfile {
                    FileOrText::File(ref filename) => task.read_data(filename.as_str()).unwrap(),
                    FileOrText::Text(ref data)     => task.read_ptf_string(data.as_str()).unwrap()
                }
                if let Some(ref cert) = cert {
                    task.put_str_param(Sparam::REMOTE_TLS_CERT_PATH,cert.as_str())?;
                }

                println!("Starting polling loop...");
                for i in 0..numpolls {
                    sleep(Duration::new(1,0));

                    println!("\tpoll {}...", i);

                    let mut trm  : i32 = 0;
                    let mut resp : i32 = 0;

                    let respavailable = task.async_poll(addr.as_str(),
                                                        "",
                                                        token.as_str(),
                                                        & mut resp,
                                                        & mut trm)?;

                    if respavailable {
                        println!("solution available!");

                        task.async_get_result(addr.as_str(),
                                              "",
                                              token.as_str(),
                                              & mut resp,
                                              & mut trm)?;

                        task.solution_summary (Streamtype::LOG)?;
                        return Ok(());
                    }
                }

                println!("max num polls reached, stopping host.");
                task.async_stop (addr.as_str(), "", token.as_str())?;
                Err("Max num polls".to_string())
            }))
}