Interoperability

LINE supports multiple interoperability features, enabling model exchange across different languages (MATLAB, Java/Kotlin, Python), transformation between queueing model formalisms, and import/export of models from external tools.

Cross-Language Execution

LINE solvers can execute using either native implementations or Java/Kotlin backend implementations via the lang option. This allows MATLAB and Python users to leverage fast Java solver implementations when needed.

% MATLAB Example: Force Java backend execution
model = Network('MyModel');
% ... define model ...

% Use MATLAB native implementation (default)
solver = MVA(model, 'lang','matlab');

% Use Java backend implementation
solver = MVA(model, 'lang','java');
# Python: Force Java backend execution
from line_solver import Network, MVA

model = Network('MyModel')
# ... define model ...

# Use Python native implementation (default)
solver = MVA(model, lang='python')

# Use Java backend implementation
solver = MVA(model, lang='java')

Model Transformations and Formats

LINE supports bidirectional transformations between different queueing model representations, import from external tools, and export to various formats:

TypeFunction/FormatDirectionDescription
TransformLINE2JLINEMATLAB → JavaConvert MATLAB objects to Java/Kotlin objects
TransformJLINE2LINEJava → MATLABConvert Java/Kotlin objects to MATLAB objects
TransformQN2LQNNetwork → LQNConvert queueing networks to layered queueing networks
ImportJSIM2LINE(filename)JSIM/JSIMG → LINEImport JMT simulation models with full node, distribution, and routing definitions
ImportLayeredNetwork.parseXML(file)LQNX → LINEImport layered queueing network models from LQNS XML format
ImportWfCommonsLoader.load(file)WfCommons → LINEImport scientific workflow traces (JSON format, schemas 1.3-1.5)
ExportQN2JSIMG()LINE → JSIMGExport to JMT graphical simulator format for visualization and simulation
ExportLayeredNetwork.writeXML(file)LINE → LQNXExport layered networks to LQNX format for LQNS solver
ExportQN2MATLABNetwork → CodeGenerate MATLAB script for queueing networks
ExportLQN2MATLABLayeredNetwork → CodeGenerate MATLAB script for layered queueing networks
ExportQN2JAVANetwork → CodeGenerate Java code for programmatic model definition
% MATLAB: Model transformations
matlab_model = Network('Example');
% ... build model ...

% Transform to Java backend
java_model = JLINE.line_to_jline(matlab_model);
recovered_model = JLINE.jline_to_line(java_model);

% Import a JMT model
model = JSIM2LINE('mymodel.jsimg');
solver = MVA(model);
results = solver.avgTable();

% Import LQNS model
lqn_model = LQN2MATLAB('system.lqnx');
solver = LN(lqn_model);

% Export model to JMT format
QN2JSIMG(model, 'exported_model.jsimg');

% Export LayeredNetwork to LQNX
lqn = LayeredNetwork('WebService');
% ... build layered model ...
lqn.writeXML('webservice.lqnx');
# Python: Model transformations
from line_solver import Network, Source, Queue, Sink
from line_solver import SchedStrategy, Exp, OpenClass
from line_solver import JLINE, JSIM2LINE, MVA, QN2JSIMG, M2M, SolverLN

# Build and transform model
model = Network('Example')
source = Source(model, 'Source')
queue = Queue(model, 'Queue', SchedStrategy.FCFS)
sink = Sink(model, 'Sink')
jobclass = OpenClass(model, 'Class1')
source.setArrival(jobclass, Exp(1.0))
queue.setService(jobclass, Exp(2.0))
model.link(Network.serialRouting(source, queue, sink))

# Transform to/from Java backend
java_model = JLINE.line_to_jline(model)
recovered_model = JLINE.jline_to_line(java_model)

# Import JMT model
model = JSIM2LINE('mymodel.jsimg')
solver = MVA(model)
results = solver.avg_table()

# Import LQNS model
m2m = M2M()
lqn_model = m2m.LQN2PYTHON('system.lqnx')
solver = SolverLN(lqn_model)

# Export to JMT format
QN2JSIMG(model, 'exported_model.jsimg')

MAP/PH Distribution Format Conversion

LINE uses the BUTools representation format natively for Markovian Arrival Processes (MAPs) and Phase-Type (PH) distributions. MAPs are represented by two matrices (D0, D1), and PH distributions by an initial probability vector (alpha) and subgenerator matrix (T). This format is directly compatible with the BUTools library and other tools using this standard representation.

Native BUTools Format

LINE MAP and PH objects directly expose their internal representation matrices, which are in BUTools format:

% MATLAB: Accessing MAP matrices (BUTools format)
map = MAP.rand(3);  % Create random 3-phase MAP

% Extract D0 and D1 matrices (BUTools format)
D0 = map.D(0);  % Generator matrix for transitions without arrivals
D1 = map.D(1);  % Rate matrix for transitions with arrivals

