Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Combinatorial classes #627

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ docs/content/Contributing.md
docs/content/Contributors.md
docs/content/ReleaseNotes.md
docs/content/ReleaseNotes-*.md

NUnitTests.csproj
NUnitTests/
50 changes: 39 additions & 11 deletions .paket/Paket.Restore.targets
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,43 @@
<PaketExeImage Condition=" '$(PaketBootstrapperStyle)' == 'proj' ">native</PaketExeImage>
<MonoPath Condition="'$(MonoPath)' == '' And Exists('/Library/Frameworks/Mono.framework/Commands/mono')">/Library/Frameworks/Mono.framework/Commands/mono</MonoPath>
<MonoPath Condition="'$(MonoPath)' == ''">mono</MonoPath>
<!-- Paket command -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketToolsPath)paket')">$(PaketToolsPath)paket</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketRootPath)paket.exe')">$(PaketRootPath)paket.exe</PaketExePath>

<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketExeImage)' == 'assembly' ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketExeImage)' == 'native' ">$(PaketToolsPath)paket</PaketExePath>
<!-- PaketBootStrapper -->
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' AND Exists('$(PaketRootPath)paket.bootstrapper.exe')">$(PaketRootPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
<PaketBootStrapperExeDir Condition=" Exists('$(PaketBootStrapperExePath)') " >$([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\</PaketBootStrapperExeDir>

<!-- Paket -->

<!-- windows, root => tool => proj style => bootstrapper => global -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(_PaketBootStrapperExeDir)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' ">paket.exe</PaketExePath>

<!-- no windows, try native paket as default, root => tool => proj style => mono paket => bootstrpper => global -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket') ">$(PaketRootPath)paket</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket') ">$(PaketToolsPath)paket</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket</PaketExePath>

<!-- no windows, try mono paket -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>

<!-- no windows, try bootstrapper -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(PaketBootStrapperExeDir)paket.exe</PaketExePath>

<!-- no windows, try global native paket -->
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' ">paket</PaketExePath>

<!-- Paket command -->
<_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))</_PaketExeExtension>
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' == 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' != 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
<PaketCommand Condition=" '$(PaketCommand)' == '' ">"$(PaketExePath)"</PaketCommand>


<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' AND Exists('$(PaketRootPath)paket.bootstrapper.exe')">$(PaketRootPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
<PaketBootStrapperCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>
<PaketBootStrapperCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>

Expand All @@ -42,6 +62,9 @@
<!-- see https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1032-fsharp-in-dotnet-sdk.md -->
<DisableImplicitFSharpCoreReference>true</DisableImplicitFSharpCoreReference>
<DisableImplicitSystemValueTupleReference>true</DisableImplicitSystemValueTupleReference>

<!-- Disable Paket restore under NCrunch build -->
<PaketRestoreDisabled Condition="'$(NCrunch)' == '1'">True</PaketRestoreDisabled>
</PropertyGroup>

<Target Name="PaketBootstrapping" Condition="Exists('$(PaketToolsPath)paket.bootstrapper.proj')">
Expand Down Expand Up @@ -82,7 +105,11 @@
<PaketRestoreRequired Condition=" '$(PaketRestoreLockFileHash)' == '' ">true</PaketRestoreRequired>
</PropertyGroup>

<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.174.2' ">
<!--
This value should match the version in the props generated by paket
If they differ, this means we need to do a restore in order to ensure correct dependencies
-->
<PropertyGroup Condition="'$(PaketPropsVersion)' != '5.185.3' ">
<PaketRestoreRequired>true</PaketRestoreRequired>
</PropertyGroup>

Expand Down Expand Up @@ -163,6 +190,7 @@
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' == '6' And %(PaketReferencesFileLinesInfo.CopyLocal) == 'false'">runtime</ExcludeAssets>
<ExcludeAssets Condition=" '%(PaketReferencesFileLinesInfo.Splits)' != '6' And %(PaketReferencesFileLinesInfo.AllPrivateAssets) == 'exclude'">runtime</ExcludeAssets>
<Publish Condition=" '$(PackAsTool)' == 'true' ">true</Publish>
<AllowExplicitVersion>true</AllowExplicitVersion>
</PackageReference>
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions MathNet.Numerics.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F374
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Numerics", "src\Numerics\Numerics.csproj", "{B7CAE5F4-A23F-4438-B5BE-41226618B695}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp", "src\FSharp\FSharp.fsproj", "{37E8E802-A354-4114-BFC1-6E1357DA605B}"
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp", "src\FSharp\FSharp.fsproj", "{37E8E802-A354-4114-BFC1-6E1357DA605B}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Tests", "src\FSharp.Tests\FSharp.Tests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}"
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Tests", "src\FSharp.Tests\FSharp.Tests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Numerics.Tests", "src\Numerics.Tests\Numerics.Tests.csproj", "{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}"
EndProject
Expand Down
2 changes: 1 addition & 1 deletion src/FSharp/FSharp.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,4 @@ Linear Algebra: optimized range checking in vectors and matrices</PackageRelease
<None Include="MathNet.Numerics.IfSharp.fsx" />
</ItemGroup>
<Import Project="..\..\.paket\Paket.Restore.targets" />
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
// </copyright>

