LQNS (Layered Queueing Network Solver)
Methods · qnsolver · Configuration · Shared options · All solvers
The LQNS wrapper integrates the Layered Queueing Network Solver developed by the RADS group at Carleton University. LINE automatically exports network models to LQNS format, invokes the external LQNS tool, and imports the results back into LINE's data structures. The same solver also accepts an ordinary (non-layered) Network, which it analyzes with qnsolver, the product-form queueing network tool of the same suite, in the way JMT hosts both JSIM and JMVA. This qnsolver path replaces the former standalone QNS solver.
Methods
The method names and defaults below describe the MATLAB interface. Aliases share a row; model-specific restrictions and backend differences are noted. Use solver.listValidMethods() to inspect the names available for your model.
| Method | Algorithm and applicability |
|---|---|
default | Run lqns with -Pstop-on-message-loss=false. |
lqns | The same as default, asked for by name. |
srvn | lqns -Playering=srvn: the SRVN layering strategy. |
exactmva | lqns -Pmva=exact: exact MVA inside the layer solves. |
srvn.exactmva | Both of the above: SRVN layering with exact MVA. |
sim, lqsim | lqsim, the LQN discrete-event simulator, at options.samples run length. |
lqns.default | Plain lqns with no LINE pragmas at all, i.e. the tool's own defaults. |
The multiserver approximation passed as -Pmultiserver= comes from options.config.multiserver (rolia when left at default): conway [31], [38], reiser [90], rolia in its per-class Rolia-Franks form [95], [46], zhou [114], [115], suri [103] or schmidt [99].
Methods on a Network (qnsolver)
When the model is a flat Network, the method names select the multiserver approximation qnsolver -m (or, on a closed non-product-form model, lqns through QN2LQN) will use. Product-form or open models are written as a JMVA document and solved by qnsolver; closed non-product-form models are converted to a layered network with QN2LQN and solved by lqns. The qns methods are refused on a LayeredNetwork, and the layered methods above are not offered on a Network. Results are labelled with the method name, e.g. qns.conway, or default/qns.rolia when default is asked. Use SolverLQNS.hasQnsolver() to check that the qnsolver binary is available. Under AUTO these methods belong to the lqns family (lqns.qns.conway, ...); on the command line they are line-cli -s lqns --method qns.conway.
| Method | Algorithm and applicability | Reference |
|---|---|---|
default, qns | The rolia multiserver approximation below. | - |
qns.conway | Conway's multiserver approximation for chain-dependent FCFS queues, built on the multinomial all-servers-busy probability of de Souza e Silva and Muntz. | [31], [38] |
qns.rolia | Rolia's multiserver approximation, in the per-class Rolia-Franks form that LQNS implements. | [95], [96], [46] |
qns.zhou | Zhou's arrival-theorem binomial (AB) multiserver approximation, with class merging for multiple classes. | [114], [115] |
qns.suri | Suri-Sahu-Vernon multiserver approximation; refused on the qnsolver path where a multi-server station is present, since qnsolver -m does not know it. | [103] |
qns.reiser | Reiser-Lavenberg MVA with load-dependent marginal probabilities, exact for a product-form multi-server station. | [90], [88] |
qns.schmidt | Schmidt's multiserver approximation for class-dependent exponential servers; same restriction as qns.suri. | [99] |
Configuration options
The solver-specific fields below belong to options.config. Set them on an options struct, for example opt.config.name = value, and pass that struct to the solver constructor. See shared solver options for all top-level fields, shared configuration, defaults and usage. Options apply only to the methods and model features that consume them.
Relevant top-level options: samples, keep, timeout.
The wrapper uses local lqns/lqsim binaries unless config.remote selects the LQNS REST service. config.multiserver='default' resolves to rolia. On a Network the local qnsolver binary is required (and lqns for the closed non-product-form fallback). container is ignored by LQNS, lqsim and qnsolver.
| Option | Default | Description and values |
|---|---|---|
remote | false | LQNS: solve through the lqns-rest service instead of the local binary. |
remote_url | 'http://localhost:8080' | URL of that service. |
multiserver | 'default' | On a LayeredNetwork: the multiserver approximation passed through to lqns (-Pmultiserver=). On a Network it is derived from the qns method name, overriding a supplied configuration value (default resolves to rolia), and passed as qnsolver -m when multiserver stations are present, or as lqns -Pmultiserver= on the closed non-product-form fallback. |
Example
This example demonstrates the LQNS solver integration with the external Layered Queueing Network Solver. The unique feature of LQNS is its integration with the external LQNS tool from Carleton University, which LINE automatically invokes by exporting the model, running LQNS, and importing the results.
% Create a layered network for LQNS analysis
model = LayeredNetwork('LQNS Example');
% Define processor and task
processor = Processor(model, 'WebServer', 1, SchedStrategy.PS);
task = Task(model, 'WebTask', 1, SchedStrategy.REF);
entry = Entry(model, 'processRequest');
% Set service time
entry.setService(Exp(0.5));
% Link task to processor
task.on(processor);
task.addEntry(entry);
% Solve with external LQNS tool
LQNS(model).avgTable()
Output:
LQNS analysis [method: lqns; type: approximate, deterministic; lang: matlab; env: 2025a] completed in 0.15s. Processor Task Entry Util Throughput RespT WebServer WebTask processRequest 0.75 1.5 0.5
// Create a layered network for LQNS analysis
LayeredNetwork model = new LayeredNetwork("LQNS Example");
// Define processor and task
Processor processor = new Processor(model, "WebServer", 1, SchedStrategy.PS);
Task task = new Task(model, "WebTask", 1, SchedStrategy.REF);
Entry entry = new Entry(model, "processRequest");
// Set service time
entry.setService(new Exp(0.5));
// Link task to processor
task.on(processor);
task.addEntry(entry);
// Solve with external LQNS tool
new LQNS(model).getLNAvgTable().print();
Output:
LQNS analysis [method: lqns; type: approximate, deterministic; lang: java; env: 17.0.9] completed. Processor Task Entry Util Throughput RespT WebServer WebTask processRequest 0.75 1.5 0.5
# Create a layered network for LQNS analysis
from line_solver import *
model = LayeredNetwork("LQNS Example")
# Define processor and task
processor = Processor(model, "WebServer", 1, SchedStrategy.PS)
task = Task(model, "WebTask", 1, SchedStrategy.REF)
entry = Entry(model, "processRequest")
# Set service time
entry.set_service(Exp(0.5))
# Link task to processor
task.on(processor)
task.add_entry(entry)
# Solve with external LQNS tool
print(LQNS(model).avg_table)
Output:
LQNS analysis [method: lqns; type: approximate, deterministic; lang: python; env: 3.13.7] completed. Processor Task Entry Util Throughput RespT WebServer WebTask processRequest 0.75 1.5 0.5
Example: a Network through qnsolver
This example solves a simple open tandem queueing network (not layered) with the qnsolver path of the LQNS solver.
% Create an open queueing network (tandem queues)
model = Network('qnsolver Example');
source = Source(model, 'Source');
queue1 = Queue(model, 'Queue1', SchedStrategy.FCFS);
queue2 = Queue(model, 'Queue2', SchedStrategy.FCFS);
sink = Sink(model, 'Sink');
jobclass = OpenClass(model, 'Class1');
source.setArrival(jobclass, Exp(0.7));
queue1.setService(jobclass, Exp(1.0));
queue2.setService(jobclass, Exp(1.5));
P = model.initRoutingMatrix();
P.set(jobclass, jobclass, source, queue1, 1.0);
P.set(jobclass, jobclass, queue1, queue2, 1.0);
P.set(jobclass, jobclass, queue2, sink, 1.0);
model.link(P);
LQNS(model, 'qns').avgTable()
// Create an open queueing network (tandem queues)
Network model = new Network("qnsolver Example");
Source source = new Source(model, "Source");
Queue queue1 = new Queue(model, "Queue1", SchedStrategy.FCFS);
Queue queue2 = new Queue(model, "Queue2", SchedStrategy.FCFS);
Sink sink = new Sink(model, "Sink");
OpenClass jobclass = new OpenClass(model, "Class1");
source.setArrival(jobclass, new Exp(0.7));
queue1.setService(jobclass, new Exp(1.0));
queue2.setService(jobclass, new Exp(1.5));
RoutingMatrix P = model.initRoutingMatrix();
P.set(jobclass, jobclass, source, queue1, 1.0);
P.set(jobclass, jobclass, queue1, queue2, 1.0);
P.set(jobclass, jobclass, queue2, sink, 1.0);
model.link(P);
new LQNS(model, "qns").getAvgTable().print();
# Create an open queueing network (tandem queues)
from line_solver import *
model = Network("qnsolver Example")
source = Source(model, "Source")
queue1 = Queue(model, "Queue1", SchedStrategy.FCFS)
queue2 = Queue(model, "Queue2", SchedStrategy.FCFS)
sink = Sink(model, "Sink")
jobclass = OpenClass(model, "Class1")
source.set_arrival(jobclass, Exp(0.7))
queue1.set_service(jobclass, Exp(1.0))
queue2.set_service(jobclass, Exp(1.5))
P = model.init_routing_matrix()
P.set(jobclass, jobclass, source, queue1, 1.0)
P.set(jobclass, jobclass, queue1, queue2, 1.0)
P.set(jobclass, jobclass, queue2, sink, 1.0)
model.link(P)
print(LQNS(model, method='qns').avg_table)