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

CSharpMath.Evaluation.Interpret tests #151

Merged
merged 23 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from 18 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
9 changes: 4 additions & 5 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,11 @@ categories:
label: 'Type/Housekeeping'
# Extra line before $BODY or markdown on the first line of $BODY will be interpreted as plain text
change-template: |
<details><summary>$TITLE (#$NUMBER) @$AUTHOR</summary>
<details><summary>`$TITLE` (#$NUMBER) @$AUTHOR</summary><table><td>

$BODY
</details>
</td></table></details>
no-changes-template: '* (No changes)'
replacers:
# We don't support nested <summary> and <details> so we add a (?!<details>|<summary>)
- search: '/<details><summary>((?:(?!<details>|<summary>).)+?)<\/summary>\s*<\/details>/g'
- search: '/<details><summary>(.+?)<\/summary><table><td>\s*<\/td><\/table><\/details>/g'
replace: '- $1'
2 changes: 1 addition & 1 deletion .github/workflows/Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
uses: warrenbuckley/Setup-MSBuild@v1
- name: Restore NuGet Packages
run: nuget restore CSharpMath.sln
- name: Build CI artifacts
- name: Build Everything
run: msbuild CSharpMath.sln /p:Configuration=Release
26 changes: 15 additions & 11 deletions CSharpMath.Evaluation.Tests/EvaluationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
using Xunit;
using AngouriMath;

namespace CSharpMath {
namespace CSharpMath.EvaluationTests {
using Atom;
public partial class EvluationTests {
MathList ParseLaTeX(string latex) =>
public class EvaluationTests {
internal static MathList ParseLaTeX(string latex) =>
LaTeXParser.MathListFromLaTeX(latex).Match(list => list, e => throw new Xunit.Sdk.XunitException(e));
Evaluation.MathItem ParseMath(string latex) =>
static Evaluation.MathItem ParseMath(string latex) =>
Evaluation.Evaluate(ParseLaTeX(latex)).Match(entity => entity, e => throw new Xunit.Sdk.XunitException(e));
void Test(string input, string converted, string? result) {
void Test(string input) {
Expand Down Expand Up @@ -424,7 +424,10 @@ public void Numbers(string input, string converted, string output) =>
[InlineData(@"\sin^a\ \; (x)^2(x)", @"\sin \left( x\right) ^{a\times 2}\times x", @"\sin \left( x\right) ^{2\times a}\times x")]
[InlineData(@"\sin (\frac\pi2)", @"\sin \left( \frac{\pi }{2}\right) ", @"1")]
[InlineData(@"\sin (\frac\pi2)+1", @"\sin \left( \frac{\pi }{2}\right) +1", @"2")]
public void Parentheses(string latex, string converted, string result) => Test(latex, converted, result);
public void Parentheses(string latex, string converted, string result) {
Test(latex, converted, result);
Test(latex.Replace('(', '[').Replace(')', ']'), converted, result);
}
[Theory]
[InlineData(@"\begin{matrix}1\end{matrix}", @"\left( \begin{matrix}1\end{matrix}\right) ", @"\left( \begin{matrix}1\end{matrix}\right) ")]
[InlineData(@"\begin{pmatrix}1\end{pmatrix}", @"\left( \begin{matrix}1\end{matrix}\right) ", @"\left( \begin{matrix}1\end{matrix}\right) ")]
Expand Down Expand Up @@ -580,11 +583,12 @@ public void Numbers(string input, string converted, string output) =>
[InlineData(@"\left(1+\right]", "Missing right operand for +")]
[InlineData(@"\left(2,3\right]^\square", "Placeholders should be filled")]
[InlineData(@"(2,3]^\square", "Placeholders should be filled")]
[InlineData(@"[]", "Unrecognized bracket pair [ ]")]
[InlineData(@"[x]", "Unrecognized bracket pair [ ]")]
[InlineData(@"[[x]", "Unrecognized bracket pair [ ]")]
[InlineData(@"[x]]", "Unrecognized bracket pair [ ]")]
[InlineData(@"\left[\right]", "Unrecognized bracket pair [ ]")]
[InlineData(@"[]", "Missing math inside [ ]")]
[InlineData(@"[[x]", "Missing ]")]
[InlineData(@"[x]]", "Missing [")]
[InlineData(@"[_\square x]", "Subscripts are unsupported for Open [")]
[InlineData(@"[x]_\square", "Subscripts are unsupported for Close ]")]
[InlineData(@"\left[\right]", "Missing math inside [ ]")]
[InlineData(@"\left[1+\right]", "Missing right operand for +")]
[InlineData(@"\left[2,3\right]^\square", "Placeholders should be filled")]
[InlineData(@"[2,3]^\square", "Placeholders should be filled")]
Expand Down Expand Up @@ -633,7 +637,7 @@ public void Numbers(string input, string converted, string output) =>
[InlineData(@"+(3,4]", "Set cannot be right operand for +")]
[InlineData(@"[5,6)\times", "Set cannot be left operand for ×")]
[InlineData(@"\frac{[7,8]}{9}", "Set cannot be numerator")]
[InlineData(@"\sqrt[{[]}]{}", "Unrecognized bracket pair [ ]")]
[InlineData(@"\sqrt[{[)}]{}", "Unrecognized bracket pair [ )")]
[InlineData(@"\sqrt[{[a,b]}]{}", "Set cannot be degree")]
[InlineData(@"\{\{\}\}", "Set cannot be set element")]
[InlineData(@"\cap", "Unsupported Unary Operator ∩")]
Expand Down
26 changes: 26 additions & 0 deletions CSharpMath.Evaluation.Tests/InterpretTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Linq;
using Xunit;
namespace CSharpMath.EvaluationTests {
public class InterpretTests {
[Theory]
[InlineData(@"", @"\color{red}\text{There is nothing to evaluate}")]
[InlineData(@"1", @"\underline\mathrm{Input}\\1\\\\\underline\mathrm{Simplified}\\1\\\\\underline\mathrm{Value\ (100\ digits)}\\1")]
[InlineData(@"1+", @"\color{red}\text{Missing right operand for +}")]
[InlineData(@"1+2", @"\underline\mathrm{Input}\\1+2\\\\\underline\mathrm{Simplified}\\3\\\\\underline\mathrm{Value\ (100\ digits)}\\3")]
[InlineData(@"1+\sqrt", @"\color{red}\text{Missing radicand}")]
[InlineData(@"1+\sqrt2", @"\underline\mathrm{Input}\\1+\sqrt{2}\\\\\underline\mathrm{Simplified}\\1+\sqrt{2}\\\\\underline\mathrm{Value\ (100\ digits)}\\2.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573")]
[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_{}}")]
[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_{}}")]
[InlineData(@"=1+\sqrt{2xy}", @"\color{red}\text{Missing left side of equation}")]
[InlineData(@"1+\sqrt{2xy}=", @"\color{red}\text{Missing right side of equation}")]
[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\}\\")]
[InlineData(@"1=3", @"\underline\mathrm{Input}\\1=3\\\\\underline\mathrm{Result}\\\text{False}")]
[InlineData(@"1=1", @"\underline\mathrm{Input}\\1=1\\\\\underline\mathrm{Result}\\\text{True}")]
public void Interpret(string input, string expected) {
var actual = Evaluation.Interpret(EvaluationTests.ParseLaTeX(input));
Assert.Equal(expected, actual);
Assert.NotEmpty(EvaluationTests.ParseLaTeX(actual));
}
}
}
110 changes: 54 additions & 56 deletions CSharpMath.Evaluation.Tests/PredictTests.cs
Original file line number Diff line number Diff line change
@@ -1,62 +1,60 @@
using System;
using System.Linq;
using Xunit;
namespace CSharpMath {
public partial class EvaluationTests {
public class PredictTests {
[Theory]
[InlineData(1, 1, 1)]
[InlineData(2, 2, 2)]
[InlineData(1, 2, 3, 4)]
[InlineData(3, 4, 5, 6)]
[InlineData(1, 2, 3, 4, 5)]
[InlineData(3, 4, 5, 6, 7)]
[InlineData(1, 3, 5, 7)]
[InlineData(8, 10, 12, 14)]
[InlineData(1, 3, 5, 7, 9)]
[InlineData(8, 10, 12, 14, 16)]
[InlineData(1, 4, 7, 10)]
[InlineData(1, 4, 7, 10, 13)]
[InlineData(24, 31, 38, 45)]
[InlineData(24, 31, 38, 45, 52)]
[InlineData(17, 21, 25, 29)]
[InlineData(17, 21, 25, 29, 33)]
[InlineData(1, 1, 1, 1)]
[InlineData(1, 1, 1, 1, 1)]
[InlineData(1, 3, 1, 3, 1)]
[InlineData(1, 3, 1, 3, 1, 3)]
[InlineData(1, 2, 4, 8)]
[InlineData(1, 2, 4, 8, 16)]
[InlineData(1, 3, 9, 27)]
[InlineData(1, 3, 9, 27, 81)]
[InlineData(1, -2, 4, -8)]
[InlineData(-1, 2, -4, 8)]
[InlineData(30, 31, 40, 41, 50, 51)]
[InlineData(61, 62, 63, 71, 72, 73, 81, 82)]
[InlineData(2, 4, 8, 24, 48, 96, 288, 576, 1152)]
[InlineData(0, 0, 0, 1, 0, 0, 0, 1, 0)]
[InlineData(39, 34, 27, 22, 15, 10)]
[InlineData(39, 34, 27, 22, 15, 10, 3)]
[InlineData(31, 30, 22, 21, 13, 12)]
[InlineData(31, 30, 22, 21, 13, 12, 4)]
// Use int instead of double because https://github.com/xunit/xunit/issues/1670#issuecomment-373566797
public void Integer(params int[] input) {
static void Test(System.Collections.Generic.IEnumerable<int> seq) =>
Assert.Equal(seq.Last(), Assert.IsType<double>(Evaluation.Predict(seq.Select(x => (double)x).SkipLast(1).ToArray())), 12);
Test(input);
Test(input.Reverse());
}
[Theory]
[InlineData(new int[0])]
[InlineData(1)]
[InlineData(1, 2)]
[InlineData(2, 1)]
[InlineData(1, 2, 1)]
[InlineData(1, 2, 1, 3)]
[InlineData(39, 34, 27, 22)]
[InlineData(31, 30, 22, 21)]
public void IntegerFail(params int[] input) =>
Assert.Null(Evaluation.Predict(input.Select(x => (double)x).ToArray()));
namespace CSharpMath.EvaluationTests {
public class PredictTests {
[Theory]
[InlineData(1, 1, 1)]
[InlineData(2, 2, 2)]
[InlineData(1, 2, 3, 4)]
[InlineData(3, 4, 5, 6)]
[InlineData(1, 2, 3, 4, 5)]
[InlineData(3, 4, 5, 6, 7)]
[InlineData(1, 3, 5, 7)]
[InlineData(8, 10, 12, 14)]
[InlineData(1, 3, 5, 7, 9)]
[InlineData(8, 10, 12, 14, 16)]
[InlineData(1, 4, 7, 10)]
[InlineData(1, 4, 7, 10, 13)]
[InlineData(24, 31, 38, 45)]
[InlineData(24, 31, 38, 45, 52)]
[InlineData(17, 21, 25, 29)]
[InlineData(17, 21, 25, 29, 33)]
[InlineData(1, 1, 1, 1)]
[InlineData(1, 1, 1, 1, 1)]
[InlineData(1, 3, 1, 3, 1)]
[InlineData(1, 3, 1, 3, 1, 3)]
[InlineData(1, 2, 4, 8)]
[InlineData(1, 2, 4, 8, 16)]
[InlineData(1, 3, 9, 27)]
[InlineData(1, 3, 9, 27, 81)]
[InlineData(1, -2, 4, -8)]
[InlineData(-1, 2, -4, 8)]
[InlineData(30, 31, 40, 41, 50, 51)]
[InlineData(61, 62, 63, 71, 72, 73, 81, 82)]
[InlineData(2, 4, 8, 24, 48, 96, 288, 576, 1152)]
[InlineData(0, 0, 0, 1, 0, 0, 0, 1, 0)]
[InlineData(39, 34, 27, 22, 15, 10)]
[InlineData(39, 34, 27, 22, 15, 10, 3)]
[InlineData(31, 30, 22, 21, 13, 12)]
[InlineData(31, 30, 22, 21, 13, 12, 4)]
// Use int instead of double because https://github.com/xunit/xunit/issues/1670#issuecomment-373566797
public void Integer(params int[] input) {
static void Test(System.Collections.Generic.IEnumerable<int> seq) =>
Assert.Equal(seq.Last(), Assert.IsType<double>(Evaluation.Predict(seq.Select(x => (double)x).SkipLast(1).ToArray())), 12);
Test(input);
Test(input.Reverse());
}
[Theory]
[InlineData(new int[0])]
[InlineData(1)]
[InlineData(1, 2)]
[InlineData(2, 1)]
[InlineData(1, 2, 1)]
[InlineData(1, 2, 1, 3)]
[InlineData(39, 34, 27, 22)]
[InlineData(31, 30, 22, 21)]
public void IntegerFail(params int[] input) =>
Assert.Null(Evaluation.Predict(input.Select(x => (double)x).ToArray()));
}
}
36 changes: 14 additions & 22 deletions CSharpMath.Evaluation/Evaluation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@ static Result<MathItem> TryMakeSet(MathItem.Comma c, bool leftClosed, bool right
_ => "Unrecognized bracket pair ( ]"
} },
{ ("[", "]"), item => item switch {
null => "Missing math inside [ ]",
MathItem.Comma c => TryMakeSet(c, true, true),
_ => "Unrecognized bracket pair [ ]"
_ => item
} },
{ ("{", "}"), item => item.AsEntities("set element").Bind(entities => (MathItem)MathS.Sets.Finite(entities)) }
};
Expand Down Expand Up @@ -392,14 +393,18 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
handlePrecendence = Precedence.SetOperation;
handleBinarySet = (l, r) => l - r;
goto handleBinarySet;
// Until C# allows declaring variables under "or pattern"s...
case Atoms.Inner { LeftBoundary:{ Nucleus:"[" }, InnerList:{ Count:1 } inner, RightBoundary:{ Nucleus:"]" } }
when inner[0] is Atoms.Table { Environment: "matrix" } table:
var matrix = table;
goto handleMatrix;
case Atoms.Table { Environment: "matrix" } table:
matrix = table;
goto handleMatrix;
case Atoms.Table { Environment: "matrix" } matrix:
var (rows, cols, cells) = (matrix.NRows, matrix.NColumns, matrix.Cells);
var matrixElements = new Entity[rows * cols];
for (var row = 0; row < rows; row++)
for (var col = 0; col < cols; col++) {
if (cells[row].Count <= col)
return $"There are empty slots in the {rows}×{cols} matrix";
(matrixElements[row * cols + col], error) = Transform(cells[row][col]).ExpectEntity("matrix element");
if (error != null) return error;
}
@this = MathS.Matrices.Matrix(rows, cols, matrixElements);
goto handleThis;
case Atoms.Open { Nucleus: var opening }:
if (!OpenBracketInfo.TryGetValue(opening, out var bracketInfo))
return "Unsupported opening bracket " + opening;
Expand Down Expand Up @@ -463,19 +468,6 @@ _ when LaTeXSettings.CommandForAtom(atom) is string s => MathS.Var(s + subscript
return $"Unsupported table environment {table.Environment}";
default:
return $"Unsupported {atom.TypeName} {atom.Nucleus}";

handleMatrix:
var (rows, cols, cells) = (matrix.NRows, matrix.NColumns, matrix.Cells);
var matrixElements = new Entity[rows * cols];
for (var row = 0; row < rows; row++)
for (var col = 0; col < cols; col++) {
if (cells[row].Count <= col)
return $"There are empty slots in the {rows}×{cols} matrix";
(matrixElements[row * cols + col], error) = Transform(cells[row][col]).ExpectEntity("matrix element");
if (error != null) return error;
}
@this = MathS.Matrices.Matrix(rows, cols, matrixElements);
goto handleThis;
#pragma warning disable CS0162 // Unreachable code detected
#pragma warning disable CS0164 // This label has not been referenced
handleFunction:
Expand Down
4 changes: 0 additions & 4 deletions CSharpMath.Evaluation/Interpret.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ public static string Interpret(Atom.MathList mathList, System.Func<string, strin
latex.AppendLaTeXHeader("Expanded").AppendLaTeX(entity.Expand());
latex.AppendLaTeXHeader("Factorized").AppendLaTeX(entity.Collapse());
}
foreach (AngouriMath.VariableEntity variable in AngouriMath.MathS.Utils.GetUniqueVariables(entity).FiniteSet())
latex.AppendLaTeXHeader(@"\mathnormal\frac\partial{\partial " + variable.Latexise() + @"}")
.AppendLaTeX(entity.Derive(variable).Simplify());
// TryOutput("Alternate forms", () => entity.Alternate(5));
break;
case MathItem.Set _:
case MathItem.Comma _:
Expand Down
Loading