Skip to content

Commit 0f81662

Browse files
authored
CSharpMath.Evaluation.Interpret tests (#151)
* Added Interpret Tests + Deterministic Builds * Fix build * Fix build 2 * Simplify stuff * Make Extensions.cs the top-level source file of CSharpMath * ?? Windows? * Update Build.yml * E * Update Build.yml * Try fix? * Update Build.yml * Detect dotnet msbuild * Update Directory.Build.props * Update Test.yml * Update Test.yml * Sleeping does nothing * Simplify * Update Test.yml * Update local build version * Update Test.yml
1 parent cecc4b0 commit 0f81662

20 files changed

+279
-320
lines changed

.github/release-drafter.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,11 @@ categories:
3939
label: 'Type/Housekeeping'
4040
# Extra line before $BODY or markdown on the first line of $BODY will be interpreted as plain text
4141
change-template: |
42-
<details><summary>$TITLE (#$NUMBER) @$AUTHOR</summary>
43-
42+
<details><summary>`$TITLE` (#$NUMBER) @$AUTHOR</summary><table><td>
43+
4444
$BODY
45-
</details>
45+
</td></table></details>
4646
no-changes-template: '* (No changes)'
4747
replacers:
48-
# We don't support nested <summary> and <details> so we add a (?!<details>|<summary>)
49-
- search: '/<details><summary>((?:(?!<details>|<summary>).)+?)<\/summary>\s*<\/details>/g'
48+
- search: '/<details><summary>(.+?)<\/summary><table><td>\s*<\/td><\/table><\/details>/g'
5049
replace: '- $1'

.github/workflows/Build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ jobs:
1818
uses: warrenbuckley/Setup-MSBuild@v1
1919
- name: Restore NuGet Packages
2020
run: nuget restore CSharpMath.sln
21-
- name: Build CI artifacts
21+
- name: Build Everything
2222
run: msbuild CSharpMath.sln /p:Configuration=Release

.github/workflows/Test.yml

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ jobs:
1010
uses: release-drafter/release-drafter@v5
1111
env:
1212
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13-
- uses: cardinalby/git-get-release-action@v1
14-
id: release_info
15-
env:
16-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17-
with:
18-
releaseId: ${{ steps.release_drafter.outputs.id }}
1913
- uses: actions/checkout@v2
2014
with:
2115
submodules: 'recursive'
@@ -35,9 +29,9 @@ jobs:
3529
- name: Build and Test
3630
env:
3731
RELEASE_NOTES: |
38-
# ${{ steps.release_info.outputs.name }}
32+
# ${{ steps.release_drafter.outputs.name }}
3933
40-
${{ steps.release_info.outputs.body }}
34+
${{ steps.release_drafter.outputs.body }}
4135
# run: dotnet test CSharpMath.CrossPlatform.slnf
4236
run: | # https://github.com/dotnet/sdk/issues/10409, https://github.com/dotnet/sdk/issues/11417
4337
# .NET Core MSBuild cannot parse , and ; correctly so we replace them with substitutions: https://github.com/dotnet/msbuild/issues/471#issuecomment-366268743
@@ -60,16 +54,17 @@ jobs:
6054
dotnet add "$p" package Microsoft.NET.Test.Sdk # Update is required for GitHubActionsTestLogger to print anything
6155
dotnet add "$p" package GitHubActionsTestLogger
6256
# -r for restore
63-
dotnet msbuild -r -p:Configuration=Release -p:PackageVersion=${{ steps.release_drafter.outputs.tag_name }}-ci-${{ github.sha }} -p:PackageReleaseNotes="$RELEASE_NOTES" "$p"
57+
dotnet msbuild -r -p:Configuration=Release -p:PackageVersion=${{ steps.release_drafter.outputs.tag_name || format('{0}-pr', github.event.number) }}-ci-${{ github.sha }} -p:PackageReleaseNotes="$RELEASE_NOTES" "$p"
6458
# --no-build because building again will produce additional NuGet packages without the PackageVersion setting above
6559
dotnet test "$p" --no-build -c Release -l GitHubActions --blame
6660
done
67-
- uses: actions/upload-artifact@v2
61+
- name: Upload CSharpMath.Rendering.Tests results as CI artifacts
62+
uses: actions/upload-artifact@v2
6863
if: always() # Run even when a previous step failed: https://stackoverflow.com/a/58859404/5429648
6964
with:
7065
name: CSharpMath.Rendering.Tests results
7166
path: CSharpMath.Rendering.Tests/*/*.png
72-
- name: Upload CI artifacts
67+
- name: Upload NuGet packages as CI artifacts
7368
uses: actions/upload-artifact@v2
7469
if: always()
7570
with:

CSharpMath.Evaluation.Tests/EvaluationTests.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
using Xunit;
44
using AngouriMath;
55

6-
namespace CSharpMath {
6+
namespace CSharpMath.EvaluationTests {
77
using Atom;
8-
public partial class EvluationTests {
9-
MathList ParseLaTeX(string latex) =>
8+
public class EvaluationTests {
9+
internal static MathList ParseLaTeX(string latex) =>
1010
LaTeXParser.MathListFromLaTeX(latex).Match(list => list, e => throw new Xunit.Sdk.XunitException(e));
11-
Evaluation.MathItem ParseMath(string latex) =>
11+
static Evaluation.MathItem ParseMath(string latex) =>
1212
Evaluation.Evaluate(ParseLaTeX(latex)).Match(entity => entity, e => throw new Xunit.Sdk.XunitException(e));
1313
void Test(string input, string converted, string? result) {
1414
void Test(string input) {
@@ -424,7 +424,10 @@ public void Numbers(string input, string converted, string output) =>
424424
[InlineData(@"\sin^a\ \; (x)^2(x)", @"\sin \left( x\right) ^{a\times 2}\times x", @"\sin \left( x\right) ^{2\times a}\times x")]
425425
[InlineData(@"\sin (\frac\pi2)", @"\sin \left( \frac{\pi }{2}\right) ", @"1")]
426426
[InlineData(@"\sin (\frac\pi2)+1", @"\sin \left( \frac{\pi }{2}\right) +1", @"2")]
427-
public void Parentheses(string latex, string converted, string result) => Test(latex, converted, result);
427+
public void Parentheses(string latex, string converted, string result) {
428+
Test(latex, converted, result);
429+
Test(latex.Replace('(', '[').Replace(')', ']'), converted, result);
430+
}
428431
[Theory]
429432
[InlineData(@"\begin{matrix}1\end{matrix}", @"\left( \begin{matrix}1\end{matrix}\right) ", @"\left( \begin{matrix}1\end{matrix}\right) ")]
430433
[InlineData(@"\begin{pmatrix}1\end{pmatrix}", @"\left( \begin{matrix}1\end{matrix}\right) ", @"\left( \begin{matrix}1\end{matrix}\right) ")]
@@ -580,11 +583,12 @@ public void Numbers(string input, string converted, string output) =>
580583
[InlineData(@"\left(1+\right]", "Missing right operand for +")]
581584
[InlineData(@"\left(2,3\right]^\square", "Placeholders should be filled")]
582585
[InlineData(@"(2,3]^\square", "Placeholders should be filled")]
583-
[InlineData(@"[]", "Unrecognized bracket pair [ ]")]
584-
[InlineData(@"[x]", "Unrecognized bracket pair [ ]")]
585-
[InlineData(@"[[x]", "Unrecognized bracket pair [ ]")]
586-
[InlineData(@"[x]]", "Unrecognized bracket pair [ ]")]
587-
[InlineData(@"\left[\right]", "Unrecognized bracket pair [ ]")]
586+
[InlineData(@"[]", "Missing math inside [ ]")]
587+
[InlineData(@"[[x]", "Missing ]")]
588+
[InlineData(@"[x]]", "Missing [")]
589+
[InlineData(@"[_\square x]", "Subscripts are unsupported for Open [")]
590+
[InlineData(@"[x]_\square", "Subscripts are unsupported for Close ]")]
591+
[InlineData(@"\left[\right]", "Missing math inside [ ]")]
588592
[InlineData(@"\left[1+\right]", "Missing right operand for +")]
589593
[InlineData(@"\left[2,3\right]^\square", "Placeholders should be filled")]
590594
[InlineData(@"[2,3]^\square", "Placeholders should be filled")]
@@ -633,7 +637,7 @@ public void Numbers(string input, string converted, string output) =>
633637
[InlineData(@"+(3,4]", "Set cannot be right operand for +")]
634638
[InlineData(@"[5,6)\times", "Set cannot be left operand for ×")]
635639
[InlineData(@"\frac{[7,8]}{9}", "Set cannot be numerator")]
636-
[InlineData(@"\sqrt[{[]}]{}", "Unrecognized bracket pair [ ]")]
640+
[InlineData(@"\sqrt[{[)}]{}", "Unrecognized bracket pair [ )")]
637641
[InlineData(@"\sqrt[{[a,b]}]{}", "Set cannot be degree")]
638642
[InlineData(@"\{\{\}\}", "Set cannot be set element")]
639643
[InlineData(@"\cap", "Unsupported Unary Operator ∩")]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Linq;
3+
using Xunit;
4+
namespace CSharpMath.EvaluationTests {
5+
public class InterpretTests {
6+
[Theory]
7+
[InlineData(@"", @"\color{red}\text{There is nothing to evaluate}")]
8+
[InlineData(@"1", @"\underline\mathrm{Input}\\1\\\\\underline\mathrm{Simplified}\\1\\\\\underline\mathrm{Value\ (100\ digits)}\\1")]
9+
[InlineData(@"1+", @"\color{red}\text{Missing right operand for +}")]
10+
[InlineData(@"1+2", @"\underline\mathrm{Input}\\1+2\\\\\underline\mathrm{Simplified}\\3\\\\\underline\mathrm{Value\ (100\ digits)}\\3")]
11+
[InlineData(@"1+\sqrt", @"\color{red}\text{Missing radicand}")]
12+
[InlineData(@"1+\sqrt2", @"\underline\mathrm{Input}\\1+\sqrt{2}\\\\\underline\mathrm{Simplified}\\1+\sqrt{2}\\\\\underline\mathrm{Value\ (100\ digits)}\\2.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573")]
13+
[InlineData(@"1+\sqrt{2x}", @"\underline\mathrm{Input}\\1+\sqrt{2\times x_{}}\\\\\underline\mathrm{Simplified}\\1+\sqrt{2\times x_{}}\\\\\underline\mathrm{Expanded}\\1+\sqrt{2\times x_{}}\\\\\underline\mathrm{Factorized}\\1+\sqrt{2\times x_{}}")]
14+
[InlineData(@"1+\sqrt{2xy}", @"\underline\mathrm{Input}\\1+\sqrt{2\times x_{}\times y_{}}\\\\\underline\mathrm{Simplified}\\1+\sqrt{2\times x_{}\times y_{}}\\\\\underline\mathrm{Expanded}\\1+\sqrt{2\times x_{}\times y_{}}\\\\\underline\mathrm{Factorized}\\1+\sqrt{2\times x_{}\times y_{}}")]
15+
[InlineData(@"=1+\sqrt{2xy}", @"\color{red}\text{Missing left side of equation}")]
16+
[InlineData(@"1+\sqrt{2xy}=", @"\color{red}\text{Missing right side of equation}")]
17+
[InlineData(@"1+\sqrt{2xy}=3", @"\underline\mathrm{Input}\\1+\sqrt{2\times x_{}\times y_{}}=3\\\\\underline\mathrm{Solutions}\\x_{}\in \left\{\frac{--\frac{4}{y_{}}}{2}\right\}\\y_{}\in \left\{\frac{4}{2\times x_{}}\right\}\\")]
18+
[InlineData(@"1=3", @"\underline\mathrm{Input}\\1=3\\\\\underline\mathrm{Result}\\\text{False}")]
19+
[InlineData(@"1=1", @"\underline\mathrm{Input}\\1=1\\\\\underline\mathrm{Result}\\\text{True}")]
20+
public void Interpret(string input, string expected) {
21+
var actual = Evaluation.Interpret(EvaluationTests.ParseLaTeX(input));
22+
Assert.Equal(expected, actual);
23+
Assert.NotEmpty(EvaluationTests.ParseLaTeX(actual));
24+
}
25+
}
26+
}
Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,60 @@
11
using System;
22
using System.Linq;
33
using Xunit;
4-
namespace CSharpMath {
5-
public partial class EvaluationTests {
6-
public class PredictTests {
7-
[Theory]
8-
[InlineData(1, 1, 1)]
9-
[InlineData(2, 2, 2)]
10-
[InlineData(1, 2, 3, 4)]
11-
[InlineData(3, 4, 5, 6)]
12-
[InlineData(1, 2, 3, 4, 5)]
13-
[InlineData(3, 4, 5, 6, 7)]
14-
[InlineData(1, 3, 5, 7)]
15-
[InlineData(8, 10, 12, 14)]
16-
[InlineData(1, 3, 5, 7, 9)]
17-
[InlineData(8, 10, 12, 14, 16)]
18-
[InlineData(1, 4, 7, 10)]
19-
[InlineData(1, 4, 7, 10, 13)]
20-
[InlineData(24, 31, 38, 45)]
21-
[InlineData(24, 31, 38, 45, 52)]
22-
[InlineData(17, 21, 25, 29)]
23-
[InlineData(17, 21, 25, 29, 33)]
24-
[InlineData(1, 1, 1, 1)]
25-
[InlineData(1, 1, 1, 1, 1)]
26-
[InlineData(1, 3, 1, 3, 1)]
27-
[InlineData(1, 3, 1, 3, 1, 3)]
28-
[InlineData(1, 2, 4, 8)]
29-
[InlineData(1, 2, 4, 8, 16)]
30-
[InlineData(1, 3, 9, 27)]
31-
[InlineData(1, 3, 9, 27, 81)]
32-
[InlineData(1, -2, 4, -8)]
33-
[InlineData(-1, 2, -4, 8)]
34-
[InlineData(30, 31, 40, 41, 50, 51)]
35-
[InlineData(61, 62, 63, 71, 72, 73, 81, 82)]
36-
[InlineData(2, 4, 8, 24, 48, 96, 288, 576, 1152)]
37-
[InlineData(0, 0, 0, 1, 0, 0, 0, 1, 0)]
38-
[InlineData(39, 34, 27, 22, 15, 10)]
39-
[InlineData(39, 34, 27, 22, 15, 10, 3)]
40-
[InlineData(31, 30, 22, 21, 13, 12)]
41-
[InlineData(31, 30, 22, 21, 13, 12, 4)]
42-
// Use int instead of double because https://github.com/xunit/xunit/issues/1670#issuecomment-373566797
43-
public void Integer(params int[] input) {
44-
static void Test(System.Collections.Generic.IEnumerable<int> seq) =>
45-
Assert.Equal(seq.Last(), Assert.IsType<double>(Evaluation.Predict(seq.Select(x => (double)x).SkipLast(1).ToArray())), 12);
46-
Test(input);
47-
Test(input.Reverse());
48-
}
49-
[Theory]
50-
[InlineData(new int[0])]
51-
[InlineData(1)]
52-
[InlineData(1, 2)]
53-
[InlineData(2, 1)]
54-
[InlineData(1, 2, 1)]
55-
[InlineData(1, 2, 1, 3)]
56-
[InlineData(39, 34, 27, 22)]
57-
[InlineData(31, 30, 22, 21)]
58-
public void IntegerFail(params int[] input) =>
59-
Assert.Null(Evaluation.Predict(input.Select(x => (double)x).ToArray()));
4+
namespace CSharpMath.EvaluationTests {
5+
public class PredictTests {
6+
[Theory]
7+
[InlineData(1, 1, 1)]
8+
[InlineData(2, 2, 2)]
9+
[InlineData(1, 2, 3, 4)]
10+
[InlineData(3, 4, 5, 6)]
11+
[InlineData(1, 2, 3, 4, 5)]
12+
[InlineData(3, 4, 5, 6, 7)]
13+
[InlineData(1, 3, 5, 7)]
14+
[InlineData(8, 10, 12, 14)]
15+
[InlineData(1, 3, 5, 7, 9)]
16+
[InlineData(8, 10, 12, 14, 16)]
17+
[InlineData(1, 4, 7, 10)]
18+
[InlineData(1, 4, 7, 10, 13)]
19+
[InlineData(24, 31, 38, 45)]
20+
[InlineData(24, 31, 38, 45, 52)]
21+
[InlineData(17, 21, 25, 29)]
22+
[InlineData(17, 21, 25, 29, 33)]
23+
[InlineData(1, 1, 1, 1)]
24+
[InlineData(1, 1, 1, 1, 1)]
25+
[InlineData(1, 3, 1, 3, 1)]
26+
[InlineData(1, 3, 1, 3, 1, 3)]
27+
[InlineData(1, 2, 4, 8)]
28+
[InlineData(1, 2, 4, 8, 16)]
29+
[InlineData(1, 3, 9, 27)]
30+
[InlineData(1, 3, 9, 27, 81)]
31+
[InlineData(1, -2, 4, -8)]
32+
[InlineData(-1, 2, -4, 8)]
33+
[InlineData(30, 31, 40, 41, 50, 51)]
34+
[InlineData(61, 62, 63, 71, 72, 73, 81, 82)]
35+
[InlineData(2, 4, 8, 24, 48, 96, 288, 576, 1152)]
36+
[InlineData(0, 0, 0, 1, 0, 0, 0, 1, 0)]
37+
[InlineData(39, 34, 27, 22, 15, 10)]
38+
[InlineData(39, 34, 27, 22, 15, 10, 3)]
39+
[InlineData(31, 30, 22, 21, 13, 12)]
40+
[InlineData(31, 30, 22, 21, 13, 12, 4)]
41+
// Use int instead of double because https://github.com/xunit/xunit/issues/1670#issuecomment-373566797
42+
public void Integer(params int[] input) {
43+
static void Test(System.Collections.Generic.IEnumerable<int> seq) =>
44+
Assert.Equal(seq.Last(), Assert.IsType<double>(Evaluation.Predict(seq.Select(x => (double)x).SkipLast(1).ToArray())), 12);
45+
Test(input);
46+
Test(input.Reverse());
6047
}
48+
[Theory]
49+
[InlineData(new int[0])]
50+
[InlineData(1)]
51+
[InlineData(1, 2)]
52+
[InlineData(2, 1)]
53+
[InlineData(1, 2, 1)]
54+
[InlineData(1, 2, 1, 3)]
55+
[InlineData(39, 34, 27, 22)]
56+
[InlineData(31, 30, 22, 21)]
57+
public void IntegerFail(params int[] input) =>
58+
Assert.Null(Evaluation.Predict(input.Select(x => (double)x).ToArray()));
6159
}
6260
}

CSharpMath.Evaluation/Evaluation.cs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,9 @@ static Result<MathItem> TryMakeSet(MathItem.Comma c, bool leftClosed, bool right
167167
_ => "Unrecognized bracket pair ( ]"
168168
} },
169169
{ ("[", "]"), item => item switch {
170+
null => "Missing math inside [ ]",
170171
MathItem.Comma c => TryMakeSet(c, true, true),
171-
_ => "Unrecognized bracket pair [ ]"
172+
_ => item
172173
} },
173174
{ ("{", "}"), item => item.AsEntities("set element").Bind(entities => (MathItem)MathS.Sets.Finite(entities)) }
174175
};
@@ -392,14 +393,18 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
392393
handlePrecendence = Precedence.SetOperation;
393394
handleBinarySet = (l, r) => l - r;
394395
goto handleBinarySet;
395-
// Until C# allows declaring variables under "or pattern"s...
396-
case Atoms.Inner { LeftBoundary:{ Nucleus:"[" }, InnerList:{ Count:1 } inner, RightBoundary:{ Nucleus:"]" } }
397-
when inner[0] is Atoms.Table { Environment: "matrix" } table:
398-
var matrix = table;
399-
goto handleMatrix;
400-
case Atoms.Table { Environment: "matrix" } table:
401-
matrix = table;
402-
goto handleMatrix;
396+
case Atoms.Table { Environment: "matrix" } matrix:
397+
var (rows, cols, cells) = (matrix.NRows, matrix.NColumns, matrix.Cells);
398+
var matrixElements = new Entity[rows * cols];
399+
for (var row = 0; row < rows; row++)
400+
for (var col = 0; col < cols; col++) {
401+
if (cells[row].Count <= col)
402+
return $"There are empty slots in the {rows}×{cols} matrix";
403+
(matrixElements[row * cols + col], error) = Transform(cells[row][col]).ExpectEntity("matrix element");
404+
if (error != null) return error;
405+
}
406+
@this = MathS.Matrices.Matrix(rows, cols, matrixElements);
407+
goto handleThis;
403408
case Atoms.Open { Nucleus: var opening }:
404409
if (!OpenBracketInfo.TryGetValue(opening, out var bracketInfo))
405410
return "Unsupported opening bracket " + opening;
@@ -463,19 +468,6 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
463468
return $"Unsupported table environment {table.Environment}";
464469
default:
465470
return $"Unsupported {atom.TypeName} {atom.Nucleus}";
466-
467-
handleMatrix:
468-
var (rows, cols, cells) = (matrix.NRows, matrix.NColumns, matrix.Cells);
469-
var matrixElements = new Entity[rows * cols];
470-
for (var row = 0; row < rows; row++)
471-
for (var col = 0; col < cols; col++) {
472-
if (cells[row].Count <= col)
473-
return $"There are empty slots in the {rows}×{cols} matrix";
474-
(matrixElements[row * cols + col], error) = Transform(cells[row][col]).ExpectEntity("matrix element");
475-
if (error != null) return error;
476-
}
477-
@this = MathS.Matrices.Matrix(rows, cols, matrixElements);
478-
goto handleThis;
479471
#pragma warning disable CS0162 // Unreachable code detected
480472
#pragma warning disable CS0164 // This label has not been referenced
481473
handleFunction:

CSharpMath.Evaluation/Interpret.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ public static string Interpret(Atom.MathList mathList, System.Func<string, strin
5353
latex.AppendLaTeXHeader("Expanded").AppendLaTeX(entity.Expand());
5454
latex.AppendLaTeXHeader("Factorized").AppendLaTeX(entity.Collapse());
5555
}
56-
foreach (AngouriMath.VariableEntity variable in AngouriMath.MathS.Utils.GetUniqueVariables(entity).FiniteSet())
57-
latex.AppendLaTeXHeader(@"\mathnormal\frac\partial{\partial " + variable.Latexise() + @"}")
58-
.AppendLaTeX(entity.Derive(variable).Simplify());
59-
// TryOutput("Alternate forms", () => entity.Alternate(5));
6056
break;
6157
case MathItem.Set _:
6258
case MathItem.Comma _:

0 commit comments

Comments
 (0)