Tutorial 2: Multiclass M/G/1 Queue
This example considers a more challenging variant with two classes of incoming jobs with non-exponential service times. For the first class, service times are Erlang distributed; for the second class, they are read from a trace file. Both classes have exponentially distributed inter-arrival times.
% Example 2: A multiclass M/G/1 queue
model = Network('M/G/1');
source = Source(model,'Source');
queue = Queue(model, 'Queue', SchedStrategy.FCFS);
sink = Sink(model,'Sink');
jobclass1 = OpenClass(model, 'Class1');
jobclass2 = OpenClass(model, 'Class2');
source.setArrival(jobclass1, Exp(0.5));
source.setArrival(jobclass2, Exp(0.5));
queue.setService(jobclass1, Erlang.fitMeanAndSCV(1,1/3));
queue.setService(jobclass2, Replayer(which('example_trace.txt')));
P = model.initRoutingMatrix();
P.set(jobclass1, Network.serialRouting(source,queue,sink));
P.set(jobclass2, Network.serialRouting(source,queue,sink));
model.link(P);
ldesAvgTable = LDES(model,'seed',23000,'samples',10000).avgTable()
queue.setService(jobclass2, Replayer(which('example_trace.txt')).fitAPH());
mamAvgTable = MAM(model).avgTable()
from line_solver import *
model = Network('M/G/1')
source = Source(model, 'Source')
queue = Queue(model, 'Queue', SchedStrategy.FCFS)
sink = Sink(model, 'Sink')
jobclass1 = OpenClass(model, 'Class1')
jobclass2 = OpenClass(model, 'Class2')
source.set_arrival(jobclass1, Exp(0.5))
source.set_arrival(jobclass2, Exp(0.5))
queue.set_service(jobclass1, Erlang.fit_mean_and_scv(1.0, 1/3))
queue.set_service(jobclass2, Replayer(lineRootFolder() +
"/examples/gettingstarted/example_trace.txt").fit_aph())
P = model.init_routing_matrix()
P.set(jobclass1, Network.serial_routing(source,queue,sink))
P.set(jobclass2, Network.serial_routing(source,queue,sink))
model.link(P)
ldesAvgTable = LDES(model, seed=23000, samples=10000).avg_table()
mamAvgTable = MAM(model).avg_table()
import jline.examples.ExampleData;
import jline.lang.RoutingMatrix;
import jline.lang.processes.Erlang;
import jline.lang.processes.Replayer;
import jline.solvers.NetworkAvgTable;
import jline.solvers.ldes.LDES;
import jline.solvers.mam.MAM;
Network model = new Network("M/G/1");
Source source = new Source(model, "Source");
Queue queue = new Queue(model, "Queue", SchedStrategy.FCFS);
Sink sink = new Sink(model, "Sink");
OpenClass jobclass1 = new OpenClass(model, "Class1");
OpenClass jobclass2 = new OpenClass(model, "Class2");
source.setArrival(jobclass1, new Exp(0.5));
source.setArrival(jobclass2, new Exp(0.5));
queue.setService(jobclass1, Erlang.fitMeanAndSCV(1, (double) 1 / 3));
String fileName = ExampleData.path("/example_trace.txt");
queue.setService(jobclass2, new Replayer(fileName));
RoutingMatrix P = model.initRoutingMatrix();
P.set(jobclass1, jobclass1, Network.serialRouting(source, queue, sink));
P.set(jobclass2, jobclass2, Network.serialRouting(source, queue, sink));
model.link(P);
NetworkAvgTable ldesAvgTable = new LDES(model, "seed", 23000, "samples", 10000).avgTable();
ldesAvgTable.print();
queue.setService(jobclass2, new Replayer(fileName).fitAPH());
new MAM(model).avgTable().print();
#include "line/solvers/wrappers/ldes/solver_ldes.h"
#include "line/solvers/mam/solver_mam_runner.h"
Network model("M/G/1");
Source source(model, "Source");
Queue queue(model, "Queue", SchedStrategy::FCFS);
Sink sink(model, "Sink");
OpenClass jobclass1(model, "Class1");
OpenClass jobclass2(model, "Class2");
source.set_arrival(jobclass1, Exp(0.5));
source.set_arrival(jobclass2, Exp(0.5));
queue.set_service(jobclass1, Distrib<double>::erlang_fit(1.0, 1.0 / 3.0));
const std::vector<double> samples{/* values from example_trace.txt */};
queue.set_service(jobclass2, Replayer(samples));
Routing P;
for (std::size_t r : {jobclass1, jobclass2}) {
P.set(r, r, source, queue, 1.0);
P.set(r, r, queue, sink, 1.0);
}
model.link(P);
// Simulate the raw trace with the LDES client, then fit and solve with MAM.
ldes::LdesOptions sim;
sim.seed = 23000;
sim.samples = 10000;
const ldes::LdesResult sres = ldes::solver_ldes(model.get_struct(), sim);
mam::MamOptions opt;
const mva::AvgResult<double> res =
mam::solver_mam_run_analyzer(model.get_struct(), opt);
Expected Output (LDES solver)
ldesAvgTable =
Station JobClass QLen Util RespT ResidT ArvR Tput
_______ ________ _______ ________ _______ _______ _______ _______
Source Class1 0 0 0 0 0 0.5
Source Class2 0 0 0 0 0 0.5
Queue Class1 0.83114 0.48506 1.7003 1.7003 0.4891 0.48871
Queue Class2 0.41233 0.050177 0.83801 0.83801 0.49234 0.49165
Expected Output (MAM solver)
mamAvgTable =
Station JobClass QLen Util RespT ResidT ArvR Tput
_______ ________ _______ ________ _______ _______ ____ ____
Source Class1 0 0 0 0 0 0.5
Source Class2 0 0 0 0 0 0.5
Queue Class1 0.87646 0.5 1.7529 1.7529 0.5 0.5
Queue Class2 0.427 0.050536 0.85399 0.85399 0.5 0.5