2323import java .util .concurrent .atomic .AtomicInteger ;
2424import java .util .function .BiPredicate ;
2525import java .util .function .BooleanSupplier ;
26+ import java .util .function .Consumer ;
2627import java .util .function .Supplier ;
2728import java .util .stream .Collectors ;
2829import java .util .stream .Stream ;
@@ -252,19 +253,19 @@ public static AtomicInteger[] initialize_array(final int LENGTH)
252253 */
253254 public static <C extends Collection <Scenario >> ArrayList <Scenario > purify_forest (final C RAW_FOREST )
254255 {
255- ArrayList <Scenario > filtered_trees = new ArrayList < Scenario >( RAW_FOREST .parallelStream ().filter (tree -> tree .DISPLAY ).collect (Collectors .toList () ));
256+ ArrayList <Scenario > filtered_trees = RAW_FOREST .parallelStream ().filter (tree -> tree .DISPLAY ).collect (Collectors .toCollection ( ArrayList :: new ));
256257 filtered_trees .trimToSize ();
257258 return filtered_trees ;
258259 }
259260
260261 /**
261262 * Subroutine to draw a hand. Note, returns shallow.
262- *
263+ *
263264 * @param <R> the type of cards in the deck
264- *
265+ *
265266 * @param HAND_SIZE to draw, should be >= DECK's size
266267 * @param DECK to draw from
267- *
268+ *
268269 * @return created hand, backed ({@link ArrayList#subList(int, int)}) by the original deck
269270 */
270271 public static <R extends Reservable > ArrayList <R > draw_hand (final int HAND_SIZE , final ArrayList <R > DECK )
@@ -273,6 +274,41 @@ public static <R extends Reservable> ArrayList<R> draw_hand(final int HAND_SIZE,
273274 return new ArrayList <R >(DECK .subList (0 , HAND_SIZE ));
274275 }
275276
277+ /**
278+ * Subroutine to draw a hand. Note, returns shallow.
279+ *
280+ * @param <R> the type of cards in the deck
281+ *
282+ * @param HAND_SIZE to draw, should be >= DECK's size
283+ * @param DECK to draw from
284+ *
285+ * @return created hand, backed ({@link ArrayList#subList(int, int)}) by the original deck
286+ */
287+ public static <R extends Reservable > ArrayList <R > sample_hand (final int HAND_SIZE , final ArrayList <R > DECK , Random r )
288+ {
289+ // Based on libstdc++'s implementation of std::sample
290+ ArrayList <R > toReturn = new ArrayList <>(HAND_SIZE );
291+ Iterator <R > inputIterator = DECK .iterator ();
292+
293+ int unsampled_size = DECK .size ();
294+ int n = Math .min (HAND_SIZE , unsampled_size );
295+
296+ for (R current = inputIterator .next (); n != 0 ; current = inputIterator .next ()) {
297+ if (r .nextInt (--unsampled_size ) < n ) {
298+ toReturn .add (current );
299+ --n ;
300+ }
301+ }
302+
303+ return toReturn ;
304+ }
305+
306+ public static <R extends Reservable > ArrayList <R > draw_hand (final int HAND_SIZE , final ArrayList <R > DECK , Random rnd )
307+ {
308+ Collections .shuffle (DECK , rnd );
309+ return new ArrayList <R >(DECK .subList (0 , HAND_SIZE ));
310+ }
311+
276312 /**
277313 * Frees all cards in hand. {@link Reservable#release()}
278314 *
@@ -302,6 +338,7 @@ public String simulate(final boolean OVERRIDE, final int HAND_SIZE, final int TE
302338 final int CORE_COUNT = Runtime .getRuntime ().availableProcessors ();
303339
304340 if (CORE_COUNT > 1 )
341+ // return this.parallel_simulation(CORE_COUNT, HAND_SIZE, TEST_HAND_COUNT);
305342 return this .parallel_simulation2 (HAND_SIZE , TEST_HAND_COUNT );
306343 else if (CORE_COUNT == 1 )
307344 return Simulation .sequential_simulation (HAND_SIZE , TEST_HAND_COUNT , this .DECK , this .FOREST );
@@ -321,52 +358,49 @@ class ScenarioCount {
321358 this .equation = equation ;
322359 this .count = new AtomicInteger ();
323360 }
324- }
325361
326- class Equation implements Runnable {
327- final ScenarioCount scenario ;
328- final ArrayList <Deck_Card > hand ;
329-
330- Equation (ScenarioCount equation , ArrayList <Deck_Card > hand ) {
331- this .scenario = equation ;
332- this .hand = hand ;
362+ void run_hand (ArrayList <Deck_Card > hand ) {
363+ if (this .equation .evaluate (hand )) {
364+ this .count .incrementAndGet ();
365+ }
333366 }
367+ }
368+
369+ final List <ScenarioCount > forestCount = FOREST .stream ().map (ScenarioCount ::new ).collect (Collectors .toList ());
334370
335- public void run () {
336- if (this .scenario .equation .evaluate (this .hand )) {
337- this .scenario .count .incrementAndGet ();
371+ /*
372+ Minimalist Strategy
373+ Only create a single thread for each drawn hand, and have each hand test all scenarios
374+ */
375+ class HandGenerator implements Supplier <ArrayList <Deck_Card >> {
376+ @ Override
377+ public ArrayList <Deck_Card > get () {
378+ synchronized (DECK ) {
379+ return Deck_Card .deep_copy (draw_hand (HAND_SIZE , DECK ));
338380 }
339381 }
340382 }
341383
342- class EquationLooper implements Supplier <Equation > {
343- Iterator <ScenarioCount > current ;
344- final List <ScenarioCount > list = FOREST .stream ().map (ScenarioCount ::new ).collect (Collectors .toList ());
345- ArrayList <Deck_Card > hand ;
346-
384+ class HandTester implements Consumer <ArrayList <Deck_Card >> {
347385 @ Override
348- public Equation get () {
349- synchronized (list ) {
350- if (current == null || !current .hasNext ()) {
351- hand = draw_hand (HAND_SIZE , DECK );
352- current = list .iterator ();
353- }
354- return new Equation (current .next (), Deck_Card .deep_copy (hand ));
386+ public void accept (ArrayList <Deck_Card > hand ) {
387+ for (ScenarioCount sc : forestCount ) {
388+ sc .run_hand (hand );
389+ reset_hand (hand );
355390 }
356391 }
357392 }
358393
394+
359395 final long START_TIME ; //simulation start time in milliseconds
360396
361397 synchronized (Simulation .PARALLEL_SIMULATION_LOCK ) {
362398 START_TIME = System .currentTimeMillis ();
363- EquationLooper evaluator = new EquationLooper ();
364- final int FOREST_SIZE = this .FOREST .size ();
365399
366- Stream <Equation > loopingScenario = Stream .generate (evaluator );
367- loopingScenario .parallel ().limit (( long ) FOREST_SIZE * TEST_HAND_COUNT ).forEach (Equation :: run );
400+ Stream <ArrayList < Deck_Card >> random_hands = Stream .generate (new HandGenerator () );
401+ random_hands .parallel ().limit (TEST_HAND_COUNT ).forEach (new HandTester () );
368402
369- AtomicInteger [] HITS = evaluator . list .stream ().map (a -> a .count ).toArray (AtomicInteger []::new );
403+ AtomicInteger [] HITS = forestCount .stream ().map (a -> a .count ).toArray (AtomicInteger []::new );
370404
371405 return Simulation .assemble_results_subroutine (HAND_SIZE , TEST_HAND_COUNT , START_TIME , HITS , this .FOREST );
372406 }
@@ -391,12 +425,12 @@ class Hand_Tester implements Runnable
391425 /**
392426 * Counts number of times this test has passed.
393427 */
394- private final AtomicInteger HIT_COUNTER ;
428+ private final AtomicInteger [] HIT_COUNTER ;
395429
396430 /**
397431 * How to test hand.
398432 */
399- private final Scenario EQUATION ;
433+ private final ArrayList < Scenario > EQUATION ;
400434
401435 /**
402436 * Hand to be tested.
@@ -410,7 +444,7 @@ class Hand_Tester implements Runnable
410444 * @param EQUATION to perform testing on {@link #TEST_HAND}
411445 * @param TEST_HAND to be tested by {@link #EQUATION}
412446 */
413- public Hand_Tester (final AtomicInteger HIT_COUNTER , final Scenario EQUATION , final ArrayList <Deck_Card > TEST_HAND )
447+ public Hand_Tester (final AtomicInteger [] HIT_COUNTER , final ArrayList < Scenario > EQUATION , final ArrayList <Deck_Card > TEST_HAND )
414448 {
415449 this .HIT_COUNTER = HIT_COUNTER ;
416450 this .EQUATION = EQUATION ;
@@ -420,8 +454,12 @@ public Hand_Tester(final AtomicInteger HIT_COUNTER, final Scenario EQUATION, fin
420454 @ Override
421455 public void run ()
422456 {
423- if (this .EQUATION .evaluate (this .TEST_HAND ))
424- this .HIT_COUNTER .incrementAndGet ();
457+ for (int i = 0 ; i < this .EQUATION .size (); ++i ) {
458+ Scenario branch = this .EQUATION .get (i );
459+ if (branch .evaluate (this .TEST_HAND ))
460+ this .HIT_COUNTER [i ].incrementAndGet ();
461+ reset_hand (this .TEST_HAND );
462+ }
425463 }
426464 }
427465
@@ -553,6 +591,8 @@ protected void modulate_parallelization()
553591 //control partition size
554592 {
555593 final int BLOCKING_QUEUE_SIZE = this .TASK_OVERSEER .getQueue ().size ();
594+ /*System.err.printf("Blocking queue size: %d, Completed Tasks: %d, Available Processors: %d, Partition Count %d, Partition Size %d\n",
595+ BLOCKING_QUEUE_SIZE, this.TASK_OVERSEER.getTaskCount(), Runtime.getRuntime().availableProcessors(), this.partition_count, this.partition_size);*/
556596 //Magic numbers have been tested to be rather good, also feels right as well.
557597 final int UPPER_THRESHOLD = 125 ;
558598 final int LOWER_THRESHOLD = 25 ;
@@ -589,9 +629,7 @@ protected void run_subroutine(final int START, final int END)
589629 current_hand = Deck_Card .deep_copy (draw_hand (HAND_SIZE , this .DECK ));
590630 }
591631
592- this .TASK_OVERSEER .execute (new Hand_Tester (this .HITS [0 ], this .FOREST .get (0 ), current_hand ));
593- for (int j = 1 ; j < this .FOREST .size (); ++j )
594- this .TASK_OVERSEER .execute (new Hand_Tester (this .HITS [j ], this .FOREST .get (j ), Deck_Card .deep_copy (current_hand )));
632+ this .TASK_OVERSEER .execute (new Hand_Tester (this .HITS , this .FOREST , current_hand ));
595633 }
596634 }
597635 }
0 commit comments