using NUnit.Framework;
using MathNet.Numerics;

namespace MathNet.Numerics.UnitTests.CombinatoricsTests
{
Expand Down
103 changes: 103 additions & 0 deletions src/Numerics.Tests/CombinatoricsTests/CombinatoricsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using MathNet.Numerics.Combinations;
using NUnit.Framework;
using System;

namespace NUnitTests
{
/// <summary>
/// Permutation tests.
/// </summary>
[TestFixture()]
public class CombinatoricsTest
{
/// <summary>
/// Can create permutation from int array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { -1 })]
[TestCase(new[] { 0 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 5 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 4 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 0 })]
[TestCase(new[] { 0, 4, 3, 2, 1, 5 })]
[TestCase(new[] { 0, 3, 2, 1, 4, 5 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 7 })]
public void CanCreateIntegerPermutation(int[] idx)
{
GC.KeepAlive(new Permutations<int>(idx));
}

/// <summary>
/// Can create permutation from char array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { 'A' })]
[TestCase(new[] { 'A', 'A', 'B', 'C', 'D', 'E' })]
[TestCase(new[] { 'A', 'B', 'C', 'D', 'E', 'F' })]
[TestCase(new[] { 'D', 'E', 'F', 'A', 'B', 'C' })]
public void CanCreateCharPermutation(char[] idx)
{
GC.KeepAlive(new Permutations<char>(idx));
}

/// <summary>
/// Can create permutation from int array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { -1 })]
[TestCase(new[] { 0 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 5 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 4 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 0 })]
[TestCase(new[] { 0, 4, 3, 2, 1, 5 })]
[TestCase(new[] { 0, 3, 2, 1, 4, 5 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 7 })]
public void CanCreateIntegerCombination(int[] idx)
{
GC.KeepAlive(new Combinations<int>(idx, 3));
}

/// <summary>
/// Can create permutation from char array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { 'A' })]
[TestCase(new[] { 'A', 'A', 'B', 'C', 'D', 'E' })]
[TestCase(new[] { 'A', 'B', 'C', 'D', 'E', 'F' })]
[TestCase(new[] { 'D', 'E', 'F', 'A', 'B', 'C' })]
public void CanCreateCharCombination(char[] idx)
{
GC.KeepAlive(new Combinations<char>(idx, 3));
}

/// <summary>
/// Can create permutation from int array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { -1 })]
[TestCase(new[] { 0 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 5 })]
[TestCase(new[] { 0, 1, 2, 3, 4, 4 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 0 })]
[TestCase(new[] { 0, 4, 3, 2, 1, 5 })]
[TestCase(new[] { 0, 3, 2, 1, 4, 5 })]
[TestCase(new[] { 5, 4, 3, 2, 1, 7 })]
public void CanCreateIntegerVariation(int[] idx)
{
GC.KeepAlive(new Variations<int>(idx, 3));
}

/// <summary>
/// Can create permutation from char array.
/// </summary>
/// <param name="idx">Permutations index set.</param>
[TestCase(new[] { 'A' })]
[TestCase(new[] { 'A', 'A', 'B', 'C', 'D', 'E' })]
[TestCase(new[] { 'A', 'B', 'C', 'D', 'E', 'F' })]
[TestCase(new[] { 'D', 'E', 'F', 'A', 'B', 'C' })]
public void CanCreateCharVariation(char[] idx)
{
GC.KeepAlive(new Variations<char>(idx, 3));
}
}
}
68 changes: 68 additions & 0 deletions src/Numerics/Combinatorics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -418,5 +418,73 @@ public static IEnumerable<T> SelectVariationWithRepetition<T>(this IEnumerable<T
yield return array[indices[i]];
}
}

/// <summary>
/// Test if two lists are equal
/// </summary>
/// <returns><c>true</c>, if equal was unordereded, <c>false</c> otherwise.</returns>
/// <param name="a">The first list to compare.</param>
/// <param name="b">The second list to compare.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static bool UnorderedEqual<T>(ICollection<T> a, ICollection<T> b)
{
// Require that the counts are equal
if (a.Count != b.Count)
{
return false;
}

// Initialize new Dictionary of the type
Dictionary<T, int> d = new Dictionary<T, int>();

// Add each key's frequency from collection A to the Dictionary
foreach (T item in a)
{
int c;
if (d.TryGetValue(item, out c))
{
d[item] = c + 1;
}
else
{
d.Add(item, 1);
}
}

// Add each key's frequency from collection B to the Dictionary
// Return early if we detect a mismatch
foreach (T item in b)
{
int c;
if (d.TryGetValue(item, out c))
{
if (c == 0)
{
return false;
}
else
{
d[item] = c - 1;
}
}
else
{
// Not in dictionary
return false;
}
}

// Verify that all frequencies are zero
foreach (int v in d.Values)
{
if (v != 0)
{
return false;
}
}

// We know the collections are equal
return true;
}
}
}
Loading