Skip to content

Commit bab14b1

Browse files
committed
Implement enabling/disabling of monitors
1 parent 3dd0e54 commit bab14b1

File tree

8 files changed

+299
-90
lines changed

8 files changed

+299
-90
lines changed

Samples/KanbanControl.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ private IEnumerable<Event> Produce(Request kb) {
5353
}
5454
}
5555

56-
public void Simulate() {
56+
public void Simulate(int rseed = 42) {
5757
completedOrders = 0;
58-
env = new Simulation();
58+
env = new Simulation(randomSeed: rseed);
5959
env.Log("== Kanban controlled production system ==");
6060
kanban = new Resource(env, capacity: 15);
6161
server = new Resource(env, capacity: 1);
@@ -67,7 +67,7 @@ public void Simulate() {
6767
env.Run(TimeSpan.FromDays(180));
6868
Console.WriteLine("Kanbans in stock: {0} ; {1:F1}±{2:F1} ; {3} (Min;Mean±StdDev;Max) kanbans ", stockStat.Min, stockStat.Mean, stockStat.StdDev, stockStat.Max);
6969
Console.WriteLine("Produced kanbans: {0:N0}", completedOrders);
70-
Console.WriteLine(stockStat.Summarize(histInterval: 1));
70+
Console.WriteLine(stockStat.Summarize(binWidth: 1));
7171
}
7272
}
7373
}

Samples/MM1Queueing.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,30 @@ private IEnumerable<Event> Order(Simulation env, Resource server) {
3838
}
3939
}
4040

