Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.2/SimSharp-3.3.2/Core/Resources/Container.cs @ 18023

Last change on this file since 18023 was 18023, checked in by jkarder, 3 years ago

#3065: update Sim# to 3.3.2

File size: 5.6 KB
Line 
1#region License Information
2/*
3 * This file is part of SimSharp which is licensed under the MIT license.
4 * See the LICENSE file in the project root for more information.
5 */
6#endregion
7
8using System;
9using System.Collections.Generic;
10
11namespace SimSharp {
12  /// <summary>
13  /// A container holds a variable amount of a single continuous entity, e.g. water, coal, grain, etc.
14  ///
15  /// Put and Get are in FIFO order only when they can be satisfied.
16  /// Any put or get that can be satisfied takes precedence.
17  /// Put events that attempt to add more to the Container than there is capacity for and
18  /// Get events that remove more than there is are backlogged.
19  /// </summary>
20  public class Container {
21
22    public double Capacity { get; protected set; }
23
24    public double Level { get; protected set; }
25
26    protected Simulation Environment { get; private set; }
27
28    protected Queue<ContainerPut> PutQueue { get; private set; }
29    protected Queue<ContainerGet> GetQueue { get; private set; }
30    protected SimplePriorityQueue<Event, double> WhenAtLeastQueue { get; private set; }
31    protected SimplePriorityQueue<Event, double> WhenAtMostQueue { get; private set; }
32    protected List<Event> WhenChangeQueue { get; private set; }
33
34    public ITimeSeriesMonitor Fillrate { get; set; }
35    public ITimeSeriesMonitor PutQueueLength { get; set; }
36    public ISampleMonitor PutWaitingTime { get; set; }
37    public ITimeSeriesMonitor GetQueueLength { get; set; }
38    public ISampleMonitor GetWaitingTime { get; set; }
39
40    public Container(Simulation environment, double capacity = double.MaxValue, double initial = 0) {
41      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
42      if (initial < 0) throw new ArgumentException("Initial must be >= 0", "initial");
43      if (initial > capacity) throw new ArgumentException("Initial must be <= capacity", "initial");
44      Environment = environment;
45      Capacity = capacity;
46      Level = initial;
47      PutQueue = new Queue<ContainerPut>();
48      GetQueue = new Queue<ContainerGet>();
49      WhenAtLeastQueue = new SimplePriorityQueue<Event, double>();
50      WhenAtMostQueue = new SimplePriorityQueue<Event, double>(new ReverseComparer<double>());
51      WhenChangeQueue = new List<Event>();
52    }
53
54    public virtual ContainerPut Put(double amount) {
55      if (amount < 0) throw new ArgumentException("Cannot put negative amount", "amount");
56      if (amount > Capacity) throw new ArgumentException("Cannot put more than capacity", "amount");
57      var put = new ContainerPut(Environment, TriggerGet, amount);
58      PutQueue.Enqueue(put);
59      TriggerPut();
60      return put;
61    }
62
63    public virtual ContainerGet Get(double amount) {
64      if (amount < 0) throw new ArgumentException("Cannot get negative amount", "amount");
65      if (amount > Capacity) throw new ArgumentException("Cannot get more than capacity", "amount");
66      var get = new ContainerGet(Environment, TriggerPut, amount);
67      GetQueue.Enqueue(get);
68      TriggerGet();
69      return get;
70    }
71
72    public virtual Event WhenAtLeast(double level) {
73      var whenAtLeast = new Event(Environment);
74      WhenAtLeastQueue.Enqueue(whenAtLeast, level);
75      TriggerWhenAtLeast();
76      return whenAtLeast;
77    }
78
79    public virtual Event WhenFull() {
80      return WhenAtLeast(Capacity);
81    }
82
83    public virtual Event WhenAtMost(double level) {
84      var whenAtMost = new Event(Environment);
85      WhenAtMostQueue.Enqueue(whenAtMost, level);
86      TriggerWhenAtMost();
87      return whenAtMost;
88    }
89
90    public virtual Event WhenEmpty() {
91      return WhenAtMost(0);
92    }
93
94    public virtual Event WhenChange() {
95      var whenChange = new Event(Environment);
96      WhenChangeQueue.Add(whenChange);
97      return whenChange;
98    }
99
100    protected virtual void DoPut(ContainerPut put) {
101      if (Capacity - Level >= put.Amount) {
102        PutWaitingTime?.Add(Environment.ToDouble(Environment.Now - put.Time));
103        Level += put.Amount;
104        put.Succeed();
105      }
106    }
107
108    protected virtual void DoGet(ContainerGet get) {
109      if (Level >= get.Amount) {
110        GetWaitingTime?.Add(Environment.ToDouble(Environment.Now - get.Time));
111        Level -= get.Amount;
112        get.Succeed();
113      }
114    }
115
116    protected virtual void TriggerPut(Event @event = null) {
117      while (PutQueue.Count > 0) {
118        var put = PutQueue.Peek();
119        DoPut(put);
120        if (put.IsTriggered) {
121          PutQueue.Dequeue();
122          TriggerWhenAtLeast();
123          TriggerWhenChange();
124        } else break;
125      }
126      Fillrate?.UpdateTo(Level / Capacity);
127      PutQueueLength?.UpdateTo(PutQueue.Count);
128    }
129
130    protected virtual void TriggerGet(Event @event = null) {
131      while (GetQueue.Count > 0) {
132        var get = GetQueue.Peek();
133        DoGet(get);
134        if (get.IsTriggered) {
135          GetQueue.Dequeue();
136          TriggerWhenAtMost();
137          TriggerWhenChange();
138        } else break;
139      }
140      Fillrate?.UpdateTo(Level / Capacity);
141      GetQueueLength?.UpdateTo(GetQueue.Count);
142    }
143
144    protected virtual void TriggerWhenAtLeast() {
145      while (WhenAtLeastQueue.Count > 0 && Level >= WhenAtLeastQueue.Peek) {
146        var whenAtLeast = WhenAtLeastQueue.Dequeue();
147        whenAtLeast.Succeed();
148      }
149    }
150
151    protected virtual void TriggerWhenAtMost() {
152      while (WhenAtMostQueue.Count > 0 && Level <= WhenAtMostQueue.Peek) {
153        var whenAtMost = WhenAtMostQueue.Dequeue();
154        whenAtMost.Succeed();
155      }
156    }
157
158    protected virtual void TriggerWhenChange() {
159      if (WhenChangeQueue.Count == 0) return;
160      foreach (var evt in WhenChangeQueue)
161        evt.Succeed();
162      WhenChangeQueue.Clear();
163    }
164  }
165}
Note: See TracBrowser for help on using the repository browser.