% These matrices can be used directly with BUTools functions
% e.g., matlab/lib/thirdparty/BUTools/map/*

% For PH distributions:
ph = PH.fit(2.0, 1.5, 2.0);  % Fit from moments
alpha = ph.getInitProb();    % Initial probability vector
T = ph.getSubgenerator();    % Subgenerator matrix
// Java: Accessing MAP matrices (BUTools format)
import jline.lang.processes.MAP;
import jline.lang.processes.PH;
import jline.util.matrix.Matrix;

MAP map = MAP.rand(3);  // Create random 3-phase MAP

// Extract D0 and D1 matrices (BUTools format)
Matrix D0 = map.D(0);  // Generator matrix for transitions without arrivals
Matrix D1 = map.D(1);  // Rate matrix for transitions with arrivals

// For PH distributions:
PH ph = PH.fit(2.0, 1.5, 2.0);  // Fit from moments
Matrix alpha = ph.getInitProb();      // Initial probability vector
Matrix T = ph.getSubgenerator();      // Subgenerator matrix
# Python: Accessing MAP matrices (BUTools format)
from line_solver import MAP, PH

map_proc = MAP.rand(3)  # Create random 3-phase MAP

# Extract D0 and D1 matrices (BUTools format)
D0 = map_proc.D(0)  # Generator matrix for transitions without arrivals
D1 = map_proc.D(1)  # Rate matrix for transitions with arrivals

# For PH distributions:
ph = PH.fit(2.0, 1.5, 2.0)  # Fit from moments
alpha = ph.getInitProb()    # Initial probability vector
T = ph.getSubgenerator()    # Subgenerator matrix

MAP Representation Conversions

LINE provides methods to convert MAPs between different representations for analysis and compatibility with other tools:

MethodDescriptionUse Case
map.D(i)Access Di matrix (i=0,1 for MAP)Extract BUTools-compatible matrices for external analysis
map.toTimeReversed()Compute time-reversed MAPQueue analysis requiring reversed processes
map.toMMDP()Convert MAP to Markov-Modulated Deterministic ProcessFluid queue analysis and matrix-analytic methods
map.getRenewalProcess()Remove temporal dependence to get renewal PH processSimplify analysis by removing correlation structure
ph.getInitProb()Extract initial probability vector (alpha)Access PH representation for BUTools PH functions
ph.getSubgenerator()Extract subgenerator matrix (T)Access PH representation for matrix operations
% MATLAB: MAP representation conversions
map = MAP.rand(3);

% Get time-reversed MAP (useful for queue analysis)
map_reversed = map.toTimeReversed();

% Convert to MMDP for fluid queue analysis
mmdp = map.toMMDP();

% Get renewal process (removes temporal correlation)
renewal_process = map.getRenewalProcess();  % Returns {T, t} cell array

% Extract moments and statistics
mean_interarrival = map.getMean();
scv = map.getIDC();  % Index of dispersion for counts
acf = map.getACF([1,2,3]);  % Autocorrelation function at lags 1,2,3
// Java: MAP representation conversions
import jline.lang.processes.MAP;
import jline.lang.processes.MMDP;
import jline.util.matrix.MatrixCell;

MAP map = MAP.rand(3);

// Get time-reversed MAP (useful for queue analysis)
MAP mapReversed = map.toTimeReversed();

// Convert to MMDP for fluid queue analysis
MMDP mmdp = MMDP.fromMAP(map);

// Get renewal process (removes temporal correlation)
MatrixCell renewalProcess = map.getRenewalProcess();

// Extract moments and statistics
double meanInterarrival = map.getMean();
double scv = map.getSCV();
double skewness = map.getSkewness();

Compatibility Notes

LINE's MAP/PH format is compatible with:

REST API Interface

LINE provides a RESTful API for solving queueing models programmatically over HTTP. This enables integration with web applications, microservices, and any language that can make HTTP requests.

Starting the REST API Server

# Start REST API server on default port (8080)
python line.py rest

# Start on custom port
python line.py rest -p 9000

# Using the JAR directly
java -jar jline.jar -r 8080
// Start REST server programmatically
import jline.api.REST;

// Start server on port 8080
REST.start(8080);

API Endpoints

EndpointMethodDescription
/solvePOSTSolve a queueing model. Accepts model in request body with solver options as query parameters.
/healthGETHealth check endpoint. Returns server status.

Solve Endpoint Parameters

ParameterTypeDefaultDescription
solverQueryautoSolver algorithm: auto, ctmc, des, fld, jmt, ln, lqns, mam, mva, nc, qns, ssa
formatQueryjsimgInput format: jsim, jsimg, jsimw, lqnx, xml
analysisQueryallAnalysis type: all, avg, sys, etc.
BodyRequest-Model content (XML for JSIM/JSIMG, or JSON)

Example Request

# Solve a JSIMG model using MVA solver
curl -X POST "http://localhost:8080/solve?solver=mva&format=jsimg" \
     -H "Content-Type: application/xml" \
     -d @mymodel.jsimg

# Health check
curl http://localhost:8080/health
import requests

# Read model file
with open('mymodel.jsimg', 'r') as f:
    model_content = f.read()

# Solve using REST API
response = requests.post(
    'http://localhost:8080/solve',
    params={'solver': 'mva', 'format': 'jsimg'},
    headers={'Content-Type': 'application/xml'},
    data=model_content
)

# Parse results
results = response.json()
print(results)
// Solve a model using fetch API
async function solveModel(modelContent) {
    const response = await fetch(
        'http://localhost:8080/solve?solver=mva&format=jsimg',
        {
            method: 'POST',
            headers: { 'Content-Type': 'application/xml' },
            body: modelContent
        }
    );

    const results = await response.json();
    console.log(results);
    return results;
}

// Health check
fetch('http://localhost:8080/health')
    .then(r => r.json())
    .then(console.log);

Response Format

The REST API returns JSON responses with the following structure:

{
  "success": true,
  "execution_time": 0.123,
  "avgTable": [
    {"station": "Queue1", "class": "Class1", "metric": "QLen", "value": 2.5, "unit": ""},
    {"station": "Queue1", "class": "Class1", "metric": "Tput", "value": 0.8, "unit": ""}
  ],
  "sysTable": [
    {"station": "Chain1", "class": "Class1", "metric": "SysRespT", "value": 3.125, "unit": ""}
  ]
}