@@ -27,11 +27,6 @@ internal class PCTScheduler : IScheduler
2727 /// </summary>
2828 private readonly IRandomValueGenerator _randomValueGenerator ;
2929
30- /// <summary>
31- /// The maximum number of steps to schedule.
32- /// </summary>
33- private readonly int MaxScheduledSteps ;
34-
3530 /// <summary>
3631 /// The number of scheduled steps.
3732 /// </summary>
@@ -50,18 +45,13 @@ internal class PCTScheduler : IScheduler
5045 /// <summary>
5146 /// List of prioritized operations.
5247 /// </summary>
53- private readonly List < AsyncOperation > PrioritizedOperations ;
54-
55- /// <summary>
56- /// Next execution point where the priority should be changed.
57- /// </summary>
58- private int _nextPriorityChangePoint ;
48+ private readonly List < AsyncOperation > PrioritizedOperations = new ( ) ;
5949
6050 /// <summary>
61- /// Number of switch points left (leq MaxPrioritySwitchPoints) .
51+ /// Set of priority change points .
6252 /// </summary>
63- private int _numSwitchPointsLeft ;
64-
53+ private readonly SortedSet < int > PriorityChangePoints = new ( ) ;
54+
6555 /// <summary>
6656 /// Initializes a new instance of the <see cref="PCTStrategy"/> class.
6757 /// </summary>
@@ -71,14 +61,11 @@ public PCTScheduler(int maxPrioritySwitchPoints, int scheduleLength, IRandomValu
7161 ScheduledSteps = 0 ;
7262 ScheduleLength = scheduleLength ;
7363 MaxPrioritySwitchPoints = maxPrioritySwitchPoints ;
74- PrioritizedOperations = new List < AsyncOperation > ( ) ;
75- double switchPointProbability = 0.1 ;
7664 if ( ScheduleLength != 0 )
7765 {
78- switchPointProbability = 1.0 * _numSwitchPointsLeft / ( ScheduleLength - ScheduledSteps + 1 ) ;
66+ PreparePriorityChangePoints ( ScheduleLength ) ;
7967 }
80- _nextPriorityChangePoint = Generator . Mutator . Utils . SampleGeometric ( switchPointProbability , random . NextDouble ( ) ) ;
81-
68+
8269 }
8370
8471 public virtual bool GetNextOperation ( AsyncOperation current , IEnumerable < AsyncOperation > ops ,
@@ -89,28 +76,37 @@ public virtual bool GetNextOperation(AsyncOperation current, IEnumerable<AsyncOp
8976 var enabledOperations = ops . Where ( op => op . Status is AsyncOperationStatus . Enabled ) . ToList ( ) ;
9077 if ( enabledOperations . Count == 0 )
9178 {
92- if ( _nextPriorityChangePoint == ScheduledSteps )
79+ if ( PriorityChangePoints . Contains ( ScheduledSteps ) )
9380 {
9481 MovePriorityChangePointForward ( ) ;
9582 }
9683
9784 return false ;
9885 }
9986
100- var highestEnabledOp = GetPrioritizedOperation ( enabledOperations , current ) ;
101- if ( next is null )
102- {
103- next = highestEnabledOp ;
104- }
87+ next = GetPrioritizedOperation ( enabledOperations , current ) ;
10588
10689 return true ;
10790 }
10891
92+ /// <summary>
93+ /// Moves the current priority change point forward. This is a useful
94+ /// optimization when a priority change point is assigned in either a
95+ /// sequential execution or a nondeterministic choice.
96+ /// </summary>
10997 private void MovePriorityChangePointForward ( )
11098 {
111- _nextPriorityChangePoint += 1 ;
112- Debug . WriteLine ( "<PCTLog> Moving priority change to '{0}'." , _nextPriorityChangePoint ) ;
99+ PriorityChangePoints . Remove ( ScheduledSteps ) ;
100+ var newPriorityChangePoint = ScheduledSteps + 1 ;
101+ while ( PriorityChangePoints . Contains ( newPriorityChangePoint ) )
102+ {
103+ newPriorityChangePoint ++ ;
104+ }
105+
106+ PriorityChangePoints . Add ( newPriorityChangePoint ) ;
107+ Debug . WriteLine ( "<PCTLog> Moving priority change to '{0}'." , newPriorityChangePoint ) ;
113108 }
109+
114110
115111 private AsyncOperation GetHighestPriorityEnabledOperation ( IEnumerable < AsyncOperation > choices )
116112 {
@@ -146,36 +142,21 @@ private AsyncOperation GetPrioritizedOperation(List<AsyncOperation> ops, AsyncOp
146142 }
147143
148144
149- var prioritizedSchedulable = GetHighestPriorityEnabledOperation ( ops ) ;
150- if ( _nextPriorityChangePoint == ScheduledSteps )
145+ if ( PriorityChangePoints . Contains ( ScheduledSteps ) )
151146 {
152147 if ( ops . Count == 1 )
153148 {
154149 MovePriorityChangePointForward ( ) ;
155150 }
156151 else
157152 {
158- PrioritizedOperations . Remove ( prioritizedSchedulable ) ;
159- PrioritizedOperations . Add ( prioritizedSchedulable ) ;
160- Debug . WriteLine ( "<PCTLog> Operation '{0}' changes to lowest priority." , prioritizedSchedulable ) ;
161-
162- _numSwitchPointsLeft -= 1 ;
163- // Update the next priority change point.
164- if ( _numSwitchPointsLeft > 0 )
165- {
166- double switchPointProbability = 0.1 ;
167- if ( ScheduleLength != 0 )
168- {
169- switchPointProbability = 1.0 * _numSwitchPointsLeft / ( ScheduleLength - ScheduledSteps + 1 ) ;
170- }
171-
172- _nextPriorityChangePoint =
173- Generator . Mutator . Utils . SampleGeometric ( switchPointProbability ,
174- _randomValueGenerator . NextDouble ( ) ) + ScheduledSteps ;
175- }
176-
153+ var priority = GetHighestPriorityEnabledOperation ( ops ) ;
154+ PrioritizedOperations . Remove ( priority ) ;
155+ PrioritizedOperations . Add ( priority ) ;
156+ Debug . WriteLine ( "<PCTLog> Operation '{0}' changes to lowest priority." , priority ) ;
177157 }
178158 }
159+ var prioritizedSchedulable = GetHighestPriorityEnabledOperation ( ops ) ;
179160
180161 if ( Debug . IsEnabled )
181162 {
@@ -209,18 +190,26 @@ public virtual bool PrepareForNextIteration()
209190 {
210191 ScheduleLength = Math . Max ( ScheduleLength , ScheduledSteps ) ;
211192 ScheduledSteps = 0 ;
212- _numSwitchPointsLeft = MaxPrioritySwitchPoints ;
213193
214194 PrioritizedOperations . Clear ( ) ;
215- double switchPointProbability = 0.1 ;
216- if ( ScheduleLength != 0 )
195+ PriorityChangePoints . Clear ( ) ;
196+ return true ;
197+ }
198+
199+ private void PreparePriorityChangePoints ( int step )
200+ {
201+ List < int > listOfInts = new List < int > ( ) ;
202+ for ( int i = 0 ; i < step ; i ++ )
217203 {
218- switchPointProbability = 1.0 * _numSwitchPointsLeft / ( ScheduleLength - ScheduledSteps + 1 ) ;
204+ listOfInts . Add ( i ) ;
219205 }
220206
221- _nextPriorityChangePoint =
222- Generator . Mutator . Utils . SampleGeometric ( switchPointProbability , _randomValueGenerator . NextDouble ( ) ) ;
223- return true ;
207+ for ( int i = 0 ; i < MaxPrioritySwitchPoints ; i ++ )
208+ {
209+ int index = _randomValueGenerator . Next ( listOfInts . Count ) ;
210+ PriorityChangePoints . Add ( listOfInts [ index ] ) ;
211+ listOfInts . RemoveAt ( index ) ;
212+ }
224213 }
225214
226215 public IScheduler Mutate ( )
0 commit comments