Changeset 16779


Ignore:
Timestamp:
04/12/19 13:45:11 (9 days ago)
Author:
abeham
Message:

#2975: Updated Sim# to 3.1.1

Location:
trunk
Files:
10 added
7 deleted
34 edited
3 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/HeuristicLab.ExtLibs.sln

    r16658 r16779  
    6767Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.EPPlus-4.0.3", "HeuristicLab.ExtLibs\HeuristicLab.EPPlus\4.0.3\HeuristicLab.EPPlus-4.0.3\HeuristicLab.EPPlus-4.0.3.csproj", "{675A6EE4-DE7C-413E-8BEF-EB21E0384C87}"
    6868EndProject
    69 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimSharp-3.0.11", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.0.11\SimSharp-3.0.11\SimSharp-3.0.11.csproj", "{9FE9C740-7859-4D01-AD07-7D4E15A6320B}"
    70 EndProject
    71 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.SimSharp-3.0.11", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.0.11\HeuristicLab.SimSharp-3.0.11\HeuristicLab.SimSharp-3.0.11.csproj", "{5C93CAF7-AE6A-4540-95B2-5DA6761A2677}"
     69Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimSharp-3.1.1", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.1.1\SimSharp-3.1.1\SimSharp-3.1.1.csproj", "{9FE9C740-7859-4D01-AD07-7D4E15A6320B}"
     70EndProject
     71Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.SimSharp-3.1.1", "HeuristicLab.ExtLibs\HeuristicLab.SimSharp\3.1.1\HeuristicLab.SimSharp-3.1.1\HeuristicLab.SimSharp-3.1.1.csproj", "{5C93CAF7-AE6A-4540-95B2-5DA6761A2677}"
    7272EndProject
    7373Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HeuristicLab.IGraph-0.8.0-pre", "HeuristicLab.ExtLibs\HeuristicLab.Igraph\0.8.0-pre\HeuristicLab.Igraph-0.8.0-pre\HeuristicLab.IGraph-0.8.0-pre.csproj", "{088D34F2-32EA-43FF-BAA8-22428D5B66BE}"
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/HeuristicLab.SimSharp-3.1.1.csproj

    r16715 r16779  
    99    <AppDesignerFolder>Properties</AppDesignerFolder>
    1010    <RootNamespace>HeuristicLab.SimSharp</RootNamespace>
    11     <AssemblyName>HeuristicLab.SimSharp-3.0.11</AssemblyName>
     11    <AssemblyName>HeuristicLab.SimSharp-3.1.1</AssemblyName>
    1212    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    1313    <FileAlignment>512</FileAlignment>
     
    9292      <Private>False</Private>
    9393    </ProjectReference>
    94     <ProjectReference Include="..\SimSharp-3.0.11\SimSharp-3.0.11.csproj">
     94    <ProjectReference Include="..\SimSharp-3.1.1\SimSharp-3.1.1.csproj">
    9595      <Project>{9fe9c740-7859-4d01-ad07-7d4e15a6320b}</Project>
    96       <Name>SimSharp-3.0.11</Name>
     96      <Name>SimSharp-3.1.1</Name>
    9797    </ProjectReference>
    9898  </ItemGroup>
    9999  <ItemGroup>
    100     <Content Include="SimSharp-3.0.11 License.txt">
     100    <Content Include="SimSharp-3.1.1 License.txt">
    101101      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    102102    </Content>
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Plugin.cs.frame

    r16565 r16779  
    2323
    2424namespace HeuristicLab.SimSharp {
    25   [Plugin("HeuristicLab.SimSharp", "Transport plugin for the simulation framework Sim#", "3.0.11.$WCREV$")]
    26   [PluginFile("HeuristicLab.SimSharp-3.0.11.dll", PluginFileType.Assembly)]
    27   [PluginFile("SimSharp-3.0.11.dll", PluginFileType.Assembly)]
    28   [PluginFile("SimSharp-3.0.11 License.txt", PluginFileType.License)]
     25  [Plugin("HeuristicLab.SimSharp", "Transport plugin for the simulation framework Sim#", "3.1.1.$WCREV$")]
     26  [PluginFile("HeuristicLab.SimSharp-3.1.1.dll", PluginFileType.Assembly)]
     27  [PluginFile("SimSharp-3.1.1.dll", PluginFileType.Assembly)]
     28  [PluginFile("SimSharp-3.1.1 License.txt", PluginFileType.License)]
    2929  public class HeuristicLabSimSharpPlugin : PluginBase {
    3030  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/HeuristicLab.SimSharp-3.1.1/Properties/AssemblyInfo.cs.frame

    r15972 r16779  
    55// set of attributes. Change these attribute values to modify the information
    66// associated with an assembly.
    7 [assembly: AssemblyTitle("HeuristicLab.SimSharp-3.0.11")]
     7[assembly: AssemblyTitle("HeuristicLab.SimSharp")]
    88[assembly: AssemblyDescription("Transport plugin for the simulation framework Sim#")]
    99[assembly: AssemblyConfiguration("")]
    1010[assembly: AssemblyCompany("HEAL")]
    1111[assembly: AssemblyProduct("HeuristicLab")]
    12 [assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
     12[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
    1313[assembly: AssemblyTrademark("")]
    1414[assembly: AssemblyCulture("")]
     
    3232// by using the '*' as shown below:
    3333// [assembly: AssemblyVersion("1.0.*")]
    34 [assembly: AssemblyVersion("3.0.11.0")]
    35 [assembly: AssemblyFileVersion("3.0.11.$WCREV$")]
     34[assembly: AssemblyVersion("3.1.1.0")]
     35[assembly: AssemblyFileVersion("3.1.1.$WCREV$")]
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Analysis/ContinuousStatistics.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2121namespace SimSharp {
    2222  public sealed class ContinuousStatistics {
    23     private readonly Environment env;
     23    private readonly Simulation env;
    2424
    2525    public int Count { get; private set; }
     
    4141
    4242
    43     public ContinuousStatistics(Environment env) {
     43    public ContinuousStatistics(Simulation env) {
    4444      this.env = env;
    4545      lastUpdateTime = env.NowD;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Collections/EventQueue.cs

    r15972 r16779  
    66  /// <summary>
    77  /// An implementation of a min-Priority Queue using a heap.  Has O(1) .Contains()!
    8   /// See https://bitbucket.org/BlueRaja/high-speed-priority-queue-for-c/wiki/Getting%20Started for more information
     8  /// See https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp/wiki/Getting-Started for more information
    99  /// </summary>
    1010  /// <remarks>
     
    4848    /// Removes every node from the queue.  O(n) (So, don't do this often!)
    4949    /// </summary>
    50 #if AGGRESSIVE_INLINING
    51         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    52 #endif
     50    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    5351    public void Clear() {
    5452      Array.Clear(_nodes, 1, _numNodes);
     
    5957    /// Returns (in O(1)!) whether the given node is in the queue.  O(1)
    6058    /// </summary>
    61 #if AGGRESSIVE_INLINING
    62         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    63 #endif
     59    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    6460    public bool Contains(EventQueueNode node) {
    6561      return (_nodes[node.QueueIndex] == node);
     
    6965    /// Enqueue a node - .Priority must be set beforehand!  O(log n)
    7066    /// </summary>
    71 #if AGGRESSIVE_INLINING
    72         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    73 #endif
     67    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    7468    public EventQueueNode Enqueue(DateTime primaryPriority, Event @event, int secondaryPriority = 0) {
    7569      var node = new EventQueueNode {
     
    8478      return node;
    8579    }
    86 
    87 #if AGGRESSIVE_INLINING
    88         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    89 #endif
     80   
     81    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    9082    private void Swap(EventQueueNode node1, EventQueueNode node2) {
    9183      //Swap the nodes
     
    115107    }
    116108
    117 #if AGGRESSIVE_INLINING
    118         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    119 #endif
     109
     110    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    120111    private void CascadeDown(EventQueueNode node) {
    121112      //aka Heapify-down
     
    170161    /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
    171162    /// </summary>
    172 #if AGGRESSIVE_INLINING
    173         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    174 #endif
     163
     164    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    175165    private bool HasHigherPriority(EventQueueNode higher, EventQueueNode lower) {
    176166      return (higher.PrimaryPriority < lower.PrimaryPriority ||
     
    204194    /// O(log n)
    205195    /// </summary>
    206 #if AGGRESSIVE_INLINING
    207         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    208 #endif
     196
     197    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
    209198    public void UpdatePriority(EventQueueNode node, DateTime primaryPriority, int secondaryPriority) {
    210199      node.PrimaryPriority = primaryPriority;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/ActiveObject.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    1818
    1919namespace SimSharp {
    20   public abstract class ActiveObject<T> where T : Environment {
     20  public abstract class ActiveObject<T> where T : Simulation {
    2121    protected T Environment { get; private set; }
    2222
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Environment.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323namespace SimSharp {
    2424  /// <summary>
    25   /// Environments hold the event queues, schedule and process events.
     25  /// Simulation hold the event queues, schedule and process events.
    2626  /// </summary>
    27   public class Environment {
     27  /// <remarks>
     28  /// This class is not thread-safe against manipulation of the event queue. If you supply a termination
     29  /// event that is set outside the simulation, please use the <see cref="ThreadSafeSimulation"/> environment.
     30  ///
     31  /// For most purposes <see cref="Simulation"/> is however the better and faster choice.
     32  /// </remarks>
     33  public class Simulation {
    2834    private const int InitialMaxEvents = 1024;
    29     private object locker = new object();
    3035
    3136    /// <summary>
     
    6570    public int ProcessedEvents { get; protected set; }
    6671
    67     public Environment() : this(new DateTime(1970, 1, 1)) { }
    68     public Environment(TimeSpan? defaultStep) : this(new DateTime(1970, 1, 1), defaultStep) { }
    69     public Environment(int randomSeed, TimeSpan? defaultStep = null) : this(new DateTime(1970, 1, 1), randomSeed, defaultStep) { }
    70     public Environment(DateTime initialDateTime, TimeSpan? defaultStep = null) {
     72    public Simulation() : this(new DateTime(1970, 1, 1)) { }
     73    public Simulation(TimeSpan? defaultStep) : this(new DateTime(1970, 1, 1), defaultStep) { }
     74    public Simulation(int randomSeed, TimeSpan? defaultStep = null) : this(new DateTime(1970, 1, 1), randomSeed, defaultStep) { }
     75    public Simulation(DateTime initialDateTime, TimeSpan? defaultStep = null) : this(new PcgRandom(), initialDateTime, defaultStep) { }
     76    public Simulation(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null) : this(new PcgRandom(randomSeed), initialDateTime, defaultStep) { }
     77    public Simulation(IRandom random, DateTime initialDateTime, TimeSpan? defaultStep = null) {
    7178      DefaultTimeStepSeconds = (defaultStep ?? TimeSpan.FromSeconds(1)).Duration().TotalSeconds;
    7279      StartDate = initialDateTime;
    7380      Now = initialDateTime;
    74       Random = new SystemRandom();
    75       ScheduleQ = new EventQueue(InitialMaxEvents);
    76       Logger = Console.Out;
    77     }
    78     public Environment(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null) {
    79       DefaultTimeStepSeconds = (defaultStep ?? TimeSpan.FromSeconds(1)).Duration().TotalSeconds;
    80       StartDate = initialDateTime;
    81       Now = initialDateTime;
    82       Random = new SystemRandom(randomSeed);
     81      Random = random;
    8382      ScheduleQ = new EventQueue(InitialMaxEvents);
    8483      Logger = Console.Out;
     
    127126      ProcessedEvents = 0;
    128127      Now = StartDate;
    129       Random = new SystemRandom(randomSeed);
     128      Random = new PcgRandom(randomSeed);
    130129      ScheduleQ = new EventQueue(InitialMaxEvents);
     130      useSpareNormal = false;
    131131    }
    132132
     
    139139    /// </summary>
    140140    /// <param name="event">The event that should be scheduled.</param>
    141     /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param></param>
     141    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
    142142    public virtual void Schedule(Event @event, int priority = 0) {
    143       lock (locker) {
    144         DoSchedule(Now, @event, priority);
    145       }
     143      DoSchedule(Now, @event, priority);
    146144    }
    147145
     
    158156      if (delay < TimeSpan.Zero)
    159157        throw new ArgumentException("Negative delays are not allowed in Schedule(TimeSpan, Event).");
    160       lock (locker) {
    161         var eventTime = Now + delay;
    162         DoSchedule(eventTime, @event, priority);
    163       }
     158      var eventTime = Now + delay;
     159      DoSchedule(eventTime, @event, priority);
    164160    }
    165161
     
    193189    }
    194190
     191    protected bool _stopRequested = false;
     192    /// <summary>
     193    /// Run until a certain event is processed.
     194    /// </summary>
     195    /// <remarks>
     196    /// This simulation environment is not thread-safe, thus triggering this event outside the environment
     197    /// leads to potential race conditions. Please use the <see cref="ThreadSafeSimulation"/> environment in case you
     198    /// require this functionality. Note that the performance of <see cref="ThreadSafeSimulation"/> is lower due to locking.
     199    ///
     200    /// For real-time based termination, you can also call <see cref="StopAsync"/> which sets a flag indicating the simulation
     201    /// to stop before processing the next event.
     202    /// </remarks>
     203    /// <param name="stopEvent">The event that stops the simulation.</param>
     204    /// <returns></returns>
    195205    public virtual object Run(Event stopEvent = null) {
     206      _stopRequested = false;
    196207      if (stopEvent != null) {
    197208        if (stopEvent.IsProcessed) return stopEvent.Value;
     
    200211
    201212      try {
    202         var stop = ScheduleQ.Count == 0;
     213        var stop = ScheduleQ.Count == 0 || _stopRequested;
    203214        while (!stop) {
    204215          Step();
    205216          ProcessedEvents++;
    206           lock (locker) {
    207             stop = ScheduleQ.Count == 0;
     217          stop = ScheduleQ.Count == 0 || _stopRequested;
     218        }
     219      } catch (StopSimulationException e) { return e.Value; }
     220      if (stopEvent == null) return null;
     221      if (!stopEvent.IsTriggered) throw new InvalidOperationException("No scheduled events left but \"until\" event was not triggered.");
     222      return stopEvent.Value;
     223    }
     224
     225    public virtual void StopAsync() {
     226      _stopRequested = true;
     227    }
     228
     229    /// <summary>
     230    /// Performs a single step of the simulation, i.e. process a single event
     231    /// </summary>
     232    /// <remarks>
     233    /// This method is not thread-safe
     234    /// </remarks>
     235    public virtual void Step() {
     236      Event evt;
     237      var next = ScheduleQ.Dequeue();
     238      Now = next.PrimaryPriority;
     239      evt = next.Event;
     240      evt.Process();
     241    }
     242
     243    /// <summary>
     244    /// Peeks at the time of the next event in terms of the defined step
     245    /// </summary>
     246    /// <remarks>
     247    /// This method is not thread-safe
     248    /// </remarks>
     249    public virtual double PeekD() {
     250      if (ScheduleQ.Count == 0) return double.MaxValue;
     251      return (Peek() - StartDate).TotalSeconds / DefaultTimeStepSeconds;
     252    }
     253
     254    /// <summary>
     255    /// Peeks at the time of the next event
     256    /// </summary>
     257    /// <remarks>
     258    /// This method is not thread-safe
     259    /// </remarks>
     260    public virtual DateTime Peek() {
     261      return ScheduleQ.Count > 0 ? ScheduleQ.First.PrimaryPriority : DateTime.MaxValue;
     262    }
     263
     264    protected virtual void StopSimulation(Event @event) {
     265      throw new StopSimulationException(@event.Value);
     266    }
     267
     268    public virtual void Log(string message, params object[] args) {
     269      if (Logger != null)
     270        Logger.WriteLine(message, args);
     271    }
     272
     273    #region Random number distributions
     274    public double RandUniform(IRandom random, double a, double b) {
     275      return a + (b - a) * random.NextDouble();
     276    }
     277    public double RandUniform(double a, double b) {
     278      return RandUniform(Random, a, b);
     279    }
     280
     281    public TimeSpan RandUniform(IRandom random, TimeSpan a, TimeSpan b) {
     282      return TimeSpan.FromSeconds(RandUniform(random, a.TotalSeconds, b.TotalSeconds));
     283    }
     284    public TimeSpan RandUniform(TimeSpan a, TimeSpan b) {
     285      return RandUniform(Random, a, b);
     286    }
     287    public double RandTriangular(IRandom random, double low, double high) {
     288      var u = random.NextDouble();
     289      if (u > 0.5)
     290        return high + (low - high) * Math.Sqrt(((1.0 - u) / 2));
     291      return low + (high - low) * Math.Sqrt(u / 2);
     292    }
     293    public double RandTriangular(double low, double high) {
     294      return RandTriangular(Random, low, high);
     295    }
     296
     297    public TimeSpan RandTriangular(IRandom random, TimeSpan low, TimeSpan high) {
     298      return TimeSpan.FromSeconds(RandTriangular(random, low.TotalSeconds, high.TotalSeconds));
     299    }
     300    public TimeSpan RandTriangular(TimeSpan low, TimeSpan high) {
     301      return RandTriangular(Random, low, high);
     302    }
     303
     304    public double RandTriangular(IRandom random, double low, double high, double mode) {
     305      var u = random.NextDouble();
     306      var c = (mode - low) / (high - low);
     307      if (u > c)
     308        return high + (low - high) * Math.Sqrt(((1.0 - u) * (1.0 - c)));
     309      return low + (high - low) * Math.Sqrt(u * c);
     310    }
     311    public double RandTriangular(double low, double high, double mode) {
     312      return RandTriangular(Random, low, high, mode);
     313    }
     314
     315    public TimeSpan RandTriangular(IRandom random, TimeSpan low, TimeSpan high, TimeSpan mode) {
     316      return TimeSpan.FromSeconds(RandTriangular(random, low.TotalSeconds, high.TotalSeconds, mode.TotalSeconds));
     317    }
     318    public TimeSpan RandTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
     319      return RandTriangular(Random, low, high, mode);
     320    }
     321
     322    /// <summary>
     323    /// Returns a number that is exponentially distributed given a certain mean.
     324    /// </summary>
     325    /// <remarks>
     326    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
     327    /// </remarks>
     328    /// <param name="random">The random number generator to use.</param>
     329    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
     330    /// <returns>A number that is exponentially distributed</returns>
     331    public double RandExponential(IRandom random, double mean) {
     332      return -Math.Log(1 - random.NextDouble()) * mean;
     333    }
     334    /// <summary>
     335    /// Returns a number that is exponentially distributed given a certain mean.
     336    /// </summary>
     337    /// <remarks>
     338    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
     339    /// </remarks>
     340    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
     341    /// <returns>A number that is exponentially distributed</returns>
     342    public double RandExponential(double mean) {
     343      return RandExponential(Random, mean);
     344    }
     345
     346    /// <summary>
     347    /// Returns a timespan that is exponentially distributed given a certain mean.
     348    /// </summary>
     349    /// <remarks>
     350    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
     351    /// </remarks>
     352    /// <param name="random">The random number generator to use.</param>
     353    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
     354    /// <returns>A number that is exponentially distributed</returns>
     355    public TimeSpan RandExponential(IRandom random, TimeSpan mean) {
     356      return TimeSpan.FromSeconds(RandExponential(random, mean.TotalSeconds));
     357    }
     358    /// <summary>
     359    /// Returns a timespan that is exponentially distributed given a certain mean.
     360    /// </summary>
     361    /// <remarks>
     362    /// Unlike in other APIs here the mean should be given and not the lambda parameter.
     363    /// </remarks>
     364    /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
     365    /// <returns>A number that is exponentially distributed</returns>
     366    public TimeSpan RandExponential(TimeSpan mean) {
     367      return RandExponential(Random, mean);
     368    }
     369
     370    private bool useSpareNormal = false;
     371    private double spareNormal = double.NaN;
     372    /// <summary>
     373    /// Uses the Marsaglia polar method to generate a random variable
     374    /// from two uniform random distributed values.
     375    /// </summary>
     376    /// <remarks>
     377    /// A spare random variable is generated from the second uniformly
     378    /// distributed value. Thus, the two calls to the uniform random number
     379    /// generator will be made only every second call.
     380    /// </remarks>
     381    /// <param name="random">The random number generator to use.</param>
     382    /// <param name="mu">The mean of the normal distribution.</param>
     383    /// <param name="sigma">The standard deviation of the normal distribution.</param>
     384    /// <returns>A number that is normal distributed.</returns>
     385    public virtual double RandNormal(IRandom random, double mu, double sigma) {
     386      if (useSpareNormal) {
     387        useSpareNormal = false;
     388        return spareNormal * sigma + mu;
     389      } else {
     390        double u, v, s;
     391        do {
     392          u = random.NextDouble() * 2 - 1;
     393          v = random.NextDouble() * 2 - 1;
     394          s = u * u + v * v;
     395        } while (s >= 1 || s == 0);
     396        var mul = Math.Sqrt(-2.0 * Math.Log(s) / s);
     397        spareNormal = v * mul;
     398        useSpareNormal = true;
     399        return mu + sigma * u * mul;
     400      }
     401    }
     402    /// <summary>
     403    /// Uses the Marsaglia polar method to generate a random variable
     404    /// from two uniform random distributed values.
     405    /// </summary>
     406    /// <remarks>
     407    /// A spare random variable is generated from the second uniformly
     408    /// distributed value. Thus, the two calls to the uniform random number
     409    /// generator will be made only every second call.
     410    /// </remarks>
     411    /// <param name="mu">The mean of the normal distribution.</param>
     412    /// <param name="sigma">The standard deviation of the normal distribution.</param>
     413    /// <returns>A number that is normal distributed.</returns>
     414    public double RandNormal(double mu, double sigma) {
     415      return RandNormal(Random, mu, sigma);
     416    }
     417
     418    /// <summary>
     419    /// Uses the Marsaglia polar method to generate a random variable
     420    /// from two uniform random distributed values.
     421    /// </summary>
     422    /// <remarks>
     423    /// A spare random variable is generated from the second uniformly
     424    /// distributed value. Thus, the two calls to the uniform random number
     425    /// generator will be made only every second call.
     426    /// </remarks>
     427    /// <param name="random">The random number generator to use.</param>
     428    /// <param name="mu">The mean of the normal distribution.</param>
     429    /// <param name="sigma">The standard deviation of the normal distribution.</param>
     430    /// <returns>A number that is normal distributed.</returns>
     431    public TimeSpan RandNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
     432      return TimeSpan.FromSeconds(RandNormal(random, mu.TotalSeconds, sigma.TotalSeconds));
     433    }
     434    /// <summary>
     435    /// Uses the Marsaglia polar method to generate a random variable
     436    /// from two uniform random distributed values.
     437    /// </summary>
     438    /// <remarks>
     439    /// A spare random variable is generated from the second uniformly
     440    /// distributed value. Thus, the two calls to the uniform random number
     441    /// generator will be made only every second call.
     442    /// </remarks>
     443    /// <param name="mu">The mean of the normal distribution.</param>
     444    /// <param name="sigma">The standard deviation of the normal distribution.</param>
     445    /// <returns>A number that is normal distributed.</returns>
     446    public TimeSpan RandNormal(TimeSpan mu, TimeSpan sigma) {
     447      return RandNormal(Random, mu, sigma);
     448    }
     449
     450    public double RandNormalPositive(IRandom random, double mu, double sigma) {
     451      double val;
     452      do {
     453        val = RandNormal(random, mu, sigma);
     454      } while (val <= 0);
     455      return val;
     456    }
     457    public double RandNormalPositive(double mu, double sigma) {
     458      return RandNormalPositive(Random, mu, sigma);
     459    }
     460
     461    public TimeSpan RandNormalPositive(IRandom random, TimeSpan mu, TimeSpan sigma) {
     462      return TimeSpan.FromSeconds(RandNormalPositive(random, mu.TotalSeconds, sigma.TotalSeconds));
     463    }
     464    public TimeSpan RandNormalPositive(TimeSpan mu, TimeSpan sigma) {
     465      return RandNormalPositive(Random, mu, sigma);
     466    }
     467
     468    public double RandNormalNegative(IRandom random, double mu, double sigma) {
     469      double val;
     470      do {
     471        val = RandNormal(random, mu, sigma);
     472      } while (val >= 0);
     473      return val;
     474    }
     475    public double RandNormalNegative(double mu, double sigma) {
     476      return RandNormalNegative(Random, mu, sigma);
     477    }
     478
     479    public TimeSpan RandNormalNegative(IRandom random, TimeSpan mu, TimeSpan sigma) {
     480      return TimeSpan.FromSeconds(RandNormalNegative(random, mu.TotalSeconds, sigma.TotalSeconds));
     481    }
     482    public TimeSpan RandNormalNegative(TimeSpan mu, TimeSpan sigma) {
     483      return RandNormalNegative(Random, mu, sigma);
     484    }
     485
     486    /// <summary>
     487    /// Returns values from a log-normal distribution with the mean
     488    /// exp(mu + sigma^2 / 2)
     489    /// and the standard deviation
     490    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
     491    /// </summary>
     492    /// <param name="random">The random number generator to use.</param>
     493    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
     494    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
     495    /// <returns>A log-normal distributed random value.</returns>
     496    public double RandLogNormal(IRandom random, double mu, double sigma) {
     497      return Math.Exp(RandNormal(random, mu, sigma));
     498    }
     499    /// <summary>
     500    /// Returns values from a log-normal distribution with the mean
     501    /// exp(mu + sigma^2 / 2)
     502    /// and the standard deviation
     503    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
     504    /// </summary>
     505    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
     506    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
     507    /// <returns>A log-normal distributed random value.</returns>
     508    public double RandLogNormal(double mu, double sigma) {
     509      return RandLogNormal(Random, mu, sigma);
     510    }
     511
     512    /// <summary>
     513    /// Returns values from a log-normal distribution with
     514    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
     515    /// </summary>
     516    /// <param name="random">The random number generator to use.</param>
     517    /// <param name="mean">The distribution mean.</param>
     518    /// <param name="stdev">The distribution standard deviation.</param>
     519    /// <returns>A log-normal distributed random value.</returns>
     520    public double RandLogNormal2(IRandom random, double mean, double stdev) {
     521      if (stdev == 0) return mean;
     522      var alpha = Math.Sqrt(mean * stdev) / mean;
     523      var sigma = Math.Sqrt(Math.Log(1 + (alpha * alpha)));
     524      var mu = Math.Log(mean) - 0.5 * sigma * sigma;
     525      return Math.Exp(RandNormal(random, mu, sigma));
     526    }
     527    /// <summary>
     528    /// Returns values from a log-normal distribution with
     529    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
     530    /// </summary>
     531    /// <param name="mean">The distribution mean.</param>
     532    /// <param name="stdev">The distribution standard deviation.</param>
     533    /// <returns>A log-normal distributed random value.</returns>
     534    public double RandLogNormal2(double mean, double stdev) {
     535      return RandLogNormal2(Random, mean, stdev);
     536    }
     537
     538    /// <summary>
     539    /// Returns a timespan value from a log-normal distribution with the mean
     540    /// exp(mu + sigma^2 / 2)
     541    /// and the standard deviation
     542    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
     543    /// </summary>
     544    /// <param name="random">The random number generator to use.</param>
     545    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
     546    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
     547    /// <returns>A log-normal distributed random timespan.</returns>
     548    public TimeSpan RandLogNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
     549      return TimeSpan.FromSeconds(RandLogNormal(random, mu.TotalSeconds, sigma.TotalSeconds));
     550    }
     551    /// <summary>
     552    /// Returns a timespan value from a log-normal distribution with the mean
     553    /// exp(mu + sigma^2 / 2)
     554    /// and the standard deviation
     555    /// sqrt([exp(sigma^2)-1] * exp(2 * mu + sigma^2))
     556    /// </summary>
     557    /// <param name="mu">The mu parameter of the log-normal distribution (not the mean).</param>
     558    /// <param name="sigma">The sigma parameter of the log-normal distribution (not the standard deviation).</param>
     559    /// <returns>A log-normal distributed random timespan.</returns>
     560    public TimeSpan RandLogNormal(TimeSpan mu, TimeSpan sigma) {
     561      return RandLogNormal(Random, mu, sigma);
     562    }
     563
     564    /// <summary>
     565    /// Returns a timespan value from a log-normal distribution with
     566    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
     567    /// </summary>
     568    /// <param name="random">The random number generator to use.</param>
     569    /// <param name="mean">The distribution mean.</param>
     570    /// <param name="stdev">The distribution standard deviation.</param>
     571    /// <returns>A log-normal distributed random timespan.</returns>
     572    public TimeSpan RandLogNormal2(IRandom random, TimeSpan mean, TimeSpan stdev) {
     573      return TimeSpan.FromSeconds(RandLogNormal2(random, mean.TotalSeconds, stdev.TotalSeconds));
     574    }
     575    /// <summary>
     576    /// Returns a timespan value from a log-normal distribution with
     577    /// the mean <paramref name="mean"/> and standard deviation <paramref name="stdev"/>.
     578    /// </summary>
     579    /// <param name="mean">The distribution mean.</param>
     580    /// <param name="stdev">The distribution standard deviation.</param>
     581    /// <returns>A log-normal distributed random timespan.</returns>
     582    public TimeSpan RandLogNormal2(TimeSpan mean, TimeSpan stdev) {
     583      return RandLogNormal2(Random, mean, stdev);
     584    }
     585
     586    public double RandCauchy(IRandom random, double x0, double gamma) {
     587      return x0 + gamma * Math.Tan(Math.PI * (random.NextDouble() - 0.5));
     588    }
     589    public double RandCauchy(double x0, double gamma) {
     590      return RandCauchy(Random, x0, gamma);
     591    }
     592
     593    public TimeSpan RandCauchy(IRandom random, TimeSpan x0, TimeSpan gamma) {
     594      return TimeSpan.FromSeconds(RandCauchy(random, x0.TotalSeconds, gamma.TotalSeconds));
     595    }
     596    public TimeSpan RandCauchy(TimeSpan x0, TimeSpan gamma) {
     597      return RandCauchy(Random, x0, gamma);
     598    }
     599
     600    public double RandWeibull(IRandom random, double alpha, double beta) {
     601      return alpha * Math.Pow(-Math.Log(1 - random.NextDouble()), 1 / beta);
     602    }
     603    public double RandWeibull(double alpha, double beta) {
     604      return RandWeibull(Random, alpha, beta);
     605    }
     606
     607    public TimeSpan RandWeibull(IRandom random, TimeSpan alpha, TimeSpan beta) {
     608      return TimeSpan.FromSeconds(RandWeibull(random, alpha.TotalSeconds, beta.TotalSeconds));
     609    }
     610    public TimeSpan RandWeibull(TimeSpan alpha, TimeSpan beta) {
     611      return RandWeibull(Random, alpha, beta);
     612    }
     613    #endregion
     614
     615    #region Random timeouts
     616    public Timeout TimeoutUniformD(IRandom random, double a, double b) {
     617      return new Timeout(this, ToTimeSpan(RandUniform(random, a, b)));
     618    }
     619    public Timeout TimeoutUniformD(double a, double b) {
     620      return TimeoutUniformD(Random, a, b);
     621    }
     622
     623    public Timeout TimeoutUniform(IRandom random, TimeSpan a, TimeSpan b) {
     624      return new Timeout(this, RandUniform(random, a, b));
     625    }
     626    public Timeout TimeoutUniform(TimeSpan a, TimeSpan b) {
     627      return TimeoutUniform(Random, a, b);
     628    }
     629
     630    public Timeout TimeoutTriangularD(IRandom random, double low, double high) {
     631      return new Timeout(this, ToTimeSpan(RandTriangular(random, low, high)));
     632    }
     633    public Timeout TimeoutTriangularD(double low, double high) {
     634      return TimeoutTriangularD(Random, low, high);
     635    }
     636
     637    public Timeout TimeoutTriangular(IRandom random, TimeSpan low, TimeSpan high) {
     638      return new Timeout(this, RandTriangular(random, low, high));
     639    }
     640    public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high) {
     641      return TimeoutTriangular(Random, low, high);
     642    }
     643
     644    public Timeout TimeoutTriangularD(IRandom random, double low, double high, double mode) {
     645      return new Timeout(this, ToTimeSpan(RandTriangular(random, low, high, mode)));
     646    }
     647    public Timeout TimeoutTriangularD(double low, double high, double mode) {
     648      return TimeoutTriangularD(Random, low, high, mode);
     649    }
     650
     651    public Timeout TimeoutTriangular(IRandom random, TimeSpan low, TimeSpan high, TimeSpan mode) {
     652      return new Timeout(this, RandTriangular(random, low, high, mode));
     653    }
     654    public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
     655      return TimeoutTriangular(Random, low, high, mode);
     656    }
     657
     658    public Timeout TimeoutExponentialD(IRandom random, double mean) {
     659      return new Timeout(this, ToTimeSpan(RandExponential(random, mean)));
     660    }
     661    public Timeout TimeoutExponentialD(double mean) {
     662      return TimeoutExponentialD(Random, mean);
     663    }
     664
     665    public Timeout TimeoutExponential(IRandom random, TimeSpan mean) {
     666      return new Timeout(this, RandExponential(random, mean));
     667    }
     668    public Timeout TimeoutExponential(TimeSpan mean) {
     669      return TimeoutExponential(Random, mean);
     670    }
     671
     672    public Timeout TimeoutNormalPositiveD(IRandom random, double mu, double sigma) {
     673      return new Timeout(this, ToTimeSpan(RandNormalPositive(random, mu, sigma)));
     674    }
     675    public Timeout TimeoutNormalPositiveD(double mu, double sigma) {
     676      return TimeoutNormalPositiveD(Random, mu, sigma);
     677    }
     678
     679    public Timeout TimeoutNormalPositive(IRandom random, TimeSpan mu, TimeSpan sigma) {
     680      return new Timeout(this, RandNormalPositive(random, mu, sigma));
     681    }
     682    public Timeout TimeoutNormalPositive(TimeSpan mu, TimeSpan sigma) {
     683      return TimeoutNormalPositive(Random, mu, sigma);
     684    }
     685
     686    public Timeout TimeoutLogNormalD(IRandom random, double mu, double sigma) {
     687      return new Timeout(this, ToTimeSpan(RandLogNormal(random, mu, sigma)));
     688    }
     689    public Timeout TimeoutLogNormalD(double mu, double sigma) {
     690      return TimeoutLogNormalD(Random, mu, sigma);
     691    }
     692
     693    public Timeout TimeoutLogNormal2D(IRandom random, double mean, double stdev) {
     694      return new Timeout(this, ToTimeSpan(RandLogNormal2(random, mean, stdev)));
     695    }
     696    public Timeout TimeoutLogNormal2D(double mean, double stdev) {
     697      return TimeoutLogNormal2D(Random, mean, stdev);
     698    }
     699
     700    public Timeout TimeoutLogNormal(IRandom random, TimeSpan mu, TimeSpan sigma) {
     701      return new Timeout(this, RandLogNormal(random, mu, sigma));
     702    }
     703    public Timeout TimeoutLogNormal(TimeSpan mu, TimeSpan sigma) {
     704      return TimeoutLogNormal(Random, mu, sigma);
     705    }
     706
     707    public Timeout TimeoutLogNormal2(IRandom random, TimeSpan mean, TimeSpan stdev) {
     708      return new Timeout(this, RandLogNormal2(random, mean, stdev));
     709    }
     710    public Timeout TimeoutLogNormal2(TimeSpan mean, TimeSpan stdev) {
     711      return TimeoutLogNormal2(Random, mean, stdev);
     712    }
     713    #endregion
     714  }
     715
     716  /// <summary>
     717  /// Provides a simulation environment that is thread-safe against manipulations of the event queue.
     718  /// Its performance is somewhat lower than the non-thread-safe environment (cf. <see cref="Simulation"/>)
     719  /// due to the locking involved.
     720  /// </summary>
     721  /// <remarks>
     722  /// Please carefully consider if you must really schedule the stop event in a separate thread. You can also
     723  /// call <see cref="Simulation.StopAsync"/> to request termination after the current event has been processed.
     724  ///
     725  /// The simulation will still run in only one thread and execute all events sequentially.
     726  /// </remarks>
     727  public class ThreadSafeSimulation : Simulation {
     728    protected object _locker;
     729
     730    public ThreadSafeSimulation() : this(new DateTime(1970, 1, 1)) { }
     731    public ThreadSafeSimulation(TimeSpan? defaultStep) : this(new DateTime(1970, 1, 1), defaultStep) { }
     732    public ThreadSafeSimulation(DateTime initialDateTime, TimeSpan? defaultStep = null) : this(new PcgRandom(), initialDateTime, defaultStep) { }
     733    public ThreadSafeSimulation(int randomSeed, TimeSpan? defaultStep = null) : this(new DateTime(1970, 1, 1), randomSeed, defaultStep) { }
     734    public ThreadSafeSimulation(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null) : this(new PcgRandom(randomSeed), initialDateTime, defaultStep) { }
     735    public ThreadSafeSimulation(IRandom random, DateTime initialDateTime, TimeSpan? defaultStep = null) : base(random, initialDateTime, defaultStep) {
     736      _locker = new object();
     737    }
     738
     739
     740    /// <summary>
     741    /// Schedules an event to occur at the same simulation time as the call was made.
     742    /// </summary>
     743    /// <remarks>
     744    /// This method is thread-safe against manipulations of the event queue
     745    /// </remarks>
     746    /// <param name="event">The event that should be scheduled.</param>
     747    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
     748    public override void Schedule(Event @event, int priority = 0) {
     749      lock (_locker) {
     750        DoSchedule(Now, @event, priority);
     751      }
     752    }
     753
     754    /// <summary>
     755    /// Schedules an event to occur after a certain (positive) delay.
     756    /// </summary>
     757    /// <remarks>
     758    /// This method is thread-safe against manipulations of the event queue
     759    /// </remarks>
     760    /// <exception cref="ArgumentException">
     761    /// Thrown when <paramref name="delay"/> is negative.
     762    /// </exception>
     763    /// <param name="delay">The (positive) delay after which the event should be fired.</param>
     764    /// <param name="event">The event that should be scheduled.</param>
     765    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
     766    public override void Schedule(TimeSpan delay, Event @event, int priority = 0) {
     767      if (delay < TimeSpan.Zero)
     768        throw new ArgumentException("Negative delays are not allowed in Schedule(TimeSpan, Event).");
     769      lock (_locker) {
     770        var eventTime = Now + delay;
     771        DoSchedule(eventTime, @event, priority);
     772      }
     773    }
     774
     775    /// <summary>
     776    /// Run until a certain event is processed.
     777    /// </summary>
     778    /// <remarks>
     779    /// This method is thread-safe against manipulations of the event queue
     780    /// </remarks>
     781    /// <param name="stopEvent">The event that stops the simulation.</param>
     782    /// <returns></returns>
     783    public override object Run(Event stopEvent = null) {
     784      _stopRequested = false;
     785      if (stopEvent != null) {
     786        if (stopEvent.IsProcessed) return stopEvent.Value;
     787        stopEvent.AddCallback(StopSimulation);
     788      }
     789
     790      try {
     791        var stop = false;
     792        lock (_locker) {
     793          stop = ScheduleQ.Count == 0 || _stopRequested;
     794        }
     795        while (!stop) {
     796          Step();
     797          ProcessedEvents++;
     798          lock (_locker) {
     799            stop = ScheduleQ.Count == 0 || _stopRequested;
    208800          }
    209801        }
     
    214806    }
    215807
    216     public virtual void Step() {
     808    /// <summary>
     809    /// Performs a single step of the simulation, i.e. process a single event
     810    /// </summary>
     811    /// <remarks>
     812    /// This method is thread-safe against manipulations of the event queue
     813    /// </remarks>
     814    public override void Step() {
    217815      Event evt;
    218       lock (locker) {
     816      lock (_locker) {
    219817        var next = ScheduleQ.Dequeue();
    220818        Now = next.PrimaryPriority;
     
    224822    }
    225823
    226     public virtual double PeekD() {
    227       lock (locker) {
     824    /// <summary>
     825    /// Peeks at the time of the next event in terms of the defined step
     826    /// </summary>
     827    /// <remarks>
     828    /// This method is thread-safe against manipulations of the event queue
     829    /// </remarks>
     830    public override double PeekD() {
     831      lock (_locker) {
    228832        if (ScheduleQ.Count == 0) return double.MaxValue;
    229833        return (Peek() - StartDate).TotalSeconds / DefaultTimeStepSeconds;
     
    231835    }
    232836
    233     public virtual DateTime Peek() {
    234       lock (locker) {
     837    /// <summary>
     838    /// Peeks at the time of the next event
     839    /// </summary>
     840    /// <remarks>
     841    /// This method is thread-safe against manipulations of the event queue
     842    /// </remarks>
     843    public override DateTime Peek() {
     844      lock (_locker) {
    235845        return ScheduleQ.Count > 0 ? ScheduleQ.First.PrimaryPriority : DateTime.MaxValue;
    236846      }
    237847    }
    238 
    239     protected virtual void StopSimulation(Event @event) {
    240       throw new StopSimulationException(@event.Value);
    241     }
    242 
    243     public virtual void Log(string message, params object[] args) {
    244       if (Logger != null)
    245         Logger.WriteLine(message, args);
    246     }
    247 
    248     #region Random number distributions
     848  }
     849
     850  /// <summary>
     851  /// Environments hold the event queues, schedule and process events.
     852  /// </summary>
     853  [Obsolete("Use class Simulation or ThreadSafeSimulation instead. Due to name clashes with System.Environment the class SimSharp.Environment is being outphased.")]
     854  public class Environment : ThreadSafeSimulation {
     855    public Environment()
     856      : base() {
     857      Random = new SystemRandom();
     858    }
     859    public Environment(TimeSpan? defaultStep)
     860      : base(defaultStep) {
     861      Random = new SystemRandom();
     862    }
     863    public Environment(int randomSeed, TimeSpan? defaultStep = null)
     864      : base(randomSeed, defaultStep) {
     865      Random = new SystemRandom(randomSeed);
     866    }
     867    public Environment(DateTime initialDateTime, TimeSpan? defaultStep = null)
     868      : base(initialDateTime, defaultStep) {
     869      Random = new SystemRandom();
     870    }
     871    public Environment(DateTime initialDateTime, int randomSeed, TimeSpan? defaultStep = null)
     872      : base(initialDateTime, randomSeed, defaultStep) {
     873      Random = new SystemRandom(randomSeed);
     874    }
     875
    249876    protected static readonly double NormalMagicConst = 4 * Math.Exp(-0.5) / Math.Sqrt(2.0);
    250 
    251     public double RandUniform(double a, double b) {
    252       return a + (b - a) * Random.NextDouble();
    253     }
    254 
    255     public TimeSpan RandUniform(TimeSpan a, TimeSpan b) {
    256       return TimeSpan.FromSeconds(RandUniform(a.TotalSeconds, b.TotalSeconds));
    257     }
    258 
    259     public double RandTriangular(double low, double high) {
    260       var u = Random.NextDouble();
    261       if (u > 0.5)
    262         return high + (low - high) * Math.Sqrt(((1.0 - u) / 2));
    263       return low + (high - low) * Math.Sqrt(u / 2);
    264     }
    265 
    266     public TimeSpan RandTriangular(TimeSpan low, TimeSpan high) {
    267       return TimeSpan.FromSeconds(RandTriangular(low.TotalSeconds, high.TotalSeconds));
    268     }
    269 
    270     public double RandTriangular(double low, double high, double mode) {
    271       var u = Random.NextDouble();
    272       var c = (mode - low) / (high - low);
    273       if (u > c)
    274         return high + (low - high) * Math.Sqrt(((1.0 - u) * (1.0 - c)));
    275       return low + (high - low) * Math.Sqrt(u * c);
    276     }
    277 
    278     public TimeSpan RandTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
    279       return TimeSpan.FromSeconds(RandTriangular(low.TotalSeconds, high.TotalSeconds, mode.TotalSeconds));
    280     }
    281 
    282     /// <summary>
    283     /// Returns a number that is exponentially distributed given a certain mean.
    284     /// </summary>
    285     /// <remarks>
    286     /// Unlike in other APIs here the mean should be given and not the lambda parameter.
    287     /// </remarks>
    288     /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
    289     /// <returns>A number that is exponentially distributed</returns>
    290     public double RandExponential(double mean) {
    291       return -Math.Log(1 - Random.NextDouble()) * mean;
    292     }
    293 
    294     /// <summary>
    295     /// Returns a timespan that is exponentially distributed given a certain mean.
    296     /// </summary>
    297     /// <remarks>
    298     /// Unlike in other APIs here the mean should be given and not the lambda parameter.
    299     /// </remarks>
    300     /// <param name="mean">The mean(!) of the distribution is 1 / lambda.</param>
    301     /// <returns>A number that is exponentially distributed</returns>
    302     public TimeSpan RandExponential(TimeSpan mean) {
    303       return TimeSpan.FromSeconds(RandExponential(mean.TotalSeconds));
    304     }
    305 
    306     public double RandNormal(double mu, double sigma) {
     877    public override double RandNormal(IRandom random, double mu, double sigma) {
    307878      double z, zz, u1, u2;
    308879      do {
    309         u1 = Random.NextDouble();
    310         u2 = 1 - Random.NextDouble();
     880        u1 = random.NextDouble();
     881        u2 = 1 - random.NextDouble();
    311882        z = NormalMagicConst * (u1 - 0.5) / u2;
    312883        zz = z * z / 4.0;
     
    314885      return mu + z * sigma;
    315886    }
    316 
    317     public TimeSpan RandNormal(TimeSpan mu, TimeSpan sigma) {
    318       return TimeSpan.FromSeconds(RandNormal(mu.TotalSeconds, sigma.TotalSeconds));
    319     }
    320 
    321     public double RandNormalPositive(double mu, double sigma) {
    322       double val;
    323       do {
    324         val = RandNormal(mu, sigma);
    325       } while (val <= 0);
    326       return val;
    327     }
    328 
    329     public TimeSpan RandNormalPositive(TimeSpan mu, TimeSpan sigma) {
    330       return TimeSpan.FromSeconds(RandNormalPositive(mu.TotalSeconds, sigma.TotalSeconds));
    331     }
    332 
    333     public double RandNormalNegative(double mu, double sigma) {
    334       double val;
    335       do {
    336         val = RandNormal(mu, sigma);
    337       } while (val >= 0);
    338       return val;
    339     }
    340 
    341     public TimeSpan RandNormalNegative(TimeSpan mu, TimeSpan sigma) {
    342       return TimeSpan.FromSeconds(RandNormalNegative(mu.TotalSeconds, sigma.TotalSeconds));
    343     }
    344 
    345     public double RandLogNormal(double mu, double sigma) {
    346       return Math.Exp(RandNormal(mu, sigma));
    347     }
    348 
    349     public TimeSpan RandLogNormal(TimeSpan mu, TimeSpan sigma) {
    350       return TimeSpan.FromSeconds(RandLogNormal(mu.TotalSeconds, sigma.TotalSeconds));
    351     }
    352 
    353     public double RandCauchy(double x0, double gamma) {
    354       return x0 + gamma * Math.Tan(Math.PI * (Random.NextDouble() - 0.5));
    355     }
    356 
    357     public TimeSpan RandCauchy(TimeSpan x0, TimeSpan gamma) {
    358       return TimeSpan.FromSeconds(RandCauchy(x0.TotalSeconds, gamma.TotalSeconds));
    359     }
    360 
    361     public double RandWeibull(double alpha, double beta) {
    362       return alpha * Math.Pow(-Math.Log(1 - Random.NextDouble()), 1 / beta);
    363     }
    364 
    365     public TimeSpan RandWeibull(TimeSpan mu, TimeSpan sigma) {
    366       return TimeSpan.FromSeconds(RandWeibull(mu.TotalSeconds, sigma.TotalSeconds));
    367     }
    368     #endregion
    369 
    370     #region Random timeouts
    371     public Timeout TimeoutUniformD(double a, double b) {
    372       return new Timeout(this, ToTimeSpan(RandUniform(a, b)));
    373     }
    374 
    375     public Timeout TimeoutUniform(TimeSpan a, TimeSpan b) {
    376       return new Timeout(this, RandUniform(a, b));
    377     }
    378 
    379     public Timeout TimeoutTriangularD(double low, double high) {
    380       return new Timeout(this, ToTimeSpan(RandTriangular(low, high)));
    381     }
    382 
    383     public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high) {
    384       return new Timeout(this, RandTriangular(low, high));
    385     }
    386 
    387     public Timeout TimeoutTriangularD(double low, double high, double mode) {
    388       return new Timeout(this, ToTimeSpan(RandTriangular(low, high, mode)));
    389     }
    390 
    391     public Timeout TimeoutTriangular(TimeSpan low, TimeSpan high, TimeSpan mode) {
    392       return new Timeout(this, RandTriangular(low, high, mode));
    393     }
    394 
    395     public Timeout TimeoutExponentialD(double mean) {
    396       return new Timeout(this, ToTimeSpan(RandExponential(mean)));
    397     }
    398 
    399     public Timeout TimeoutExponential(TimeSpan mean) {
    400       return new Timeout(this, RandExponential(mean));
    401     }
    402 
    403     public Timeout TimeoutNormalPositiveD(double mu, double sigma) {
    404       return new Timeout(this, ToTimeSpan(RandNormalPositive(mu, sigma)));
    405     }
    406 
    407     public Timeout TimeoutNormalPositive(TimeSpan mu, TimeSpan sigma) {
    408       return new Timeout(this, RandNormalPositive(mu, sigma));
    409     }
    410 
    411     public Timeout TimeoutLogNormalD(double mu, double sigma) {
    412       return new Timeout(this, ToTimeSpan(RandLogNormal(mu, sigma)));
    413     }
    414 
    415     public Timeout TimeoutLogNormal(TimeSpan mu, TimeSpan sigma) {
    416       return new Timeout(this, RandLogNormal(mu, sigma));
    417     }
    418     #endregion
    419887  }
    420888}
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AllOf.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2121namespace SimSharp {
    2222  public class AllOf : Condition {
    23     public AllOf(Environment environment, params Event[] events) : base(environment, events) { }
    24     public AllOf(Environment environment, IEnumerable<Event> events) : base(environment, events) { }
     23    public AllOf(Simulation environment, params Event[] events) : base(environment, events) { }
     24    public AllOf(Simulation environment, IEnumerable<Event> events) : base(environment, events) { }
    2525
    2626    protected override bool Evaluate() {
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/AnyOf.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2121namespace SimSharp {
    2222  public class AnyOf : Condition {
    23     public AnyOf(Environment environment, params Event[] events) : base(environment, events) { }
    24     public AnyOf(Environment environment, IEnumerable<Event> events) : base(environment, events) { }
     23    public AnyOf(Simulation environment, params Event[] events) : base(environment, events) { }
     24    public AnyOf(Simulation environment, IEnumerable<Event> events) : base(environment, events) { }
    2525
    2626    protected override bool Evaluate() {
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Condition.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    3636    protected List<Event> FiredEvents { get; private set; }
    3737
    38     protected Condition(Environment environment, params Event[] events)
     38    protected Condition(Simulation environment, params Event[] events)
    3939      : this(environment, (IEnumerable<Event>)events) { }
    40     protected Condition(Environment environment, IEnumerable<Event> events)
     40    protected Condition(Simulation environment, IEnumerable<Event> events)
    4141      : base(environment) {
    4242      CallbackList.Add(CollectValues);
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Event.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    3636  /// </summary>
    3737  public class Event {
    38     protected internal Environment Environment { get; private set; }
     38    protected internal Simulation Environment { get; private set; }
    3939    protected List<Action<Event>> CallbackList { get; set; }
    4040
     
    7373    public bool IsTriggered { get; protected set; }
    7474
    75     public Event(Environment environment) {
     75    public Event(Simulation environment) {
    7676      Environment = environment;
    7777      CallbackList = new List<Action<Event>>();
     
    186186      if (IsProcessed) throw new InvalidOperationException("Event has already been processed.");
    187187      IsProcessed = true;
    188       foreach (var callback in CallbackList)
    189         callback(this);
     188      for (var i = 0; i < CallbackList.Count; i++)
     189        CallbackList[i](this);
    190190      CallbackList = null;
    191191    }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Process.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    5050    /// <param name="generator">The generator function of the process.</param>
    5151    /// <param name="priority">The priority if multiple processes are started at the same time.</param>
    52     public Process(Environment environment, IEnumerable<Event> generator, int priority = 0)
     52    public Process(Simulation environment, IEnumerable<Event> generator, int priority = 0)
    5353      : base(environment) {
    5454      this.generator = generator.GetEnumerator();
     
    128128      Environment.ActiveProcess = null;
    129129    }
    130 
     130   
    131131    protected virtual bool ProceedToEvent() {
    132132      target = generator.Current;
     
    156156
    157157    private class Initialize : Event {
    158       public Initialize(Environment environment, Process process, int priority)
     158      public Initialize(Simulation environment, Process process, int priority)
    159159        : base(environment) {
    160160        CallbackList.Add(process.Resume);
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Events/Timeout.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    3636    /// <param name="isOk">Whether the timeout should succeed or fail.</param>
    3737    /// <param name="priority">The priority to rank events at the same time (smaller value = higher priority).</param>
    38     public Timeout(Environment environment, TimeSpan delay, object value = null, bool isOk = true, int priority = 0)
     38    public Timeout(Simulation environment, TimeSpan delay, object value = null, bool isOk = true, int priority = 0)
    3939      : base(environment) {
    4040      IsOk = isOk;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Exceptions/EmptyScheduleException.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Preempted.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Container.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    1919using System;
    2020using System.Collections.Generic;
    21 using System.Linq;
    2221
    2322namespace SimSharp {
     23  /// <summary>
     24  /// A container holds a variable amount of a single continuous entity, e.g. water, coal, grain, etc.
     25  ///
     26  /// Put and Get are in FIFO order only when they can be satisfied.
     27  /// Any put or get that can be satisfied takes precedence.
     28  /// Put events that attempt to add more to the Container than there is capacity for and
     29  /// Get events that remove more than there is are backlogged.
     30  /// </summary>
    2431  public class Container {
     32
     33    public double Capacity { get; protected set; }
     34
    2535    public double Level { get; protected set; }
    26     public double Capacity { get; protected set; }
    27     protected Environment Environment { get; private set; }
     36
     37    protected Simulation Environment { get; private set; }
    2838
    2939    protected Queue<ContainerPut> PutQueue { get; private set; }
    3040    protected Queue<ContainerGet> GetQueue { get; private set; }
     41    protected SimplePriorityQueue<Event, double> WhenAtLeastQueue { get; private set; }
     42    protected SimplePriorityQueue<Event, double> WhenAtMostQueue { get; private set; }
     43    protected List<Event> WhenChangeQueue { get; private set; }
    3144
    32     public Container(Environment environment, double capacity = double.MaxValue, double initial = 0) {
     45    public Container(Simulation environment, double capacity = double.MaxValue, double initial = 0) {
    3346      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
    3447      if (initial < 0) throw new ArgumentException("Initial must be >= 0", "initial");
     
    3952      PutQueue = new Queue<ContainerPut>();
    4053      GetQueue = new Queue<ContainerGet>();
     54      WhenAtLeastQueue = new SimplePriorityQueue<Event, double>();
     55      WhenAtMostQueue = new SimplePriorityQueue<Event, double>(new ReverseComparer<double>());
     56      WhenChangeQueue = new List<Event>();
    4157    }
    4258
     
    5571      TriggerGet();
    5672      return get;
     73    }
     74
     75    public virtual Event WhenAtLeast(double level) {
     76      var whenAtLeast = new Event(Environment);
     77      WhenAtLeastQueue.Enqueue(whenAtLeast, level);
     78      TriggerWhenAtLeast();
     79      return whenAtLeast;
     80    }
     81
     82    public virtual Event WhenFull() {
     83      return WhenAtLeast(Capacity);
     84    }
     85
     86    public virtual Event WhenAtMost(double level) {
     87      var whenAtMost = new Event(Environment);
     88      WhenAtMostQueue.Enqueue(whenAtMost, level);
     89      TriggerWhenAtMost();
     90      return whenAtMost;
     91    }
     92
     93    public virtual Event WhenEmpty() {
     94      return WhenAtMost(0);
     95    }
     96
     97    public virtual Event WhenChange() {
     98      var whenChange = new Event(Environment);
     99      WhenChangeQueue.Add(whenChange);
     100      return whenChange;
    57101    }
    58102
     
    77121        if (put.IsTriggered) {
    78122          PutQueue.Dequeue();
     123          TriggerWhenAtLeast();
     124          TriggerWhenChange();
    79125        } else break;
    80126      }
     
    87133        if (get.IsTriggered) {
    88134          GetQueue.Dequeue();
     135          TriggerWhenAtMost();
     136          TriggerWhenChange();
    89137        } else break;
    90138      }
    91139    }
     140
     141    protected virtual void TriggerWhenAtLeast() {
     142      while (WhenAtLeastQueue.Count > 0 && Level >= WhenAtLeastQueue.Peek) {
     143        var whenAtLeast = WhenAtLeastQueue.Dequeue();
     144        whenAtLeast.Succeed();
     145      }
     146    }
     147
     148    protected virtual void TriggerWhenAtMost() {
     149      while (WhenAtMostQueue.Count > 0 && Level <= WhenAtMostQueue.Peek) {
     150        var whenAtMost = WhenAtMostQueue.Dequeue();
     151        whenAtMost.Succeed();
     152      }
     153    }
     154
     155    protected virtual void TriggerWhenChange() {
     156      if (WhenChangeQueue.Count == 0) return;
     157      foreach (var evt in WhenChangeQueue)
     158        evt.Succeed();
     159      WhenChangeQueue.Clear();
     160    }
    92161  }
    93162}
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerGet.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    public double Amount { get; protected set; }
    2424    public DateTime Time { get; private set; }
    25     public Process Process { get; private set; }
     25    public Process Owner { get; set; }
    2626
    27     public ContainerGet(Environment environment, Action<Event> callback, double amount)
     27    public ContainerGet(Simulation environment, Action<Event> callback, double amount)
    2828      : base(environment) {
    2929      if (amount <= 0) throw new ArgumentException("Amount must be > 0.", "amount");
     
    3131      CallbackList.Add(callback);
    3232      Time = environment.Now;
    33       Process = environment.ActiveProcess;
     33      Owner = environment.ActiveProcess;
    3434    }
    3535  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ContainerPut.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    public double Amount { get; protected set; }
    2424    public DateTime Time { get; private set; }
    25     public Process Process { get; private set; }
     25    public Process Owner { get; set; }
    2626
    27     public ContainerPut(Environment environment, Action<Event> callback, double amount)
     27    public ContainerPut(Simulation environment, Action<Event> callback, double amount)
    2828      : base(environment) {
    2929      if (amount <= 0) throw new ArgumentException("Amount must be > 0.", "amount");
     
    3131      CallbackList.Add(callback);
    3232      Time = environment.Now;
    33       Process = environment.ActiveProcess;
     33      Owner = environment.ActiveProcess;
    3434    }
    3535  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/FilterStoreGet.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    public Func<object, bool> Filter { get; private set; }
    2424
    25     public FilterStoreGet(Environment environment, Action<Event> callback, Func<object, bool> filter)
     25    public FilterStoreGet(Simulation environment, Action<Event> callback, Func<object, bool> filter)
    2626      : base(environment, callback) {
    2727      Filter = filter;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/PreemptiveRequest.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2020
    2121namespace SimSharp {
    22   public sealed class PreemptiveRequest : PriorityRequest {
     22  public sealed class PreemptiveRequest : Request, IComparable<PreemptiveRequest>, IComparable {
     23    public double Priority { get; private set; }
    2324    public bool Preempt { get; private set; }
     25    public bool IsPreempted { get; internal set; }
    2426
    25     public PreemptiveRequest(Environment environment, Action<Event> callback, Action<Event> disposeCallback, int priority = 1, bool preempt = false)
    26       : base(environment, callback, disposeCallback, priority) {
     27    public PreemptiveRequest(Simulation environment, Action<Event> callback, Action<Event> disposeCallback, double priority = 1, bool preempt = false)
     28      : base(environment, callback, disposeCallback) {
     29      Priority = priority;
    2730      Preempt = preempt;
     31    }
     32
     33    public int CompareTo(PreemptiveRequest other) {
     34      if (Priority > other.Priority) return 1;
     35      else if (Priority < other.Priority) return -1;
     36      if (Time > other.Time) return 1;
     37      else if (Time < other.Time) return -1;
     38      if (!Preempt && other.Preempt) return 1;
     39      else if (Preempt && !other.Preempt) return -1;
     40      return 0;
     41    }
     42
     43    public int CompareTo(object obj) {
     44      if (obj is PreemptiveRequest other) return CompareTo(other);
     45      if (obj == null) return 1;
     46      throw new ArgumentException("Can only compare to other objects of type PreemptiveRequest");
    2847    }
    2948  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Release.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    public Request Request { get; private set; }
    2424
    25     public Release(Environment environment, Request request, Action<Event> callback)
     25    public Release(Simulation environment, Request request, Action<Event> callback)
    2626      : base(environment) {
    2727      Request = request;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/Request.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    private readonly Action<Event> disposeCallback;
    2424    public DateTime Time { get; private set; }
    25     public Process Process { get; private set; }
     25    public Process Owner { get; set; }
    2626
    27     public Request(Environment environment, Action<Event> callback, Action<Event> disposeCallback)
     27    public Request(Simulation environment, Action<Event> callback, Action<Event> disposeCallback)
    2828      : base(environment) {
    2929      CallbackList.Add(callback);
    3030      this.disposeCallback = disposeCallback;
    3131      Time = environment.Now;
    32       Process = environment.ActiveProcess;
     32      Owner = environment.ActiveProcess;
    3333    }
    3434
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/ResourcePoolRequest.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2323    public Func<object, bool> Filter { get; private set; }
    2424
    25     public ResourcePoolRequest(Environment environment, Action<Event> callback, Action<Event> disposeCallback, Func<object, bool> filter)
     25    public ResourcePoolRequest(Simulation environment, Action<Event> callback, Action<Event> disposeCallback, Func<object, bool> filter)
    2626      : base(environment, callback, disposeCallback) {
    2727      Filter = filter;
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StoreGet.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2222  public class StoreGet : Event {
    2323    public DateTime Time { get; private set; }
    24     public Process Process { get; private set; }
     24    public Process Owner { get; set; }
    2525
    26     public StoreGet(Environment environment, Action<Event> callback)
     26    public StoreGet(Simulation environment, Action<Event> callback)
    2727      : base(environment) {
    2828      CallbackList.Add(callback);
    2929      Time = environment.Now;
    30       Process = environment.ActiveProcess;
     30      Owner = environment.ActiveProcess;
    3131    }
    3232  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Events/StorePut.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2222  public class StorePut : Event {
    2323    public DateTime Time { get; private set; }
    24     public Process Process { get; private set; }
     24    public Process Owner { get; set; }
    2525
    26     public StorePut(Environment environment, Action<Event> callback, object value)
     26    public StorePut(Simulation environment, Action<Event> callback, object value)
    2727      : base(environment) {
    2828      if (value == null) throw new ArgumentNullException("value", "Value to put in a Store cannot be null.");
     
    3030      Value = value;
    3131      Time = environment.Now;
    32       Process = environment.ActiveProcess;
     32      Owner = environment.ActiveProcess;
    3333    }
    3434  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/FilterStore.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2222
    2323namespace SimSharp {
     24  /// <summary>
     25  /// A filter store is similar to a <see cref="Store"/>.
     26  /// However, in Get it is possible to specify the property of the item wished to retrieve.
     27  ///
     28  /// FilterStore holds a variable number of individual items.
     29  /// Put are always performed in FIFO order.
     30  /// Get are performed in FIFO order only when they match at least one item in the store.
     31  /// </summary>
    2432  public class FilterStore {
     33    protected static readonly Func<object, bool> TrueFunc = _ => true;
     34
     35    public int Capacity { get; protected set; }
     36
    2537    public int Count { get { return Items.Count; } }
    26     public int Capacity { get; protected set; }
    27     protected Environment Environment { get; private set; }
     38
     39    protected Simulation Environment { get; private set; }
    2840
    2941    protected Queue<StorePut> PutQueue { get; private set; }
    3042    protected LinkedList<FilterStoreGet> GetQueue { get; private set; }
    3143    protected List<object> Items { get; private set; }
    32 
    33     public FilterStore(Environment environment, int capacity = int.MaxValue) {
     44    protected List<Event> WhenNewQueue { get; private set; }
     45    protected List<Event> WhenAnyQueue { get; private set; }
     46    protected List<Event> WhenFullQueue { get; private set; }
     47    protected List<Event> WhenEmptyQueue { get; private set; }
     48    protected List<Event> WhenChangeQueue { get; private set; }
     49
     50    public FilterStore(Simulation environment, int capacity = int.MaxValue) {
    3451      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
    3552      Environment = environment;
     
    3855      GetQueue = new LinkedList<FilterStoreGet>();
    3956      Items = new List<object>();
    40     }
    41     public FilterStore(Environment environment, IEnumerable<object> items, int capacity = int.MaxValue) {
     57      WhenNewQueue = new List<Event>();
     58      WhenAnyQueue = new List<Event>();
     59      WhenFullQueue = new List<Event>();
     60      WhenEmptyQueue = new List<Event>();
     61      WhenChangeQueue = new List<Event>();
     62    }
     63    public FilterStore(Simulation environment, IEnumerable<object> items, int capacity = int.MaxValue) {
    4264      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
    4365      Environment = environment;
     
    4668      GetQueue = new LinkedList<FilterStoreGet>();
    4769      Items = new List<object>(items);
     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>();
    4875      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
    4976    }
     
    6188
    6289    public virtual FilterStoreGet Get(Func<object, bool> filter = null) {
    63       if (filter == null) filter = _ => true;
    64       var get = new FilterStoreGet(Environment, TriggerPut, filter);
     90      var get = new FilterStoreGet(Environment, TriggerPut, filter ?? TrueFunc);
    6591      GetQueue.AddLast(get);
    6692      TriggerGet();
    6793      return get;
     94    }
     95
     96    public virtual Event WhenNew() {
     97      var whenNew = new Event(Environment);
     98      WhenNewQueue.Add(whenNew);
     99      return whenNew;
     100    }
     101
     102    public virtual Event WhenAny() {
     103      var whenAny = new Event(Environment);
     104      WhenAnyQueue.Add(whenAny);
     105      TriggerWhenAny();
     106      return whenAny;
     107    }
     108
     109    public virtual Event WhenFull() {
     110      var whenFull = new Event(Environment);
     111      WhenFullQueue.Add(whenFull);
     112      TriggerWhenFull();
     113      return whenFull;
     114    }
     115
     116    public virtual Event WhenEmpty() {
     117      var whenEmpty = new Event(Environment);
     118      WhenEmptyQueue.Add(whenEmpty);
     119      TriggerWhenEmpty();
     120      return whenEmpty;
     121    }
     122
     123    public virtual Event WhenChange() {
     124      var whenChange = new Event(Environment);
     125      WhenChangeQueue.Add(whenChange);
     126      return whenChange;
    68127    }
    69128
     
    91150        if (put.IsTriggered) {
    92151          PutQueue.Dequeue();
     152          TriggerWhenNew();
     153          TriggerWhenAny();
     154          TriggerWhenFull();
     155          TriggerWhenChange();
    93156        } else break;
    94157      }
     
    104167          GetQueue.Remove(current);
    105168          current = next;
     169          TriggerWhenEmpty();
     170          TriggerWhenChange();
    106171        } else current = current.Next;
    107172        if (Items.Count == 0) break;
    108173      }
    109174    }
     175
     176    protected virtual void TriggerWhenNew() {
     177      if (WhenNewQueue.Count == 0) return;
     178      foreach (var evt in WhenNewQueue)
     179        evt.Succeed();
     180      WhenNewQueue.Clear();
     181    }
     182
     183    protected virtual void TriggerWhenAny() {
     184      if (Items.Count > 0) {
     185        if (WhenAnyQueue.Count == 0) return;
     186        foreach (var evt in WhenAnyQueue)
     187          evt.Succeed();
     188        WhenAnyQueue.Clear();
     189      }
     190    }
     191
     192    protected virtual void TriggerWhenFull() {
     193      if (Count == Capacity) {
     194        if (WhenFullQueue.Count == 0) return;
     195        foreach (var evt in WhenFullQueue)
     196          evt.Succeed();
     197        WhenFullQueue.Clear();
     198      }
     199    }
     200
     201    protected virtual void TriggerWhenEmpty() {
     202      if (Count == 0) {
     203        if (WhenEmptyQueue.Count == 0) return;
     204        foreach (var evt in WhenEmptyQueue)
     205          evt.Succeed();
     206        WhenEmptyQueue.Clear();
     207      }
     208    }
     209
     210    protected virtual void TriggerWhenChange() {
     211      if (WhenChangeQueue.Count == 0) return;
     212      foreach (var evt in WhenChangeQueue)
     213        evt.Succeed();
     214      WhenChangeQueue.Clear();
     215    }
    110216  }
    111217}
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PreemptiveResource.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2222
    2323namespace SimSharp {
     24  /// <summary>
     25  /// A PreemptiveResource is similar to a <see cref="PriorityResource"/>. However,
     26  /// it may be possible to interrupt a lower-priority user and hand over the resource.
     27  ///
     28  /// PreemptiveResource holds a fixed amount of anonymous entities.
     29  /// Requests are processed in this order: priority, time, preemption, and finally FIFO.
     30  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
     31  /// </summary>
     32  /// <remarks>
     33  /// Working with PreemptiveResource, a process holding a request must always call
     34  /// <see cref="Process.HandleFault"/> after yielding an event and handle a potential
     35  /// interruption.
     36  /// </remarks>
    2437  public class PreemptiveResource {
    2538
     
    3043    public int Remaining { get { return Capacity - InUse; } }
    3144
    32     protected Environment Environment { get; private set; }
    33 
    34     protected SortedList<int, LinkedList<PreemptiveRequest>> RequestQueue { get; private set; }
     45    protected Simulation Environment { get; private set; }
     46
     47    protected SimplePriorityQueue<PreemptiveRequest> RequestQueue { get; private set; }
    3548    protected Queue<Release> ReleaseQueue { get; private set; }
    36     protected HashSet<Request> Users { get; private set; }
    37 
    38     public PreemptiveResource(Environment environment, int capacity = 1) {
     49    protected HashSet<PreemptiveRequest> Users { get; private set; }
     50    protected List<Event> WhenAnyQueue { get; private set; }
     51    protected List<Event> WhenFullQueue { get; private set; }
     52    protected List<Event> WhenEmptyQueue { get; private set; }
     53    protected List<Event> WhenChangeQueue { get; private set; }
     54
     55    public PreemptiveResource(Simulation environment, int capacity = 1) {
    3956      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
    4057      Environment = environment;
    4158      Capacity = capacity;
    42       RequestQueue = new SortedList<int, LinkedList<PreemptiveRequest>>();
     59      RequestQueue = new SimplePriorityQueue<PreemptiveRequest>();
    4360      ReleaseQueue = new Queue<Release>();
    44       Users = new HashSet<Request>();
    45     }
    46 
    47     public virtual PreemptiveRequest Request(int priority = 1, bool preempt = false) {
     61      Users = new HashSet<PreemptiveRequest>();
     62      WhenAnyQueue = new List<Event>();
     63      WhenFullQueue = new List<Event>();
     64      WhenEmptyQueue = new List<Event>();
     65      WhenChangeQueue = new List<Event>();
     66    }
     67
     68    public virtual PreemptiveRequest Request(double priority = 1, bool preempt = false) {
    4869      var request = new PreemptiveRequest(Environment, TriggerRelease, DisposeCallback, priority, preempt);
    49       if (!RequestQueue.ContainsKey(request.Priority))
    50         RequestQueue.Add(request.Priority, new LinkedList<PreemptiveRequest>());
    51       RequestQueue[request.Priority].AddLast(request);
     70      RequestQueue.Enqueue(request);
    5271      TriggerRequest();
    5372      return request;
     
    6180    }
    6281
     82    public virtual Event WhenAny() {
     83      var whenAny = new Event(Environment);
     84      WhenAnyQueue.Add(whenAny);
     85      TriggerWhenAny();
     86      return whenAny;
     87    }
     88
     89    public virtual Event WhenFull() {
     90      var whenFull = new Event(Environment);
     91      WhenFullQueue.Add(whenFull);
     92      TriggerWhenFull();
     93      return whenFull;
     94    }
     95
     96    public virtual Event WhenEmpty() {
     97      var whenEmpty = new Event(Environment);
     98      WhenEmptyQueue.Add(whenEmpty);
     99      TriggerWhenEmpty();
     100      return whenEmpty;
     101    }
     102
     103    public virtual Event WhenChange() {
     104      var whenChange = new Event(Environment);
     105      WhenChangeQueue.Add(whenChange);
     106      return whenChange;
     107    }
     108
    63109    protected void DisposeCallback(Event @event) {
    64110      var request = @event as PreemptiveRequest;
     
    69115      if (Users.Count >= Capacity && request.Preempt) {
    70116        // Check if we can preempt another process
    71         var oldest = Users.OfType<PreemptiveRequest>().Select((r, i) => new { Request = r, Index = i })
    72           .OrderByDescending(x => x.Request.Priority)
    73           .ThenByDescending(x => x.Request.Time)
    74           .ThenByDescending(x => x.Request.Preempt)
    75           .ThenByDescending(x => x.Index)
    76           .First().Request;
    77         if (oldest.Priority > request.Priority || (oldest.Priority == request.Priority
    78             && (!oldest.Preempt && request.Preempt || (oldest.Preempt == request.Preempt
    79               && oldest.Time > request.Time)))) {
    80           Users.Remove(oldest);
    81           oldest.Process.Interrupt(new Preempted(request.Process, oldest.Time));
     117        // MaxItems are the least important according to priorty, time, and preemption flag
     118        var preempt = Users.MaxItems(x => x).Last();
     119        if (preempt.CompareTo(request) > 0) {
     120          preempt.IsPreempted = true;
     121          Users.Remove(preempt);
     122          preempt.Owner?.Interrupt(new Preempted(request.Owner, preempt.Time));
    82123        }
    83124      }
     
    89130
    90131    protected virtual void DoRelease(Release release) {
    91       if (!Users.Remove(release.Request)) {
    92         var preemptRequest = release.Request as PreemptiveRequest;
    93         if (preemptRequest != null) {
    94           var current = RequestQueue[preemptRequest.Priority].First;
    95           while (current != null && current.Value != release.Request)
    96             current = current.Next;
    97           if (current != null) RequestQueue[preemptRequest.Priority].Remove(current);
    98         }
    99       }
     132      var req = (PreemptiveRequest)release.Request;
     133      if (!Users.Remove(req) && !req.IsPreempted)
     134        throw new InvalidOperationException("Released request does not have a user.");
    100135      release.Succeed();
    101136    }
    102137
    103138    protected virtual void TriggerRequest(Event @event = null) {
    104       foreach (var entry in RequestQueue) {
    105         var requests = entry.Value;
    106         var current = requests.First;
    107         while (current != null) {
    108           var request = current.Value;
    109           DoRequest(request);
    110           if (request.IsTriggered) {
    111             var next = current.Next;
    112             requests.Remove(current);
    113             current = next;
    114           } else current = current.Next;
    115         }
     139      while (RequestQueue.Count > 0) {
     140        var request = RequestQueue.First;
     141        DoRequest(request);
     142        if (request.IsTriggered) {
     143          RequestQueue.Dequeue();
     144          TriggerWhenEmpty();
     145          TriggerWhenChange();
     146        } else break;
    116147      }
    117148    }
     
    120151      while (ReleaseQueue.Count > 0) {
    121152        var release = ReleaseQueue.Peek();
    122         DoRelease(release);
    123         if (release.IsTriggered) {
     153        if (release.Request.IsAlive) {
     154          if (!RequestQueue.TryRemove((PreemptiveRequest)release.Request))
     155            throw new InvalidOperationException("Failed to cancel a request.");
     156          release.Succeed();
    124157          ReleaseQueue.Dequeue();
    125         } else break;
    126       }
     158        } else {
     159          DoRelease(release);
     160          if (release.IsTriggered) {
     161            ReleaseQueue.Dequeue();
     162            TriggerWhenAny();
     163            TriggerWhenFull();
     164            TriggerWhenChange();
     165          } else break;
     166        }
     167      }
     168    }
     169
     170    protected virtual void TriggerWhenAny() {
     171      if (Remaining > 0) {
     172        if (WhenAnyQueue.Count == 0) return;
     173        foreach (var evt in WhenAnyQueue)
     174          evt.Succeed();
     175        WhenAnyQueue.Clear();
     176      }
     177    }
     178
     179    protected virtual void TriggerWhenFull() {
     180      if (InUse == 0) {
     181        if (WhenFullQueue.Count == 0) return;
     182        foreach (var evt in WhenFullQueue)
     183          evt.Succeed();
     184        WhenFullQueue.Clear();
     185      }
     186    }
     187
     188    protected virtual void TriggerWhenEmpty() {
     189      if (Remaining == 0) {
     190        if (WhenEmptyQueue.Count == 0) return;
     191        foreach (var evt in WhenEmptyQueue)
     192          evt.Succeed();
     193        WhenEmptyQueue.Clear();
     194      }
     195    }
     196
     197    protected virtual void TriggerWhenChange() {
     198      if (WhenChangeQueue.Count == 0) return;
     199      foreach (var evt in WhenChangeQueue)
     200        evt.Succeed();
     201      WhenChangeQueue.Clear();
    127202    }
    128203  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityResource.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2121
    2222namespace SimSharp {
     23  /// <summary>
     24  /// A PriorityResource is similar to a <see cref="Resource"/>.
     25  /// However, it enables prioritizing requests.
     26  ///
     27  /// PriorityResource holds a fixed number of anonymous entities.
     28  /// Requests are processed in order priority first, FIFO second.
     29  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
     30  /// </summary>
    2331  public class PriorityResource {
    2432
     
    2937    public int Remaining { get { return Capacity - InUse; } }
    3038
    31     protected Environment Environment { get; private set; }
     39    protected Simulation Environment { get; private set; }
    3240
    33     protected SortedList<int, LinkedList<PriorityRequest>> RequestQueue { get; private set; }
     41    protected SimplePriorityQueue<Request, double> RequestQueue { get; private set; }
    3442    protected Queue<Release> ReleaseQueue { get; private set; }
    3543    protected HashSet<Request> Users { get; private set; }
     44    protected List<Event> WhenAnyQueue { get; private set; }
     45    protected List<Event> WhenFullQueue { get; private set; }
     46    protected List<Event> WhenEmptyQueue { get; private set; }
     47    protected List<Event> WhenChangeQueue { get; private set; }
    3648
    37     public PriorityResource(Environment environment, int capacity = 1) {
     49    public PriorityResource(Simulation environment, int capacity = 1) {
    3850      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
    3951      Environment = environment;
    4052      Capacity = capacity;
    41       RequestQueue = new SortedList<int, LinkedList<PriorityRequest>>();
     53      RequestQueue = new SimplePriorityQueue<Request, double>();
    4254      ReleaseQueue = new Queue<Release>();
    4355      Users = new HashSet<Request>();
     56      WhenAnyQueue = new List<Event>();
     57      WhenFullQueue = new List<Event>();
     58      WhenEmptyQueue = new List<Event>();
     59      WhenChangeQueue = new List<Event>();
    4460    }
    4561
    46     public virtual PriorityRequest Request(int priority = 1) {
    47       var request = new PriorityRequest(Environment, TriggerRelease, DisposeCallback, priority);
    48       if (!RequestQueue.ContainsKey(priority))
    49         RequestQueue.Add(priority, new LinkedList<PriorityRequest>());
    50       RequestQueue[priority].AddLast(request);
     62    public virtual Request Request(double priority = 1) {
     63      var request = new Request(Environment, TriggerRelease, DisposeCallback);
     64      RequestQueue.Enqueue(request, priority);
    5165      TriggerRequest();
    5266      return request;
    5367    }
    5468
    55     public virtual Release Release(PriorityRequest request) {
     69    public virtual Release Release(Request request) {
    5670      var release = new Release(Environment, request, TriggerRequest);
    5771      ReleaseQueue.Enqueue(release);
     
    6074    }
    6175
     76    public virtual Event WhenAny() {
     77      var whenAny = new Event(Environment);
     78      WhenAnyQueue.Add(whenAny);
     79      TriggerWhenAny();
     80      return whenAny;
     81    }
     82
     83    public virtual Event WhenFull() {
     84      var whenFull = new Event(Environment);
     85      WhenFullQueue.Add(whenFull);
     86      TriggerWhenFull();
     87      return whenFull;
     88    }
     89
     90    public virtual Event WhenEmpty() {
     91      var whenEmpty = new Event(Environment);
     92      WhenEmptyQueue.Add(whenEmpty);
     93      TriggerWhenEmpty();
     94      return whenEmpty;
     95    }
     96
     97    public virtual Event WhenChange() {
     98      var whenChange = new Event(Environment);
     99      WhenChangeQueue.Add(whenChange);
     100      return whenChange;
     101    }
     102
    62103    protected void DisposeCallback(Event @event) {
    63       var request = @event as PriorityRequest;
     104      var request = @event as Request;
    64105      if (request != null) Release(request);
    65106    }
     
    73114
    74115    protected virtual void DoRelease(Release release) {
    75       if (!Users.Remove(release.Request)) {
    76         var prioRequest = release.Request as PriorityRequest;
    77         if (prioRequest != null) {
    78           var current = RequestQueue[prioRequest.Priority].First;
    79           while (current != null && current.Value != release.Request)
    80             current = current.Next;
    81           if (current != null) RequestQueue[prioRequest.Priority].Remove(current);
    82         }
    83       }
     116      if (!Users.Remove(release.Request))
     117        throw new InvalidOperationException("Released request does not have a user.");
    84118      release.Succeed();
    85119    }
    86120
    87121    protected virtual void TriggerRequest(Event @event = null) {
    88       foreach (var entry in RequestQueue) {
    89         var cascade = false;
    90         var requests = entry.Value;
    91         while (requests.Count > 0) {
    92           var req = requests.First.Value;
    93           DoRequest(req);
    94           if (req.IsTriggered) {
    95             requests.RemoveFirst();
    96           } else {
    97             cascade = true;
    98             break;
    99           }
    100         }
    101         if (cascade) break;
     122      while (RequestQueue.Count > 0) {
     123        var request = RequestQueue.First;
     124        DoRequest(request);
     125        if (request.IsTriggered) {
     126          RequestQueue.Dequeue();
     127          TriggerWhenEmpty();
     128          TriggerWhenChange();
     129        } else break;
    102130      }
    103131    }
     
    106134      while (ReleaseQueue.Count > 0) {
    107135        var release = ReleaseQueue.Peek();
     136        if (release.Request.IsAlive) {
     137          if (!RequestQueue.TryRemove(release.Request))
     138            throw new InvalidOperationException("Failed to cancel a request.");
     139          release.Succeed();
     140          ReleaseQueue.Dequeue();
     141        }
    108142        DoRelease(release);
    109143        if (release.IsTriggered) {
    110144          ReleaseQueue.Dequeue();
     145          TriggerWhenAny();
     146          TriggerWhenFull();
     147          TriggerWhenChange();
    111148        } else break;
    112149      }
    113150    }
     151
     152    protected virtual void TriggerWhenAny() {
     153      if (Remaining > 0) {
     154        if (WhenAnyQueue.Count == 0) return;
     155        foreach (var evt in WhenAnyQueue)
     156          evt.Succeed();
     157        WhenAnyQueue.Clear();
     158      }
     159    }
     160
     161    protected virtual void TriggerWhenFull() {
     162      if (InUse == 0) {
     163        if (WhenFullQueue.Count == 0) return;
     164        foreach (var evt in WhenFullQueue)
     165          evt.Succeed();
     166        WhenFullQueue.Clear();
     167      }
     168    }
     169
     170    protected virtual void TriggerWhenEmpty() {
     171      if (Remaining == 0) {
     172        if (WhenEmptyQueue.Count == 0) return;
     173        foreach (var evt in WhenEmptyQueue)
     174          evt.Succeed();
     175        WhenEmptyQueue.Clear();
     176      }
     177    }
     178
     179    protected virtual void TriggerWhenChange() {
     180      if (WhenChangeQueue.Count == 0) return;
     181      foreach (var evt in WhenChangeQueue)
     182        evt.Succeed();
     183      WhenChangeQueue.Clear();
     184    }
    114185  }
    115186}
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Resource.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2121
    2222namespace SimSharp {
     23  /// <summary>
     24  /// A resource holds a fixed number of anonymous entities.
     25  ///
     26  /// Requests are processed in FIFO order.
     27  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
     28  /// </summary>
    2329  public class Resource {
    2430
     
    2935    public int Remaining { get { return Capacity - InUse; } }
    3036
    31     protected Environment Environment { get; private set; }
     37    protected Simulation Environment { get; private set; }
    3238
    3339    protected LinkedList<Request> RequestQueue { get; private set; }
    3440    protected Queue<Release> ReleaseQueue { get; private set; }
    3541    protected HashSet<Request> Users { get; private set; }
     42    protected List<Event> WhenAnyQueue { get; private set; }
     43    protected List<Event> WhenFullQueue { get; private set; }
     44    protected List<Event> WhenEmptyQueue { get; private set; }
     45    protected List<Event> WhenChangeQueue { get; private set; }
    3646
    37     public Resource(Environment environment, int capacity = 1) {
     47    public Resource(Simulation environment, int capacity = 1) {
    3848      if (capacity <= 0) throw new ArgumentException("Capacity must > 0.", "capacity");
    3949      Environment = environment;
     
    4252      ReleaseQueue = new Queue<Release>();
    4353      Users = new HashSet<Request>();
     54      WhenAnyQueue = new List<Event>();
     55      WhenFullQueue = new List<Event>();
     56      WhenEmptyQueue = new List<Event>();
     57      WhenChangeQueue = new List<Event>();
    4458    }
    4559
     
    5670      TriggerRelease();
    5771      return release;
     72    }
     73
     74    public virtual Event WhenAny() {
     75      var whenAny = new Event(Environment);
     76      WhenAnyQueue.Add(whenAny);
     77      TriggerWhenAny();
     78      return whenAny;
     79    }
     80
     81    public virtual Event WhenFull() {
     82      var whenFull = new Event(Environment);
     83      WhenFullQueue.Add(whenFull);
     84      TriggerWhenFull();
     85      return whenFull;
     86    }
     87
     88    public virtual Event WhenEmpty() {
     89      var whenEmpty = new Event(Environment);
     90      WhenEmptyQueue.Add(whenEmpty);
     91      TriggerWhenEmpty();
     92      return whenEmpty;
     93    }
     94
     95    public virtual Event WhenChange() {
     96      var whenChange = new Event(Environment);
     97      WhenChangeQueue.Add(whenChange);
     98      return whenChange;
    5899    }
    59100
     
    73114
    74115    protected virtual void DoRelease(Release release) {
    75       if (!Users.Remove(release.Request)) {
    76         var current = RequestQueue.First;
    77         while (current != null && current.Value != release.Request)
    78           current = current.Next;
    79         if (current != null) RequestQueue.Remove(current);
    80       }
     116      if (!Users.Remove(release.Request))
     117        throw new InvalidOperationException("Released request does not have a user.");
    81118      release.Succeed();
    82119    }
     
    88125        if (request.IsTriggered) {
    89126          RequestQueue.RemoveFirst();
     127          TriggerWhenEmpty();
     128          TriggerWhenChange();
    90129        } else break;
    91130      }
     
    95134      while (ReleaseQueue.Count > 0) {
    96135        var release = ReleaseQueue.Peek();
    97         DoRelease(release);
    98         if (release.IsTriggered) {
     136        if (release.Request.IsAlive) {
     137          if (!RequestQueue.Remove(release.Request))
     138            throw new InvalidOperationException("Failed to cancel a request.");
     139          release.Succeed();
    99140          ReleaseQueue.Dequeue();
    100         } else break;
     141        } else {
     142          DoRelease(release);
     143          if (release.IsTriggered) {
     144            ReleaseQueue.Dequeue();
     145            TriggerWhenAny();
     146            TriggerWhenFull();
     147            TriggerWhenChange();
     148          } else break;
     149        }
    101150      }
     151    }
     152
     153    protected virtual void TriggerWhenAny() {
     154      if (Remaining > 0) {
     155        if (WhenAnyQueue.Count == 0) return;
     156        foreach (var evt in WhenAnyQueue)
     157          evt.Succeed();
     158        WhenAnyQueue.Clear();
     159      }
     160    }
     161
     162    protected virtual void TriggerWhenFull() {
     163      if (InUse == 0) {
     164        if (WhenFullQueue.Count == 0) return;
     165        foreach (var evt in WhenFullQueue)
     166          evt.Succeed();
     167        WhenFullQueue.Clear();
     168      }
     169    }
     170
     171    protected virtual void TriggerWhenEmpty() {
     172      if (Remaining == 0) {
     173        if (WhenEmptyQueue.Count == 0) return;
     174        foreach (var evt in WhenEmptyQueue)
     175          evt.Succeed();
     176        WhenEmptyQueue.Clear();
     177      }
     178    }
     179
     180    protected virtual void TriggerWhenChange() {
     181      if (WhenChangeQueue.Count == 0) return;
     182      foreach (var evt in WhenChangeQueue)
     183        evt.Succeed();
     184      WhenChangeQueue.Clear();
    102185    }
    103186  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/ResourcePool.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    2222
    2323namespace SimSharp {
     24  /// <summary>
     25  /// A ResourcePool is a crossover between a <see cref="Resource"/> and a <see cref="Store"/>.
     26  /// There is a fixed number of non-anonymous resources.
     27  ///
     28  /// Requests are performed in FIFO order only when they match at least one resource in the pool.
     29  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
     30  /// </summary>
    2431  public class ResourcePool {
    2532    protected static readonly Func<object, bool> TrueFunc = _ => true;
     
    3138    public int Remaining { get { return Resources.Count; } }
    3239
    33     protected Environment Environment { get; private set; }
     40    protected Simulation Environment { get; private set; }
    3441
    3542    protected LinkedList<ResourcePoolRequest> RequestQueue { get; private set; }
    3643    protected Queue<Release> ReleaseQueue { get; private set; }
    3744    protected List<object> Resources { get; private set; }
     45    protected List<Event> WhenAnyQueue { get; private set; }
     46    protected List<Event> WhenFullQueue { get; private set; }
     47    protected List<Event> WhenEmptyQueue { get; private set; }
     48    protected List<Event> WhenChangeQueue { get; private set; }
    3849
    39     public ResourcePool(Environment environment, IEnumerable<object> resources) {
     50    public ResourcePool(Simulation environment, IEnumerable<object> resources) {
    4051      Environment = environment;
    4152      if (resources == null) throw new ArgumentNullException("resources");
     
    4556      RequestQueue = new LinkedList<ResourcePoolRequest>();
    4657      ReleaseQueue = new Queue<Release>();
     58      WhenAnyQueue = new List<Event>();
     59      WhenFullQueue = new List<Event>();
     60      WhenEmptyQueue = new List<Event>();
     61      WhenChangeQueue = new List<Event>();
    4762    }
    4863
     
    6378      TriggerRelease();
    6479      return release;
     80    }
     81
     82    public virtual Event WhenAny() {
     83      var whenAny = new Event(Environment);
     84      WhenAnyQueue.Add(whenAny);
     85      TriggerWhenAny();
     86      return whenAny;
     87    }
     88
     89    public virtual Event WhenFull() {
     90      var whenFull = new Event(Environment);
     91      WhenFullQueue.Add(whenFull);
     92      TriggerWhenFull();
     93      return whenFull;
     94    }
     95
     96    public virtual Event WhenEmpty() {
     97      var whenEmpty = new Event(Environment);
     98      WhenEmptyQueue.Add(whenEmpty);
     99      TriggerWhenEmpty();
     100      return whenEmpty;
     101    }
     102
     103    public virtual Event WhenChange() {
     104      var whenChange = new Event(Environment);
     105      WhenChangeQueue.Add(whenChange);
     106      return whenChange;
    65107    }
    66108
     
    93135          RequestQueue.Remove(current);
    94136          current = next;
     137          TriggerWhenEmpty();
     138          TriggerWhenChange();
    95139        } else current = current.Next;
    96140        if (Resources.Count == 0) break;
     
    101145      while (ReleaseQueue.Count > 0) {
    102146        var release = ReleaseQueue.Peek();
    103         DoRelease(release);
    104         if (release.IsTriggered) {
     147        if (release.Request.IsAlive) {
     148          if (!RequestQueue.Remove((ResourcePoolRequest)release.Request))
     149            throw new InvalidOperationException("Failed to cancel a request.");
     150          release.Succeed();
    105151          ReleaseQueue.Dequeue();
    106         } else break;
     152        } else {
     153          DoRelease(release);
     154          if (release.IsTriggered) {
     155            ReleaseQueue.Dequeue();
     156            TriggerWhenAny();
     157            TriggerWhenFull();
     158            TriggerWhenChange();
     159          } else break;
     160        }
    107161      }
     162    }
     163
     164    protected virtual void TriggerWhenAny() {
     165      if (Remaining > 0) {
     166        if (WhenAnyQueue.Count == 0) return;
     167        foreach (var evt in WhenAnyQueue)
     168          evt.Succeed();
     169        WhenAnyQueue.Clear();
     170      }
     171    }
     172
     173    protected virtual void TriggerWhenFull() {
     174      if (InUse == 0) {
     175        if (WhenFullQueue.Count == 0) return;
     176        foreach (var evt in WhenFullQueue)
     177          evt.Succeed();
     178        WhenFullQueue.Clear();
     179      }
     180    }
     181
     182    protected virtual void TriggerWhenEmpty() {
     183      if (Remaining == 0) {
     184        if (WhenEmptyQueue.Count == 0) return;
     185        foreach (var evt in WhenEmptyQueue)
     186          evt.Succeed();
     187        WhenEmptyQueue.Clear();
     188      }
     189    }
     190
     191    protected virtual void TriggerWhenChange() {
     192      if (WhenChangeQueue.Count == 0) return;
     193      foreach (var evt in WhenChangeQueue)
     194        evt.Succeed();
     195      WhenChangeQueue.Clear();
    108196    }
    109197  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/Store.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
     
    1919using System;
    2020using System.Collections.Generic;
    21 using System.Linq;
    2221
    2322namespace SimSharp {
     23  /// <summary>
     24  /// The store holds a variable number of individual items.
     25  /// The items are removed from the store in FIFO order.
     26  ///
     27  /// Put are processed in FIFO order.
     28  /// Get are processed in FIFO order.
     29  /// </summary>
    2430  public class Store {
     31
     32    public int Capacity { get; protected set; }
     33
    2534    public int Count { get { return Items.Count; } }
    26     public int Capacity { get; protected set; }
    27     protected Environment Environment { get; private set; }
     35
     36    protected Simulation Environment { get; private set; }
    2837
    2938    protected Queue<StorePut> PutQueue { get; private set; }
    3039    protected Queue<StoreGet> GetQueue { get; private set; }
    31     protected List<object> Items { get; private set; }
    32 
    33     public Store(Environment environment, int capacity = int.MaxValue) {
     40    protected Queue<object> Items { get; private set; }
     41    protected List<Event> WhenNewQueue { get; private set; }
     42    protected List<Event> WhenAnyQueue { get; private set; }
     43    protected List<Event> WhenFullQueue { get; private set; }
     44    protected List<Event> WhenEmptyQueue { get; private set; }
     45    protected List<Event> WhenChangeQueue { get; private set; }
     46
     47    public Store(Simulation environment, int capacity = int.MaxValue) {
    3448      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
    3549      Environment = environment;
     
    3751      PutQueue = new Queue<StorePut>();
    3852      GetQueue = new Queue<StoreGet>();
    39       Items = new List<object>();
     53      Items = new Queue<object>();
     54      WhenNewQueue = new List<Event>();
     55      WhenAnyQueue = new List<Event>();
     56      WhenFullQueue = new List<Event>();
     57      WhenEmptyQueue = new List<Event>();
     58      WhenChangeQueue = new List<Event>();
     59    }
     60    public Store(Simulation environment, IEnumerable<object> items, int capacity = int.MaxValue) {
     61      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
     62      Environment = environment;
     63      Capacity = capacity;
     64      PutQueue = new Queue<StorePut>();
     65      GetQueue = new Queue<StoreGet>();
     66      Items = new Queue<object>(items);
     67      WhenNewQueue = new List<Event>();
     68      WhenAnyQueue = new List<Event>();
     69      WhenFullQueue = new List<Event>();
     70      WhenEmptyQueue = new List<Event>();
     71      WhenChangeQueue = new List<Event>();
     72      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
    4073    }
    4174
     
    5487    }
    5588
     89    public virtual Event WhenNew() {
     90      var whenNew = new Event(Environment);
     91      WhenNewQueue.Add(whenNew);
     92      return whenNew;
     93    }
     94
     95    public virtual Event WhenAny() {
     96      var whenAny = new Event(Environment);
     97      WhenAnyQueue.Add(whenAny);
     98      TriggerWhenAny();
     99      return whenAny;
     100    }
     101
     102    public virtual Event WhenFull() {
     103      var whenFull = new Event(Environment);
     104      WhenFullQueue.Add(whenFull);
     105      TriggerWhenFull();
     106      return whenFull;
     107    }
     108
     109    public virtual Event WhenEmpty() {
     110      var whenEmpty = new Event(Environment);
     111      WhenEmptyQueue.Add(whenEmpty);
     112      TriggerWhenEmpty();
     113      return whenEmpty;
     114    }
     115
     116    public virtual Event WhenChange() {
     117      var whenChange = new Event(Environment);
     118      WhenChangeQueue.Add(whenChange);
     119      return whenChange;
     120    }
     121
    56122    protected virtual void DoPut(StorePut put) {
    57123      if (Items.Count < Capacity) {
    58         Items.Add(put.Value);
     124        Items.Enqueue(put.Value);
    59125        put.Succeed();
    60126      }
     
    63129    protected virtual void DoGet(StoreGet get) {
    64130      if (Items.Count > 0) {
    65         var item = Items.First();
    66         Items.RemoveAt(0);
     131        var item = Items.Dequeue();
    67132        get.Succeed(item);
    68133      }
     
    75140        if (put.IsTriggered) {
    76141          PutQueue.Dequeue();
     142          TriggerWhenNew();
     143          TriggerWhenAny();
     144          TriggerWhenFull();
     145          TriggerWhenChange();
    77146        } else break;
    78147      }
     
    85154        if (get.IsTriggered) {
    86155          GetQueue.Dequeue();
     156          TriggerWhenEmpty();
     157          TriggerWhenChange();
    87158        } else break;
    88159      }
     160    }
     161
     162    protected virtual void TriggerWhenNew() {
     163      if (WhenNewQueue.Count == 0) return;
     164      foreach (var evt in WhenNewQueue)
     165        evt.Succeed();
     166      WhenNewQueue.Clear();
     167    }
     168
     169    protected virtual void TriggerWhenAny() {
     170      if (Count > 0) {
     171        if (WhenAnyQueue.Count == 0) return;
     172        foreach (var evt in WhenAnyQueue)
     173          evt.Succeed();
     174        WhenAnyQueue.Clear();
     175      }
     176    }
     177
     178    protected virtual void TriggerWhenFull() {
     179      if (Count == Capacity) {
     180        if (WhenFullQueue.Count == 0) return;
     181        foreach (var evt in WhenFullQueue)
     182          evt.Succeed();
     183        WhenFullQueue.Clear();
     184      }
     185    }
     186
     187    protected virtual void TriggerWhenEmpty() {
     188      if (Count == 0) {
     189        if (WhenEmptyQueue.Count == 0) return;
     190        foreach (var evt in WhenEmptyQueue)
     191          evt.Succeed();
     192        WhenEmptyQueue.Clear();
     193      }
     194    }
     195
     196    protected virtual void TriggerWhenChange() {
     197      if (WhenChangeQueue.Count == 0) return;
     198      foreach (var evt in WhenChangeQueue)
     199        evt.Succeed();
     200      WhenChangeQueue.Clear();
    89201    }
    90202  }
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Properties/AssemblyInfo.cs

    r15972 r16779  
    2828[assembly: AssemblyCompany("HEAL")]
    2929[assembly: AssemblyProduct("SimSharp")]
    30 [assembly: AssemblyCopyright("(c) 2002-2018 HEAL")]
     30[assembly: AssemblyCopyright("(c) 2002-2019 HEAL")]
    3131[assembly: AssemblyTrademark("")]
    3232[assembly: AssemblyCulture("")]
     
    5050// by using the '*' as shown below:
    5151// [assembly: AssemblyVersion("1.0.*")]
    52 [assembly: AssemblyVersion("3.0.11.0")]
    53 [assembly: AssemblyFileVersion("3.0.11.0")]
     52[assembly: AssemblyVersion("3.1.1.0")]
     53[assembly: AssemblyFileVersion("3.1.1.0")]
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/IRandom.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
  • trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Random/SystemRandom.cs

    r15972 r16779  
    11#region License Information
    22/* SimSharp - A .NET port of SimPy, discrete event simulation framework
    3 Copyright (C) 2016  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44
    55This program is free software: you can redistribute it and/or modify
Note: See TracChangeset for help on using the changeset viewer.