41-
public void Simulate() {
42-
var lambda = 1 / OrderArrivalTime.TotalMinutes;
43-
var mu = 1 / ProcessingTime.TotalMinutes;
41+
private IEnumerable<Event> HandleWarmup(Simulation env, TimeSpan warmupTime, params IMonitor[] monitors) {
42+
foreach (var mon in monitors) mon.Active = false;
43+
yield return env.Timeout(warmupTime);
44+
foreach (var mon in monitors) mon.Active = true;
45+
}
46+
47+
public void Simulate(int repetitions = 5) {
48+
var lambda = 1 / OrderArrivalTime.TotalDays;
49+
var mu = 1 / ProcessingTime.TotalDays;
4450
var rho = lambda / mu;
4551
var analyticWIP = rho / (1 - rho);
4652
var analyticLeadtime = 1 / (mu - lambda);
4753
var analyticWaitingtime = rho / (mu - lambda);
4854

49-
var env = new Simulation(randomSeed: 1, defaultStep: TimeSpan.FromMinutes(1));
55+
var env = new Simulation(randomSeed: 1, defaultStep: TimeSpan.FromDays(1));
5056
var utilization = new TimeSeriesMonitor(env, name: "Utilization");
5157
var wip = new TimeSeriesMonitor(env, name: "WIP", collect: true);
5258
var leadtime = new SampleMonitor(name: "Lead time", collect: true);
5359
var waitingtime = new SampleMonitor(name: "Waiting time", collect: true);
5460

5561
env.Log("Analytical results of this system:");
56-
env.Log("\tUtilization.Mean\tWIP.Mean\tLeadtime.Mean\tWaitingTime.Mean");
57-
env.Log("\t{0}\t{1}\t{2}\t{3}", rho, analyticWIP, analyticLeadtime, analyticWaitingtime);
62+
env.Log("Time\tUtilization.Mean\tWIP.Mean\tLeadtime.Mean\tWaitingTime.Mean");
63+
env.Log("{4}\t{0}\t{1}\t{2}\t{3}", rho, analyticWIP, analyticLeadtime, analyticWaitingtime, double.PositiveInfinity);
64+
env.Log("");
5865

5966
// example to create a running report of these measures every simulated week
6067
//var report = Report.CreateBuilder(env)
@@ -78,11 +85,11 @@ public void Simulate() {
7885
.SetTimeAPI(useDApi: true)
7986
.Build();
8087

81-
env.Log("Simulated results of this system:");
88+
env.Log("Simulated results of this system (" + repetitions + " repetitions):");
8289
env.Log("");
8390
summary.WriteHeader(); // write the header just once
8491

85-
for (var i = 0; i < 5; i++) {
92+
for (var i = 0; i < repetitions; i++) {
8693
env.Reset(i + 1); // reset environment
8794
utilization.Reset(); // reset monitors
8895
wip.Reset();
@@ -96,16 +103,17 @@ public void Simulate() {
96103
};
97104

98105
env.Process(Source(env, server));
106+
env.Process(HandleWarmup(env, TimeSpan.FromDays(32), utilization, wip, leadtime, waitingtime));
99107
env.Run(TimeSpan.FromDays(365));
100108
}
101109

102110
env.Log("");
103111
env.Log("Detailed results from the last run:");
104112
env.Log("");
105113
env.Log(utilization.Summarize());
106-
env.Log(wip.Summarize(maxBins: 10, histInterval: 2));
107-
env.Log(leadtime.Summarize(maxBins: 10, histInterval: 5));
108-
env.Log(waitingtime.Summarize(maxBins: 10, histInterval: 4)); ;
114+
env.Log(wip.Summarize(maxBins: 10, binWidth: 2));
115+
env.Log(leadtime.Summarize(maxBins: 10, binWidth: 5 / 1440.0));
116+
env.Log(waitingtime.Summarize(maxBins: 10, binWidth: 4 / 1440.0)); ;
109117
}
110118
}
111119
}

SimSharp/Analysis/IMonitor.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ You should have received a copy of the GNU General Public License
2020

2121
namespace SimSharp {
2222
public interface IMonitor {
23+
bool Active { get; set; }
24+
string Name { get; }
25+
26+
string Summarize();
27+
28+
29+
event EventHandler Updated;
30+
}
31+
32+
public interface INumericMonitor : IMonitor {
2333
bool Collect { get; }
2434

2535
double Min { get; }
@@ -31,17 +41,13 @@ public interface IMonitor {
3141

3242
double GetMedian();
3343
double GetPercentile(double p);
34-
35-
string Summarize();
36-
37-
event EventHandler Updated;
3844
}
3945

40-
public interface ISampleMonitor : IMonitor {
46+
public interface ISampleMonitor : INumericMonitor {
4147
void Add(double value);
4248
}
4349

44-
public interface ITimeSeriesMonitor : IMonitor {
50+
public interface ITimeSeriesMonitor : INumericMonitor {
4551
void Increase(double value);
4652
void Decrease(double value);
4753
void UpdateTo(double value);

SimSharp/Analysis/Report.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public Builder(Simulation env) {
237237
/// or when <paramref name="measure"/> is not valid.</exception>
238238
/// <exception cref="ArgumentNullException">Thrown when <paramref name="statistics"/> is null.</exception>
239239
/// <returns>This builder instance.</returns>
240-
public Builder Add(string name, IMonitor statistics, Measures measure = Measures.All) {
240+
public Builder Add(string name, INumericMonitor statistics, Measures measure = Measures.All) {
241241
if (string.IsNullOrEmpty(name)) throw new ArgumentException("Name must be a non-empty string", "name");
242242
if (statistics == null) throw new ArgumentNullException("statistics");
243243
if (measure == 0 || measure > Measures.All) throw new ArgumentException("No measures have been selected.", "measure");
@@ -383,7 +383,7 @@ private static int CountSetBits(int num) {
383383

384384
private class Key {
385385
public string Name { get; set; }
386-
public IMonitor Statistics { get; set; }
386+
public INumericMonitor Statistics { get; set; }
387387
public Measures Measure { get; set; }
388388
public int TotalMeasures { get; set; }
389389
}

SimSharp/Analysis/SampleMonitor.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public sealed class SampleMonitor : ISampleMonitor {
3737
/// </summary>
3838
public bool Collect { get; }
3939

40+
/// <summary>
41+
/// The monitor can be set to suppress updates. When it is set
42+
/// to false, the statistics will not be updated and new samples
43+
/// are ignored.
44+
/// </summary>
45+
public bool Active { get; set; }
46+
4047
/// <summary>
4148
/// The name of the variable that is being monitored.
4249
/// Used for output in <see cref="Summarize(bool, int, double?, double?)"/>.
@@ -48,7 +55,7 @@ public sealed class SampleMonitor : ISampleMonitor {
4855
public double Min { get; private set; }
4956
public double Max { get; private set; }
5057
public double Total { get; private set; }
51-
double IMonitor.Sum { get { return Total; } }
58+
double INumericMonitor.Sum { get { return Total; } }
5259
public double Mean { get; private set; }
5360
public double StdDev { get { return Math.Sqrt(Variance); } }
5461
public double Variance { get { return (Count > 0) ? variance / Count : 0.0; } }
@@ -104,6 +111,7 @@ private static double GetPercentile(IList<double> s, double p) {
104111
}
105112

106113
public SampleMonitor(string name = null, bool collect = false) {
114+
Active = true;
107115
Name = name;
108116
Collect = collect;
109117
if (collect) samples = new List<double>(64);
@@ -118,6 +126,8 @@ public void Reset() {
118126
}
119127

120128
public void Add(double value) {
129+
if (!Active) return;
130+
121131
if (double.IsNaN(value) || double.IsInfinity(value))
122132
throw new ArgumentException("Not a valid double", "value");
123133
Count++;
@@ -157,7 +167,7 @@ string IMonitor.Summarize() {
157167
/// the data to produce the histogram is not available in the first place.</param>
158168
/// <param name="maxBins">The maximum number of bins that should be used.
159169
/// Note that the bin width and thus the number of bins is also governed by
160-
/// <paramref name="histInterval"/> if it is defined.
170+
/// <paramref name="binWidth"/> if it is defined.
161171
/// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
162172
/// was set to true, otherwise the data to produce the histogram is not available
163173
/// in the first place.</param>
@@ -166,14 +176,14 @@ string IMonitor.Summarize() {
166176
/// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
167177
/// was set to true, otherwise the data to produce the histogram is not available
168178
/// in the first place.</param>
169-
/// <param name="histInterval">The interval for the bins of the histogram or the
179+
/// <param name="binWidth">The interval for the bins of the histogram or the
170180
/// range (<see cref="Max"/> - <see cref="Min"/>) divided by the number of bins
171181
/// (<paramref name="maxBins"/>) in case the default value (null) is given.
172182
/// This is only effective if <see cref="Collect"/> and <paramref name="withHistogram"/>
173183
/// was set to true, otherwise the data to produce the histogram is not available
174184
/// in the first place.</param>
175185
/// <returns>A formatted string that provides a summary of the statistics.</returns>
176-
public string Summarize(bool withHistogram = true, int maxBins = 20, double? histMin = null, double? histInterval = null) {
186+
public string Summarize(bool withHistogram = true, int maxBins = 20, double? histMin = null, double? binWidth = null) {
177187
var nozero = Collect ? samples.Where(x => x != 0).ToList() : new List<double>();
178188
var nozeromin = nozero.Count > 0 ? nozero.Min() : double.NaN;
179189
var nozeromax = nozero.Count > 0 ? nozero.Max() : double.NaN;
@@ -200,7 +210,7 @@ public string Summarize(bool withHistogram = true, int maxBins = 20, double? his
200210

201211
if (Collect && withHistogram) {
202212
var min = histMin ?? Min;
203-
var interval = histInterval ?? (Max - Min) / maxBins;
213+
var interval = binWidth ?? (Max - Min) / maxBins;
204214
var histData = samples.GroupBy(x => x <= min ? 0 : (int)Math.Floor(Math.Min((x - min + interval) / interval, maxBins)))
205215
.Select(x => new { Key = x.Key, Value = x.Count() })
206216
.OrderBy(x => x.Key);

0 commit comments

Comments
 (0)