Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.1/SimSharp-3.3.1/Core/Resources/PriorityStore.cs @ 17487

Last change on this file since 17487 was 17487, checked in by abeham, 4 years ago

#3065: update Sim# to 3.3.1

File size: 7.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;
10using System.Linq;
11
12namespace SimSharp {
13  /// <summary>
14  /// A PriorityStore is similar to a <see cref="Store"/>.
15  /// However, items are removed from the store in order of their priority.
16  ///
17  /// PriorityStore holds a variable number of individual items.
18  /// Put and Get are both processed in strict FIFO order.
19  /// </summary>
20  public class PriorityStore {
21
22    public int Capacity { get; protected set; }
23
24    public int Count { get { return Items.Count; } }
25
26    protected Simulation Environment { get; private set; }
27
28    protected Queue<StorePut> PutQueue { get; private set; }
29    protected Queue<StoreGet> GetQueue { get; private set; }
30    protected SimplePriorityQueue<StoreItem, double> Items { get; private set; }
31    protected List<Event> WhenNewQueue { get; private set; }
32    protected List<Event> WhenAnyQueue { get; private set; }
33    protected List<Event> WhenFullQueue { get; private set; }
34    protected List<Event> WhenEmptyQueue { get; private set; }
35    protected List<Event> WhenChangeQueue { get; private set; }
36
37    public ITimeSeriesMonitor Utilization { get; set; }
38    public ITimeSeriesMonitor WIP { get; set; }
39    public ISampleMonitor LeadTime { get; set; }
40    public ITimeSeriesMonitor PutQueueLength { get; set; }
41    public ISampleMonitor PutWaitingTime { get; set; }
42    public ITimeSeriesMonitor GetQueueLength { get; set; }
43    public ISampleMonitor GetWaitingTime { get; set; }
44
45    public PriorityStore(Simulation environment, int capacity = int.MaxValue) {
46      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
47      Environment = environment;
48      Capacity = capacity;
49      PutQueue = new Queue<StorePut>();
50      GetQueue = new Queue<StoreGet>();
51      Items = new SimplePriorityQueue<StoreItem, double>();
52      WhenNewQueue = new List<Event>();
53      WhenAnyQueue = new List<Event>();
54      WhenFullQueue = new List<Event>();
55      WhenEmptyQueue = new List<Event>();
56      WhenChangeQueue = new List<Event>();
57    }
58    public PriorityStore(Simulation environment, IEnumerable<object> items, IEnumerable<double> priorities, int capacity = int.MaxValue) {
59      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
60      Environment = environment;
61      Capacity = capacity;
62      PutQueue = new Queue<StorePut>();
63      GetQueue = new Queue<StoreGet>();
64      Items = new SimplePriorityQueue<StoreItem, double>();
65      var itemsList = items.ToList();
66      foreach (var zip in itemsList.Zip(priorities, (a, b) => new { Item = a, Prio = b }))
67        Items.Enqueue(new StoreItem() { AdmissionDate = environment.Now, Item = zip.Item }, zip.Prio);
68      if (Items.Count != itemsList.Count) throw new ArgumentException("Fewer priorities than items are given.", "priorities");
69
70      WhenNewQueue = new List<Event>();
71      WhenAnyQueue = new List<Event>();
72      WhenFullQueue = new List<Event>();
73      WhenEmptyQueue = new List<Event>();
74      WhenChangeQueue = new List<Event>();
75      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
76    }
77
78    public virtual StorePut Put(object item, double priority = 1) {
79      var put = new StorePut(Environment, TriggerGet, new PriorityItem(priority, item));
80      PutQueue.Enqueue(put);
81      TriggerPut();
82      return put;
83    }
84
85    public virtual StoreGet Get() {
86      var get = new StoreGet(Environment, TriggerPut);
87      GetQueue.Enqueue(get);
88      TriggerGet();
89      return get;
90    }
91
92    public virtual Event WhenNew() {
93      var whenNew = new Event(Environment);
94      WhenNewQueue.Add(whenNew);
95      return whenNew;
96    }
97
98    public virtual Event WhenAny() {
99      var whenAny = new Event(Environment);
100      WhenAnyQueue.Add(whenAny);
101      TriggerWhenAny();
102      return whenAny;
103    }
104
105    public virtual Event WhenFull() {
106      var whenFull = new Event(Environment);
107      WhenFullQueue.Add(whenFull);
108      TriggerWhenFull();
109      return whenFull;
110    }
111
112    public virtual Event WhenEmpty() {
113      var whenEmpty = new Event(Environment);
114      WhenEmptyQueue.Add(whenEmpty);
115      TriggerWhenEmpty();
116      return whenEmpty;
117    }
118
119    public virtual Event WhenChange() {
120      var whenChange = new Event(Environment);
121      WhenChangeQueue.Add(whenChange);
122      return whenChange;
123    }
124
125    protected virtual void DoPut(StorePut put) {
126      if (Items.Count < Capacity) {
127        var pi = (PriorityItem)put.Value;
128        PutWaitingTime?.Add(Environment.ToDouble(Environment.Now - put.Time));
129        Items.Enqueue(new StoreItem() { AdmissionDate = Environment.Now, Item = pi.Item}, pi.Priority);
130        put.Succeed();
131      }
132    }
133
134    protected virtual void DoGet(StoreGet get) {
135      if (Items.Count > 0) {
136        var item = Items.Dequeue();
137        GetWaitingTime?.Add(Environment.ToDouble(Environment.Now - get.Time));
138        LeadTime?.Add(Environment.ToDouble(Environment.Now - item.AdmissionDate));
139        get.Succeed(item.Item);
140      }
141    }
142
143    protected virtual void TriggerPut(Event @event = null) {
144      while (PutQueue.Count > 0) {
145        var put = PutQueue.Peek();
146        DoPut(put);
147        if (put.IsTriggered) {
148          PutQueue.Dequeue();
149          TriggerWhenNew();
150          TriggerWhenAny();
151          TriggerWhenFull();
152          TriggerWhenChange();
153        } else break;
154      }
155      Utilization?.UpdateTo(Count / (double)Capacity);
156      WIP?.UpdateTo(Count + PutQueue.Count + GetQueue.Count);
157      PutQueueLength?.UpdateTo(PutQueue.Count);
158    }
159
160    protected virtual void TriggerGet(Event @event = null) {
161      while (GetQueue.Count > 0) {
162        var get = GetQueue.Peek();
163        DoGet(get);
164        if (get.IsTriggered) {
165          GetQueue.Dequeue();
166          TriggerWhenEmpty();
167          TriggerWhenChange();
168        } else break;
169      }
170      Utilization?.UpdateTo(Count / (double)Capacity);
171      WIP?.UpdateTo(Count + PutQueue.Count + GetQueue.Count);
172      GetQueueLength?.UpdateTo(GetQueue.Count);
173    }
174
175    protected virtual void TriggerWhenNew() {
176      if (WhenNewQueue.Count == 0) return;
177      foreach (var evt in WhenNewQueue)
178        evt.Succeed();
179      WhenNewQueue.Clear();
180    }
181
182    protected virtual void TriggerWhenAny() {
183      if (Items.Count > 0) {
184        if (WhenAnyQueue.Count == 0) return;
185        foreach (var evt in WhenAnyQueue)
186          evt.Succeed();
187        WhenAnyQueue.Clear();
188      }
189    }
190
191    protected virtual void TriggerWhenFull() {
192      if (Count == Capacity) {
193        if (WhenFullQueue.Count == 0) return;
194        foreach (var evt in WhenFullQueue)
195          evt.Succeed();
196        WhenFullQueue.Clear();
197      }
198    }
199
200    protected virtual void TriggerWhenEmpty() {
201      if (Count == 0) {
202        if (WhenEmptyQueue.Count == 0) return;
203        foreach (var evt in WhenEmptyQueue)
204          evt.Succeed();
205        WhenEmptyQueue.Clear();
206      }
207    }
208
209    protected virtual void TriggerWhenChange() {
210      if (WhenChangeQueue.Count == 0) return;
211      foreach (var evt in WhenChangeQueue)
212        evt.Succeed();
213      WhenChangeQueue.Clear();
214    }
215
216    protected struct PriorityItem {
217      public double Priority { get; }
218      public object Item { get; }
219
220      public PriorityItem(double priority, object item) {
221        Priority = priority;
222        Item = item;
223      }
224    }
225  }
226}
Note: See TracBrowser for help on using the repository browser.