// ************************************************************************ public void ExecuteForEachPermutation(Action <int[]> action) { // Console.WriteLine($"Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} started: {_indexFirst} {_indexLastExclusive}"); long index = _indexFirst; PermutationOuelletLexico3 <int> permutationOuellet = new PermutationOuelletLexico3 <int>(_sortedValues); permutationOuellet.GetValuesForIndex(index); action(permutationOuellet.Result); index++; int[] values = permutationOuellet.Result; while (index < _indexLastExclusive) { PermutationSaniSinghHuttunen.NextPermutation(values); action(values); index++; } // Console.WriteLine($"Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} ended: {DateTime.Now.ToString("yyyyMMdd_HHmmss_ffffff")}"); }
// ************************************************************************ private int RunTest() { try { bool canRun = false; lock (_lockObj) { if (!IsTestRunning) { canRun = true; IsTestRunning = true; } } if (!canRun) { MessageBox.Show("Already running test. Please try later."); return(0); } Action <IEnumerable <int> > actionToDoOnPermutation = null; Predicate <int[]> funcToDoOnPermutation = null; // Direct function for Sam to be fair (I do not want to add an additional indirection) switch (EnumAction) { case EnumAction.Nothing_BestForPerformanceTest: actionToDoOnPermutation = DoNothing; funcToDoOnPermutation = DoNothingFunc; break; case EnumAction.CountItemWithBugWithMultithreadedCode: actionToDoOnPermutation = IncreaseCount; funcToDoOnPermutation = IncreaseCountFunc; break; case EnumAction.CountItemSafeInterlockedIncrement: actionToDoOnPermutation = IncreaseCountSafeInterlockedIncrement; funcToDoOnPermutation = IncreaseCountSafeInterlockedIncrementFunc; break; case EnumAction.CountItemSafeSpinLock: actionToDoOnPermutation = IncreaseCountSafeSpinLock; funcToDoOnPermutation = IncreaseCountSafeSpinLockFunc; break; case EnumAction.DumpPermutatedValuesAndCount: actionToDoOnPermutation = DumpValues; funcToDoOnPermutation = DumpValuesFunc; if (CountOfElementsToPermute > 5) { var result = MessageBox.Show( "The count of item to permute is greater than 5, it could take long to dump every items, are you sure you want to continue?", "Warning", MessageBoxButton.OKCancel); if (result == MessageBoxResult.Cancel) { return(0); } } break; } EnumAlgoPermutation algoPermutation = AlgoPermutation; EnumAlgoPermutation algoPermutationActive; _testCount++; WriteLine($"Test {_testCount} started. Count {CountOfElementsToPermute}!. Action: {EnumUtil.GetEnumDescription(EnumAction)}."); int[] values; Stopwatch stopwatch = new Stopwatch(); // Eric OuelletHeap Algorithm algoPermutationActive = EnumAlgoPermutation.OuelletHeap; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); PermutationOuellet.ForAllPermutation(values, (vals) => { actionToDoOnPermutation?.Invoke(vals); return(false); }); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } // Eric OuelletHeap indexed Algorithm algoPermutationActive = EnumAlgoPermutation.OuelletIndexed; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); var permutationGenerator = new PermutationOuelletLexico <int>(values); // int[] result = new int[values.Length]; for (long i = 0; i < permutationGenerator.MaxIndex; i++) { permutationGenerator.GetSortedValuesFor(i); { actionToDoOnPermutation?.Invoke(permutationGenerator.Result); } } stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } // Eric OuelletHeap indexed Algorithm v2 algoPermutationActive = EnumAlgoPermutation.OuelletIndexedv2; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); var permutationGenerator = new PermutationOuelletLexico2 <int>(values); // int[] result = new int[values.Length]; for (long i = 0; i < permutationGenerator.MaxIndex; i++) { permutationGenerator.GetSortedValuesFor(i); { actionToDoOnPermutation?.Invoke(permutationGenerator.Result); } } stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } // Eric OuelletHeap indexed Algorithm v3 algoPermutationActive = EnumAlgoPermutation.OuelletIndexedv3; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); var permutationGenerator = new PermutationOuelletLexico3 <int>(values); // int[] result = new int[values.Length]; for (long i = 0; i < permutationGenerator.MaxIndex; i++) { permutationGenerator.GetValuesForIndex(i); { actionToDoOnPermutation?.Invoke(permutationGenerator.Result); } } stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } //// Eric OuelletHeap indexed Algorithm v4 //algoPermutationActive = EnumAlgoPermutation.OuelletIndexedv4; //if (algoPermutation.HasFlag(algoPermutationActive)) //{ // _count = 0; // values = GetValues(); // stopwatch.Reset(); // stopwatch.Start(); // var permutationGenerator = new PermutationOuelletLexico4<int>(values); // // int[] result = new int[values.Length]; // for (int i = 0; i < permutationGenerator.MaxIndex; i++) // { // permutationGenerator.GetValuesForIndex(i); // { // actionDumpValues?.Invoke(permutationGenerator.Result); // } // } // stopwatch.Stop(); // WriteResult(algoPermutationActive, stopwatch); //} algoPermutationActive = EnumAlgoPermutation.SaniSinghHuttunen; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); do { actionToDoOnPermutation?.Invoke(values); }while (PermutationSaniSinghHuttunen.NextPermutation(values)); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.OuelletIndexedv3HuttunenST; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); PermutationMixOuelletSaniSinghHuttunen mix = new PermutationMixOuelletSaniSinghHuttunen(values); mix.ExecuteForEachPermutation(actionToDoOnPermutation); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.SimpleVar; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); do { actionToDoOnPermutation?.Invoke(values); }while (!PermutationSimpleVar.NextPermutation(values)); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.SimpleVarUnsafe; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); PermutationSimpleVarUnsafe permutations = new PermutationSimpleVarUnsafe(); permutations.Permutate(0, values.Length, (int[] vals) => { actionToDoOnPermutation?.Invoke(vals); }); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } // ErezRobinson Algorithm algoPermutationActive = EnumAlgoPermutation.ErezRobinson; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); foreach (var vals in PermutationErezRobinson.QuickPerm(values)) { actionToDoOnPermutation?.Invoke(vals); } stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.Sam; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); var pf = new PermutationFinder <int>(); pf.Evaluate(values, funcToDoOnPermutation); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.Ziezi; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); PermutationZiezi.EnumeratePermutation(values, actionToDoOnPermutation); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } // Pengyang linq algorithm algoPermutationActive = EnumAlgoPermutation.Pengyang; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); foreach (var vals in PermutationPengyang.GetPermutations(values, values.Length)) { actionToDoOnPermutation?.Invoke(vals); } stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.OuelletIndexedMT; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); int[] result = new int[values.Length]; Parallel.For <PermutationOuelletLexico <int> > ( 0, Factorial.GetFactorial(values.Length), () => new PermutationOuelletLexico <int>(GetValues()), (index, state, permutationOuellet) => { permutationOuellet.GetSortedValuesFor(index); actionToDoOnPermutation?.Invoke(permutationOuellet.Result); return(permutationOuellet); }, (permutationOuellet) => { } ); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.OuelletIndexedv3MT; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); int[] result = new int[values.Length]; Parallel.For <PermutationOuelletLexico3 <int> > ( 0, Factorial.GetFactorial(values.Length), () => new PermutationOuelletLexico3 <int>(GetValues()), (index, state, permutationOuellet) => { permutationOuellet.GetValuesForIndex(index); actionToDoOnPermutation?.Invoke(permutationOuellet.Result); return(permutationOuellet); }, (permutationOuellet) => { } ); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } algoPermutationActive = EnumAlgoPermutation.OuelletHuttunenMT; if (algoPermutation.HasFlag(algoPermutationActive)) { WriteIntro(algoPermutationActive); _count = 0; values = GetValues(); stopwatch.Reset(); stopwatch.Start(); PermutationMixOuelletSaniSinghHuttunen.ExecuteForEachPermutationMT(values, actionToDoOnPermutation); stopwatch.Stop(); WriteResult(algoPermutationActive, stopwatch); } WriteLine("Test " + _testCount + " ended."); WriteLine("---------------------------------------------------------------"); return(_count); } finally { IsTestRunning = false; } }