Showing preview only (350K chars total). Download the full file or copy to clipboard to get everything.
Repository: dharmatech/Symbolism
Branch: master
Commit: e10887dcf9e2
Files: 31
Total size: 336.5 KB
Directory structure:
gitextract_i2j1v7op/
├── .gitattributes
├── .gitignore
├── Examples/
│ ├── pse-example-5.10-Obj.md
│ ├── symbolism-linux.md
│ └── unit-test-index.md
├── README.md
├── Symbolism/
│ ├── AlgebraicExpand.cs
│ ├── CoefficientGpe.cs
│ ├── DeepSelect.cs
│ ├── DegreeGpe.cs
│ ├── EliminateVariable.cs
│ ├── ExpandPower.cs
│ ├── ExpandProduct.cs
│ ├── Has.cs
│ ├── IsolateVariable.cs
│ ├── LeadingCoefficientGpe.cs
│ ├── LogicalExpand.cs
│ ├── PolynomialDivision.cs
│ ├── PolynomialGcd.cs
│ ├── RationalExpand.cs
│ ├── RationalizeExpression.cs
│ ├── SimplifyEquation.cs
│ ├── SimplifyLogical.cs
│ ├── Substitute.cs
│ ├── Symbolism.cs
│ ├── Symbolism.csproj
│ ├── Trigonometric.cs
│ └── Utils.cs
├── Symbolism.sln
└── Tests/
├── Tests.cs
└── Tests.csproj
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
================================================
FILE: Examples/pse-example-5.10-Obj.md
================================================
# Classes for representing forces on objects
In [this walkthrough](https://gist.github.com/dharmatech/a14d1a29a7d4c0728d37), one thing you may notice is the large number of `Symbol` objects that are defined. For example, for just the ball, the following are defined:
```C#
var F1_m1 = new Symbol("F1_m1"); // force 1 on mass 1
var F2_m1 = new Symbol("F2_m1"); // force 2 on mass 1
var th1_m1 = new Symbol("th1_m1"); // direction of force 1 on mass 1
var th2_m1 = new Symbol("th2_m1"); // direction of force 2 on mass 1
var F1x_m1 = new Symbol("F1x_m1"); // x-component of force 1 on mass 1
var F2x_m1 = new Symbol("F2x_m1"); // x-component of force 2 on mass 1
var F1y_m1 = new Symbol("F1y_m1"); // y-component of force 1 on mass 1
var F2y_m1 = new Symbol("F2y_m1"); // y-component of force 2 on mass 1
var Fx_m1 = new Symbol("Fx_m1"); // x-component of total force on mass 1
var Fy_m1 = new Symbol("Fy_m1"); // y-component of total force on mass 1
var ax_m1 = new Symbol("ax_m1"); // x-component of acceleration of mass 1
var ay_m1 = new Symbol("ay_m1"); // y-component of acceleration of mass 1
```
Then we have the many equations for the ball:
```C#
F1x_m1 == F1_m1 * cos(th1_m1),
F2x_m1 == F2_m1 * cos(th2_m1),
F1y_m1 == F1_m1 * sin(th1_m1),
F2y_m1 == F2_m1 * sin(th2_m1),
Fx_m1 == F1x_m1 + F2x_m1,
Fy_m1 == F1y_m1 + F2y_m1,
Fx_m1 == m1 * ax_m1,
Fy_m1 == m1 * ay_m1,
```
That's just for an object with two forces acting on it! The block, which has three forces acting on it, has more even more `Symbol`s and more equations.
I've defined a class [`Obj2`](https://github.com/dharmatech/Symbolism/blob/ffa322d81cc0e8de932b3ae2d3dcf7b90b7c5bfd/Tests/Tests.cs#L112) which represents an object with two forces acting on it. So now, instead of all those symbols and equations for the ball, we write:
```C#
var bal = new Obj2("bal");
```
A nice benefit is that now the ball's associated symbols are object members and can be accessed easily via intellisense:

Moreover, the laws of motion equations can be generated with the `Equations` method:
```C#
bal.Equations().DispLong()
```
displays the following at the console:

The block, which has three forces acting on it is similarly represented with an `Obj3`:
```C#
var blk = new Obj3("blk");
```
Now the definition of the equations, which [took up about 40 lines](https://github.com/dharmatech/Symbolism/blob/ffa322d81cc0e8de932b3ae2d3dcf7b90b7c5bfd/Tests/Tests.cs#L3595-L3635) in the original example, is simply:
```C#
var eqs = new And(
blk.ax == bal.ay, // the block moves right as the ball moves up
a == blk.ax,
bal.Equations(),
blk.Equations()
);
```
Let's display the resulting set of equations:
```C#
eqs.DispLong()
```

The symbolic values are also specified in terms of the members of `bal` and `blk`:
```C#
var vals = new List<Equation>
{
bal.ax == 0,
bal.m == m1,
bal.F1 == T, bal.th1 == (90).ToRadians(), // force 1 is straight up
bal.F2 == m1 * g, bal.th2 == (270).ToRadians(), // force 2 is straight down
blk.ay == 0,
blk.m == m2,
blk.F1 == n, blk.th1 == (90).ToRadians(), // force 1 is straight up
blk.F2 == T, blk.th2 == (180).ToRadians(), // force 2 is straight down
blk.F3 == m2 * g, blk.th3 == (270).ToRadians() + th // force 3 direction
};
```
If we substitute those values:
```C#
eqs.SubstituteEqLs(vals).DispLong()
```
the equations become:

OK, let's find the acceleration. We eliminate unknown values and isolate `a`:
```C#
eqs
.SubstituteEqLs(vals)
.EliminateVariables(
bal.ΣFx, bal.F1x, bal.F2x,
bal.ΣFy, bal.F1y, bal.F2y,
blk.ΣFx, blk.F1x, blk.F2x, blk.F3x,
blk.ΣFy, blk.F1y, blk.F2y, blk.F3y,
blk.ax, bal.ay,
T, n
)
.IsolateVariable(a)
.DispLong()
```
to get:

This version of the example in terms of `Obj2` and `Obj3` is checked in as a [test](https://github.com/dharmatech/Symbolism/blob/ffa322d81cc0e8de932b3ae2d3dcf7b90b7c5bfd/Tests/Tests.cs#L3730).
================================================
FILE: Examples/symbolism-linux.md
================================================
This is a tutorial on how to build and run a simple Symbolism program on Linux.
The following instructions have been tested on Ubuntu 16.04.3.
Install [.NET Core SDK](https://dotnet.microsoft.com/download).
Install [Visual Studio Code](https://code.visualstudio.com/).
Install the [C# for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp) extension.
Create a new console project:
$ mkdir symbolism-example
$ cd symbolism-example
$ dotnet new console
Add the Symbolism nuget package:
$ dotnet add package Symbolism
Start Visual Studio Code.
$ code
Select "File -> Open Folder" from the vscode menu. Select the *symbolism-example* folder.
Select `Program.cs` in the Explorer pane. Replace the code with the following which solves a simple physics exercise:
``` csharp
using System;
using System.Collections.Generic;
using System.Linq;
using Symbolism;
using Symbolism.Substitute;
using Symbolism.EliminateVariable;
using Symbolism.IsolateVariable;
using Symbolism.LogicalExpand;
using Symbolism.SimplifyLogical;
using Symbolism.Utils;
using static Symbolism.Constructors;
using static Symbolism.Trigonometric.Constructors;
namespace symbolism_example
{
class Program
{
static void Main(string[] args)
{
// In a local bar, a customer slides an empty beer mug
// down the counter for a refill. The bartender is momentarily
// distracted and does not see the mug, which slides
// off the counter and strikes the floor 1.40 m from the
// base of the counter. If the height of the counter is
// 0.860 m, (a) with what velocity did the mug leave the
// counter and (b) what was the direction of the mug’s
// velocity just before it hit the floor?
var xA = new Symbol("xA");
var yA = new Symbol("yA");
var xB = new Symbol("xB");
var yB = new Symbol("yB");
var vxA = new Symbol("vxA");
var vyA = new Symbol("vyA");
var vxB = new Symbol("vxB");
var vyB = new Symbol("vyB");
var tAB = new Symbol("tAB");
var ax = new Symbol("ax");
var ay = new Symbol("ay");
var thB = new Symbol("thB");
var vB = new Symbol("vB");
var eqs = and(
vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,
tan(thB) == vyB / vxB,
xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,
xB != 0
);
var vals = new List<Equation>() { xA == 0, yA == 0.86, /* vxA */ vyA == 0, xB == 1.4, yB == 0, /* vxB vyB vB thB */ /* tAB */ ax == 0, ay == -9.8 };
var zeros = vals.Where(eq => eq.b == 0).ToList();
DoubleFloat.tolerance = 0.00001;
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(thB, vxB, vyB, tAB)
.IsolateVariable(vxA)
.LogicalExpand()
.DispLong()
.SubstituteEqLs(vals)
.Disp();
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxB, vyB, tAB, vxA)
.LogicalExpand()
.CheckVariable(xB)
.SimplifyLogical()
.IsolateVariable(thB)
.DispLong()
.SubstituteEqLs(vals)
.Disp();
DoubleFloat.tolerance = null;
}
}
}
```
Press `ctrl+f5` to run the program.
The symbolic and numeric answers will be displayed in the console:

================================================
FILE: Examples/unit-test-index.md
================================================
Index of examples in unit tests.
# Physics Examples
## Motion in Two Dimensions
* [PSE 5E E4.3](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L1450)
* [PSE 5E P4.9](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L5686)
* [PSE 5E P4.11](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L5686)
* [PSE 5E P4.13](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2419)
* [PSE 5E P4.15](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2499)
* [PSE 5E P4.17](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2590)
* [PSE 5E P4.19](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2702)
* [PSE 5E P4.21](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2808)
* [PSE 5E P4.23](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L2890)
## The Laws of Motion
* [PSE 5E E5.1](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L3124)
* [PSE 5E E5.4](https://github.com/dharmatech/Symbolism/blob/450ece65ce4ca4f196b512cba0f5ddeabd024690/Tests/Tests.cs#L3308)
* [PSE 5E E5.6](https://github.com/dharmatech/Symbolism/blob/450ece65ce4ca4f196b512cba0f5ddeabd024690/Tests/Tests.cs#L3424)
## Work and Kinetic Energy
* [PSE 5E E7.8](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L5519)
* [PSE 5E E7.11](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L5596)
* [PSE 6E P7.3](https://github.com/dharmatech/Symbolism/blob/e6cf94395a92127b7b25c97748ced065433f00b1/Tests/Tests.cs#L5686)
* [PSE 5E P7.23](https://github.com/dharmatech/Symbolism/blob/8f8f618f1f2f2f38c6c4961222b19b8feb4739bf/Tests/Tests.cs#L5738)
* [PSE 5E P7.33](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L5782)
* [PSE 5E P7.35](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L5893)
* [PSE 5E P7.39](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L6026)
* [PSE 5E P7.41](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L6094)
* [PSE 5E P7.55](https://github.com/dharmatech/Symbolism/blob/531deeccc941bfa891302fd1e02090780c52d49b/Tests/Tests.cs#L6183)
## Potential Energy and Conservation of Energy
* [PSE 5E E8.2](https://github.com/dharmatech/Symbolism/blob/39d80bcee6ed96f14bc5cf6b787f62a326e9f410/Tests/Tests.cs#L6220)
* [PSE 5E E8.3](https://github.com/dharmatech/Symbolism/blob/39d80bcee6ed96f14bc5cf6b787f62a326e9f410/Tests/Tests.cs#L6306)
================================================
FILE: README.md
================================================
# Symbolism - A Computer Algebra Library for C#
Library that implements automatic simplification of algebraic expressions in C#.
To get an idea of the kinds of expressions it handles, see the [tests in this file](Tests/Tests.cs).
The automatic simplification algorithm comes from the book "Computer Algebra and Symbolic Computation: Mathematical Methods" by Joel S. Cohen.
The core of the system is in [Symbolism.cs](Symbolism/Symbolism.cs).
Symbolism currently targets .NET Standard 2.0 and thus can be used in .NET projects on Windows, Linux, and Mac.
Nuget package [available here](https://www.nuget.org/packages/Symbolism/).
# Setup on Linux
[Tutorial](Examples/symbolism-linux.md) on how to build and run a simple Symbolism program on Linux.
# Examples
The "PSE 5E" examples and problems in the unit tests are from the textbook "Physics for Scientists and Engineers, 5th Edition" by Serway and Jewett. Here's an [index](Examples/unit-test-index.md) of some of the examples.
[Here's a walk-through of solving a physics problem](https://gist.github.com/dharmatech/d6d499f14c808b159689).
A slightly more complex [walk-through](https://gist.github.com/dharmatech/a5e74ef03d98b3ff1c45).
[Walk-through](https://gist.github.com/dharmatech/a14d1a29a7d4c0728d37) of solving a laws of motion problem.
In action:

[Unit test](https://github.com/dharmatech/Symbolism/blob/ff09e2c20e026091225f4f303bbb06487a08f58d/Tests/Tests.cs#L2732) for that example.
# See also
Symbolism began as a port of the Scheme [MPL library](https://github.com/dharmatech/mpl) to C#.
[GiNaC](http://www.ginac.de/) and [SymbolicC++](http://issc.uj.ac.za/symbolic/symbolic.html) are of course very inspirational.
# References
Computer Algebra and Symbolic Computation: Elementary Algorithms
by Joel S. Cohen
Computer Algebra and Symbolic Computation: Mathematical Methods
by Joel S. Cohen
================================================
FILE: Symbolism/AlgebraicExpand.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.ExpandProduct;
using Symbolism.ExpandPower;
namespace Symbolism
{
namespace AlgebraicExpand
{
public static class Extensions
{
public static MathObject AlgebraicExpand(this MathObject u)
{
if (u is Equation)
{
var eq = u as Equation;
return eq.a.AlgebraicExpand() == eq.b.AlgebraicExpand();
}
if (u is Sum)
return (u as Sum).Map(elt => elt.AlgebraicExpand());
if (u is Product)
{
var v = (u as Product).elts[0];
return v.AlgebraicExpand()
.ExpandProduct( (u / v).AlgebraicExpand() );
}
if (u is Power)
{
var bas = (u as Power).bas;
var exp = (u as Power).exp;
if (exp is Integer && (exp as Integer).val >= 2)
return bas.AlgebraicExpand().ExpandPower((exp as Integer).val);
else
return u;
}
if (u is Function)
{
var u_ = u as Function;
return new Function(
u_.name,
u_.proc,
u_.args.ConvertAll(elt => elt.AlgebraicExpand()))
.Simplify();
}
return u;
}
}
}
}
================================================
FILE: Symbolism/CoefficientGpe.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Symbolism.Has;
namespace Symbolism
{
namespace CoefficientGpe
{
public static class Extensions
{
public static Tuple<MathObject, BigInteger> CoefficientMonomialGpe(this MathObject u, MathObject x)
{
if (u == x) return Tuple.Create((MathObject)1, (BigInteger)1);
if (u is Power &&
(u as Power).bas == x &&
(u as Power).exp is Integer &&
((u as Power).exp as Integer).val > 1)
return Tuple.Create((MathObject)1, ((u as Power).exp as Integer).val);
if (u is Product)
{
var m = (BigInteger) 0;
var c = u;
foreach (var elt in (u as Product).elts)
{
var f = elt.CoefficientMonomialGpe(x);
if (f == null) return null;
if (f.Item2 != 0)
{
m = f.Item2;
c = u / (x ^ m);
}
}
return Tuple.Create(c, m);
}
if (u.FreeOf(x)) return Tuple.Create(u, (BigInteger)0);
return null;
}
public static MathObject CoefficientGpe(this MathObject u, MathObject x, BigInteger j)
{
if (!(u is Sum))
{
var f = u.CoefficientMonomialGpe(x);
if (f == null) return null;
if (f.Item2 == j) return f.Item1;
return 0;
}
if (u == x) return j == 1 ? 1 : 0;
var c = (MathObject)0;
foreach (var elt in (u as Sum).elts)
{
var f = elt.CoefficientMonomialGpe(x);
if (f == null) return null;
if (f.Item2 == j) c = c + f.Item1;
}
return c;
}
}
}
}
================================================
FILE: Symbolism/DeepSelect.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism
{
namespace DeepSelect
{
public static class Extensions
{
public static MathObject DeepSelect(this MathObject obj, Func<MathObject, MathObject> proc)
{
var result = proc(obj);
if (result is Power)
return
(result as Power).bas.DeepSelect(proc) ^
(result as Power).exp.DeepSelect(proc);
if (result is Or)
return (result as Or).Map(elt => elt.DeepSelect(proc));
if (result is And)
return (result as And).Map(elt => elt.DeepSelect(proc));
if (result is Equation)
return
new Equation(
(result as Equation).a.DeepSelect(proc),
(result as Equation).b.DeepSelect(proc),
(result as Equation).Operator);
if (result is Sum)
return
(result as Sum).Map(elt => elt.DeepSelect(proc));
if (result is Product)
return
(result as Product).Map(elt => elt.DeepSelect(proc));
return result;
}
}
}
}
================================================
FILE: Symbolism/DegreeGpe.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using Symbolism.Has;
namespace Symbolism
{
namespace DegreeGpe
{
public static class Extensions
{
public static BigInteger DegreeMonomialGpe(this MathObject u, List<MathObject> v)
{
if (v.All(u.FreeOf)) return 0;
if (v.Contains(u)) return 1;
if (u is Power && ((Power)u).exp is Integer && ((Integer)((Power)u).exp).val > 1)
return ((Integer)((Power)u).exp).val;
//if (u is Product)
// return ((Product)u).elts.Select(elt => elt.DegreeMonomialGpe(v)).Sum();
if (u is Product)
return ((Product)u).elts.Select(elt => elt.DegreeMonomialGpe(v)).Aggregate(BigInteger.Add);
return 0;
}
public static BigInteger DegreeGpe(this MathObject u, List<MathObject> v)
{
if (u is Sum)
return ((Sum)u).elts.Select(elt => elt.DegreeMonomialGpe(v)).Max();
return u.DegreeMonomialGpe(v);
}
}
}
}
================================================
FILE: Symbolism/EliminateVariable.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.Substitute;
using Symbolism.Has;
using Symbolism.AlgebraicExpand;
using Symbolism.IsolateVariable;
using Symbolism.SimplifyEquation;
namespace Symbolism.EliminateVariable
{
public static class Extensions
{
public static MathObject CheckVariableEqLs(this List<Equation> eqs, Symbol sym)
{
// (a == 10, a == 0) -> 10 == 0 -> false
if (eqs.EliminateVariableEqLs(sym) == false) return false;
// (1/a != 0 && a != 0) -> a != 0
if (eqs.Any(eq => eq.Operator == Equation.Operators.NotEqual && eq.a == sym && eq.b == 0)
&&
eqs.Any(eq => eq.Operator == Equation.Operators.NotEqual && eq.a == 1 / sym && eq.b == 0))
return eqs
.Where(eq => (eq.Operator == Equation.Operators.NotEqual && eq.a == 1 / sym && eq.b == 0) == false)
.ToList()
.CheckVariableEqLs(sym);
// x + y == z && x / y == 0 && x != 0 -> false
if (eqs.Any(eq => eq.Operator == Equation.Operators.Equal && eq.a.Numerator() == sym && eq.a.Denominator().FreeOf(sym) && eq.b == 0) &&
eqs.Any(eq => eq == (sym != 0)))
return false;
return And.FromRange(eqs.Select(eq => eq as MathObject));
}
public static MathObject CheckVariable(this MathObject expr, Symbol sym)
{
// 1 / x == 0
// 1 / x^2 == 0
if (expr is Equation &&
(expr as Equation).Operator == Equation.Operators.Equal &&
(expr as Equation).b == 0 &&
(expr as Equation).a.Has(sym) &&
(expr as Equation).SimplifyEquation() is Equation &&
((expr as Equation).SimplifyEquation() as Equation).a is Power &&
(((expr as Equation).SimplifyEquation() as Equation).a as Power).exp is Integer &&
((((expr as Equation).SimplifyEquation() as Equation).a as Power).exp as Integer).val < 0)
return false;
if (expr is And)
{
var result = (expr as And).Map(elt => elt.CheckVariable(sym));
if (result is And)
{
var eqs = (expr as And).args.Select(elt => elt as Equation).ToList();
return eqs.CheckVariableEqLs(sym);
}
return result;
}
if (expr is Or &&
(expr as Or).args.All(elt => elt is And))
return (expr as Or).Map(elt => elt.CheckVariable(sym));
return expr;
}
// EliminateVarAnd
// EliminateVarOr
// EliminateVarLs
// EliminateVar
// EliminateVars
public static MathObject EliminateVariableEqLs(this List<Equation> eqs, Symbol sym)
{
if (eqs.Any(elt =>
elt.Operator == Equation.Operators.Equal &&
elt.Has(sym) &&
elt.AlgebraicExpand().Has(sym) &&
elt.IsolateVariableEq(sym).Has(obj => obj is Equation && (obj as Equation).a == sym && (obj as Equation).b.FreeOf(sym))
) == false)
return And.FromRange(eqs.Select(elt => elt as MathObject));
var eq = eqs.First(elt =>
elt.Operator == Equation.Operators.Equal &&
elt.Has(sym) &&
elt.AlgebraicExpand().Has(sym) &&
elt.IsolateVariableEq(sym).Has(obj => obj is Equation && (obj as Equation).a == sym && (obj as Equation).b.FreeOf(sym)));
var rest = eqs.Except(new List<Equation>() { eq });
var result = eq.IsolateVariableEq(sym);
// sym was not isolated
if (result is Equation &&
((result as Equation).a != sym || (result as Equation).b.Has(sym)))
return And.FromRange(eqs.Select(elt => elt as MathObject));
if (result is Equation)
{
var eq_sym = result as Equation;
return And.FromRange(rest.Select(elt => elt.Substitute(sym, eq_sym.b))).Simplify();
// return new And() { args = rest.Select(rest_eq => rest_eq.SubstituteEq(eq_sym)).ToList() };
// rest.Map(rest_eq => rest_eq.Substitute(eq_sym)
}
// Or(
// And(eq0, eq1, eq2, ...)
// And(eq3, eq4, eq5, ...)
// )
if (result is Or && (result as Or).args.All(elt => elt is And))
return (result as Or).Map(elt => (elt as And).AddRange(rest).EliminateVariable(sym));
if (result is Or)
{
var items = new List<MathObject>();
foreach (Equation eq_sym in (result as Or).args)
items.Add(new And(rest.Select(rest_eq => rest_eq.Substitute(sym, eq_sym.b)).ToArray()).Simplify());
return Or.FromRange(items);
}
throw new Exception();
}
public static MathObject EliminateVariable(this MathObject expr, Symbol sym)
{
if (expr is And)
{
var eqs = (expr as And).args.Select(elt => elt as Equation);
return EliminateVariableEqLs(eqs.ToList(), sym);
}
if (expr is Or)
{
return Or.FromRange((expr as Or).args.Select(and_expr => and_expr.EliminateVariable(sym)));
// expr.Map(and_expr => and_expr.EliminateVar(sym))
}
throw new Exception();
}
public static MathObject EliminateVariables(this MathObject expr, params Symbol[] syms) =>
syms.Aggregate(expr, (result, sym) => result.EliminateVariable(sym));
}
}
================================================
FILE: Symbolism/ExpandPower.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;
using Symbolism.ExpandProduct;
namespace Symbolism
{
namespace ExpandPower
{
public static class Extensions
{
static BigInteger Factorial(BigInteger n)
{
var result = (BigInteger) 1;
for (var i = 1; i <= n; i++)
{
result *= i;
}
return result;
// return Enumerable.Range(1, n).Aggregate((acc, elt) => acc * elt);
}
public static MathObject ExpandPower(this MathObject u, BigInteger n)
{
if (u is Sum)
{
var f = (u as Sum).elts[0];
var r = u - f;
MathObject s = 0;
var k = 0;
while (true)
{
if (k > n) return s;
else
{
var c =
Factorial(n)
/
(Factorial(k) * Factorial(n - k));
s = s + (c * (f ^ (n - k))).ExpandProduct(r.ExpandPower(k));
k++;
}
}
}
else return u ^ n;
}
}
}
}
================================================
FILE: Symbolism/ExpandProduct.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism
{
namespace ExpandProduct
{
public static class Extensions
{
public static MathObject ExpandProduct(this MathObject r, MathObject s)
{
if (r is Sum)
{
var f = (r as Sum).elts[0];
return f.ExpandProduct(s) + (r - f).ExpandProduct(s);
}
if (s is Sum) return s.ExpandProduct(r);
return r * s;
}
}
}
}
================================================
FILE: Symbolism/Has.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism
{
namespace Has
{
public static class Extensions
{
public static bool Has(this MathObject obj, MathObject a)
{
if (obj == a) return true;
if (obj is Equation) return (obj as Equation).a.Has(a) || (obj as Equation).b.Has(a);
if (obj is Power) return (((Power)obj).bas.Has(a) || ((Power)obj).exp.Has(a));
if (obj is Product) return ((Product)obj).elts.Any(elt => elt.Has(a));
if (obj is Sum) return ((Sum)obj).elts.Any(elt => elt.Has(a));
if (obj is Function) return ((Function)obj).args.Any(elt => elt.Has(a));
return false;
}
public static bool Has(this MathObject obj, Func<MathObject, bool> proc)
{
if (proc(obj)) return true;
if (obj is Equation) return (obj as Equation).a.Has(proc) || (obj as Equation).b.Has(proc);
if (obj is Power) return (obj as Power).bas.Has(proc) || (obj as Power).exp.Has(proc);
if (obj is Product) return (obj as Product).elts.Any(elt => elt.Has(proc));
if (obj is Sum) return (obj as Sum).elts.Any(elt => elt.Has(proc));
if (obj is Function) return (obj as Function).args.Any(elt => elt.Has(proc));
return false;
}
public static bool FreeOf(this MathObject obj, MathObject a) => !obj.Has(a);
}
}
}
================================================
FILE: Symbolism/IsolateVariable.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.Has;
using Symbolism.Trigonometric;
using Symbolism.CoefficientGpe;
using Symbolism.AlgebraicExpand;
using Symbolism.DegreeGpe;
namespace Symbolism.IsolateVariable
{
public static class Extensions
{
public static MathObject IsolateVariableEq(this Equation eq, Symbol sym)
{
if (eq.Operator == Equation.Operators.NotEqual) return eq;
if (eq.FreeOf(sym)) return eq;
// sin(x) / cos(x) == y -> tan(x) == y
if (eq.a is Product && (eq.a as Product).elts.Any(elt => elt == new Sin(sym)) &&
eq.a is Product && (eq.a as Product).elts.Any(elt => elt == 1 / new Cos(sym)))
return
(eq.a / new Sin(sym) * new Cos(sym) * new Tan(sym) == eq.b).IsolateVariableEq(sym);
// A sin(x)^2 == B sin(x) cos(x) -> A sin(x)^2 / (B sin(x) cos(x)) == 1
if (
eq.a is Product &&
(eq.a as Product).elts.Any(elt =>
(elt == new Sin(sym)) ||
((elt is Power) && (elt as Power).bas == new Sin(sym) && (elt as Power).exp is Number)) &&
eq.b is Product &&
(eq.b as Product).elts.Any(elt =>
(elt == new Sin(sym)) ||
((elt is Power) && (elt as Power).bas == new Sin(sym) && (elt as Power).exp is Number))
)
return
(eq.a / eq.b == 1).IsolateVariableEq(sym);
if (eq.b.Has(sym)) return IsolateVariableEq(new Equation(eq.a - eq.b, 0), sym);
if (eq.a == sym) return eq;
// (a x^2 + c) / x == - b
if (eq.a is Product &&
(eq.a as Product).elts.Any(
elt =>
elt is Power &&
(elt as Power).bas == sym &&
(elt as Power).exp == -1))
return IsolateVariableEq(eq.a * sym == eq.b * sym, sym);
//if (eq.a is Product &&
// (eq.a as Product).elts.Any(
// elt =>
// elt is Power &&
// (elt as Power).bas == sym &&
// (elt as Power).exp is Integer &&
// ((elt as Power).exp as Integer).val < 0))
// return IsolateVariableEq(eq.a * sym == eq.b * sym, sym);
// if (eq.a.Denominator() is Product &&
// (eq.a.Denominator() as Product).Any(elt => elt.Base() == sym)
//
//
// (x + y)^(1/2) == z
//
// x == -y + z^2 && z >= 0
if (eq.a is Power && (eq.a as Power).exp == new Integer(1) / 2)
return IsolateVariableEq((eq.a ^ 2) == (eq.b ^ 2), sym);
// 1 / sqrt(x) == y
if (eq.a is Power && (eq.a as Power).exp == -new Integer(1) / 2)
return (eq.a / eq.a == eq.b / eq.a).IsolateVariable(sym);
// x ^ 2 == y
// x ^ 2 - y == 0
if (eq.a.AlgebraicExpand().DegreeGpe(new List<MathObject>() { sym }) == 2 &&
eq.b != 0)
{
return
(eq.a - eq.b == 0).IsolateVariable(sym);
}
// a x^2 + b x + c == 0
if (eq.a.AlgebraicExpand().DegreeGpe(new List<MathObject>() { sym }) == 2)
{
var a = eq.a.AlgebraicExpand().CoefficientGpe(sym, 2);
var b = eq.a.AlgebraicExpand().CoefficientGpe(sym, 1);
var c = eq.a.AlgebraicExpand().CoefficientGpe(sym, 0);
if (a == null || b == null || c == null) return eq;
return new Or(
new And(
sym == (-b + (((b ^ 2) - 4 * a * c) ^ (new Integer(1) / 2))) / (2 * a),
(a != 0).Simplify()
).Simplify(),
new And(
sym == (-b - (((b ^ 2) - 4 * a * c) ^ (new Integer(1) / 2))) / (2 * a),
(a != 0).Simplify()
).Simplify(),
new And(sym == -c / b, a == 0, (b != 0).Simplify()).Simplify(),
new And(
(a == 0).Simplify(),
(b == 0).Simplify(),
(c == 0).Simplify()
).Simplify()
).Simplify();
}
// (x + y == z).IsolateVariable(x)
if (eq.a is Sum && (eq.a as Sum).elts.Any(elt => elt.FreeOf(sym)))
{
var items = ((Sum)eq.a).elts.FindAll(elt => elt.FreeOf(sym));
//return IsolateVariable(
// new Equation(
// eq.a - new Sum() { elts = items }.Simplify(),
// eq.b - new Sum() { elts = items }.Simplify()),
// sym);
//var new_a = eq.a; items.ForEach(elt => new_a = new_a - elt);
//var new_b = eq.b; items.ForEach(elt => new_b = new_b - elt);
var new_a = Sum.FromRange((eq.a as Sum).elts.Where(elt => items.Contains(elt) == false)).Simplify();
var new_b = eq.b; items.ForEach(elt => new_b = new_b - elt);
// (new_a as Sum).Where(elt => items.Contains(elt) == false)
return IsolateVariableEq(new Equation(new_a, new_b), sym);
//return IsolateVariable(
// new Equation(
// eq.a + new Sum() { elts = items.ConvertAll(elt => elt * -1) }.Simplify(),
// eq.b - new Sum() { elts = items }.Simplify()),
// sym);
}
// a b + a c == d
// a + a c == d
if (eq.a is Sum && (eq.a as Sum).elts.All(elt => elt.DegreeGpe(new List<MathObject>() { sym }) == 1))
{
//return
// (new Sum() { elts = (eq.a as Sum).elts.Select(elt => elt / sym).ToList() }.Simplify() == eq.b / sym)
// .IsolateVariable(sym);
return
(sym * Sum.FromRange((eq.a as Sum).elts.Select(elt => elt / sym)).Simplify() == eq.b)
.IsolateVariable(sym);
}
// -sqrt(x) + z * x == y
if (eq.a is Sum && eq.a.Has(sym ^ (new Integer(1) / 2))) return eq;
// sqrt(a + x) - z * x == -y
if (eq.a is Sum && eq.a.Has(elt => elt is Power && (elt as Power).exp == new Integer(1) / 2 && (elt as Power).bas.Has(sym)))
return eq;
if (eq.a is Sum && eq.AlgebraicExpand().Equals(eq)) return eq;
if (eq.a is Sum) return eq.AlgebraicExpand().IsolateVariable(sym);
// (x + 1) / (x + 2) == 3
if (eq.a.Numerator().Has(sym) && eq.a.Denominator().Has(sym))
{
return IsolateVariableEq(eq.a * eq.a.Denominator() == eq.b * eq.a.Denominator(), sym);
}
// sqrt(2 + x) * sqrt(3 + x) == y
if (eq.a is Product && (eq.a as Product).elts.All(elt => elt.Has(sym))) return eq;
if (eq.a is Product)
{
var items = ((Product)eq.a).elts.FindAll(elt => elt.FreeOf(sym));
return IsolateVariableEq(
new Equation(
eq.a / Product.FromRange(items).Simplify(),
eq.b / Product.FromRange(items).Simplify()),
sym);
}
// x ^ -2 == y
if (eq.a is Power &&
(eq.a as Power).bas == sym &&
(eq.a as Power).exp is Integer &&
((eq.a as Power).exp as Integer).val < 0)
return (eq.a / eq.a == eq.b / eq.a).IsolateVariableEq(sym);
if (eq.a is Power) return eq;
// sin(x) == y
// Or(x == asin(y), x == Pi - asin(y))
if (eq.a is Sin)
return
new Or(
(eq.a as Sin).args[0] == new Asin(eq.b),
(eq.a as Sin).args[0] == new Symbol("Pi") - new Asin(eq.b))
.IsolateVariable(sym);
// tan(x) == y
// x == atan(t)
if (eq.a is Tan)
return
((eq.a as Tan).args[0] == new Atan(eq.b))
.IsolateVariable(sym);
// asin(x) == y
//
// x == sin(y)
if (eq.a is Asin)
return
((eq.a as Asin).args[0] == new Sin(eq.b))
.IsolateVariable(sym);
throw new Exception();
}
public static MathObject IsolateVariable(this MathObject obj, Symbol sym)
{
if (obj is Or) return Or.FromRange((obj as Or).args.Select(elt => elt.IsolateVariable(sym))).Simplify();
if (obj is And) return And.FromRange((obj as And).args.Select(elt => elt.IsolateVariable(sym))).Simplify();
if (obj is Equation) return (obj as Equation).IsolateVariableEq(sym);
throw new Exception();
}
}
}
================================================
FILE: Symbolism/LeadingCoefficientGpe.cs
================================================
using System.Collections.Generic;
using Symbolism.CoefficientGpe;
using Symbolism.DegreeGpe;
namespace Symbolism
{
namespace LeadingCoefficientGpe
{
public static class Extensions
{
public static MathObject LeadingCoefficientGpe(this MathObject u, MathObject x) =>
u.CoefficientGpe(x, u.DegreeGpe(new List<MathObject>() { x }));
}
}
}
================================================
FILE: Symbolism/LogicalExpand.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism.LogicalExpand
{
public static class Extensions
{
public static MathObject LogicalExpand(this MathObject obj)
{
if (obj is Or)
{
return (obj as Or).Map(elt => elt.LogicalExpand());
}
if (obj is And &&
(obj as And).args.Any(elt => elt is Or) &&
(obj as And).args.Count() > 1)
{
var before = new List<MathObject>();
Or or = null;
var after = new List<MathObject>();
foreach (var elt in (obj as And).args)
{
if (elt is Or && or == null) or = elt as Or;
else if (or == null) before.Add(elt);
else after.Add(elt);
}
return
or.Map(or_elt =>
new And(
And.FromRange(before).Simplify().LogicalExpand(),
or_elt,
And.FromRange(after).Simplify().LogicalExpand()).Simplify()).LogicalExpand();
}
return obj;
}
}
}
================================================
FILE: Symbolism/PolynomialDivision.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.DegreeGpe;
using Symbolism.LeadingCoefficientGpe;
using Symbolism.AlgebraicExpand;
namespace Symbolism
{
namespace PolynomialDivision
{
public static class Extensions
{
public static (MathObject quotient, MathObject remainder) PolynomialDivision(MathObject u, MathObject v, MathObject x)
{
var q = (MathObject)0;
var r = u;
var m = r.DegreeGpe(new List<MathObject> { x });
var n = v.DegreeGpe(new List<MathObject> { x });
var lcv = v.LeadingCoefficientGpe(x);
while (m >= n && r != 0)
{
var lcr = r.LeadingCoefficientGpe(x);
var s = lcr / lcv;
q = q + s * (x ^ (m - n));
r = ((r - (lcr * (x ^ m))) - (v - lcv * (x ^ n)) * s * (x ^ (m - n))).AlgebraicExpand();
m = r.DegreeGpe(new List<MathObject> { x });
}
return (q, r);
}
}
}
}
================================================
FILE: Symbolism/PolynomialGcd.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.LeadingCoefficientGpe;
using Symbolism.AlgebraicExpand;
namespace Symbolism
{
namespace PolynomialGcd
{
using static Symbolism.PolynomialDivision.Extensions;
public static class Extensions
{
public static MathObject PolynomialGcd(MathObject u, MathObject v, MathObject x)
{
if (u == 0 && v == 0) return 0;
var u_ = u;
var v_ = v;
while (true)
{
if (v_ == 0) return (u_ / u_.LeadingCoefficientGpe(x)).AlgebraicExpand();
(u_, v_) = (v_, PolynomialDivision(u_, v_, x).remainder);
}
}
}
}
}
================================================
FILE: Symbolism/RationalExpand.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Symbolism.AlgebraicExpand;
using Symbolism.RationalizeExpression;
namespace Symbolism
{
namespace RationalExpand
{
public static class Extensions
{
public static MathObject RationalExpand(this MathObject u)
{
var f = u.Numerator().AlgebraicExpand();
var g = u.Denominator().AlgebraicExpand();
if (g == 0) return false;
var h = (f / g).RationalizeExpression();
if (h == u) return u;
return h.RationalExpand();
}
}
}
}
================================================
FILE: Symbolism/RationalizeExpression.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism
{
namespace RationalizeExpression
{
public static class Extensions
{
static MathObject RationalizeSum(MathObject u, MathObject v)
{
var m = u.Numerator();
var r = u.Denominator();
var n = v.Numerator();
var s = v.Denominator();
if (r == 1 && s == 1) return u + v;
return RationalizeSum(m * s, n * r) / (r * s);
}
public static MathObject RationalizeExpression(this MathObject u)
{
if (u is Equation)
return new Equation(
(u as Equation).a.RationalizeExpression(),
(u as Equation).b.RationalizeExpression(),
(u as Equation).Operator);
if (u is Power)
return (u as Power).bas.RationalizeExpression() ^ (u as Power).exp;
if (u is Product)
return
(u as Product).Map(elt => elt.RationalizeExpression());
if (u is Sum)
{
var f = (u as Sum).elts[0];
var g = f.RationalizeExpression();
var r = (u - f).RationalizeExpression();
return RationalizeSum(g, r);
}
return u;
}
}
}
}
================================================
FILE: Symbolism/SimplifyEquation.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism.SimplifyEquation
{
public static class Extensions
{
public static MathObject SimplifyEquation(this MathObject expr)
{
// 10 * x == 0 -> x == 0
// 10 * x != 0 -> x == 0
if (expr is Equation &&
(expr as Equation).a is Product &&
((expr as Equation).a as Product).elts.Any(elt => elt is Number) &&
((expr as Equation).b == 0))
return new Equation(
Product.FromRange(((expr as Equation).a as Product).elts.Where(elt => !(elt is Number))).Simplify(),
0,
(expr as Equation).Operator).Simplify();
// x ^ 2 == 0 -> x == 0
// x ^ 2 != 0 -> x == 0
if (expr is Equation &&
(expr as Equation).b == 0 &&
(expr as Equation).a is Power &&
((expr as Equation).a as Power).exp is Integer &&
(((expr as Equation).a as Power).exp as Integer).val > 0)
return ((expr as Equation).a as Power).bas == 0;
if (expr is And) return (expr as And).Map(elt => elt.SimplifyEquation());
if (expr is Or) return (expr as Or).Map(elt => elt.SimplifyEquation());
return expr;
}
}
}
================================================
FILE: Symbolism/SimplifyLogical.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism.SimplifyLogical
{
public static class Extensions
{
static bool HasDuplicates(this IEnumerable<MathObject> ls)
{
foreach (var elt in ls) if (ls.Count(item => item.Equals(elt)) > 1) return true;
return false;
}
static IEnumerable<MathObject> RemoveDuplicates(this IEnumerable<MathObject> seq)
{
var ls = new List<MathObject>();
foreach (var elt in seq)
if (ls.Any(item => item.Equals(elt)) == false)
ls.Add(elt);
return ls;
}
public static MathObject SimplifyLogical(this MathObject expr)
{
if (expr is And && (expr as And).args.HasDuplicates())
return And.FromRange((expr as And).args.RemoveDuplicates());
if (expr is Or && (expr as Or).args.HasDuplicates())
return
Or.FromRange((expr as Or).args.RemoveDuplicates())
.SimplifyLogical();
if (expr is Or) return (expr as Or).Map(elt => elt.SimplifyLogical());
return expr;
}
}
}
================================================
FILE: Symbolism/Substitute.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Symbolism
{
namespace Substitute
{
public static class Extensions
{
public static MathObject Substitute(this MathObject obj, MathObject a, MathObject b)
{
if (obj == a) return b;
if (obj is Equation)
{
if ((obj as Equation).Operator == Equation.Operators.Equal)
return ((obj as Equation).a.Substitute(a, b) == (obj as Equation).b.Substitute(a, b)).Simplify();
if ((obj as Equation).Operator == Equation.Operators.NotEqual)
return ((obj as Equation).a.Substitute(a, b) != (obj as Equation).b.Substitute(a, b)).Simplify();
if ((obj as Equation).Operator == Equation.Operators.LessThan)
return ((obj as Equation).a.Substitute(a, b) < (obj as Equation).b.Substitute(a, b)).Simplify();
if ((obj as Equation).Operator == Equation.Operators.GreaterThan)
return ((obj as Equation).a.Substitute(a, b) > (obj as Equation).b.Substitute(a, b)).Simplify();
throw new Exception();
}
if (obj is Power) return (obj as Power).bas.Substitute(a, b) ^ (obj as Power).exp.Substitute(a, b);
if (obj is Product)
return
(obj as Product).Map(elt => elt.Substitute(a, b));
if (obj is Sum)
return
(obj as Sum).Map(elt => elt.Substitute(a, b));
if (obj is Function)
{
var obj_ = obj as Function;
return new Function(
obj_.name,
obj_.proc,
obj_.args.ConvertAll(arg => arg.Substitute(a, b)))
.Simplify();
}
return obj;
}
public static MathObject SubstituteEq(this MathObject obj, Equation eq) =>
obj.Substitute(eq.a, eq.b);
public static MathObject SubstituteEqLs(this MathObject obj, List<Equation> eqs) =>
eqs.Aggregate(obj, (a, eq) => a.SubstituteEq(eq));
public static MathObject Substitute(this MathObject obj, MathObject a, int b) =>
obj.Substitute(a, new Integer(b));
public static MathObject Substitute(this MathObject obj, MathObject a, double b) =>
obj.Substitute(a, new DoubleFloat(b));
}
}
}
================================================
FILE: Symbolism/Symbolism.cs
================================================
/* Copyright 2013 Eduardo Cavazos
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using static Symbolism.ListConstructor;
namespace Symbolism
{
public abstract class MathObject
{
//////////////////////////////////////////////////////////////////////
public static implicit operator MathObject(int n) => new Integer(n);
public static implicit operator MathObject(BigInteger n) => new Integer(n);
public static implicit operator MathObject(bool val) => new Bool(val);
public static implicit operator MathObject(double val) => new DoubleFloat(val);
//////////////////////////////////////////////////////////////////////
#region overloads for 'int'
public static MathObject operator +(MathObject a, int b) => a + new Integer(b);
public static MathObject operator -(MathObject a, int b) => a - new Integer(b);
public static MathObject operator *(MathObject a, int b) => a * new Integer(b);
public static MathObject operator /(MathObject a, int b) => a / new Integer(b);
public static MathObject operator ^(MathObject a, int b) => a ^ new Integer(b);
public static MathObject operator +(int a, MathObject b) => new Integer(a) + b;
public static MathObject operator -(int a, MathObject b) => new Integer(a) - b;
public static MathObject operator *(int a, MathObject b) => new Integer(a) * b;
public static MathObject operator /(int a, MathObject b) => new Integer(a) / b;
public static MathObject operator ^(int a, MathObject b) => new Integer(a) ^ b;
#endregion
//////////////////////////////////////////////////////////////////////
#region overloads for 'BigInteger'
public static MathObject operator +(MathObject a, BigInteger b) => a + new Integer(b);
public static MathObject operator -(MathObject a, BigInteger b) => a - new Integer(b);
public static MathObject operator *(MathObject a, BigInteger b) => a * new Integer(b);
public static MathObject operator /(MathObject a, BigInteger b) => a / new Integer(b);
public static MathObject operator ^(MathObject a, BigInteger b) => a ^ new Integer(b);
public static MathObject operator +(BigInteger a, MathObject b) => new Integer(a) + b;
public static MathObject operator -(BigInteger a, MathObject b) => new Integer(a) - b;
public static MathObject operator *(BigInteger a, MathObject b) => new Integer(a) * b;
public static MathObject operator /(BigInteger a, MathObject b) => new Integer(a) / b;
public static MathObject operator ^(BigInteger a, MathObject b) => new Integer(a) ^ b;
#endregion
//////////////////////////////////////////////////////////////////////
#region overloads for 'double'
public static MathObject operator +(MathObject a, double b) => a + new DoubleFloat(b);
public static MathObject operator -(MathObject a, double b) => a - new DoubleFloat(b);
public static MathObject operator *(MathObject a, double b) => a * new DoubleFloat(b);
public static MathObject operator /(MathObject a, double b) => a / new DoubleFloat(b);
public static MathObject operator ^(MathObject a, double b) => a ^ new DoubleFloat(b);
public static MathObject operator +(double a, MathObject b) => new DoubleFloat(a) + b;
public static MathObject operator -(double a, MathObject b) => new DoubleFloat(a) - b;
public static MathObject operator *(double a, MathObject b) => new DoubleFloat(a) * b;
public static MathObject operator /(double a, MathObject b) => new DoubleFloat(a) / b;
public static MathObject operator ^(double a, MathObject b) => new DoubleFloat(a) ^ b;
#endregion
//////////////////////////////////////////////////////////////////////
public static Equation operator ==(MathObject a, MathObject b) => new Equation(a, b);
public static Equation operator !=(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.NotEqual);
public static Equation operator <(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.LessThan);
public static Equation operator >(MathObject a, MathObject b) => new Equation(a, b, Equation.Operators.GreaterThan);
public static Equation operator ==(MathObject a, double b) => new Equation(a, new DoubleFloat(b));
public static Equation operator ==(double a, MathObject b) => new Equation(new DoubleFloat(a), b);
public static Equation operator !=(MathObject a, double b) => new Equation(a, new DoubleFloat(b), Equation.Operators.NotEqual);
public static Equation operator !=(double a, MathObject b) => new Equation(new DoubleFloat(a), b, Equation.Operators.NotEqual);
public static Equation operator ==(MathObject a, int b) => new Equation(a, new Integer(b));
public static Equation operator ==(int a, MathObject b) => new Equation(new Integer(a), b);
public static Equation operator !=(MathObject a, int b) => new Equation(a, new Integer(b), Equation.Operators.NotEqual);
public static Equation operator !=(int a, MathObject b) => new Equation(new Integer(a), b, Equation.Operators.NotEqual);
//////////////////////////////////////////////////////////////////////
public static MathObject operator +(MathObject a, MathObject b) => new Sum(a, b).Simplify();
public static MathObject operator -(MathObject a, MathObject b) => new Difference(a, b).Simplify();
public static MathObject operator *(MathObject a, MathObject b) => new Product(a, b).Simplify();
public static MathObject operator /(MathObject a, MathObject b) => new Quotient(a, b).Simplify();
public static MathObject operator ^(MathObject a, MathObject b) => new Power(a, b).Simplify();
public static MathObject operator -(MathObject a) { return new Difference(a).Simplify(); }
// Precedence is used for printing purposes.
// Thus, the precedence values below do not necessarily reflect
// the C# operator precedence values.
// For example, in C#, the precedence of ^ is lower than +.
// But for printing purposes, we'd like ^ to have a
// higher precedence than +.
public int Precedence()
{
if (this is Integer) return 1000;
if (this is DoubleFloat) return 1000;
if (this is Symbol) return 1000;
if (this is Function) return 1000;
if (this is Fraction) return 1000;
if (this is Power) return 130;
if (this is Product) return 120;
if (this is Sum) return 110;
Console.WriteLine(this.GetType().Name);
throw new Exception();
}
public enum ToStringForms { Full, Standard }
public static ToStringForms ToStringForm = ToStringForms.Full;
public virtual string FullForm() => base.ToString();
public virtual string StandardForm() => FullForm();
public override string ToString()
{
if (ToStringForm == ToStringForms.Full) return FullForm();
if (ToStringForm == ToStringForms.Standard) return StandardForm();
throw new Exception();
}
public virtual MathObject Numerator() => this;
public virtual MathObject Denominator() => 1;
public override bool Equals(object obj)
{ throw new Exception("MathObject.Equals called - abstract class"); }
public override int GetHashCode() => base.GetHashCode();
}
public class Equation : MathObject
{
public enum Operators { Equal, NotEqual, LessThan, GreaterThan }
public readonly MathObject a;
public readonly MathObject b;
public Operators Operator;
public Equation(MathObject x, MathObject y)
{ a = x; b = y; Operator = Operators.Equal; }
public Equation(MathObject x, MathObject y, Operators op)
{ a = x; b = y; Operator = op; }
public override string FullForm()
{
if (Operator == Operators.Equal) return a + " == " + b;
if (Operator == Operators.NotEqual) return a + " != " + b;
if (Operator == Operators.LessThan) return a + " < " + b;
if (Operator == Operators.GreaterThan) return a + " > " + b;
throw new Exception();
}
public override bool Equals(object obj) =>
obj is Equation &&
a.Equals((obj as Equation).a) &&
b.Equals((obj as Equation).b) &&
Operator == (obj as Equation).Operator;
Boolean ToBoolean()
{
if (a is Bool && b is Bool) return (a as Bool).Equals(b);
if (a is Equation && b is Equation) return (a as Equation).Equals(b);
if (a is Integer && b is Integer) return ((Integer)a).Equals(b);
if (a is DoubleFloat && b is DoubleFloat) return ((DoubleFloat)a).Equals(b);
if (a is Symbol && b is Symbol) return ((Symbol)a).Equals(b);
if (a is Sum && b is Sum) return ((Sum)a).Equals(b);
if (a is Product && b is Product) return ((Product)a).Equals(b);
if (a is Fraction && b is Fraction) return ((Fraction)a).Equals(b);
if (a is Power && b is Power) return ((Power)a).Equals(b);
if (a is Function && b is Function) return ((Function)a).Equals(b);
if ((((object)a) == null) && (((object)b) == null)) return true;
if (((object)a) == null) return false;
if (((object)b) == null) return false;
if (a.GetType() != b.GetType()) return false;
Console.WriteLine("" + a.GetType() + " " + b.GetType());
throw new Exception();
}
public static implicit operator Boolean(Equation eq)
{
if (eq.Operator == Operators.Equal)
return (eq.a == eq.b).ToBoolean();
if (eq.Operator == Operators.NotEqual)
return !((eq.a == eq.b).ToBoolean());
if (eq.Operator == Operators.LessThan)
if (eq.a is Number && eq.b is Number)
return (eq.a as Number).ToDouble().val < (eq.b as Number).ToDouble().val;
if (eq.Operator == Operators.GreaterThan)
if (eq.a is Number && eq.b is Number)
return (eq.a as Number).ToDouble().val > (eq.b as Number).ToDouble().val;
throw new Exception();
}
public MathObject Simplify()
{
if (a is Number && b is Number) return (bool)this;
return this;
}
public override int GetHashCode() => new { a, b }.GetHashCode();
}
public class Bool : MathObject
{
public readonly bool val;
public Bool(bool b) { val = b; }
public override string FullForm() => val.ToString();
public override bool Equals(object obj) => val == (obj as Bool)?.val;
public override int GetHashCode() => val.GetHashCode();
}
//public class NotEqual
//{
// public MathObject a;
// public MathObject b;
// public NotEqual(MathObject x, MathObject y)
// { a = x; b = y; }
// public static implicit operator Boolean(NotEqual eq)
// { return !((eq.a == eq.b).ToBoolean()); }
//}
public abstract class Number : MathObject
{
public abstract DoubleFloat ToDouble();
}
public class Integer : Number
{
public readonly BigInteger val;
public Integer(int n) { val = n; }
public Integer(BigInteger n) { val = n; }
public static implicit operator Integer(BigInteger n) => new Integer(n);
// public static MathObject operator *(MathObject a, MathObject b) => new Product(a, b).Simplify();
public static Integer operator +(Integer a, Integer b) => a.val + b.val;
public static Integer operator -(Integer a, Integer b) => a.val - b.val;
public static Integer operator *(Integer a, Integer b) => a.val * b.val;
public override string FullForm() => val.ToString();
public override bool Equals(object obj) => val == (obj as Integer)?.val;
public override int GetHashCode() => val.GetHashCode();
public override DoubleFloat ToDouble() => new DoubleFloat((double)val);
}
public class DoubleFloat : Number
{
public static double? tolerance;
public readonly double val;
public DoubleFloat(double n) { val = n; }
public override string FullForm() => val.ToString("R");
//public bool EqualWithinTolerance(DoubleFloat obj)
//{
// if (tolerance.HasValue)
// return Math.Abs(val - obj.val) < tolerance;
// throw new Exception();
//}
public override bool Equals(object obj)
{
if (obj is DoubleFloat && tolerance.HasValue)
return Math.Abs(val - (obj as DoubleFloat).val) < tolerance;
if (obj is DoubleFloat) return val == ((DoubleFloat)obj).val;
return false;
}
public override int GetHashCode() => val.GetHashCode();
public override DoubleFloat ToDouble() => this;
}
public class Fraction : Number
{
public readonly Integer numerator;
public readonly Integer denominator;
public Fraction(Integer a, Integer b)
{ numerator = a; denominator = b; }
public override string FullForm() => numerator + "/" + denominator;
public override DoubleFloat ToDouble() => new DoubleFloat((double)numerator.val / (double)denominator.val);
//////////////////////////////////////////////////////////////////////
public override bool Equals(object obj) =>
numerator == (obj as Fraction)?.numerator
&&
denominator == (obj as Fraction)?.denominator;
public override int GetHashCode() => new { numerator, denominator }.GetHashCode();
public override MathObject Numerator() => numerator;
public override MathObject Denominator() => denominator;
}
public static class Rational
{
static BigInteger Div(BigInteger a, BigInteger b)
{ BigInteger rem; return BigInteger.DivRem(a, b, out rem); }
static BigInteger Rem(BigInteger a, BigInteger b)
{ BigInteger rem; BigInteger.DivRem(a, b, out rem); return rem; }
static BigInteger Gcd(BigInteger a, BigInteger b)
{
BigInteger r;
while (b != 0)
{
r = Rem(a, b);
a = b;
b = r;
}
return BigInteger.Abs(a);
}
public static MathObject SimplifyRationalNumber(MathObject u)
{
if (u is Integer) return u;
if (u is Fraction)
{
var u_ = (Fraction)u;
var n = u_.numerator.val;
var d = u_.denominator.val;
if (Rem(n, d) == 0) return Div(n, d);
var g = Gcd(n, d);
if (d > 0) return new Fraction(Div(n, g), Div(d, g));
if (d < 0) return new Fraction(Div(-n, g), Div(-d, g));
}
throw new Exception();
}
public static Integer Numerator(MathObject u)
{
// (a / b) / (c / d)
// (a / b) * (d / c)
// (a * d) / (b * c)
if (u is Integer) return (Integer)u;
if (u is Fraction)
{
var u_ = u as Fraction;
//return
// Numerator(u_.numerator).val
// *
// Denominator(u_.denominator).val;
return
Numerator(u_.numerator)
*
Denominator(u_.denominator);
}
throw new Exception();
}
public static Integer Denominator(MathObject u)
{
// (a / b) / (c / d)
// (a / b) * (d / c)
// (a * d) / (b * c)
if (u is Integer) return new Integer(1);
if (u is Fraction)
{
var u_ = u as Fraction;
return
Denominator(u_.numerator)
*
Numerator(u_.denominator);
}
throw new Exception();
}
public static Fraction EvaluateSum(MathObject v, MathObject w) =>
// a / b + c / d
// a d / b d + c b / b d
// (a d + c b) / (b d)
new Fraction(
Numerator(v) * Denominator(w) + Numerator(w) * Denominator(v),
Denominator(v) * Denominator(w));
public static Fraction EvaluateDifference(MathObject v, MathObject w) =>
new Fraction(
Numerator(v) * Denominator(w) - Numerator(w) * Denominator(v),
Denominator(v) * Denominator(w));
public static Fraction EvaluateProduct(MathObject v, MathObject w) =>
new Fraction(
Numerator(v) * Numerator(w),
Denominator(v) * Denominator(w));
public static MathObject EvaluateQuotient(MathObject v, MathObject w)
{
if (Numerator(w).val == 0) return new Undefined();
return
new Fraction(
Numerator(v) * Denominator(w),
Numerator(w) * Denominator(v));
}
public static MathObject EvaluatePower(MathObject v, BigInteger n)
{
if (Numerator(v).val != 0)
{
if (n > 0) return EvaluateProduct(EvaluatePower(v, n - 1), v);
if (n == 0) return 1;
if (n == -1) return new Fraction(Denominator(v), Numerator(v));
if (n < -1)
{
var s = new Fraction(Denominator(v), Numerator(v));
return EvaluatePower(s, -n);
}
}
if (n >= 1) return 0;
if (n <= 0) return new Undefined();
throw new Exception();
}
public static MathObject SimplifyRNERec(MathObject u)
{
if (u is Integer) return u;
if (u is Fraction)
if (Denominator((Fraction)u).val == 0) return new Undefined();
else return u;
if (u is Sum && ((Sum)u).elts.Count == 1)
{ return SimplifyRNERec(((Sum)u).elts[0]); }
if (u is Difference && ((Difference)u).elts.Count == 1)
{
var v = SimplifyRNERec(((Difference)u).elts[0]);
if (v == new Undefined()) return v;
return EvaluateProduct(-1, v);
}
if (u is Sum && ((Sum)u).elts.Count == 2)
{
var v = SimplifyRNERec(((Sum)u).elts[0]);
var w = SimplifyRNERec(((Sum)u).elts[1]);
if (v == new Undefined() || w == new Undefined())
return new Undefined();
return EvaluateSum(v, w);
}
if (u is Product && ((Product)u).elts.Count == 2)
{
var v = SimplifyRNERec(((Product)u).elts[0]);
var w = SimplifyRNERec(((Product)u).elts[1]);
if (v == new Undefined() || w == new Undefined())
return new Undefined();
return EvaluateProduct(v, w);
}
if (u is Difference && ((Difference)u).elts.Count == 2)
{
var v = SimplifyRNERec(((Difference)u).elts[0]);
var w = SimplifyRNERec(((Difference)u).elts[1]);
if (v == new Undefined() || w == new Undefined())
return new Undefined();
return EvaluateDifference(v, w);
}
if (u is Fraction)
{
var v = SimplifyRNERec(((Fraction)u).numerator);
var w = SimplifyRNERec(((Fraction)u).denominator);
if (v == new Undefined() || w == new Undefined())
return new Undefined();
return EvaluateQuotient(v, w);
}
if (u is Power)
{
var v = SimplifyRNERec(((Power)u).bas);
if (v == new Undefined()) return v;
return EvaluatePower(v, ((Integer)((Power)u).exp).val);
}
throw new Exception();
}
public static MathObject SimplifyRNE(MathObject u)
{
var v = SimplifyRNERec(u);
if (v is Undefined) return v;
return SimplifyRationalNumber(v);
}
}
public class Undefined : MathObject { }
public static class MiscUtils { }
public class Symbol : MathObject
{
public readonly String name;
public Symbol(String str) { name = str; }
public override string FullForm() => name;
public override int GetHashCode() => name.GetHashCode();
public override bool Equals(Object obj) =>
obj is Symbol ? name == (obj as Symbol).name : false;
}
public static class ListConstructor
{
public static List<T> List<T>(params T[] items) => new List<T>(items);
public static ImmutableList<T> ImList<T>(params T[] items) => ImmutableList.Create(items);
}
public static class ListUtils
{
public static ImmutableList<MathObject> Cons(this ImmutableList<MathObject> obj, MathObject elt) =>
obj.Insert(0, elt);
public static ImmutableList<MathObject> Cdr(this ImmutableList<MathObject> obj) => obj.RemoveAt(0);
public static bool equal(ImmutableList<MathObject> a, ImmutableList<MathObject> b)
{
if (a.Count == 0 && b.Count == 0) return true;
if (a.Count == 0) return false;
if (b.Count == 0) return false;
if (a[0] == b[0]) return equal(a.Cdr(), b.Cdr());
return false;
}
}
public class Function : MathObject
{
public delegate MathObject Proc(params MathObject[] ls);
public readonly String name;
public readonly Proc proc;
public readonly ImmutableList<MathObject> args;
public Function(string name, Proc proc, IEnumerable<MathObject> args)
{
this.name = name;
this.proc = proc;
this.args = ImmutableList.CreateRange(args);
}
public override bool Equals(object obj) =>
GetType() == obj.GetType() &&
name == (obj as Function).name &&
ListUtils.equal(args, ((Function)obj).args);
public MathObject Simplify() => proc == null ? this : proc(args.ToArray());
public override string FullForm() => $"{name}({string.Join(", ", args)})";
public MathObject Clone() => MemberwiseClone() as MathObject;
public override int GetHashCode() => new { name, args }.GetHashCode();
}
public static class FunctionExtensions
{
//public static MathObject Map<T>(this T obj, Func<MathObject, MathObject> proc) where T : Function, new()
//{
// // return new T() { args = obj.args.Select(proc).ToList() }.Simplify();
// // return
//}
}
public class And : Function
{
static MathObject AndProc(MathObject[] ls)
{
if (ls.Count() == 0) return true;
if (ls.Count() == 1) return ls.First();
if (ls.Any(elt => elt == false)) return false;
if (ls.Any(elt => elt == true))
return new And(ls.Where(elt => elt != true).ToArray()).Simplify();
if (ls.Any(elt => elt is And))
{
var items = new List<MathObject>();
foreach (var elt in ls)
{
if (elt is And) items.AddRange((elt as And).args);
else items.Add(elt);
}
return And.FromRange(items).Simplify();
}
return new And(ls);
}
public And(params MathObject[] ls) : base("and", AndProc, ls) { }
public And() : base("and", AndProc, new List<MathObject>()) { }
public static And FromRange(IEnumerable<MathObject> ls) => new And(ls.ToArray());
public MathObject Add(MathObject obj) =>
And.FromRange(args.Add(obj)).Simplify();
public MathObject AddRange(IEnumerable<MathObject> ls) =>
And.FromRange(args.AddRange(ls)).Simplify();
public MathObject Map(Func<MathObject, MathObject> proc) =>
And.FromRange(args.Select(proc)).Simplify();
}
public class Or : Function
{
static MathObject OrProc(params MathObject[] ls)
{
if (ls.Count() == 1) return ls.First();
// 10 || false || 20 -> 10 || 20
if (ls.Any(elt => elt == false))
return Or.FromRange(ls.Where(elt => elt != false)).Simplify();
if (ls.Any(elt => (elt is Bool) && (elt as Bool).val)) return new Bool(true);
if (ls.All(elt => (elt is Bool) && (elt as Bool).val == false)) return new Bool(false);
if (ls.Any(elt => elt is Or))
{
var items = new List<MathObject>();
foreach (var elt in ls)
{
if (elt is Or) items.AddRange((elt as Or).args);
else items.Add(elt);
}
return Or.FromRange(items).Simplify();
}
return new Or(ls);
}
public Or(params MathObject[] ls) : base("or", OrProc, ls) { }
public Or() : base("or", OrProc, new List<MathObject>()) { }
public static Or FromRange(IEnumerable<MathObject> ls) => new Or(ls.ToArray());
public MathObject Map(Func<MathObject, MathObject> proc) => Or.FromRange(args.Select(proc)).Simplify();
}
public static class OrderRelation
{
public static MathObject Base(MathObject u) => u is Power ? (u as Power).bas : u;
public static MathObject Exponent(MathObject u) => u is Power ? (u as Power).exp : 1;
public static MathObject Term(this MathObject u)
{
if (u is Product && ((Product)u).elts[0] is Number)
return Product.FromRange((u as Product).elts.Cdr());
// return (u as Product).Cdr()
if (u is Product) return u;
return new Product(u);
}
public static MathObject Const(this MathObject u) =>
(u is Product && (u as Product).elts[0] is Number) ? (u as Product).elts[0] : 1;
public static bool O3(ImmutableList<MathObject> uElts, ImmutableList<MathObject> vElts)
{
if (uElts.IsEmpty) return true;
if (vElts.IsEmpty) return false;
var u = uElts.First();
var v = vElts.First();
return (!(u == v)) ?
Compare(u, v) :
O3(uElts.Cdr(), vElts.Cdr());
}
public static bool Compare(MathObject u, MathObject v)
{
if (u is DoubleFloat && v is DoubleFloat) return ((DoubleFloat)u).val < ((DoubleFloat)v).val;
// if (u is DoubleFloat && v is Integer) return ((DoubleFloat)u).val < ((Integer)v).val;
if (u is DoubleFloat && v is Integer) return ((DoubleFloat)u).val < ((double)((Integer)v).val);
if (u is DoubleFloat && v is Fraction) return
((DoubleFloat)u).val < ((double)((Fraction)v).numerator.val) / ((double)((Fraction)v).denominator.val);
if (u is Integer && v is DoubleFloat) return ((double)((Integer)u).val) < ((DoubleFloat)v).val;
if (u is Fraction && v is DoubleFloat) return
((double)((Fraction)u).numerator.val) / ((double)((Fraction)u).denominator.val) < ((DoubleFloat)v).val;
if (u is Integer)
return Compare(new Fraction((Integer)u, new Integer(1)), v);
if (v is Integer)
return Compare(u, new Fraction((Integer)v, new Integer(1)));
if (u is Fraction && v is Fraction)
{
var u_ = (Fraction)u;
var v_ = (Fraction)v;
// a / b < c / d
//
// (a d) / (b d) < (c b) / (b d)
return
(u_.numerator.val * v_.denominator.val)
<
(v_.numerator.val * u_.denominator.val);
}
if (u is Symbol && v is Symbol)
return
String.Compare(
((Symbol)u).name,
((Symbol)v).name) < 0;
if (u is Product && v is Product)
return O3(
(u as Product).elts.Reverse(),
(v as Product).elts.Reverse());
if (u is Sum && v is Sum)
return O3(
(u as Sum).elts.Reverse(),
(v as Sum).elts.Reverse());
if (u is Power && v is Power)
{
var u_ = (Power)u;
var v_ = (Power)v;
return (u_.bas == v_.bas) ?
Compare(u_.exp, v_.exp) :
Compare(u_.bas, v_.bas);
}
if (u is Function && v is Function)
{
var u_ = (Function)u;
var v_ = (Function)v;
return u_.name == v_.name ?
O3(u_.args, v_.args) :
String.Compare(u_.name, v_.name) < 0;
}
if (u is Number && !(v is Number)) return true;
if (u is Product &&
(v is Power || v is Sum || v is Function || v is Symbol))
return Compare(u, new Product(v));
if (u is Power && (v is Sum || v is Function || v is Symbol))
return Compare(u, new Power(v, new Integer(1)));
if (u is Sum && (v is Function || v is Symbol))
return Compare(u, new Sum(v));
if (u is Function && v is Symbol)
{
var u_ = (Function)u;
var v_ = (Symbol)v;
return u_.name == v_.name ?
false :
Compare(new Symbol(u_.name), v);
}
return !Compare(v, u);
}
}
public class Power : MathObject
{
public readonly MathObject bas;
public readonly MathObject exp;
public Power(MathObject a, MathObject b) { bas = a; exp = b; }
public override string FullForm() =>
string.Format("{0} ^ {1}",
bas.Precedence() < Precedence() ? $"({bas})" : $"{bas}",
exp.Precedence() < Precedence() ? $"({exp})" : $"{exp}");
public override string StandardForm()
{
// x ^ 1/2 -> sqrt(x)
if (exp == new Integer(1) / new Integer(2)) return $"sqrt({bas})";
return string.Format("{0} ^ {1}",
bas.Precedence() < Precedence() ? $"({bas})" : $"{bas}",
exp.Precedence() < Precedence() ? $"({exp})" : $"{exp}");
}
public override bool Equals(object obj) =>
obj is Power && bas == (obj as Power).bas && exp == (obj as Power).exp;
public MathObject Simplify()
{
var v = bas;
var w = exp;
if (v == 0) return 0;
if (v == 1) return 1;
if (w == 0) return 1;
if (w == 1) return v;
// Logic from MPL/Scheme:
//
//if (v is Integer && w is Integer)
// return
// new Integer(
// (int)Math.Pow(((Integer)v).val, ((Integer)w).val));
// C# doesn't have built-in rationals. So:
// 1 / 3 -> 3 ^ -1 -> 0.333... -> (int)... -> 0
//if (v is Integer && w is Integer && ((Integer)w).val > 1)
// return
// new Integer(
// (int)Math.Pow(((Integer)v).val, ((Integer)w).val));
var n = w;
if ((v is Integer || v is Fraction) && n is Integer)
return Rational.SimplifyRNE(new Power(v, n));
if (v is DoubleFloat && w is Integer)
return new DoubleFloat(Math.Pow(((DoubleFloat)v).val, (double) ((Integer)w).val));
if (v is DoubleFloat && w is Fraction)
return new DoubleFloat(Math.Pow(((DoubleFloat)v).val, ((Fraction)w).ToDouble().val));
if (v is Integer && w is DoubleFloat)
return new DoubleFloat(Math.Pow((double)((Integer)v).val, ((DoubleFloat)w).val));
if (v is Fraction && w is DoubleFloat)
return new DoubleFloat(Math.Pow(((Fraction)v).ToDouble().val, ((DoubleFloat)w).val));
if (v is Power && w is Integer)
{ return ((Power)v).bas ^ (((Power)v).exp * w); }
if (v is Product && w is Integer)
return (v as Product).Map(elt => elt ^ w);
return new Power(v, w);
}
public override MathObject Numerator()
{
if (exp is Integer && exp < 0) return 1;
if (exp is Fraction && exp < 0) return 1;
return this;
}
public override MathObject Denominator()
{
if (exp is Integer && exp < 0) return this ^ -1;
if (exp is Fraction && exp < 0) return this ^ -1;
return 1;
}
public override int GetHashCode() => new { bas, exp }.GetHashCode();
}
public class Product : MathObject
{
public readonly ImmutableList<MathObject> elts;
public Product(params MathObject[] ls) => elts = ImmutableList.Create(ls);
public static Product FromRange(IEnumerable<MathObject> ls) => new Product(ls.ToArray());
public override string FullForm() =>
string.Join(" * ", elts.ConvertAll(elt => elt.Precedence() < Precedence() ? $"({elt})" : $"{elt}"));
public override string StandardForm()
{
if (this.Denominator() == 1)
{
if (this.Const() < 0 && this / this.Const() is Sum) return $"-({this * -1})";
if (this.Const() < 0) return $"-{this * -1}";
return string.Join(" * ",
elts.ConvertAll(elt => elt.Precedence() < Precedence() || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? $"({elt})" : $"{elt}"));
}
var expr_a = this.Numerator();
var expr_b = this.Denominator();
var expr_a_ = expr_a is Sum || (expr_a is Power && (expr_a as Power).exp != new Integer(1) / 2) ? $"({expr_a})" : $"{expr_a}";
var expr_b_ = expr_b is Sum || expr_b is Product || (expr_b is Power && (expr_b as Power).exp != new Integer(1) / 2) ? $"({expr_b})" : $"{expr_b}";
return $"{expr_a_} / {expr_b_}";
}
public override int GetHashCode() => elts.GetHashCode();
public override bool Equals(object obj) =>
obj is Product && ListUtils.equal(elts, (obj as Product).elts);
static ImmutableList<MathObject> MergeProducts(ImmutableList<MathObject> pElts, ImmutableList<MathObject> qElts)
{
if (pElts.Count == 0) return qElts;
if (qElts.Count == 0) return pElts;
var p = pElts[0];
var ps = pElts.Cdr();
var q = qElts[0];
var qs = qElts.Cdr();
var res = RecursiveSimplify(ImList(p, q));
if (res.Count == 0) return MergeProducts(ps, qs);
if (res.Count == 1) return MergeProducts(ps, qs).Cons(res[0]);
if (ListUtils.equal(res, ImList(p, q))) return MergeProducts(ps, qElts).Cons(p);
if (ListUtils.equal(res, ImList(q, p))) return MergeProducts(pElts, qs).Cons(q);
throw new Exception();
}
static ImmutableList<MathObject> SimplifyDoubleNumberProduct(DoubleFloat a, Number b)
{
double val = 0.0;
if (b is DoubleFloat) val = a.val * ((DoubleFloat)b).val;
if (b is Integer) val = a.val * (double)((Integer)b).val;
if (b is Fraction) val = a.val * ((Fraction)b).ToDouble().val;
if (val == 1.0) return ImmutableList.Create<MathObject>();
return ImList<MathObject>(new DoubleFloat(val));
}
public static ImmutableList<MathObject> RecursiveSimplify(ImmutableList<MathObject> elts)
{
if (elts.Count == 2)
{
if (elts[0] is Product && elts[1] is Product)
return MergeProducts(
((Product)elts[0]).elts,
((Product)elts[1]).elts);
if (elts[0] is Product) return MergeProducts(((Product)elts[0]).elts, ImList(elts[1]));
if (elts[1] is Product) return MergeProducts(ImList(elts[0]), ((Product)elts[1]).elts);
//////////////////////////////////////////////////////////////////////
if (elts[0] is DoubleFloat && elts[1] is Number)
return SimplifyDoubleNumberProduct((DoubleFloat)elts[0], (Number)elts[1]);
if (elts[0] is Number && elts[1] is DoubleFloat)
return SimplifyDoubleNumberProduct((DoubleFloat)elts[1], (Number)elts[0]);
//////////////////////////////////////////////////////////////////////
if ((elts[0] is Integer || elts[0] is Fraction)
&&
(elts[1] is Integer || elts[1] is Fraction))
{
var P = Rational.SimplifyRNE(new Product(elts[0], elts[1]));
if (P == 1) return ImmutableList.Create<MathObject>();
return ImList(P);
}
if (elts[0] == 1) return ImList(elts[1]);
if (elts[1] == 1) return ImList(elts[0]);
var p = elts[0];
var q = elts[1];
if (OrderRelation.Base(p) == OrderRelation.Base(q))
{
var res = OrderRelation.Base(p) ^ (OrderRelation.Exponent(p) + OrderRelation.Exponent(q));
if (res == 1) return ImmutableList.Create<MathObject>();
return ImList(res);
}
if (OrderRelation.Compare(q, p)) return ImList(q, p);
return ImList(p, q);
}
if (elts[0] is Product)
return
MergeProducts(
((Product)elts[0]).elts,
RecursiveSimplify(elts.Cdr()));
return MergeProducts(
ImList(elts[0]),
RecursiveSimplify(elts.Cdr()));
throw new Exception();
}
public MathObject Simplify()
{
if (elts.Count == 1) return elts[0];
if (elts.Any(elt => elt == 0)) return 0;
var res = RecursiveSimplify(elts);
if (res.IsEmpty) return 1;
if (res.Count == 1) return res[0];
// Without the below, the following throws an exception:
// sqrt(a * b) * (sqrt(a * b) / a) / c
if (res.Any(elt => elt is Product)) return Product.FromRange(res).Simplify();
return Product.FromRange(res);
}
public override MathObject Numerator() =>
Product.FromRange(elts.Select(elt => elt.Numerator())).Simplify();
public override MathObject Denominator() =>
Product.FromRange(elts.Select(elt => elt.Denominator())).Simplify();
public MathObject Map(Func<MathObject, MathObject> proc) =>
Product.FromRange(elts.Select(proc)).Simplify();
}
public class Sum : MathObject
{
public readonly ImmutableList<MathObject> elts;
public Sum(params MathObject[] ls) { elts = ImmutableList.Create(ls); }
public static Sum FromRange(IEnumerable<MathObject> ls) => new Sum(ls.ToArray());
public override int GetHashCode() => elts.GetHashCode();
public override bool Equals(object obj) =>
obj is Sum && ListUtils.equal(elts, (obj as Sum).elts);
static ImmutableList<MathObject> MergeSums(ImmutableList<MathObject> pElts, ImmutableList<MathObject> qElts)
{
if (pElts.Count == 0) return qElts;
if (qElts.Count == 0) return pElts;
var p = pElts[0];
var ps = pElts.Cdr();
var q = qElts[0];
var qs = qElts.Cdr();
var res = RecursiveSimplify(ImList(p, q));
if (res.Count == 0) return MergeSums(ps, qs);
if (res.Count == 1) return MergeSums(ps, qs).Cons(res[0]);
if (ListUtils.equal(res, ImList(p, q))) return MergeSums(ps, qElts).Cons(p);
if (ListUtils.equal(res, ImList(q, p))) return MergeSums(pElts, qs).Cons(q);
throw new Exception();
}
static ImmutableList<MathObject> SimplifyDoubleNumberSum(DoubleFloat a, Number b)
{
double val = 0.0;
if (b is DoubleFloat) val = a.val + ((DoubleFloat)b).val;
if (b is Integer) val = a.val + (double)((Integer)b).val;
if (b is Fraction) val = a.val + ((Fraction)b).ToDouble().val;
if (val == 0.0) return ImmutableList.Create<MathObject>();
return ImmutableList.Create<MathObject>(new DoubleFloat(val));
}
static ImmutableList<MathObject> RecursiveSimplify(ImmutableList<MathObject> elts)
{
if (elts.Count == 2)
{
if (elts[0] is Sum && elts[1] is Sum)
return MergeSums(
((Sum)elts[0]).elts,
((Sum)elts[1]).elts);
if (elts[0] is Sum)
return MergeSums(
((Sum)elts[0]).elts,
ImList(elts[1]));
if (elts[1] is Sum)
return MergeSums(
ImList(elts[0]),
((Sum)elts[1]).elts);
//////////////////////////////////////////////////////////////////////
if (elts[0] is DoubleFloat && elts[1] is Number)
return SimplifyDoubleNumberSum((DoubleFloat)elts[0], (Number)elts[1]);
if (elts[0] is Number && elts[1] is DoubleFloat)
return SimplifyDoubleNumberSum((DoubleFloat)elts[1], (Number)elts[0]);
//////////////////////////////////////////////////////////////////////
if ((elts[0] is Integer || elts[0] is Fraction)
&&
(elts[1] is Integer || elts[1] is Fraction))
{
var P = Rational.SimplifyRNE(new Sum(elts[0], elts[1]));
if (P == 0) return ImmutableList.Create<MathObject>();
return ImList(P);
}
if (elts[0] == 0) return ImList(elts[1]);
if (elts[1] == 0) return ImList(elts[0]);
var p = elts[0];
var q = elts[1];
if (p.Term() == q.Term())
{
var res = p.Term() * (p.Const() + q.Const());
if (res == 0) return ImmutableList.Create<MathObject>();
return ImList(res);
}
if (OrderRelation.Compare(q, p)) return ImList(q, p);
return ImList(p, q);
}
if (elts[0] is Sum)
return
MergeSums(
((Sum)elts[0]).elts, RecursiveSimplify(elts.Cdr()));
return MergeSums(
ImList(elts[0]), RecursiveSimplify(elts.Cdr()));
}
public MathObject Simplify()
{
if (elts.Count == 1) return elts[0];
var res = RecursiveSimplify(elts);
if (res.Count == 0) return 0;
if (res.Count == 1) return res[0];
return Sum.FromRange(res);
}
public override string FullForm() =>
String.Join(" + ", elts.ConvertAll(elt => elt.Precedence() < Precedence() ? $"({elt})" : $"{elt}"));
public override string StandardForm()
{
var result = string.Join(" ",
elts
.ConvertAll(elt =>
{
var elt_ = elt.Const() < 0 ? elt * -1 : elt;
var elt__ = elt.Const() < 0 && elt_ is Sum || (elt is Power && (elt as Power).exp != new Integer(1) / 2) ? $"({elt_})" : $"{elt_}";
return elt.Const() < 0 ? $"- {elt__}" : $"+ {elt__}";
}));
if (result.StartsWith("+ ")) return result.Remove(0, 2); // "+ x + y" -> "x + y"
if (result.StartsWith("- ")) return result.Remove(1, 1); // "- x + y" -> "-x + y"
return result;
}
public MathObject Map(Func<MathObject, MathObject> proc) =>
Sum.FromRange(elts.Select(proc)).Simplify();
}
class Difference : MathObject
{
public readonly ImmutableList<MathObject> elts;
public Difference(params MathObject[] ls) => elts = ImmutableList.Create(ls);
public MathObject Simplify()
{
if (elts.Count == 1) return -1 * elts[0];
if (elts.Count == 2) return elts[0] + -1 * elts[1];
throw new Exception();
}
}
class Quotient : MathObject
{
public readonly ImmutableList<MathObject> elts;
public Quotient(params MathObject[] ls) => elts = ImmutableList.Create(ls);
public MathObject Simplify() => elts[0] * (elts[1] ^ -1);
}
public static class Constructors
{
public static MathObject sqrt(MathObject obj) => obj ^ (new Integer(1) / new Integer(2));
public static MathObject and(params MathObject[] ls) => And.FromRange(ls).Simplify();
public static MathObject or(params MathObject[] ls) => Or.FromRange(ls).Simplify();
}
}
================================================
FILE: Symbolism/Symbolism.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Symbolism</PackageId>
<Version>1.0.4</Version>
<Authors>Eduardo Cavazos</Authors>
<Company>dharmatech</Company>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Description>Computer Algebra Library for C#</Description>
<PackageProjectUrl>https://github.com/dharmatech/Symbolism</PackageProjectUrl>
<RepositoryUrl>https://github.com/dharmatech/Symbolism</RepositoryUrl>
<PackageTags>computer-algebra;symbolic-mathematics</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="1.5.0" />
<PackageReference Include="System.Runtime.Numerics" Version="4.3.0" />
</ItemGroup>
</Project>
================================================
FILE: Symbolism/Trigonometric.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static Symbolism.ListConstructor;
using static Symbolism.Trigonometric.Constructors;
namespace Symbolism.Trigonometric
{
public class Sin : Function
{
public static MathObject Mod(MathObject x, MathObject y)
{
if (x is Number && y is Number)
{
var result = Convert.ToInt32(Math.Floor(((x / y) as Number).ToDouble().val));
return x - y * result;
}
throw new Exception();
}
static MathObject SinProc(params MathObject[] ls)
{
var Pi = new Symbol("Pi");
var half = new Integer(1) / 2;
var u = ls[0];
if (u == 0) return 0;
if (u == Pi) return 0;
if (u is DoubleFloat)
return new DoubleFloat(Math.Sin(((DoubleFloat)u).val));
if (u is Number && u < 0) return -sin(-u);
if (u is Product &&
(u as Product).elts[0] is Number &&
(u as Product).elts[0] < 0)
return -sin(-u);
if (u is Product &&
((u as Product).elts[0] is Integer || (u as Product).elts[0] is Fraction) &&
(u as Product).elts[0] > half &&
(u as Product).elts[1] == Pi)
{
var n = (u as Product).elts[0];
if (n > 2) return sin(Mod(n, 2) * Pi);
if (n > 1) return -sin(n * Pi - Pi);
if (n > half) return sin((1 - n) * Pi);
return new Sin(n * Pi);
}
// sin(k/n pi)
// n is one of 1 2 3 4 6
if (u is Product &&
List<MathObject>(1, 2, 3, 4, 6).Any(elt =>
elt == (u as Product).elts[0].Denominator()) &&
(u as Product).elts[0].Numerator() is Integer &&
(u as Product).elts[1] == Pi)
{
var k = (u as Product).elts[0].Numerator();
var n = (u as Product).elts[0].Denominator();
if (n == 1) return 0;
if (n == 2)
{
if (Mod(k, 4) == 1) return 1;
if (Mod(k, 4) == 3) return -1;
}
if (n == 3)
{
if (Mod(k, 6) == 1) return (3 ^ half) / 2;
if (Mod(k, 6) == 2) return (3 ^ half) / 2;
if (Mod(k, 6) == 4) return -(3 ^ half) / 2;
if (Mod(k, 6) == 5) return -(3 ^ half) / 2;
}
if (n == 4)
{
if (Mod(k, 8) == 1) return 1 / (2 ^ half);
if (Mod(k, 8) == 3) return 1 / (2 ^ half);
if (Mod(k, 8) == 5) return -1 / (2 ^ half);
if (Mod(k, 8) == 7) return -1 / (2 ^ half);
}
if (n == 6)
{
if (Mod(k, 12) == 1) return half;
if (Mod(k, 12) == 5) return half;
if (Mod(k, 12) == 7) return -half;
if (Mod(k, 12) == 11) return -half;
}
}
// sin(Pi + x + y + ...) -> -sin(x + y + ...)
if (u is Sum && (u as Sum).elts.Any(elt => elt == Pi))
return -sin(u - Pi);
// sin(x + n pi)
Func<MathObject, bool> Product_n_Pi = elt =>
(elt is Product) &&
(
(elt as Product).elts[0] is Integer ||
(elt as Product).elts[0] is Fraction
) &&
Math.Abs(((elt as Product).elts[0] as Number).ToDouble().val) >= 2.0 &&
(elt as Product).elts[1] == Pi;
if (u is Sum && (u as Sum).elts.Any(Product_n_Pi))
{
var pi_elt = (u as Sum).elts.First(Product_n_Pi);
var n = (pi_elt as Product).elts[0];
return sin((u - pi_elt) + Mod(n, 2) * Pi);
}
// sin(a + b + ... + n/2 * Pi)
Func<MathObject, bool> Product_n_div_2_Pi = elt =>
elt is Product &&
(
(elt as Product).elts[0] is Integer ||
(elt as Product).elts[0] is Fraction
) &&
(elt as Product).elts[0].Denominator() == 2 &&
(elt as Product).elts[1] == Pi;
if (u is Sum && (u as Sum).elts.Any(Product_n_div_2_Pi))
{
var n_div_2_Pi = (u as Sum).elts.First(Product_n_div_2_Pi);
var other_elts = u - n_div_2_Pi;
var n = (n_div_2_Pi as Product).elts[0].Numerator();
if (Mod(n, 4) == 1) return new Cos(other_elts);
if (Mod(n, 4) == 3) return -new Cos(other_elts);
}
return new Sin(u);
}
public Sin(MathObject param) : base("sin", SinProc, new[] { param }) { }
}
public class Cos : Function
{
public static MathObject Mod(MathObject x, MathObject y)
{
if (x is Number && y is Number)
{
var result = Convert.ToInt32(Math.Floor(((x / y) as Number).ToDouble().val));
return x - y * result;
}
throw new Exception();
}
static MathObject CosProc(params MathObject[] ls)
{
var Pi = new Symbol("Pi");
var half = new Integer(1) / 2;
var u = ls[0];
if (ls[0] == 0) return 1;
if (ls[0] == new Symbol("Pi")) return -1;
if (ls[0] is DoubleFloat)
return new DoubleFloat(Math.Cos(((DoubleFloat)ls[0]).val));
if (ls[0] is Number && ls[0] < 0) return new Cos(-ls[0]);
if (ls[0] is Product &&
(ls[0] as Product).elts[0] is Number &&
((ls[0] as Product).elts[0] as Number) < 0)
return new Cos(-ls[0]).Simplify();
// cos(a/b * Pi)
// a/b > 1/2
if (ls[0] is Product &&
(
(ls[0] as Product).elts[0] is Integer ||
(ls[0] as Product).elts[0] is Fraction
) &&
((ls[0] as Product).elts[0] as Number) > new Integer(1) / 2 &&
(ls[0] as Product).elts[1] == Pi
)
{
var n = (ls[0] as Product).elts[0];
if (n > 2) return cos(Mod(n, 2) * Pi);
if (n > 1) return -cos(n * Pi - Pi);
if (n > half) return -cos(Pi - n * Pi);
return new Cos(n * Pi);
}
// cos(k/n Pi)
// n is one of 1 2 3 4 6
if (ls[0] is Product &&
List<MathObject>(1, 2, 3, 4, 6)
.Any(elt => elt == (ls[0] as Product).elts[0].Denominator()) &&
(ls[0] as Product).elts[0].Numerator() is Integer &&
(ls[0] as Product).elts[1] == Pi
)
{
var k = (ls[0] as Product).elts[0].Numerator();
var n = (ls[0] as Product).elts[0].Denominator();
if (n == 1)
{
if (Mod(k, 2) == 1) return -1;
if (Mod(k, 2) == 0) return 1;
}
if (n == 2)
{
if (Mod(k, 2) == 1) return 0;
}
if (n == 3)
{
if (Mod(k, 6) == 1) return half;
if (Mod(k, 6) == 5) return half;
if (Mod(k, 6) == 2) return -half;
if (Mod(k, 6) == 4) return -half;
}
if (n == 4)
{
if (Mod(k, 8) == 1) return 1 / (2 ^ half);
if (Mod(k, 8) == 7) return 1 / (2 ^ half);
if (Mod(k, 8) == 3) return -1 / (2 ^ half);
if (Mod(k, 8) == 5) return -1 / (2 ^ half);
}
if (n == 6)
{
if (Mod(k, 12) == 1) return (3 ^ half) / 2;
if (Mod(k, 12) == 11) return (3 ^ half) / 2;
if (Mod(k, 12) == 5) return -(3 ^ half) / 2;
if (Mod(k, 12) == 7) return -(3 ^ half) / 2;
}
}
// cos(Pi + x + y + ...) -> -cos(x + y + ...)
if (u is Sum && (u as Sum).elts.Any(elt => elt == Pi))
return -cos(u - Pi);
// cos(n Pi + x + y)
// n * Pi where n is Exact && abs(n) >= 2
Func<MathObject, bool> Product_n_Pi = elt =>
(elt is Product) &&
(
(elt as Product).elts[0] is Integer ||
(elt as Product).elts[0] is Fraction
) &&
Math.Abs(((elt as Product).elts[0] as Number).ToDouble().val) >= 2.0 &&
(elt as Product).elts[1] == Pi;
if (ls[0] is Sum && (ls[0] as Sum).elts.Any(Product_n_Pi))
{
var pi_elt = (ls[0] as Sum).elts.First(Product_n_Pi);
var n = (pi_elt as Product).elts[0];
return cos((ls[0] - pi_elt) + Mod(n, 2) * Pi);
}
Func<MathObject, bool> Product_n_div_2_Pi = elt =>
elt is Product &&
(
(elt as Product).elts[0] is Integer ||
(elt as Product).elts[0] is Fraction
) &&
(elt as Product).elts[0].Denominator() == 2 &&
(elt as Product).elts[1] == Pi;
// cos(a + b + ... + n/2 * Pi) -> sin(a + b + ...)
if (ls[0] is Sum && (ls[0] as Sum).elts.Any(Product_n_div_2_Pi))
{
var n_div_2_Pi = (ls[0] as Sum).elts.First(Product_n_div_2_Pi);
var other_elts = ls[0] - n_div_2_Pi;
var n = (n_div_2_Pi as Product).elts[0].Numerator();
if (Mod(n, 4) == 1) return -new Sin(other_elts);
if (Mod(n, 4) == 3) return new Sin(other_elts);
}
return new Cos(ls[0]);
}
public Cos(MathObject param) : base("cos", CosProc, new[] { param }) { }
}
public class Tan : Function
{
static MathObject TanProc(params MathObject[] ls)
{
if (ls[0] is DoubleFloat)
return new DoubleFloat(Math.Tan(((DoubleFloat)ls[0]).val));
return new Tan(ls[0]);
}
public Tan(MathObject param) : base("tan", TanProc, new[] { param }) { }
}
public class Asin : Function
{
static MathObject AsinProc(params MathObject[] ls)
{
if (ls[0] is DoubleFloat)
return new DoubleFloat(Math.Asin(((DoubleFloat)ls[0]).val));
return new Asin(ls[0]);
}
public Asin(MathObject param) : base("asin", AsinProc, new[] { param }) { }
}
public class Atan : Function
{
static MathObject AtanProc(params MathObject[] ls)
{
if (ls[0] is DoubleFloat)
return new DoubleFloat(Math.Atan(((DoubleFloat)ls[0]).val));
return new Atan(ls[0]);
}
public Atan(MathObject param) : base("atan", AtanProc, new[] { param }) { }
}
public class Atan2 : Function
{
static MathObject Atan2Proc(params MathObject[] ls)
{
//if (
// (ls[0] is DoubleFloat || ls[0] is Integer)
// &&
// (ls[1] is DoubleFloat || ls[1] is Integer)
// )
// return new DoubleFloat(
// Math.Atan2(
// (ls[0] as Number).ToDouble().val,
// (ls[1] as Number).ToDouble().val));
if (ls[0] is DoubleFloat && ls[1] is DoubleFloat)
return new DoubleFloat(
Math.Atan2(
((DoubleFloat)ls[0]).val,
((DoubleFloat)ls[1]).val));
if (ls[0] is Integer && ls[1] is DoubleFloat)
return new DoubleFloat(
Math.Atan2(
(double)((Integer)ls[0]).val,
((DoubleFloat)ls[1]).val));
if (ls[0] is DoubleFloat && ls[1] is Integer)
return new DoubleFloat(
Math.Atan2(
((DoubleFloat)ls[0]).val,
(double)((Integer)ls[1]).val));
if (ls[0] is Integer && ls[1] is Integer)
return new DoubleFloat(
Math.Atan2(
(double)((Integer)ls[0]).val,
(double)((Integer)ls[1]).val));
return new Atan2(ls[0], ls[1]);
}
public Atan2(MathObject a, MathObject b) : base("atan2", Atan2Proc, new[] { a, b }) { }
}
public static class Constructors
{
public static MathObject sin(MathObject obj) => new Sin(obj).Simplify();
public static MathObject cos(MathObject obj) => new Cos(obj).Simplify();
public static MathObject tan(MathObject obj) => new Tan(obj).Simplify();
public static MathObject asin(MathObject obj) => new Asin(obj).Simplify();
public static MathObject atan(MathObject obj) => new Atan(obj).Simplify();
}
public static class Extensions
{
public static Symbol Pi = new Symbol("Pi");
public static MathObject ToRadians(this MathObject n) => n * Pi / 180;
public static MathObject ToDegrees(this MathObject n) => 180 * n / Pi;
public static MathObject ToRadians(this int n) => new Integer(n) * Pi / 180;
public static MathObject ToDegrees(this int n) => 180 * new Integer(n) / Pi;
// (Integer) 180 * n / Pi
}
}
================================================
FILE: Symbolism/Utils.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace Symbolism.Utils
{
public static class Extensions
{
public static T Disp<T>(this T obj)
{
Console.WriteLine(obj);
return obj;
}
public static T Disp<T>(this T obj, string format)
{
Console.WriteLine(string.Format(format, obj));
return obj;
}
public static MathObject DispLong(this MathObject obj, int indent = 0, bool comma = false)
{
if (obj is Or || obj is And)
{
Console.WriteLine(new String(' ', indent) + (obj as Function).name + "(");
var i = 0;
foreach (var elt in (obj as Function).args)
{
if (i < (obj as Function).args.Count - 1)
elt.DispLong(indent + 2, comma: true);
else
elt.DispLong(indent + 2);
i++;
}
Console.WriteLine(new String(' ', indent) + ")" + (comma ? "," : ""));
}
else Console.WriteLine(new String(' ', indent) + obj + (comma ? "," : ""));
return obj;
}
}
}
================================================
FILE: Symbolism.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28922.388
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Symbolism", "Symbolism\Symbolism.csproj", "{9CC7DD8E-6B95-4043-AEEF-E869AF263C2E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{190D8FCC-CEAB-4A96-8581-063140DDC3AD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9CC7DD8E-6B95-4043-AEEF-E869AF263C2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9CC7DD8E-6B95-4043-AEEF-E869AF263C2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9CC7DD8E-6B95-4043-AEEF-E869AF263C2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9CC7DD8E-6B95-4043-AEEF-E869AF263C2E}.Release|Any CPU.Build.0 = Release|Any CPU
{190D8FCC-CEAB-4A96-8581-063140DDC3AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{190D8FCC-CEAB-4A96-8581-063140DDC3AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{190D8FCC-CEAB-4A96-8581-063140DDC3AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{190D8FCC-CEAB-4A96-8581-063140DDC3AD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F3C1383-76DC-4249-9DD3-5D76D1E48DC7}
EndGlobalSection
EndGlobal
================================================
FILE: Tests/Tests.cs
================================================
/* Copyright 2013 Eduardo Cavazos
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Symbolism;
using Symbolism.Has;
using Symbolism.Substitute;
using Symbolism.SimplifyLogical;
using Symbolism.LogicalExpand;
using Symbolism.SimplifyEquation;
using Symbolism.DegreeGpe;
using Symbolism.CoefficientGpe;
using Symbolism.AlgebraicExpand;
using Symbolism.IsolateVariable;
using Symbolism.EliminateVariable;
using Symbolism.RationalExpand;
using Symbolism.LeadingCoefficientGpe;
using Symbolism.Trigonometric;
using Symbolism.DeepSelect;
using Symbolism.RationalizeExpression;
using static Symbolism.Constructors;
using static Symbolism.Trigonometric.Constructors;
using static Symbolism.PolynomialDivision.Extensions;
using static Symbolism.PolynomialGcd.Extensions;
namespace SymbolismTests
{
public static class Extensions
{
// public static void AssertEqTo(this MathObject a, MathObject b) => Assert.True(a == b);
public static MathObject AssertEqTo(this MathObject a, MathObject b)
{
Assert.True(a == b);
return a;
}
public static MathObject MultiplyBothSidesBy(this MathObject obj, MathObject item)
{
//if (obj is Equation)
// return (obj as Equation).a * item == (obj as Equation).b * item;
if (obj is Equation)
return new Equation(
(obj as Equation).a * item,
(obj as Equation).b * item,
(obj as Equation).Operator);
if (obj is And) return (obj as And).Map(elt => elt.MultiplyBothSidesBy(item));
throw new Exception();
}
public static MathObject AddToBothSides(this MathObject obj, MathObject item)
{
if (obj is Equation)
return (obj as Equation).a + item == (obj as Equation).b + item;
throw new Exception();
}
}
public class Obj2
{
public Symbol ΣFx;
public Symbol ΣFy;
public Symbol m;
public Symbol ax;
public Symbol ay;
public Symbol F1, F2;
public Symbol th1, th2;
public Symbol F1x, F2x;
public Symbol F1y, F2y;
public Obj2(string name)
{
ΣFx = new Symbol($"{name}.ΣFx");
ΣFy = new Symbol($"{name}.ΣFy");
m = new Symbol($"{name}.m");
ax = new Symbol($"{name}.ax");
ay = new Symbol($"{name}.ay");
F1 = new Symbol($"{name}.F1");
F2 = new Symbol($"{name}.F2");
th1 = new Symbol($"{name}.th1");
th2 = new Symbol($"{name}.th2");
F1x = new Symbol($"{name}.F1x");
F2x = new Symbol($"{name}.F2x");
F1y = new Symbol($"{name}.F1y");
F2y = new Symbol($"{name}.F2y");
}
public And Equations()
{
return new And(
F1x == F1 * cos(th1),
F1y == F1 * sin(th1),
F2x == F2 * cos(th2),
F2y == F2 * sin(th2),
ΣFx == F1x + F2x,
ΣFx == m * ax,
ΣFy == F1y + F2y,
ΣFy == m * ay
);
}
}
public class Obj3
{
public Symbol ΣFx;
public Symbol ΣFy;
public Symbol m;
public Symbol ax;
public Symbol ay;
public Symbol F1, F2, F3;
public Symbol th1, th2, th3;
public Symbol F1x, F2x, F3x;
public Symbol F1y, F2y, F3y;
public Obj3(string name)
{
ΣFx = new Symbol($"{name}.ΣFx");
ΣFy = new Symbol($"{name}.ΣFy");
m = new Symbol($"{name}.m");
ax = new Symbol($"{name}.ax");
ay = new Symbol($"{name}.ay");
F1 = new Symbol($"{name}.F1");
F2 = new Symbol($"{name}.F2");
F3 = new Symbol($"{name}.F3");
th1 = new Symbol($"{name}.th1");
th2 = new Symbol($"{name}.th2");
th3 = new Symbol($"{name}.th3");
F1x = new Symbol($"{name}.F1x");
F2x = new Symbol($"{name}.F2x");
F3x = new Symbol($"{name}.F3x");
F1y = new Symbol($"{name}.F1y");
F2y = new Symbol($"{name}.F2y");
F3y = new Symbol($"{name}.F3y");
}
public And Equations()
{
return new And(
F1x == F1 * cos(th1),
F1y == F1 * sin(th1),
F2x == F2 * cos(th2),
F2y == F2 * sin(th2),
F3x == F3 * cos(th3),
F3y == F3 * sin(th3),
ΣFx == F1x + F2x + F3x,
ΣFx == m * ax,
ΣFy == F1y + F2y + F3y,
ΣFy == m * ay
);
}
}
public class Obj5
{
public Symbol ΣFx;
public Symbol ΣFy;
public Symbol m;
public Symbol ax;
public Symbol ay;
public Symbol F1, F2, F3, F4, F5;
public Symbol th1, th2, th3, th4, th5;
public Symbol F1x, F2x, F3x, F4x, F5x;
public Symbol F1y, F2y, F3y, F4y, F5y;
public Obj5(string name)
{
ΣFx = new Symbol($"{name}.ΣFx");
ΣFy = new Symbol($"{name}.ΣFy");
m = new Symbol($"{name}.m");
ax = new Symbol($"{name}.ax");
ay = new Symbol($"{name}.ay");
F1 = new Symbol($"{name}.F1");
F2 = new Symbol($"{name}.F2");
F3 = new Symbol($"{name}.F3");
F4 = new Symbol($"{name}.F4");
F5 = new Symbol($"{name}.F5");
th1 = new Symbol($"{name}.th1");
th2 = new Symbol($"{name}.th2");
th3 = new Symbol($"{name}.th3");
th4 = new Symbol($"{name}.th4");
th5 = new Symbol($"{name}.th5");
F1x = new Symbol($"{name}.F1x");
F2x = new Symbol($"{name}.F2x");
F3x = new Symbol($"{name}.F3x");
F4x = new Symbol($"{name}.F4x");
F5x = new Symbol($"{name}.F5x");
F1y = new Symbol($"{name}.F1y");
F2y = new Symbol($"{name}.F2y");
F3y = new Symbol($"{name}.F3y");
F4y = new Symbol($"{name}.F4y");
F5y = new Symbol($"{name}.F5y");
}
public And Equations()
{
return new And(
F1x == F1 * cos(th1),
F1y == F1 * sin(th1),
F2x == F2 * cos(th2),
F2y == F2 * sin(th2),
F3x == F3 * cos(th3),
F3y == F3 * sin(th3),
F4x == F4 * cos(th4),
F4y == F4 * sin(th4),
F5x == F5 * cos(th5),
F5y == F5 * sin(th5),
ΣFx == F1x + F2x + F3x + F4x + F5x,
ΣFx == m * ax,
ΣFy == F1y + F2y + F3y + F4y + F5y,
ΣFy == m * ay
);
}
}
public class KinematicObjectABC
{
public Symbol xA, yA, vxA, vyA, vA, thA;
public Symbol xB, yB, vxB, vyB, vB, thB;
public Symbol xC, yC, vxC, vyC, vC, thC;
public Symbol tAB, tBC, tAC;
public Symbol ax, ay;
public KinematicObjectABC(string name)
{
xA = new Symbol($"{name}.xA");
yA = new Symbol($"{name}.yA");
vxA = new Symbol($"{name}.vxA");
vyA = new Symbol($"{name}.vyA");
vA = new Symbol($"{name}.vA");
thA = new Symbol($"{name}.thA");
xB = new Symbol($"{name}.xB");
yB = new Symbol($"{name}.yB");
vxB = new Symbol($"{name}.vxB");
vyB = new Symbol($"{name}.vyB");
vB = new Symbol($"{name}.vB");
thB = new Symbol($"{name}.thB");
xC = new Symbol($"{name}.xC");
yC = new Symbol($"{name}.yC");
vxC = new Symbol($"{name}.vxC");
vyC = new Symbol($"{name}.vyC");
vC = new Symbol($"{name}.vC");
thC = new Symbol($"{name}.thC");
tAB = new Symbol($"{name}.tAB");
tBC = new Symbol($"{name}.tBC");
tAC = new Symbol($"{name}.tAC");
ax = new Symbol($"{name}.ax");
ay = new Symbol($"{name}.ay");
}
public And EquationsAB() =>
new And(
vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,
xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
);
public And EquationsBC() =>
new And(
vxC == vxB + ax * tBC,
vyC == vyB + ay * tBC,
xC == xB + vxB * tBC + ax * (tBC ^ 2) / 2,
yC == yB + vyB * tBC + ay * (tBC ^ 2) / 2
);
public And EquationsAC() =>
new And(
vxC == vxA + ax * tAC,
vyC == vyA + ay * tAC,
xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2
);
public And TrigEquationsA() =>
new And(
vxA == vA * cos(thA),
vyA == vA * sin(thA)
);
}
public class Tests
{
Symbol a = new Symbol("a");
Symbol b = new Symbol("b");
Symbol c = new Symbol("c");
Symbol d = new Symbol("d");
Symbol w = new Symbol("w");
Symbol x = new Symbol("x");
Symbol y = new Symbol("y");
Symbol z = new Symbol("z");
Integer Int(int n) => new Integer(n);
#region
[Fact] public void Test1() => Assert.True(new DoubleFloat(1.2).Equals(new DoubleFloat(1.2)));
[Fact] public void Test2() => Assert.False(new DoubleFloat(1.20000001).Equals(new DoubleFloat(1.20000002)));
[Fact]
public void Test3()
{
DoubleFloat.tolerance = 0.000000001;
Assert.True(new DoubleFloat(1.2000000000001).Equals(new DoubleFloat(1.200000000002)));
DoubleFloat.tolerance = null;
}
[Fact] public void Test4() => Assert.False(new DoubleFloat(1.2).Equals(new DoubleFloat(1.23)));
#endregion
#region Const
[Fact] public void Test5() => Assert.True((2 * x * y).Const() == 2);
[Fact] public void Test6() => Assert.True((x * y / 2).Const() == new Integer(1) / 2);
[Fact] public void Test7() => Assert.True((0.1 * x * y).Const() == 0.1);
[Fact] public void Test8() => Assert.True((x * y).Const() == 1);
#endregion
#region Simplify
[Fact] public void Test9() => Assert.True(x + x == 2 * x);
[Fact] public void Test10() => Assert.True(x + x + x == 3 * x);
[Fact] public void Test11() => Assert.True(5 + x + 2 == 7 + x);
[Fact] public void Test12() => Assert.True(3 + x + 5 + x == 8 + 2 * x);
[Fact] public void Test13() => Assert.True(4 * x + 3 * x == 7 * x);
[Fact] public void Test14() => Assert.True(x + y + z + x + y + z == 2 * x + 2 * y + 2 * z);
[Fact] public void Test15() => Assert.True(10 - x == 10 + x * -1);
[Fact] public void Test16() => Assert.True(x * y / 3 == Int(1) / 3 * x * y);
[Fact] public void Test17() => Assert.True(x / y == x * (y ^ -1));
[Fact] public void Test18() => Assert.True(x / 3 == x * (Int(1) / 3));
[Fact] public void Test19() => Assert.True(6 * x * y / 3 == 2 * x * y);
[Fact] public void Test20() => Assert.True((((x ^ Int(1) / 2) ^ Int(1) / 2) ^ 8) == (x ^ 2));
[Fact] public void Test21() => Assert.True(((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2) == (x * y * (z ^ 4)));
[Fact] public void Test22() => Assert.True(x / x == 1);
[Fact] public void Test23() => Assert.True(x / y * y / x == 1);
[Fact] public void Test24() => Assert.True((x ^ 2) * (x ^ 3) == (x ^ 5));
[Fact] public void Test25() => Assert.True(x + y + x + z + 5 + z == 5 + 2 * x + y + 2 * z);
[Fact] public void Test26() => Assert.True(((Int(1) / 2) * x + (Int(3) / 4) * x) == Int(5) / 4 * x);
[Fact] public void Test27() => Assert.True(1.2 * x + 3 * x == 4.2 * x);
[Fact] public void Test28() => Assert.True(3 * x + 1.2 * x == 4.2 * x);
[Fact] public void Test29() => Assert.True(1.2 * x * 3 * y == 3.5999999999999996 * x * y);
[Fact] public void Test30() => Assert.True(3 * x * 1.2 * y == 3.5999999999999996 * x * y);
[Fact] public void Test31() => Assert.True(3.4 * x * 1.2 * y == 4.08 * x * y);
[Fact] public void Test32() => Assert.True((a == b) == (a == b));
#endregion
#region Power.Simplify
[Fact] public void Test33() => Assert.True((0 ^ x) == 0);
[Fact] public void Test34() => Assert.True((1 ^ x) == 1);
[Fact] public void Test35() => Assert.True((x ^ 0) == 1);
[Fact] public void Test36() => Assert.True((x ^ 1) == x);
#endregion
// Product.Simplify
[Fact] public void Test37() => Assert.True(x * 0 == 0);
// Difference
[Fact] public void Test38() => Assert.True(-x == -1 * x);
[Fact] public void Test39() => Assert.True(x - y == x + -1 * y);
#region Substitute
[Fact] public void Test40() => Assert.True(Int(10).Substitute(Int(10), 20) == 20);
[Fact] public void Test41() => Assert.True(Int(10).Substitute(Int(15), 20) == 10);
[Fact] public void Test42() => Assert.True(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.0), 2.0) == 2.0);
[Fact] public void Test43() => Assert.True(new DoubleFloat(1.0).Substitute(new DoubleFloat(1.5), 2.0) == 1.0);
[Fact] public void Test44() => Assert.True((Int(1) / 2).Substitute(Int(1) / 2, Int(3) / 4) == Int(3) / 4);
[Fact] public void Test45() => Assert.True((Int(1) / 2).Substitute(Int(1) / 3, Int(3) / 4) == Int(1) / 2);
[Fact] public void Test46() => Assert.True(x.Substitute(x, y) == y);
[Fact] public void Test47() => Assert.True(x.Substitute(y, y) == x);
[Fact] public void Test48() => Assert.True((x ^ y).Substitute(x, 10) == (10 ^ y));
[Fact] public void Test49() => Assert.True((x ^ y).Substitute(y, 10) == (x ^ 10));
[Fact] public void Test50() => Assert.True((x ^ y).Substitute(x ^ y, 10) == 10);
[Fact] public void Test51() => Assert.True((x * y * z).Substitute(x, y) == ((y ^ 2) * z));
[Fact] public void Test52() => Assert.True((x * y * z).Substitute(x * y * z, x) == x);
[Fact] public void Test53() => Assert.True((x + y + z).Substitute(x, y) == ((y * 2) + z));
[Fact] public void Test54() => Assert.True((x + y + z).Substitute(x + y + z, x) == x);
[Fact] public void Test55() => Assert.True(((((x * y) ^ (Int(1) / 2)) * (z ^ 2)) ^ 2).Substitute(x, 10).Substitute(y, 20).Substitute(z, 3) == 16200);
#region Equation.Substitute
[Fact] public void Test56() => Assert.True((x == y).Substitute(y, z) == (x == z));
[Fact] public void Test57() => Assert.True((x != y).Substitute(y, z) == (x != z));
[Fact] public void Test58() => (x == 0).Substitute(x, 0).AssertEqTo(true);
[Fact] public void Test59() => (x == 0).Substitute(x, 1).AssertEqTo(false);
[Fact] public void Test60() => (x != 0).Substitute(x, 0).AssertEqTo(false);
[Fact] public void Test61() => (x != 0).Substitute(x, 1).AssertEqTo(true);
#endregion
#endregion
[Fact] public void Test62() => Assert.True(sin(new DoubleFloat(3.14159 / 2)) == 0.99999999999911982);
[Fact] public void Test63() => Assert.True(sin(x + y) + sin(x + y) == 2 * sin(x + y));
[Fact] public void Test64() => Assert.True(sin(x + x) == sin(2 * x));
[Fact] public void Test65() => Assert.True(sin(x + x).Substitute(x, 1) == sin(Int(2)));
[Fact] public void Test66() => Assert.True(sin(x + x).Substitute(x, 1.0) == 0.90929742682568171);
[Fact] public void Test67() => Assert.True(sin(2 * x).Substitute(x, y) == sin(2 * y));
// Product.RecursiveSimplify
[Fact] public void Test68() => Assert.True(1 * x == x);
[Fact] public void Test69() => Assert.True(x * 1 == x);
[Fact] public void Test70() => Assert.True(x != y);
[Fact] public void Test71() => Assert.True(x != 10);
// ==(double a, MathObject b)
[Fact] public void Test72() => Assert.True(1.0 == new DoubleFloat(3.0) - 2.0);
[Fact] public void Test73() => Assert.True((a == b) != (a != b));
[Fact] public void Test74() => (sqrt(a * b) * (sqrt(a * b) / a) / c).AssertEqTo(b / c);
void AssertToStringMatch(MathObject obj, string str) => Assert.True(obj.ToString() == str);
[Fact]
public void Test75()
{
MathObject.ToStringForm = MathObject.ToStringForms.Full;
AssertToStringMatch(x + y + z, "x + y + z");
AssertToStringMatch(x + y * z, "x + y * z");
AssertToStringMatch((x + y) * z, "(x + y) * z");
Assert.True((sin(x) * cos(y)).ToString() == "cos(y) * sin(x)", "(sin(x) * cos(y)).ToString()");
AssertToStringMatch(and(x, y, z), "and(x, y, z)");
AssertToStringMatch(x ^ y, "x ^ y");
AssertToStringMatch((x * y) ^ (x + z), "(x * y) ^ (x + z)");
Assert.True((x - y).ToString() == "x + -1 * y", "(x - y).ToString()");
Assert.True((x - y - z).ToString() == "x + -1 * y + -1 * z", "(x - y - z).ToString()");
Assert.True((x / y).ToString() == "x * y ^ -1", "(x / y).ToString()");
Assert.True((x - (y - z)).ToString() == "x + -1 * (y + -1 * z)", "(x - (y - z)).ToString()");
}
[Fact]
public void Test76()
{
MathObject.ToStringForm = MathObject.ToStringForms.Standard;
Assert.True((x + y).ToString() == "x + y", "(x + y).ToString()");
Assert.True((x - y).ToString() == "x - y", "(x - y).ToString()");
Assert.True((x - y - z).ToString() == "x - y - z", "(x - y - z).ToString()");
Assert.True((-x - y - z).ToString() == "-x - y - z", "(x - y - z).ToString()");
Assert.True((2 * x - 3 * y - 4 * z).ToString() == "2 * x - 3 * y - 4 * z", "(2 * x - 3 * y - 4 * z).ToString()");
Assert.True((x - (y - z)).ToString() == "x - (y - z)", "(x - (y - z)).ToString()");
Assert.True((x - y + z).ToString() == "x - y + z", "(x - y + z).ToString()");
Assert.True((-x).ToString() == "-x", "(-x).ToString()");
Assert.True((x / y).ToString() == "x / y", "(x / y).ToString()");
Assert.True((x / (y + z)).ToString() == "x / (y + z)", "(x / (y + z)).ToString()");
Assert.True(((x + y) / (x + z)).ToString() == "(x + y) / (x + z)", "((x + y) / (x + z)).ToString()");
Assert.True((-x * y).ToString() == "-x * y", "(-x * y).ToString()");
Assert.True((x * -y).ToString() == "-x * y", "(x * -y).ToString()");
Assert.True(sin(x / y).ToString() == "sin(x / y)", "sin(x / y).ToString()");
Assert.True(
(x == -sqrt(2 * y * (-z * a + y * (b ^ 2) / 2 - c * y * d + c * y * z * sin(x))) / y).ToString() ==
"x == -sqrt(2 * y * ((b ^ 2) * y / 2 - c * d * y - a * z + c * sin(x) * y * z)) / y",
"(x == -sqrt(2 * y * (-z * a + y * (b ^ 2) / 2 - c * y * d + c * y * z * sin(x))) / y).ToString()");
Assert.True((x * (y ^ z)).ToString() == "x * (y ^ z)", "(x * (y ^ z)).ToString()");
Assert.True((x + (y ^ z)).ToString() == "x + (y ^ z)", "((x + (y ^ z)).ToString()");
Assert.True(sqrt(x).ToString() == "sqrt(x)", "sqrt(x).ToString()");
Assert.True(sqrt(x).FullForm().ToString() == "x ^ 1/2", "sqrt(x).FullForm()");
Assert.True((x ^ (new Integer(1) / 3)).ToString() == "x ^ 1/3", "(x ^ (new Integer(1) / 3)).ToString()");
Assert.True(and(and(x, y), and(x, z)).SimplifyLogical().ToString() == "and(x, y, z)",
"and(and(x, y), and(x, z)).SimplifyLogical().ToString()");
AssertToStringMatch(x == sqrt(2 * (y * z - cos(a) * y * z)), "x == sqrt(2 * (y * z - cos(a) * y * z))");
AssertToStringMatch(
a == (-c * cos(d) - b * c * sin(d) + x * y + b * x * z) / (-y - z),
"a == (-c * cos(d) - b * c * sin(d) + x * y + b * x * z) / (-y - z)");
AssertToStringMatch(
x == -(sin(y) / cos(y) + sqrt((sin(y) ^ 2) / (cos(y) ^ 2))) * (z ^ 2) / a,
"x == -(sin(y) / cos(y) + sqrt((sin(y) ^ 2) / (cos(y) ^ 2))) * (z ^ 2) / a");
AssertToStringMatch(x * sqrt(y), "x * sqrt(y)");
AssertToStringMatch(x / sqrt(y), "x / sqrt(y)");
AssertToStringMatch(sqrt(y) / x, "sqrt(y) / x");
AssertToStringMatch((x ^ 2) / (y ^ 3), "(x ^ 2) / (y ^ 3)");
AssertToStringMatch(
x == y * sqrt(-8 * a / (y * (z ^ 2))) * (z ^ 2) / (4 * a),
"x == y * sqrt(-8 * a / (y * (z ^ 2))) * (z ^ 2) / (4 * a)");
AssertToStringMatch(-(-1 + x), "-(-1 + x)");
}
#region Equation.ToString
[Fact] public void Test77() => Assert.True((x == y).ToString() == "x == y", "x == y");
[Fact] public void Test78() => Assert.True((x != y).ToString() == "x != y", "x != y");
#endregion
#region Function.ToString
[Fact] public void Test79() => Assert.True(new And().ToString() == "and()", "and()");
#endregion
#region Equation.Simplify
[Fact] public void Test80() => (new Integer(0) == new Integer(0)).Simplify().AssertEqTo(true);
[Fact] public void Test81() => (new Integer(0) == new Integer(1)).Simplify().AssertEqTo(false);
[Fact] public void Test82() => (new Integer(0) != new Integer(1)).Simplify().AssertEqTo(true);
[Fact] public void Test83() => (new Integer(0) != new Integer(0)).Simplify().AssertEqTo(false);
#endregion
#region And
[Fact] public void Test84() => and().AssertEqTo(true);
[Fact] public void Test85() => and(10).AssertEqTo(10);
[Fact] public void Test86() => and(true).AssertEqTo(true);
[Fact] public void Test87() => and(false).AssertEqTo(false);
[Fact] public void Test88() => and(10, 20, 30).AssertEqTo(and(10, 20, 30));
[Fact] public void Test89() => and(10, false, 20).AssertEqTo(false);
[Fact] public void Test90() => and(10, true, 20).AssertEqTo(and(10, 20));
[Fact] public void Test91() => and(10, and(20, 30), 40).AssertEqTo(and(10, 20, 30, 40));
#endregion
#region Or
[Fact] public void Test92() => or(10).AssertEqTo(10);
[Fact] public void Test93() => or(true).AssertEqTo(true);
[Fact] public void Test94() => or(false).AssertEqTo(false);
[Fact] public void Test95() => or(10, 20, false).AssertEqTo(or(10, 20));
[Fact] public void Test96() => or(false, false).AssertEqTo(false);
[Fact] public void Test97() => or(10, true, 20, false).AssertEqTo(true);
[Fact] public void Test98() => or(10, false, 20).AssertEqTo(or(10, 20));
[Fact] public void Test99() => or(10, or(20, 30), 40).AssertEqTo(or(10, 20, 30, 40));
#endregion
#region Function.Map
[Fact]
public void Test100() => new And(1, 2, 3, 4, 5, 6).Map(elt => elt * 2)
.AssertEqTo(and(2, 4, 6, 8, 10, 12));
[Fact]
public void Test101() => new And(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
.AssertEqTo(false);
[Fact]
public void Test102() => new Or(1, 2, 3).Map(elt => elt * 2)
.AssertEqTo(or(2, 4, 6));
[Fact]
public void Test103() => new Or(1, 2, 3, 4, 5, 6).Map(elt => (elt is Integer) && (elt as Integer).val % 2 == 0 ? elt : false)
.AssertEqTo(or(2, 4, 6));
#endregion Function.Map
#region Sum
[Fact]
public void Test104() => Assert.True((x + y).Equals(x * y) == false, "(x + y).Equals(x * y)");
#endregion
[Fact]
public void Test105()
{
(x < y).Substitute(x, 10).Substitute(y, 20).AssertEqTo(true);
(x > y).Substitute(x, 10).Substitute(y, 20).AssertEqTo(false);
}
Symbol Pi = new Symbol("Pi");
MathObject half = new Integer(1) / 2;
#region Sin
[Fact] public void Test106() => sin(0).AssertEqTo(0);
[Fact] public void Test107() => sin(Pi).AssertEqTo(0);
[Fact] public void Test108() => sin(-10).AssertEqTo(-sin(10));
[Fact] public void Test109() => sin(-x).AssertEqTo(-sin(x));
[Fact] public void Test110() => sin(-5 * x).AssertEqTo(-sin(5 * x));
// sin(k/n pi) for n = 1 2 3 4 6
[Fact] public void Test111() => sin(-2 * Pi).AssertEqTo(0);
[Fact] public void Test112() => sin(-1 * Pi).AssertEqTo(0);
[Fact] public void Test113() => sin(2 * Pi).AssertEqTo(0);
[Fact] public void Test114() => sin(3 * Pi).AssertEqTo(0);
[Fact] public void Test115() => sin(-7 * Pi / 2).AssertEqTo(1);
[Fact] public void Test116() => sin(-5 * Pi / 2).AssertEqTo(-1);
[Fact] public void Test117() => sin(-3 * Pi / 2).AssertEqTo(1);
[Fact] public void Test118() => sin(-1 * Pi / 2).AssertEqTo(-1);
[Fact] public void Test119() => sin(1 * Pi / 2).AssertEqTo(1);
[Fact] public void Test120() => sin(3 * Pi / 2).AssertEqTo(-1);
[Fact] public void Test121() => sin(5 * Pi / 2).AssertEqTo(1);
[Fact] public void Test122() => sin(7 * Pi / 2).AssertEqTo(-1);
[Fact] public void Test123() => sin(-4 * Pi / 3).AssertEqTo(sqrt(3) / 2);
[Fact] public void Test124() => sin(-2 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
[Fact] public void Test125() => sin(-1 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
[Fact] public void Test126() => sin(1 * Pi / 3).AssertEqTo(sqrt(3) / 2);
[Fact] public void Test127() => sin(2 * Pi / 3).AssertEqTo(sqrt(3) / 2);
[Fact] public void Test128() => sin(4 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
[Fact] public void Test129() => sin(5 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
[Fact] public void Test130() => sin(7 * Pi / 3).AssertEqTo(sqrt(3) / 2);
[Fact] public void Test131() => sin(-3 * Pi / 4).AssertEqTo(-1 / sqrt(2));
[Fact] public void Test132() => sin(-1 * Pi / 4).AssertEqTo(-1 / sqrt(2));
[Fact] public void Test133() => sin(1 * Pi / 4).AssertEqTo(1 / sqrt(2));
[Fact] public void Test134() => sin(3 * Pi / 4).AssertEqTo(1 / sqrt(2));
[Fact] public void Test135() => sin(5 * Pi / 4).AssertEqTo(-1 / sqrt(2));
[Fact] public void Test136() => sin(7 * Pi / 4).AssertEqTo(-1 / sqrt(2));
[Fact] public void Test137() => sin(9 * Pi / 4).AssertEqTo(1 / sqrt(2));
[Fact] public void Test138() => sin(11 * Pi / 4).AssertEqTo(1 / sqrt(2));
[Fact] public void Test139() => sin(-5 * Pi / 6).AssertEqTo(-half);
[Fact] public void Test140() => sin(-1 * Pi / 6).AssertEqTo(-half);
[Fact] public void Test141() => sin(1 * Pi / 6).AssertEqTo(half);
[Fact] public void Test142() => sin(5 * Pi / 6).AssertEqTo(half);
[Fact] public void Test143() => sin(7 * Pi / 6).AssertEqTo(-half);
[Fact] public void Test144() => sin(11 * Pi / 6).AssertEqTo(-half);
[Fact] public void Test145() => sin(13 * Pi / 6).AssertEqTo(half);
[Fact] public void Test146() => sin(17 * Pi / 6).AssertEqTo(half);
// sin(a/b pi) where a/b > 1/2 (i.e. not in first quadrant)
[Fact] public void Test147() => sin(15 * Pi / 7).AssertEqTo(sin(1 * Pi / 7));
[Fact] public void Test148() => sin(8 * Pi / 7).AssertEqTo(-sin(1 * Pi / 7));
[Fact] public void Test149() => sin(4 * Pi / 7).AssertEqTo(sin(3 * Pi / 7));
// sin( a + b + ... + n * pi ) where abs(n) >= 2
[Fact] public void Test150() => sin(x - 3 * Pi).AssertEqTo(sin(x + Pi));
[Fact] public void Test151() => sin(x - 2 * Pi).AssertEqTo(sin(x));
[Fact] public void Test152() => sin(x + 2 * Pi).AssertEqTo(sin(x));
[Fact] public void Test153() => sin(x + 3 * Pi).AssertEqTo(sin(x + Pi));
[Fact] public void Test154() => sin(x + 7 * Pi / 2).AssertEqTo(sin(x + 3 * Pi / 2));
// sin( a + b + ... + n/2 * pi )
[Fact] public void Test155() => sin(x - 3 * Pi / 2).AssertEqTo(cos(x));
[Fact] public void Test156() => sin(x - 1 * Pi / 2).AssertEqTo(-cos(x));
[Fact] public void Test157() => sin(x + 1 * Pi / 2).AssertEqTo(cos(x));
[Fact] public void Test158() => sin(x + 3 * Pi / 2).AssertEqTo(-cos(x));
[Fact] public void Test159() => sin(Pi + x).AssertEqTo(-sin(x));
[Fact] public void Test160() => sin(Pi + x + y).AssertEqTo(-sin(x + y));
[Fact] public void Test161() => cos(Pi + x).AssertEqTo(-cos(x));
[Fact] public void Test162() => cos(Pi + x + y).AssertEqTo(-cos(x + y));
#endregion
#region Cos
[Fact] public void Test163() => cos(0).AssertEqTo(1);
[Fact] public void Test164() => cos(Pi).AssertEqTo(-1);
[Fact] public void Test165() => cos(-10).AssertEqTo(cos(10));
[Fact] public void Test166() => cos(-10 * x).AssertEqTo(cos(10 * x));
[Fact] public void Test167() => cos(3 * Pi).AssertEqTo(-1);
[Fact] public void Test168() => cos(2 * Pi * 3 / 4).AssertEqTo(0);
// cos( a + b + ... + n * pi ) where abs(n) >= 2
[Fact] public void Test169() => cos(x - 3 * Pi).AssertEqTo(cos(x + Pi));
[Fact] public void Test170() => cos(x + 3 * Pi).AssertEqTo(cos(x + Pi));
[Fact] public void Test171() => cos(x - 2 * Pi).AssertEqTo(cos(x));
[Fact] public void Test172() => cos(x + 2 * Pi).AssertEqTo(cos(x));
[Fact] public void Test173() => cos(x + Pi * 7 / 2).AssertEqTo(cos(x + Pi * 3 / 2));
// cos( a + b + ... + n/2 * pi )
[Fact] public void Test174() => cos(x - Pi * 3 / 2).AssertEqTo(-sin(x));
[Fact] public void Test175() => cos(x - Pi * 1 / 2).AssertEqTo(sin(x));
[Fact] public void Test176() => cos(x + Pi * 1 / 2).AssertEqTo(-sin(x));
[Fact] public void Test177() => cos(x + Pi * 3 / 2).AssertEqTo(sin(x));
#endregion
#region Has
[Fact] public void Test178() => Assert.True(a.Has(elt => elt == a), "a.Has(elt => elt == a)");
[Fact] public void Test179() => Assert.True(a.Has(elt => elt == b) == false, "a.Has(elt => elt == b) == false");
[Fact] public void Test180() => Assert.True((a == b).Has(elt => elt == a), "Has - 3");
[Fact] public void Test181() => Assert.True((a == b).Has(elt => elt == c) == false, "Has - 4");
[Fact] public void Test182() => Assert.True(((a + b) ^ c).Has(elt => elt == a + b), "Has - 5");
[Fact] public void Test183() => Assert.True(((a + b) ^ c).Has(elt => (elt is Power) && (elt as Power).exp == c), "Has - 6");
[Fact] public void Test184() => Assert.True((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).Has(b)), "Has - 7");
[Fact] public void Test185() => Assert.True((x * (a + b + c)).Has(elt => (elt is Sum) && (elt as Sum).elts.Any(obj => obj == b)), "Has - 8");
[Fact] public void Test186() => Assert.True((x * (a + b + c)).Has(elt => (elt is Product) && (elt as Product).elts.Any(obj => obj == b)) == false, "Has - 9");
#endregion
#region FreeOf
[Fact] public void Test187() => Assert.True((a + b).FreeOf(b) == false, "(a + b).FreeOf(b)");
[Fact] public void Test188() => Assert.True((a + b).FreeOf(c) == true, "(a + b).FreeOf(c)");
[Fact] public void Test189() => Assert.True(((a + b) * c).FreeOf(a + b) == false, "((a + b) * c).FreeOf(a + b)");
[Fact] public void Test190() => Assert.True((sin(x) + 2 * x).FreeOf(sin(x)) == false, "(sin(x) + 2 * x).FreeOf(sin(x))");
[Fact] public void Test191() => Assert.True(((a + b + c) * d).FreeOf(a + b) == true, "((a + b + c) * d).FreeOf(a + b)");
[Fact] public void Test192() => Assert.True(((y + 2 * x - y) / x).FreeOf(x) == true, "((y + 2 * x - y) / x).FreeOf(x)");
[Fact] public void Test193() => Assert.True(((x * y) ^ 2).FreeOf(x * y) == true, "((x * y) ^ 2).FreeOf(x * y)");
#endregion
#region Numerator
[Fact] public void Test194() => Assert.True((x ^ -1).Numerator() == 1);
[Fact] public void Test195() => Assert.True((x ^ -half).Numerator() == 1);
#endregion
#region Denominator
[Fact]
public void Test196() =>
((new Integer(2) / 3) * ((x * (x + 1)) / (x + 2)) * (y ^ z)).Denominator().AssertEqTo(3 * (x + 2));
#endregion
#region LogicalExpand
[Fact]
public void Test197() =>
and(or(a, b), c).LogicalExpand()
.AssertEqTo(
or(
and(a, c),
and(b, c)));
[Fact]
public void Test198() =>
and(a, or(b, c))
.LogicalExpand()
.AssertEqTo(or(and(a, b), and(a, c)));
[Fact]
public void Test199() =>
and(a, or(b, c), d)
.LogicalExpand()
.AssertEqTo(
or(
and(a, b, d),
and(a, c, d)));
[Fact]
public void Test200() =>
and(or(a == b, b == c), x == y)
.LogicalExpand()
.AssertEqTo(
or(
and(a == b, x == y),
and(b == c, x == y)));
[Fact]
public void Test201() =>
and(
or(a == b, b == c),
or(c == d, d == a),
x == y)
.LogicalExpand()
.AssertEqTo(
or(
and(a == b, c == d, x == y),
and(a == b, d == a, x == y),
and(b == c, c == d, x == y),
and(b == c, d == a, x == y)));
#endregion
#region SimplifyEquation
[Fact]
public void Test202() =>
(2 * x == 0)
.SimplifyEquation()
.AssertEqTo(x == 0);
[Fact]
public void Test203() =>
(2 * x != 0)
.SimplifyEquation()
.AssertEqTo(x != 0);
[Fact]
public void Test204() =>
((x ^ 2) == 0)
.SimplifyEquation()
.AssertEqTo(x == 0);
#endregion
#region SimplifyLogical
[Fact]
public void Test205() =>
and(a, b, c, a)
.SimplifyLogical()
.AssertEqTo(and(a, b, c));
#endregion SimplifyLogical
#region DegreeGpe
[Fact]
public void Test206() => Assert.True(
((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z }) == 6,
"((3 * w * x ^ 2) * (y ^ 3) * (z ^ 4)).DegreeGpe(new List<MathObject>() { x, z })");
[Fact]
public void Test207() => Assert.True(
((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x }) == 2,
"((a * x ^ 2) + b * x + c).DegreeGpe(new List<MathObject>() { x })");
[Fact]
public void Test208() => Assert.True(
(a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) }) == 2,
"(a * (sin(x) ^ 2) + b * sin(x) + c).DegreeGpe(new List<MathObject>() { sin(x) })");
[Fact]
public void Test209() => Assert.True(
(2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z }) == 7,
"(2 * (x ^ 2) * y * (z ^ 3) + w * x * (z ^ 6)).DegreeGpe(new List<MathObject>() { x, z })");
#endregion
#region CoefficientGpe
[Fact] public void Test210() => Assert.True((a * (x ^ 2) + b * x + c).CoefficientGpe(x, 2) == a);
[Fact] public void Test211() => Assert.True((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 1) == 3 * (y ^ 2) + 7);
[Fact] public void Test212() => Assert.True((3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * x + 9).CoefficientGpe(x, 3) == 0);
[Fact]
public void Test213() => Assert.True(
(3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null,
"(3 * sin(x) * (x ^ 2) + 2 * x + 4).CoefficientGpe(x, 2) == null");
#endregion
#region AlgebraicExpand
[Fact]
public void Test214() => Assert.True(
((x + 2) * (x + 3) * (x + 4)).AlgebraicExpand()
==
24 + 26 * x + 9 * (x ^ 2) + (x ^ 3));
[Fact]
public void Test215() => Assert.True(
((x + y + z) ^ 3).AlgebraicExpand()
==
(x ^ 3) + (y ^ 3) + (z ^ 3) +
3 * (x ^ 2) * y +
3 * (y ^ 2) * x +
3 * (x ^ 2) * z +
3 * (y ^ 2) * z +
3 * (z ^ 2) * x +
3 * (z ^ 2) * y +
6 * x * y * z);
[Fact]
public void Test216() => Assert.True(
(((x + 1) ^ 2) + ((y + 1) ^ 2)).AlgebraicExpand()
==
2 + 2 * x + (x ^ 2) + 2 * y + (y ^ 2));
[Fact]
public void Test217() => Assert.True(
((((x + 2) ^ 2) + 3) ^ 2).AlgebraicExpand()
==
49 + 56 * x + 30 * (x ^ 2) + 8 * (x ^ 3) + (x ^ 4));
[Fact]
public void Test218() => Assert.True(
sin(x * (y + z)).AlgebraicExpand()
==
sin(x * y + x * z));
[Fact]
public void Test219() => Assert.True(
(a * (b + c) == x * (y + z)).AlgebraicExpand()
==
(a * b + a * c == x * y + x * z));
[Fact]
public void Test220() =>
(5 * x * (500 / (x ^ 2) * (sqrt(3.0) / 4) + 1) + 2 * (x ^ 2) + (sqrt(3.0) / 2) * (x ^ 2))
.AlgebraicExpand()
.AssertEqTo(1082.5317547305483 / x + 5 * x + 2.8660254037844384 * (x ^ 2));
#endregion
#region IsolateVariable
[Fact] public void Test221() => (x + y + z == 0).IsolateVariable(a).AssertEqTo(x + y + z == 0);
// (x * a + x * b == 0).IsolateVariable(x).Disp();
[Fact]
public void Test222() => (x * (a + b) - x * a - x * b + x == c)
.IsolateVariable(x)
.AssertEqTo(x == c);
[Fact]
public void Test223() => and(x == y, a == b)
.IsolateVariable(b)
.AssertEqTo(and(x == y, b == a));
[Fact]
public void Test224() => or(and(y == x, z == x), and(b == x, c == x))
.IsolateVariable(x)
.AssertEqTo(or(and(x == y, x == z), and(x == b, x == c)));
[Fact] public void Test225() => Assert.True((0 == x - y).IsolateVariableEq(x).Equals(x == y), "(0 == x - y).IsolateVariable(x).Equals(x == y)");
[Fact]
public void Test226() => (a * (x ^ 2) + b * x + c == 0)
.IsolateVariable(x)
.AssertEqTo(
or(
and(
x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
a != 0
),
and(
x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
a != 0
),
and(x == -c / b, a == 0, b != 0),
and(a == 0, b == 0, c == 0)
)
);
[Fact]
public void Test227() => (a * (x ^ 2) + c == 0)
.IsolateVariable(x)
.AssertEqTo(
or(
and(
x == sqrt(-4 * a * c) / (2 * a),
a != 0
),
and(
x == -sqrt(-4 * a * c) / (2 * a),
a != 0
),
and(a == 0, c == 0)
)
);
// a x^2 + b x + c == 0
// a x^2 + c == - b x
// (a x^2 + c) / x == - b
[Fact]
public void Test228() => ((a * (x ^ 2) + c) / x == -b)
.IsolateVariable(x)
.AssertEqTo(
or(
and(
x == (-b + sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
a != 0
),
and(
x == (-b - sqrt((b ^ 2) + -4 * a * c)) / (2 * a),
a != 0
),
and(x == -c / b, a == 0, b != 0),
and(a == 0, b == 0, c == 0)
));
[Fact] public void Test229() => (sqrt(x + y) == z).IsolateVariable(x).AssertEqTo(x == (z ^ 2) - y);
[Fact]
public void Test230() => (a * b + a == c)
.IsolateVariable(a)
.AssertEqTo(a == c / (b + 1));
[Fact]
public void Test231() => (a * b + a * c == d)
.IsolateVariable(a)
.AssertEqTo(a == d / (b + c));
[Fact]
public void Test232() => (1 / sqrt(x) == y)
.IsolateVariable(x)
.AssertEqTo(x == (y ^ -2));
[Fact]
public void Test233() => (y == sqrt(x) / x)
.IsolateVariable(x)
.AssertEqTo(x == (y ^ -2));
[Fact]
public void Test234() => (-sqrt(x) + z * x == y)
.IsolateVariable(x)
.AssertEqTo(-sqrt(x) + z * x == y);
[Fact]
public void Test235() => (sqrt(a + x) - z * x == -y)
.IsolateVariable(x)
.AssertEqTo(sqrt(a + x) - z * x == -y);
[Fact]
public void Test236() => (sqrt(2 + x) * sqrt(3 + x) == y)
.IsolateVariable(x)
.AssertEqTo(sqrt(2 + x) * sqrt(3 + x) == y);
[Fact]
public void Test237() => ((x + 1) / (x + 2) == 3)
.IsolateVariable(x)
.AssertEqTo(x == -new Integer(5) / 2);
[Fact]
public void Test238() => ((1 + 2 * x) / (3 * x - 4) == 5)
.IsolateVariable(x)
.AssertEqTo(x == new Integer(21) / 13);
#endregion
#region EliminateVariable
[Fact]
public void Test239() => and((x ^ 3) == (y ^ 5), z == x)
.EliminateVariable(x)
.AssertEqTo((z ^ 3) == (y ^ 5));
[Fact]
public void Test241() => and((x ^ 3) == (y ^ 5), z == (x ^ 7))
.EliminateVariable(x)
.AssertEqTo(and((x ^ 3) == (y ^ 5), z == (x ^ 7)));
#endregion
[Fact] public void Test242() => and(x + y == z, x / y == 0, x != 0).CheckVariable(x).AssertEqTo(false);
#region RationalExpand
// EA: Example 6.62
[Fact]
public void Test243() => Assert.True(
(((sqrt(1 / (((x + y) ^ 2) + 1)) + 1)
*
(sqrt(1 / (((x + y) ^ 2) + 1)) - 1))
/ (x + 1))
.RationalExpand()
==
(-(x ^ 2) - 2 * x * y - (y ^ 2)) / (1 + x + (x ^ 2) + (x ^ 3) + 2 * x * y + 2 * (x ^ 2) * y + (y ^ 2) + x * (y ^ 2))
);
// EA: page 269
[Fact]
public void Test244() => Assert.True(
(1 / (1 / a + c / (a * b)) + (a * b * c + a * (c ^ 2)) / ((b + c) ^ 2) - a).RationalExpand()
==
0);
#endregion
#region LeadingCoefficientGpe
[Fact]
public void Test245() => Assert.True(
(3 * x * (y ^ 2) + 5 * (x ^ 2) * y + 7 * (x ^ 2) * (y ^ 3) + 9).LeadingCoefficientGpe(x)
==
5 * y + 7 * (y ^ 3)
);
#endregion
#region PolynomialDivision
// MM: Example 4.4
[Fact]
public void Test246()
{
var result = PolynomialDivision(5 * (x ^ 2) + 4 * x + 1, 2 * x + 3, x);
Assert.True(result.quotient == 5 * x / 2 - new Integer(7) / 4);
Assert.True(result.remainder == new Integer(25) / 4);
}
// MM: Example 4.10
[Fact]
public void Test247()
{
var result = PolynomialDivision((x ^ 2) - 4, x + 2, x);
Assert.True(result.quotient == x - 2);
Assert.True(result.remainder == 0);
}
[Fact]
public void Test248()
{
var result = PolynomialDivision((x ^ 2) + 5 * x + 6, x + 2, x);
Assert.True(result.quotient == x + 3);
Assert.True(result.remainder == 0);
}
// MM: Example 4.43
[Fact]
public void Test249()
{
var result = PolynomialDivision(3 * (x ^ 3) + (x ^ 2) - 4, (x ^ 2) - 4 * x + 2, x);
Assert.True(result.remainder == 46 * x - 30);
}
// MM: Example 4.45
[Fact]
public void Test250()
{
var i = new Symbol("i");
var result = PolynomialDivision(2 + 3 * i + 4 * (i ^ 2) + 5 * (i ^ 3) + 6 * (i ^ 4), (i ^ 2) + 1, i);
Assert.True(result.remainder == 4 - 2 * i);
}
#endregion
#region PolynomialGcd
// MM: Example 4.20
[Fact]
public void Test251() => Assert.True(
PolynomialGcd(
2 * (x ^ 3) + 12 * (x ^ 2) + 22 * x + 12,
2 * (x ^ 3) + 18 * (x ^ 2) + 52 * x + 48,
x)
==
(x ^ 2) + 5 * x + 6
);
// MM: Example 4.24
[Fact]
public void Test252() => Assert.True(
PolynomialGcd(
(x ^ 7) - 4 * (x ^ 5) - (x ^ 2) + 4,
(x ^ 5) - 4 * (x ^ 3) - (x ^ 2) + 4,
x)
==
(x ^ 3) - (x ^ 2) - 4 * x + 4
);
#endregion
[Fact]
public void Test253_a()
{
var x = new Symbol("x");
var y = new Symbol("y");
var z = new Symbol("z");
var eqs = and(
(x ^ 2) - 4 == 0,
y + x == 0,
x + z == 10
);
var half = new Integer(1) / 2;
((x ^ 2) - 4 == 0)
.IsolateVariableEq(x)
.AssertEqTo(or(x == half * sqrt(16), x == -half * sqrt(16)));
}
[Fact]
public void Test253_b()
{
var x = new Symbol("x");
var y = new Symbol("y");
var z = new Symbol("z");
var eqs = and(
(x ^ 2) - 4 == 0,
y + x == 0,
x + z == 10
);
var half = new Integer(1) / 2;
eqs.EliminateVariable(x)
.AssertEqTo(
or(
and(
half * sqrt(16) + y == 0,
half * sqrt(16) + z == 10
),
and(
-half * sqrt(16) + y == 0,
-half * sqrt(16) + z == 10
)
)
);
}
[Fact]
public void Test253()
{
var x = new Symbol("x");
var y = new Symbol("y");
var z = new Symbol("z");
var eqs = and(
(x ^ 2) - 4 == 0,
y + x == 0,
x + z == 10
);
var half = new Integer(1) / 2;
((x ^ 2) - 4 == 0)
.IsolateVariableEq(x)
.AssertEqTo(or(x == half * sqrt(16), x == -half * sqrt(16)));
eqs.EliminateVariable(x)
.AssertEqTo(
or(
and(
half * sqrt(16) + y == 0,
half * sqrt(16) + z == 10
),
and(
-half * sqrt(16) + y == 0,
-half * sqrt(16) + z == 10
)
)
);
}
And Kinematic(Symbol s, Symbol u, Symbol v, Symbol a, Symbol t) =>
new And(
v == u + a * t,
s == (u + v) * t / 2
);
[Fact]
public void PSE_Example_2_6()
{
var sAC = new Symbol("sAC");
var sAB = new Symbol("sAB");
var vA = new Symbol("vA");
var vB = new Symbol("vB");
var vC = new Symbol("vC");
var a = new Symbol("a");
var tAC = new Symbol("tAC");
var tAB = new Symbol("tAB");
var eqs = and(
tAB == tAC / 2,
Kinematic(sAC, vA, vC, a, tAC),
Kinematic(sAB, vA, vB, a, tAB)
);
var vals = new List<Equation>() { vA == 10, vC == 30, tAC == 10 };
eqs
.EliminateVariables(tAB, sAC, vB, sAB)
.IsolateVariable(a)
.AssertEqTo(a == (vC - vA) / tAC)
.SubstituteEqLs(vals)
.AssertEqTo(a == 2);
eqs
.EliminateVariables(vB, a, tAB, sAC)
.AssertEqTo(sAB == tAC / 4 * (2 * vA + (vC - vA) / 2))
.SubstituteEqLs(vals)
.AssertEqTo(sAB == 75);
}
[Fact]
public void PSE_Example_2_7()
{
// s =
// u = 63
// v = 0
// a =
// t = 2
var s = new Symbol("s");
var u = new Symbol("u");
var v = new Symbol("v");
var a = new Symbol("a");
var t = new Symbol("t");
var eqs = Kinematic(s, u, v, a, t);
var vals = new List<Equation>() { u == 63, v == 0, t == 2.0 };
eqs
.EliminateVariable(s)
.AssertEqTo(v == a * t + u)
.IsolateVariable(a)
.AssertEqTo(a == (v - u) / t)
.SubstituteEqLs(vals)
.AssertEqTo(a == -31.5);
eqs
.EliminateVariable(a)
.SubstituteEqLs(vals)
.AssertEqTo(s == 63.0);
}
[Fact]
public void PSE_Example_2_8()
{
// car
//
// s1 =
// u1 = 45
// v1 = 45
// a1 = 0
// t1 =
// officer
//
// s2 =
// u2 = 0
// v2 =
// a2 = 3
// t2
var s1 = new Symbol("s1");
var u1 = new Symbol("u1");
var v1 = new Symbol("v1");
var a1 = new Symbol("a1");
var t1 = new Symbol("t1");
var s2 = new Symbol("s2");
var u2 = new Symbol("u2");
var v2 = new Symbol("v2");
var a2 = new Symbol("a2");
var t2 = new Symbol("t2");
var eqs = and(
u1 == v1,
s1 == s2,
t2 == t1 - 1,
Kinematic(s1, u1, v1, a1, t1),
Kinematic(s2, u2, v2, a2, t2));
var vals = new List<Equation>()
{
v1 == 45.0,
u2 == 0,
a2 == 3
};
eqs
.EliminateVariables(s2, t1, a1, s1, v2, u1)
.IsolateVariable(t2)
.SubstituteEqLs(vals)
.AssertEqTo(or(t2 == -0.96871942267131317, t2 == 30.968719422671313));
}
And Kinematic(Symbol sA, Symbol sB, Symbol vA, Symbol vB, Symbol a, Symbol tA, Symbol tB) =>
new And(
vB == vA + a * (tB - tA),
sB - sA == (vA + vB) * (tB - tA) / 2);
[Fact]
public void PSE_Example_2_12()
{
var yA = new Symbol("yA");
var yB = new Symbol("yB");
var yC = new Symbol("yC");
var yD = new Symbol("yD");
var tA = new Symbol("tA");
var tB = new Symbol("tB");
var tC = new Symbol("tC");
var tD = new Symbol("tD");
var vA = new Symbol("vA");
var vB = new Symbol("vB");
var vC = new Symbol("vC");
var vD = new Symbol("vD");
var a = new Symbol("a");
var eqs = and(
Kinematic(yA, yB, vA, vB, a, tA, tB),
Kinematic(yB, yC, vB, vC, a, tB, tC),
Kinematic(yC, yD, vC, vD, a, tC, tD));
var vals = new List<Equation>()
{
yA == 50,
yC == 50,
vA == 20,
vB == 0,
a == -9.8,
tA == 0,
tD == 5
};
// velocity and position at t = 5.00 s
DoubleFloat.tolerance = 0.000000001;
eqs
.EliminateVariables(tB, tC, vC, yB, yD)
.SubstituteEqLs(vals)
.AssertEqTo(or(vD == -29.000000000000004, vD == -29.000000000000007));
eqs
.EliminateVariables(tB, tC, vC, yB, vD)
.IsolateVariable(yD)
.SubstituteEqLs(vals)
.AssertEqTo(or(yD == 27.499999999, yD == 27.499999999));
DoubleFloat.tolerance = null;
}
[Fact]
public void PSE_Example_4_3()
{
// A long-jumper leaves the ground at an angle of 20.0° above
// the horizontal and at a speed of 11.0 m/s.
// (a) How far does he jump in the horizontal direction?
// (Assume his motion is equivalent to that of a particle.)
// (b) What is the maximum height reached?
var xA = new Symbol("xA");
var xB = new Symbol("xB");
var xC = new Symbol("xC");
var yA = new Symbol("yA");
var yB = new Symbol("yB");
var yC = new Symbol("yC");
var vxA = new Symbol("vxA");
var vxB = new Symbol("vxB");
var vxC = new Symbol("vxC");
var vyA = new Symbol("vyA");
var vyB = new Symbol("vyB");
var vyC = new Symbol("vyC");
var tAB = new Symbol("tAB");
var tAC = new Symbol("tAC");
var ax = new Symbol("ax");
var ay = new Symbol("ay");
var vA = new Symbol("vA");
var thA = new Symbol("thA");
var Pi = new Symbol("Pi");
var eqs = and(
vxA == vA * cos(thA),
vyA == vA * sin(thA),
tAC == 2 * tAB,
vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,
xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,
vxC == vxA + ax * tAB,
vyC == vyA + ay * tAB,
xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2
);
var zeros = new List<Equation>() { xA == 0, yA == 0, ax == 0, vyB == 0 };
var vals = new List<Equation>() { thA == (20).ToRadians(), vA == 11.0, ay == -9.8, Pi == Math.PI };
eqs
.EliminateVariables(xB, yC, vxB, vxC, vyC, yB, tAC, vxA, vyA, tAB)
.SubstituteEqLs(zeros)
.AssertEqTo(xC == -2 * cos(thA) * sin(thA) * (vA ^ 2) / ay)
.SubstituteEqLs(vals)
.AssertEqTo(xC == 7.9364592624562507);
eqs
.EliminateVariables(xB, yC, vxB, vxC, vyC, xC, vxA, tAC, vyA, tAB)
.SubstituteEqLs(zeros)
.AssertEqTo(yB == -(sin(thA) ^ 2) * (vA ^ 2) / (2 * ay))
.SubstituteEqLs(vals)
.AssertEqTo(yB == 0.72215873425009314);
}
[Fact]
public void PSE_Example_4_3_KinematicObjectABC()
{
// A long-jumper leaves the ground at an angle of 20.0° above
// the horizontal and at a speed of 11.0 m/s.
// (a) How far does he jump in the horizontal direction?
// (Assume his motion is equivalent to that of a particle.)
// (b) What is the maximum height reached?
var obj = new KinematicObjectABC("obj");
var yB = new Symbol("yB");
var xC = new Symbol("xC");
var ay = new Symbol("ay");
var thA = new Symbol("thA");
var vA = new Symbol("vA");
var Pi = new Symbol("Pi");
var eqs = and(
obj.TrigEquationsA(),
obj.tAC == 2 * obj.tAB,
obj.EquationsAB(),
obj.EquationsAC()
);
var vals = new List<Equation>()
{
obj.xA == 0,
obj.yA == 0,
obj.vA == vA,
obj.thA == thA,
obj.yB == yB,
obj.vyB == 0,
obj.xC == xC,
obj.ax == 0,
obj.ay == ay
};
var numerical_vals = new List<Equation>()
{
thA == (20).ToRadians(),
vA == 11,
ay == -9.8,
Pi == Math.PI
};
// xC
eqs
.SubstituteEqLs(vals)
.EliminateVariables(
obj.vxA, obj.vyA, obj.vyC, obj.vxC, obj.vxB,
obj.xB, yB, obj.yC,
obj.tAC, obj.tAB
)
.AssertEqTo(xC == -2 * cos(thA) * sin(thA) * (vA ^ 2) / ay)
.SubstituteEqLs(numerical_vals)
.AssertEqTo(xC == 7.9364592624562507);
// yB
eqs
.SubstituteEqLs(vals)
.EliminateVariables(
obj.tAB, obj.tAC,
obj.vxA, obj.vxB, obj.vxC, obj.vyC, obj.vyA,
obj.xB, xC, obj.yC
)
.AssertEqTo(yB == -(sin(thA) ^ 2) * (vA ^ 2) / (2 * ay))
.SubstituteEqLs(numerical_vals)
.AssertEqTo(yB == 0.72215873425009314);
}
[Fact]
public void PSE_5E_Example_4_5()
{
var xA = new Symbol("xA");
var xB = new Symbol("xB");
var xC = new Symbol("xC");
var yA = new Symbol("yA");
var yB = new Symbol("yB");
var yC = new Symbol("yC");
var vxA = new Symbol("vxA");
var vxB = new Symbol("vxB");
var vxC = new Symbol("vxC");
var vyA = new Symbol("vyA");
var vyB = new Symbol("vyB");
var vyC = new Symbol("vyC");
var tAB = new Symbol("tAB");
var tAC = new Symbol("tAC");
var ax = new Symbol("ax");
var ay = new Symbol("ay");
var vA = new Symbol("vA");
var thA = new Symbol("thA");
var vC = new Symbol("vC");
var Pi = new Symbol("Pi");
var eqs = and(
vxA == vA * cos(thA),
vyA == vA * sin(thA),
// tAC == 2 * tAB,
// vxB == vxA + ax * tAB,
// vyB == vyA + ay * tAB,
// xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
// yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,
vxC == vxA + ax * tAC,
vyC == vyA + ay * tAC,
// xC == xA + vxA * tAC + ax * (tAC ^ 2) / 2,
yC == yA + vyA * tAC + ay * (tAC ^ 2) / 2,
vC == sqrt((vxC ^ 2) + (vyC ^ 2)),
ay != 0
);
var zeros = new List<Equation>() { ax == 0, yC == 0 };
var vals = new List<Equation>() { yA == 45, vA == 20, thA == (30).ToRadians(), ay == -9.8, Pi == Math.PI };
DoubleFloat.tolerance = 0.00001;
eqs
.EliminateVariables(vC, vxA, vxC, vyC, vyA)
.IsolateVariable(tAC)
.LogicalExpand().SimplifyEquation().SimplifyLogical()
.CheckVariable(ay)
.AssertEqTo(
or(
and(
tAC == -(sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
ay != 0),
and(
tAC == -(sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + 2 * ay * (yC - yA))) / ay,
ay != 0)))
.SubstituteEqLs(zeros)
.SubstituteEqLs(vals)
.AssertEqTo(or(tAC == 4.2180489012229376, tAC == -2.1772325746923267));
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxC, vxA, vyA, vyC, tAC)
.SimplifyEquation().SimplifyLogical()
.CheckVariable(ay)
.AssertEqTo(
or(
and(
ay != 0,
vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA + sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2))),
and(
ay != 0,
vC == sqrt((cos(thA) ^ 2) * (vA ^ 2) + ((sin(thA) * vA - (sin(thA) * vA - sqrt((sin(thA) ^ 2) * (vA ^ 2) + -2 * ay * yA))) ^ 2)))))
.SubstituteEqLs(vals)
.AssertEqTo(or(vC == 35.805027579936315, vC == 35.805027579936322));
DoubleFloat.tolerance = null;
}
[Fact]
public void PSE_5E_Example_4_6()
{
// An Alaskan rescue plane drops a package of emergency rations to
// a stranded party of explorers, as shown in Figure 4.13.
// If the plane is traveling horizontally at 40.0 m/s and is
// 100 m above the ground, where does the package strike the
// ground relative to the point at which it was released?
// What are the horizontal and vertical components
// of the velocity of the package just before it hits the ground?
var xA = new Symbol("xA");
var xB = new Symbol("xB");
var yA = new Symbol("yA");
var yB = new Symbol("yB");
var vxA = new Symbol("vxA");
var vxB = new Symbol("vxB");
var vyA = new Symbol("vyA");
var vyB = new Symbol("vyB");
var tAB = new Symbol("tAB");
var ax = new Symbol("ax");
var ay = new Symbol("ay");
var Pi = new Symbol("Pi");
var eqs = and(
vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,
xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,
vxA != 0,
ay != 0
);
var vals = new List<Equation>() { xA == 0, yA == 100, vxA == 40, vyA == 0, yB == 0, ax == 0, ay == -9.8, Pi == Math.PI };
var zeros = vals.Where(eq => eq.b == 0).ToList();
DoubleFloat.tolerance = 0.00001;
eqs
.EliminateVariables(vxB, vyB, tAB)
.IsolateVariable(xB)
.LogicalExpand().SimplifyEquation()
.CheckVariable(ay)
.CheckVariable(vxA).SimplifyLogical()
.SubstituteEq(ax == 0)
.AssertEqTo(
or(
and(
vxA != 0,
xB == -(vxA ^ 2) * (-(-vyA / vxA + ay / (vxA ^ 2) * xA) + sqrt(((-vyA / vxA + ay * xA / (vxA ^ 2)) ^ 2) + 2 * ay * (vyA * xA / vxA - ay / 2 / (vxA ^ 2) * (xA ^ 2) - yA + yB) / (vxA ^ 2))) / ay,
ay / (vxA ^ 2) != 0,
ay != 0),
and(
vxA != 0,
xB == -(vxA ^ 2) * (-(-vyA / vxA + ay / (vxA ^ 2) * xA) - sqrt(((-vyA / vxA + ay * xA / (vxA ^ 2)) ^ 2) + 2 * ay * (vyA * xA / vxA - ay / 2 / (vxA ^ 2) * (xA ^ 2) - yA + yB) / (vxA ^ 2))) / ay,
ay / (vxA ^ 2) != 0,
ay != 0)))
.SubstituteEqLs(zeros)
.AssertEqTo(
or(
and(
vxA != 0,
xB == -1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
ay / (vxA ^ 2) != 0,
ay != 0),
and(
vxA != 0,
xB == 1 / ay * (vxA ^ 2) * sqrt(-2 * ay * (vxA ^ -2) * yA),
ay / (vxA ^ 2) != 0,
ay != 0)))
.SubstituteEqLs(vals)
.AssertEqTo(or(xB == 180.70158058105022, xB == -180.70158058105022));
eqs
.EliminateVariables(vxB, xB, tAB)
.IsolateVariable(vyB)
.LogicalExpand().SimplifyEquation()
.CheckVariable(ay)
.AssertEqTo(
or(
and(
vyB == -1 * ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
vxA != 0,
ay != 0),
and(
vyB == ay * sqrt(2 * (ay ^ -1) * ((ay ^ -1) / 2 * (vyA ^ 2) + -1 * yA + yB)),
vxA != 0,
ay != 0)))
.SubstituteEqLs(zeros)
.AssertEqTo(
or(
and(
vyB == -ay * sqrt(-2 / ay * yA),
vxA != 0,
ay != 0),
and(
vyB == ay * sqrt(-2 / ay * yA),
vxA != 0,
ay != 0)))
.SubstituteEqLs(vals)
.AssertEqTo(or(vyB == 44.271887242357309, vyB == -44.271887242357309));
DoubleFloat.tolerance = null;
}
[Fact]
public void PSE_5E_Example_4_7()
{
var xA = new Symbol("xA");
var yA = new Symbol("yA");
var xB = new Symbol("xB");
var yB = new Symbol("yB");
var vxA = new Symbol("vxA");
var vyA = new Symbol("vyA");
var vxB = new Symbol("vxB");
var vyB = new Symbol("vyB");
var tAB = new Symbol("tAB");
var ax = new Symbol("ax");
var ay = new Symbol("ay");
var th = new Symbol("th");
var d = new Symbol("d");
var Pi = new Symbol("Pi");
var eqs = and(
cos(th) == (xB - xA) / d,
sin(th) == (yA - yB) / d,
vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,
xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2,
yB != 0,
ay != 0
);
var vals = new List<Equation>() { xA == 0, yA == 0, vxA == 25, vyA == 0, ax == 0, ay == -9.8, th == (35).ToRadians(), Pi == Math.PI };
var zeros = vals.Where(eq => eq.b == 0).ToList();
DoubleFloat.tolerance = 0.00001;
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxB, vyB, d, yB, tAB)
.IsolateVariable(xB)
.LogicalExpand()
.CheckVariable(ay)
.SimplifyEquation()
.AssertEqTo(
or(
and(
xB == -(sin(th) / cos(th) + sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
ay / (vxA ^ 2) != 0,
sin(th) / cos(th) * xB != 0,
ay != 0),
and(
xB == -(sin(th) / cos(th) - sqrt((cos(th) ^ -2) * (sin(th) ^ 2))) * (vxA ^ 2) / ay,
ay / (vxA ^ 2) != 0,
sin(th) / cos(th) * xB != 0,
ay != 0)))
.SubstituteEqLs(vals)
.SimplifyEquation()
.AssertEqTo(
or(
and(
xB == 89.312185996136435,
xB != 0),
and(
xB == 7.0805039835788038E-15,
xB != 0)));
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxB, vyB, d, xB, tAB)
.IsolateVariable(yB)
.LogicalExpand()
.CheckVariable(yB)
.AssertEqTo(
and(
yB == 2 * (sin(th) ^ 2) * (vxA ^ 2) / ay / (cos(th) ^ 2),
-ay * (cos(th) ^ 2) / (sin(th) ^ 2) / (vxA ^ 2) / 2 != 0,
yB != 0,
ay != 0))
.SubstituteEqLs(vals)
.AssertEqTo(
and(
yB == -62.537065888482395,
yB != 0));
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxB, vyB, d, xB, yB)
.IsolateVariable(tAB)
.LogicalExpand().CheckVariable(ay).SimplifyEquation().SimplifyLogical()
.AssertEqTo(
or(
and(
tAB == -(sin(th) * vxA / cos(th) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
ay != 0,
sin(th) * tAB * vxA / cos(th) != 0),
and(
tAB == -(sin(th) * vxA / cos(th) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / (cos(th) ^ 2))) / ay,
ay != 0,
sin(th) * tAB * vxA / cos(th) != 0)))
.SubstituteEqLs(vals)
.CheckVariable(tAB).SimplifyEquation()
.AssertEqTo(
and(
tAB == 3.5724874398454571,
tAB != 0));
eqs
.SubstituteEqLs(zeros)
.EliminateVariables(vxB, d, tAB, xB, yB)
.IsolateVariable(vyB)
.LogicalExpand()
.CheckVariable(ay)
.SimplifyEquation()
.CheckVariable(ay)
.AssertEqTo(
or(
and(
vyB == -ay * (sin(th) * vxA / (ay * cos(th)) + sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
sin(th) * vxA * vyB / (ay * cos(th)) != 0,
ay != 0),
and(
vyB == -ay * (sin(th) * vxA / (ay * cos(th)) - sqrt((sin(th) ^ 2) * (vxA ^ 2) / ((ay ^ 2) * (cos(th) ^ 2)))),
sin(th) * vxA * vyB / (ay * cos(th)) != 0,
ay != 0)))
.SubstituteEqLs(vals)
.CheckVariable(vyB)
.SimplifyEquation()
.CheckVariable(vyB)
.AssertEqTo(
and(
vyB == -35.010376910485483,
vyB != 0));
DoubleFloat.tolerance = null;
}
[Fact]
public void PSE_5E_P4_9()
{
// In a local bar, a customer slides an empty beer mug
// down the counter for a refill. The bartender
gitextract_i2j1v7op/
├── .gitattributes
├── .gitignore
├── Examples/
│ ├── pse-example-5.10-Obj.md
│ ├── symbolism-linux.md
│ └── unit-test-index.md
├── README.md
├── Symbolism/
│ ├── AlgebraicExpand.cs
│ ├── CoefficientGpe.cs
│ ├── DeepSelect.cs
│ ├── DegreeGpe.cs
│ ├── EliminateVariable.cs
│ ├── ExpandPower.cs
│ ├── ExpandProduct.cs
│ ├── Has.cs
│ ├── IsolateVariable.cs
│ ├── LeadingCoefficientGpe.cs
│ ├── LogicalExpand.cs
│ ├── PolynomialDivision.cs
│ ├── PolynomialGcd.cs
│ ├── RationalExpand.cs
│ ├── RationalizeExpression.cs
│ ├── SimplifyEquation.cs
│ ├── SimplifyLogical.cs
│ ├── Substitute.cs
│ ├── Symbolism.cs
│ ├── Symbolism.csproj
│ ├── Trigonometric.cs
│ └── Utils.cs
├── Symbolism.sln
└── Tests/
├── Tests.cs
└── Tests.csproj
SYMBOL INDEX (566 symbols across 22 files)
FILE: Symbolism/AlgebraicExpand.cs
class Extensions (line 13) | public static class Extensions
method AlgebraicExpand (line 15) | public static MathObject AlgebraicExpand(this MathObject u)
FILE: Symbolism/CoefficientGpe.cs
class Extensions (line 13) | public static class Extensions
method CoefficientMonomialGpe (line 15) | public static Tuple<MathObject, BigInteger> CoefficientMonomialGpe(thi...
method CoefficientGpe (line 51) | public static MathObject CoefficientGpe(this MathObject u, MathObject ...
FILE: Symbolism/DeepSelect.cs
class Extensions (line 10) | public static class Extensions
method DeepSelect (line 12) | public static MathObject DeepSelect(this MathObject obj, Func<MathObje...
FILE: Symbolism/DegreeGpe.cs
class Extensions (line 13) | public static class Extensions
method DegreeMonomialGpe (line 15) | public static BigInteger DegreeMonomialGpe(this MathObject u, List<Mat...
method DegreeGpe (line 33) | public static BigInteger DegreeGpe(this MathObject u, List<MathObject> v)
FILE: Symbolism/EliminateVariable.cs
class Extensions (line 14) | public static class Extensions
method CheckVariableEqLs (line 16) | public static MathObject CheckVariableEqLs(this List<Equation> eqs, Sy...
method CheckVariable (line 41) | public static MathObject CheckVariable(this MathObject expr, Symbol sym)
method EliminateVariableEqLs (line 84) | public static MathObject EliminateVariableEqLs(this List<Equation> eqs...
method EliminateVariable (line 143) | public static MathObject EliminateVariable(this MathObject expr, Symbo...
method EliminateVariables (line 162) | public static MathObject EliminateVariables(this MathObject expr, para...
FILE: Symbolism/ExpandPower.cs
class Extensions (line 14) | public static class Extensions
method Factorial (line 16) | static BigInteger Factorial(BigInteger n)
method ExpandPower (line 29) | public static MathObject ExpandPower(this MathObject u, BigInteger n)
FILE: Symbolism/ExpandProduct.cs
class Extensions (line 10) | public static class Extensions
method ExpandProduct (line 12) | public static MathObject ExpandProduct(this MathObject r, MathObject s)
FILE: Symbolism/Has.cs
class Extensions (line 10) | public static class Extensions
method Has (line 12) | public static bool Has(this MathObject obj, MathObject a)
method Has (line 27) | public static bool Has(this MathObject obj, Func<MathObject, bool> proc)
method FreeOf (line 42) | public static bool FreeOf(this MathObject obj, MathObject a) => !obj.H...
FILE: Symbolism/IsolateVariable.cs
class Extensions (line 17) | public static class Extensions
method IsolateVariableEq (line 19) | public static MathObject IsolateVariableEq(this Equation eq, Symbol sym)
method IsolateVariable (line 256) | public static MathObject IsolateVariable(this MathObject obj, Symbol sym)
FILE: Symbolism/LeadingCoefficientGpe.cs
class Extensions (line 10) | public static class Extensions
method LeadingCoefficientGpe (line 12) | public static MathObject LeadingCoefficientGpe(this MathObject u, Math...
FILE: Symbolism/LogicalExpand.cs
class Extensions (line 8) | public static class Extensions
method LogicalExpand (line 10) | public static MathObject LogicalExpand(this MathObject obj)
FILE: Symbolism/PolynomialDivision.cs
class Extensions (line 14) | public static class Extensions
method PolynomialDivision (line 16) | public static (MathObject quotient, MathObject remainder) PolynomialDi...
FILE: Symbolism/PolynomialGcd.cs
class Extensions (line 15) | public static class Extensions
method PolynomialGcd (line 17) | public static MathObject PolynomialGcd(MathObject u, MathObject v, Mat...
FILE: Symbolism/RationalExpand.cs
class Extensions (line 13) | public static class Extensions
method RationalExpand (line 15) | public static MathObject RationalExpand(this MathObject u)
FILE: Symbolism/RationalizeExpression.cs
class Extensions (line 10) | public static class Extensions
method RationalizeSum (line 12) | static MathObject RationalizeSum(MathObject u, MathObject v)
method RationalizeExpression (line 24) | public static MathObject RationalizeExpression(this MathObject u)
FILE: Symbolism/SimplifyEquation.cs
class Extensions (line 8) | public static class Extensions
method SimplifyEquation (line 10) | public static MathObject SimplifyEquation(this MathObject expr)
FILE: Symbolism/SimplifyLogical.cs
class Extensions (line 8) | public static class Extensions
method HasDuplicates (line 10) | static bool HasDuplicates(this IEnumerable<MathObject> ls)
method RemoveDuplicates (line 17) | static IEnumerable<MathObject> RemoveDuplicates(this IEnumerable<MathO...
method SimplifyLogical (line 28) | public static MathObject SimplifyLogical(this MathObject expr)
FILE: Symbolism/Substitute.cs
class Extensions (line 10) | public static class Extensions
method Substitute (line 12) | public static MathObject Substitute(this MathObject obj, MathObject a,...
method SubstituteEq (line 57) | public static MathObject SubstituteEq(this MathObject obj, Equation eq...
method SubstituteEqLs (line 60) | public static MathObject SubstituteEqLs(this MathObject obj, List<Equa...
method Substitute (line 63) | public static MathObject Substitute(this MathObject obj, MathObject a,...
method Substitute (line 66) | public static MathObject Substitute(this MathObject obj, MathObject a,...
FILE: Symbolism/Symbolism.cs
class MathObject (line 24) | public abstract class MathObject
method Precedence (line 107) | public int Precedence()
type ToStringForms (line 123) | public enum ToStringForms { Full, Standard }
method FullForm (line 127) | public virtual string FullForm() => base.ToString();
method StandardForm (line 129) | public virtual string StandardForm() => FullForm();
method ToString (line 131) | public override string ToString()
method Numerator (line 140) | public virtual MathObject Numerator() => this;
method Denominator (line 142) | public virtual MathObject Denominator() => 1;
method Equals (line 144) | public override bool Equals(object obj)
method GetHashCode (line 147) | public override int GetHashCode() => base.GetHashCode();
class Equation (line 150) | public class Equation : MathObject
type Operators (line 152) | public enum Operators { Equal, NotEqual, LessThan, GreaterThan }
method Equation (line 159) | public Equation(MathObject x, MathObject y)
method Equation (line 162) | public Equation(MathObject x, MathObject y, Operators op)
method FullForm (line 165) | public override string FullForm()
method Equals (line 174) | public override bool Equals(object obj) =>
method ToBoolean (line 180) | Boolean ToBoolean()
method Simplify (line 227) | public MathObject Simplify()
method GetHashCode (line 234) | public override int GetHashCode() => new { a, b }.GetHashCode();
class Bool (line 238) | public class Bool : MathObject
method Bool (line 242) | public Bool(bool b) { val = b; }
method FullForm (line 244) | public override string FullForm() => val.ToString();
method Equals (line 246) | public override bool Equals(object obj) => val == (obj as Bool)?.val;
method GetHashCode (line 248) | public override int GetHashCode() => val.GetHashCode();
class Number (line 263) | public abstract class Number : MathObject
method ToDouble (line 265) | public abstract DoubleFloat ToDouble();
class Integer (line 268) | public class Integer : Number
method Integer (line 272) | public Integer(int n) { val = n; }
method Integer (line 274) | public Integer(BigInteger n) { val = n; }
method FullForm (line 284) | public override string FullForm() => val.ToString();
method Equals (line 286) | public override bool Equals(object obj) => val == (obj as Integer)?.val;
method GetHashCode (line 288) | public override int GetHashCode() => val.GetHashCode();
method ToDouble (line 290) | public override DoubleFloat ToDouble() => new DoubleFloat((double)val);
class DoubleFloat (line 293) | public class DoubleFloat : Number
method DoubleFloat (line 299) | public DoubleFloat(double n) { val = n; }
method FullForm (line 301) | public override string FullForm() => val.ToString("R");
method Equals (line 311) | public override bool Equals(object obj)
method GetHashCode (line 321) | public override int GetHashCode() => val.GetHashCode();
method ToDouble (line 323) | public override DoubleFloat ToDouble() => this;
class Fraction (line 326) | public class Fraction : Number
method Fraction (line 331) | public Fraction(Integer a, Integer b)
method FullForm (line 334) | public override string FullForm() => numerator + "/" + denominator;
method ToDouble (line 336) | public override DoubleFloat ToDouble() => new DoubleFloat((double)nume...
method Equals (line 339) | public override bool Equals(object obj) =>
method GetHashCode (line 344) | public override int GetHashCode() => new { numerator, denominator }.Ge...
method Numerator (line 346) | public override MathObject Numerator() => numerator;
method Denominator (line 348) | public override MathObject Denominator() => denominator;
class Rational (line 351) | public static class Rational
method Div (line 353) | static BigInteger Div(BigInteger a, BigInteger b)
method Rem (line 356) | static BigInteger Rem(BigInteger a, BigInteger b)
method Gcd (line 359) | static BigInteger Gcd(BigInteger a, BigInteger b)
method SimplifyRationalNumber (line 371) | public static MathObject SimplifyRationalNumber(MathObject u)
method Numerator (line 393) | public static Integer Numerator(MathObject u)
method Denominator (line 419) | public static Integer Denominator(MathObject u)
method EvaluateSum (line 440) | public static Fraction EvaluateSum(MathObject v, MathObject w) =>
method EvaluateDifference (line 450) | public static Fraction EvaluateDifference(MathObject v, MathObject w) =>
method EvaluateProduct (line 455) | public static Fraction EvaluateProduct(MathObject v, MathObject w) =>
method EvaluateQuotient (line 460) | public static MathObject EvaluateQuotient(MathObject v, MathObject w)
method EvaluatePower (line 470) | public static MathObject EvaluatePower(MathObject v, BigInteger n)
method SimplifyRNERec (line 494) | public static MathObject SimplifyRNERec(MathObject u)
method SimplifyRNE (line 570) | public static MathObject SimplifyRNE(MathObject u)
class Undefined (line 578) | public class Undefined : MathObject { }
class MiscUtils (line 580) | public static class MiscUtils { }
class Symbol (line 582) | public class Symbol : MathObject
method Symbol (line 586) | public Symbol(String str) { name = str; }
method FullForm (line 588) | public override string FullForm() => name;
method GetHashCode (line 590) | public override int GetHashCode() => name.GetHashCode();
method Equals (line 592) | public override bool Equals(Object obj) =>
class ListConstructor (line 596) | public static class ListConstructor
method List (line 598) | public static List<T> List<T>(params T[] items) => new List<T>(items);
method ImList (line 600) | public static ImmutableList<T> ImList<T>(params T[] items) => Immutabl...
class ListUtils (line 603) | public static class ListUtils
method Cons (line 605) | public static ImmutableList<MathObject> Cons(this ImmutableList<MathOb...
method Cdr (line 608) | public static ImmutableList<MathObject> Cdr(this ImmutableList<MathObj...
method equal (line 610) | public static bool equal(ImmutableList<MathObject> a, ImmutableList<Ma...
class Function (line 624) | public class Function : MathObject
method Function (line 634) | public Function(string name, Proc proc, IEnumerable<MathObject> args)
method Equals (line 641) | public override bool Equals(object obj) =>
method Simplify (line 646) | public MathObject Simplify() => proc == null ? this : proc(args.ToArra...
method FullForm (line 648) | public override string FullForm() => $"{name}({string.Join(", ", args)...
method Clone (line 650) | public MathObject Clone() => MemberwiseClone() as MathObject;
method GetHashCode (line 652) | public override int GetHashCode() => new { name, args }.GetHashCode();
class FunctionExtensions (line 655) | public static class FunctionExtensions
class And (line 666) | public class And : Function
method AndProc (line 668) | static MathObject AndProc(MathObject[] ls)
method And (line 696) | public And(params MathObject[] ls) : base("and", AndProc, ls) { }
method And (line 698) | public And() : base("and", AndProc, new List<MathObject>()) { }
method FromRange (line 700) | public static And FromRange(IEnumerable<MathObject> ls) => new And(ls....
method Add (line 702) | public MathObject Add(MathObject obj) =>
method AddRange (line 705) | public MathObject AddRange(IEnumerable<MathObject> ls) =>
method Map (line 708) | public MathObject Map(Func<MathObject, MathObject> proc) =>
class Or (line 712) | public class Or : Function
method OrProc (line 714) | static MathObject OrProc(params MathObject[] ls)
method Or (line 743) | public Or(params MathObject[] ls) : base("or", OrProc, ls) { }
method Or (line 745) | public Or() : base("or", OrProc, new List<MathObject>()) { }
method FromRange (line 747) | public static Or FromRange(IEnumerable<MathObject> ls) => new Or(ls.To...
method Map (line 749) | public MathObject Map(Func<MathObject, MathObject> proc) => Or.FromRan...
class OrderRelation (line 752) | public static class OrderRelation
method Base (line 754) | public static MathObject Base(MathObject u) => u is Power ? (u as Powe...
method Exponent (line 756) | public static MathObject Exponent(MathObject u) => u is Power ? (u as ...
method Term (line 758) | public static MathObject Term(this MathObject u)
method Const (line 769) | public static MathObject Const(this MathObject u) =>
method O3 (line 772) | public static bool O3(ImmutableList<MathObject> uElts, ImmutableList<M...
method Compare (line 785) | public static bool Compare(MathObject u, MathObject v)
class Power (line 884) | public class Power : MathObject
method Power (line 889) | public Power(MathObject a, MathObject b) { bas = a; exp = b; }
method FullForm (line 891) | public override string FullForm() =>
method StandardForm (line 896) | public override string StandardForm()
method Equals (line 907) | public override bool Equals(object obj) =>
method Simplify (line 910) | public MathObject Simplify()
method Numerator (line 961) | public override MathObject Numerator()
method Denominator (line 970) | public override MathObject Denominator()
method GetHashCode (line 979) | public override int GetHashCode() => new { bas, exp }.GetHashCode();
class Product (line 982) | public class Product : MathObject
method Product (line 986) | public Product(params MathObject[] ls) => elts = ImmutableList.Create(...
method FromRange (line 988) | public static Product FromRange(IEnumerable<MathObject> ls) => new Pro...
method FullForm (line 990) | public override string FullForm() =>
method StandardForm (line 993) | public override string StandardForm()
method GetHashCode (line 1015) | public override int GetHashCode() => elts.GetHashCode();
method Equals (line 1017) | public override bool Equals(object obj) =>
method MergeProducts (line 1020) | static ImmutableList<MathObject> MergeProducts(ImmutableList<MathObjec...
method SimplifyDoubleNumberProduct (line 1044) | static ImmutableList<MathObject> SimplifyDoubleNumberProduct(DoubleFlo...
method RecursiveSimplify (line 1059) | public static ImmutableList<MathObject> RecursiveSimplify(ImmutableLis...
method Simplify (line 1126) | public MathObject Simplify()
method Numerator (line 1146) | public override MathObject Numerator() =>
method Denominator (line 1149) | public override MathObject Denominator() =>
method Map (line 1152) | public MathObject Map(Func<MathObject, MathObject> proc) =>
class Sum (line 1156) | public class Sum : MathObject
method Sum (line 1160) | public Sum(params MathObject[] ls) { elts = ImmutableList.Create(ls); }
method FromRange (line 1162) | public static Sum FromRange(IEnumerable<MathObject> ls) => new Sum(ls....
method GetHashCode (line 1164) | public override int GetHashCode() => elts.GetHashCode();
method Equals (line 1166) | public override bool Equals(object obj) =>
method MergeSums (line 1169) | static ImmutableList<MathObject> MergeSums(ImmutableList<MathObject> p...
method SimplifyDoubleNumberSum (line 1193) | static ImmutableList<MathObject> SimplifyDoubleNumberSum(DoubleFloat a...
method RecursiveSimplify (line 1208) | static ImmutableList<MathObject> RecursiveSimplify(ImmutableList<MathO...
method Simplify (line 1278) | public MathObject Simplify()
method FullForm (line 1290) | public override string FullForm() =>
method StandardForm (line 1293) | public override string StandardForm()
method Map (line 1313) | public MathObject Map(Func<MathObject, MathObject> proc) =>
class Difference (line 1317) | class Difference : MathObject
method Difference (line 1321) | public Difference(params MathObject[] ls) => elts = ImmutableList.Crea...
method Simplify (line 1323) | public MathObject Simplify()
class Quotient (line 1333) | class Quotient : MathObject
method Quotient (line 1337) | public Quotient(params MathObject[] ls) => elts = ImmutableList.Create...
method Simplify (line 1339) | public MathObject Simplify() => elts[0] * (elts[1] ^ -1);
class Constructors (line 1342) | public static class Constructors
method sqrt (line 1344) | public static MathObject sqrt(MathObject obj) => obj ^ (new Integer(1)...
method and (line 1346) | public static MathObject and(params MathObject[] ls) => And.FromRange(...
method or (line 1348) | public static MathObject or(params MathObject[] ls) => Or.FromRange(ls...
FILE: Symbolism/Trigonometric.cs
class Sin (line 12) | public class Sin : Function
method Mod (line 14) | public static MathObject Mod(MathObject x, MathObject y)
method SinProc (line 26) | static MathObject SinProc(params MathObject[] ls)
method Sin (line 165) | public Sin(MathObject param) : base("sin", SinProc, new[] { param }) { }
class Cos (line 167) | public class Cos : Function
method Mod (line 169) | public static MathObject Mod(MathObject x, MathObject y)
method CosProc (line 181) | static MathObject CosProc(params MathObject[] ls)
method Cos (line 336) | public Cos(MathObject param) : base("cos", CosProc, new[] { param }) { }
class Tan (line 338) | public class Tan : Function
method TanProc (line 340) | static MathObject TanProc(params MathObject[] ls)
method Tan (line 348) | public Tan(MathObject param) : base("tan", TanProc, new[] { param }) { }
class Asin (line 350) | public class Asin : Function
method AsinProc (line 352) | static MathObject AsinProc(params MathObject[] ls)
method Asin (line 360) | public Asin(MathObject param) : base("asin", AsinProc, new[] { param }...
class Atan (line 362) | public class Atan : Function
method AtanProc (line 364) | static MathObject AtanProc(params MathObject[] ls)
method Atan (line 372) | public Atan(MathObject param) : base("atan", AtanProc, new[] { param }...
class Atan2 (line 374) | public class Atan2 : Function
method Atan2Proc (line 376) | static MathObject Atan2Proc(params MathObject[] ls)
method Atan2 (line 416) | public Atan2(MathObject a, MathObject b) : base("atan2", Atan2Proc, ne...
class Constructors (line 419) | public static class Constructors
method sin (line 421) | public static MathObject sin(MathObject obj) => new Sin(obj).Simplify();
method cos (line 422) | public static MathObject cos(MathObject obj) => new Cos(obj).Simplify();
method tan (line 423) | public static MathObject tan(MathObject obj) => new Tan(obj).Simplify();
method asin (line 425) | public static MathObject asin(MathObject obj) => new Asin(obj).Simplif...
method atan (line 426) | public static MathObject atan(MathObject obj) => new Atan(obj).Simplif...
class Extensions (line 429) | public static class Extensions
method ToRadians (line 433) | public static MathObject ToRadians(this MathObject n) => n * Pi / 180;
method ToDegrees (line 435) | public static MathObject ToDegrees(this MathObject n) => 180 * n / Pi;
method ToRadians (line 437) | public static MathObject ToRadians(this int n) => new Integer(n) * Pi ...
method ToDegrees (line 439) | public static MathObject ToDegrees(this int n) => 180 * new Integer(n)...
FILE: Symbolism/Utils.cs
class Extensions (line 7) | public static class Extensions
method Disp (line 9) | public static T Disp<T>(this T obj)
method Disp (line 15) | public static T Disp<T>(this T obj, string format)
method DispLong (line 21) | public static MathObject DispLong(this MathObject obj, int indent = 0,...
FILE: Tests/Tests.cs
class Extensions (line 48) | public static class Extensions
method AssertEqTo (line 52) | public static MathObject AssertEqTo(this MathObject a, MathObject b)
method MultiplyBothSidesBy (line 59) | public static MathObject MultiplyBothSidesBy(this MathObject obj, Math...
method AddToBothSides (line 75) | public static MathObject AddToBothSides(this MathObject obj, MathObjec...
class Obj2 (line 84) | public class Obj2
method Obj2 (line 97) | public Obj2(string name)
method Equations (line 120) | public And Equations()
class Obj3 (line 140) | public class Obj3
method Obj3 (line 153) | public Obj3(string name)
method Equations (line 180) | public And Equations()
class Obj5 (line 203) | public class Obj5
method Obj5 (line 216) | public Obj5(string name)
method Equations (line 251) | public And Equations()
class KinematicObjectABC (line 280) | public class KinematicObjectABC
method KinematicObjectABC (line 290) | public KinematicObjectABC(string name)
method EquationsAB (line 329) | public And EquationsAB() =>
method EquationsBC (line 341) | public And EquationsBC() =>
method EquationsAC (line 353) | public And EquationsAC() =>
method TrigEquationsA (line 365) | public And TrigEquationsA() =>
class Tests (line 376) | public class Tests
method Int (line 388) | Integer Int(int n) => new Integer(n);
method Test1 (line 391) | [Fact] public void Test1() => Assert.True(new DoubleFloat(1.2).Equals(...
method Test2 (line 392) | [Fact] public void Test2() => Assert.False(new DoubleFloat(1.20000001)...
method Test3 (line 394) | [Fact]
method Test4 (line 404) | [Fact] public void Test4() => Assert.False(new DoubleFloat(1.2).Equals...
method Test5 (line 409) | [Fact] public void Test5() => Assert.True((2 * x * y).Const() == 2);
method Test6 (line 410) | [Fact] public void Test6() => Assert.True((x * y / 2).Const() == new I...
method Test7 (line 411) | [Fact] public void Test7() => Assert.True((0.1 * x * y).Const() == 0.1);
method Test8 (line 412) | [Fact] public void Test8() => Assert.True((x * y).Const() == 1);
method Test9 (line 418) | [Fact] public void Test9() => Assert.True(x + x == 2 * x);
method Test10 (line 419) | [Fact] public void Test10() => Assert.True(x + x + x == 3 * x);
method Test11 (line 420) | [Fact] public void Test11() => Assert.True(5 + x + 2 == 7 + x);
method Test12 (line 421) | [Fact] public void Test12() => Assert.True(3 + x + 5 + x == 8 + 2 * x);
method Test13 (line 422) | [Fact] public void Test13() => Assert.True(4 * x + 3 * x == 7 * x);
method Test14 (line 423) | [Fact] public void Test14() => Assert.True(x + y + z + x + y + z == 2 ...
method Test15 (line 424) | [Fact] public void Test15() => Assert.True(10 - x == 10 + x * -1);
method Test16 (line 425) | [Fact] public void Test16() => Assert.True(x * y / 3 == Int(1) / 3 * x...
method Test17 (line 426) | [Fact] public void Test17() => Assert.True(x / y == x * (y ^ -1));
method Test18 (line 427) | [Fact] public void Test18() => Assert.True(x / 3 == x * (Int(1) / 3));
method Test19 (line 428) | [Fact] public void Test19() => Assert.True(6 * x * y / 3 == 2 * x * y);
method Test20 (line 429) | [Fact] public void Test20() => Assert.True((((x ^ Int(1) / 2) ^ Int(1)...
method Test21 (line 430) | [Fact] public void Test21() => Assert.True(((((x * y) ^ (Int(1) / 2)) ...
method Test22 (line 431) | [Fact] public void Test22() => Assert.True(x / x == 1);
method Test23 (line 432) | [Fact] public void Test23() => Assert.True(x / y * y / x == 1);
method Test24 (line 433) | [Fact] public void Test24() => Assert.True((x ^ 2) * (x ^ 3) == (x ^ 5));
method Test25 (line 434) | [Fact] public void Test25() => Assert.True(x + y + x + z + 5 + z == 5 ...
method Test26 (line 435) | [Fact] public void Test26() => Assert.True(((Int(1) / 2) * x + (Int(3)...
method Test27 (line 436) | [Fact] public void Test27() => Assert.True(1.2 * x + 3 * x == 4.2 * x);
method Test28 (line 437) | [Fact] public void Test28() => Assert.True(3 * x + 1.2 * x == 4.2 * x);
method Test29 (line 438) | [Fact] public void Test29() => Assert.True(1.2 * x * 3 * y == 3.599999...
method Test30 (line 439) | [Fact] public void Test30() => Assert.True(3 * x * 1.2 * y == 3.599999...
method Test31 (line 440) | [Fact] public void Test31() => Assert.True(3.4 * x * 1.2 * y == 4.08 *...
method Test32 (line 441) | [Fact] public void Test32() => Assert.True((a == b) == (a == b));
method Test33 (line 446) | [Fact] public void Test33() => Assert.True((0 ^ x) == 0);
method Test34 (line 447) | [Fact] public void Test34() => Assert.True((1 ^ x) == 1);
method Test35 (line 448) | [Fact] public void Test35() => Assert.True((x ^ 0) == 1);
method Test36 (line 449) | [Fact] public void Test36() => Assert.True((x ^ 1) == x);
method Test37 (line 453) | [Fact] public void Test37() => Assert.True(x * 0 == 0);
method Test38 (line 456) | [Fact] public void Test38() => Assert.True(-x == -1 * x);
method Test39 (line 457) | [Fact] public void Test39() => Assert.True(x - y == x + -1 * y);
method Test40 (line 461) | [Fact] public void Test40() => Assert.True(Int(10).Substitute(Int(10),...
method Test41 (line 462) | [Fact] public void Test41() => Assert.True(Int(10).Substitute(Int(15),...
method Test42 (line 464) | [Fact] public void Test42() => Assert.True(new DoubleFloat(1.0).Substi...
method Test43 (line 465) | [Fact] public void Test43() => Assert.True(new DoubleFloat(1.0).Substi...
method Test44 (line 467) | [Fact] public void Test44() => Assert.True((Int(1) / 2).Substitute(Int...
method Test45 (line 468) | [Fact] public void Test45() => Assert.True((Int(1) / 2).Substitute(Int...
method Test46 (line 470) | [Fact] public void Test46() => Assert.True(x.Substitute(x, y) == y);
method Test47 (line 471) | [Fact] public void Test47() => Assert.True(x.Substitute(y, y) == x);
method Test48 (line 473) | [Fact] public void Test48() => Assert.True((x ^ y).Substitute(x, 10) =...
method Test49 (line 474) | [Fact] public void Test49() => Assert.True((x ^ y).Substitute(y, 10) =...
method Test50 (line 476) | [Fact] public void Test50() => Assert.True((x ^ y).Substitute(x ^ y, 1...
method Test51 (line 478) | [Fact] public void Test51() => Assert.True((x * y * z).Substitute(x, y...
method Test52 (line 479) | [Fact] public void Test52() => Assert.True((x * y * z).Substitute(x * ...
method Test53 (line 481) | [Fact] public void Test53() => Assert.True((x + y + z).Substitute(x, y...
method Test54 (line 482) | [Fact] public void Test54() => Assert.True((x + y + z).Substitute(x + ...
method Test55 (line 484) | [Fact] public void Test55() => Assert.True(((((x * y) ^ (Int(1) / 2)) ...
method Test56 (line 488) | [Fact] public void Test56() => Assert.True((x == y).Substitute(y, z) =...
method Test57 (line 490) | [Fact] public void Test57() => Assert.True((x != y).Substitute(y, z) =...
method Test58 (line 492) | [Fact] public void Test58() => (x == 0).Substitute(x, 0).AssertEqTo(tr...
method Test59 (line 493) | [Fact] public void Test59() => (x == 0).Substitute(x, 1).AssertEqTo(fa...
method Test60 (line 494) | [Fact] public void Test60() => (x != 0).Substitute(x, 0).AssertEqTo(fa...
method Test61 (line 495) | [Fact] public void Test61() => (x != 0).Substitute(x, 1).AssertEqTo(tr...
method Test62 (line 501) | [Fact] public void Test62() => Assert.True(sin(new DoubleFloat(3.14159...
method Test63 (line 503) | [Fact] public void Test63() => Assert.True(sin(x + y) + sin(x + y) == ...
method Test64 (line 505) | [Fact] public void Test64() => Assert.True(sin(x + x) == sin(2 * x));
method Test65 (line 507) | [Fact] public void Test65() => Assert.True(sin(x + x).Substitute(x, 1)...
method Test66 (line 509) | [Fact] public void Test66() => Assert.True(sin(x + x).Substitute(x, 1....
method Test67 (line 511) | [Fact] public void Test67() => Assert.True(sin(2 * x).Substitute(x, y)...
method Test68 (line 515) | [Fact] public void Test68() => Assert.True(1 * x == x);
method Test69 (line 517) | [Fact] public void Test69() => Assert.True(x * 1 == x);
method Test70 (line 519) | [Fact] public void Test70() => Assert.True(x != y);
method Test71 (line 521) | [Fact] public void Test71() => Assert.True(x != 10);
method Test72 (line 525) | [Fact] public void Test72() => Assert.True(1.0 == new DoubleFloat(3.0)...
method Test73 (line 527) | [Fact] public void Test73() => Assert.True((a == b) != (a != b));
method Test74 (line 529) | [Fact] public void Test74() => (sqrt(a * b) * (sqrt(a * b) / a) / c).A...
method AssertToStringMatch (line 531) | void AssertToStringMatch(MathObject obj, string str) => Assert.True(ob...
method Test75 (line 533) | [Fact]
method Test76 (line 561) | [Fact]
method Test77 (line 640) | [Fact] public void Test77() => Assert.True((x == y).ToString() == "x =...
method Test78 (line 642) | [Fact] public void Test78() => Assert.True((x != y).ToString() == "x !...
method Test79 (line 647) | [Fact] public void Test79() => Assert.True(new And().ToString() == "an...
method Test80 (line 653) | [Fact] public void Test80() => (new Integer(0) == new Integer(0)).Simp...
method Test81 (line 654) | [Fact] public void Test81() => (new Integer(0) == new Integer(1)).Simp...
method Test82 (line 655) | [Fact] public void Test82() => (new Integer(0) != new Integer(1)).Simp...
method Test83 (line 656) | [Fact] public void Test83() => (new Integer(0) != new Integer(0)).Simp...
method Test84 (line 661) | [Fact] public void Test84() => and().AssertEqTo(true);
method Test85 (line 663) | [Fact] public void Test85() => and(10).AssertEqTo(10);
method Test86 (line 665) | [Fact] public void Test86() => and(true).AssertEqTo(true);
method Test87 (line 667) | [Fact] public void Test87() => and(false).AssertEqTo(false);
method Test88 (line 669) | [Fact] public void Test88() => and(10, 20, 30).AssertEqTo(and(10, 20, ...
method Test89 (line 671) | [Fact] public void Test89() => and(10, false, 20).AssertEqTo(false);
method Test90 (line 673) | [Fact] public void Test90() => and(10, true, 20).AssertEqTo(and(10, 20));
method Test91 (line 675) | [Fact] public void Test91() => and(10, and(20, 30), 40).AssertEqTo(and...
method Test92 (line 680) | [Fact] public void Test92() => or(10).AssertEqTo(10);
method Test93 (line 682) | [Fact] public void Test93() => or(true).AssertEqTo(true);
method Test94 (line 684) | [Fact] public void Test94() => or(false).AssertEqTo(false);
method Test95 (line 686) | [Fact] public void Test95() => or(10, 20, false).AssertEqTo(or(10, 20));
method Test96 (line 688) | [Fact] public void Test96() => or(false, false).AssertEqTo(false);
method Test97 (line 690) | [Fact] public void Test97() => or(10, true, 20, false).AssertEqTo(true);
method Test98 (line 692) | [Fact] public void Test98() => or(10, false, 20).AssertEqTo(or(10, 20));
method Test99 (line 694) | [Fact] public void Test99() => or(10, or(20, 30), 40).AssertEqTo(or(10...
method Test100 (line 700) | [Fact]
method Test101 (line 705) | [Fact]
method Test102 (line 709) | [Fact]
method Test103 (line 713) | [Fact]
method Test104 (line 721) | [Fact]
method Test105 (line 726) | [Fact]
method Test106 (line 740) | [Fact] public void Test106() => sin(0).AssertEqTo(0);
method Test107 (line 742) | [Fact] public void Test107() => sin(Pi).AssertEqTo(0);
method Test108 (line 744) | [Fact] public void Test108() => sin(-10).AssertEqTo(-sin(10));
method Test109 (line 746) | [Fact] public void Test109() => sin(-x).AssertEqTo(-sin(x));
method Test110 (line 748) | [Fact] public void Test110() => sin(-5 * x).AssertEqTo(-sin(5 * x));
method Test111 (line 752) | [Fact] public void Test111() => sin(-2 * Pi).AssertEqTo(0);
method Test112 (line 753) | [Fact] public void Test112() => sin(-1 * Pi).AssertEqTo(0);
method Test113 (line 754) | [Fact] public void Test113() => sin(2 * Pi).AssertEqTo(0);
method Test114 (line 755) | [Fact] public void Test114() => sin(3 * Pi).AssertEqTo(0);
method Test115 (line 757) | [Fact] public void Test115() => sin(-7 * Pi / 2).AssertEqTo(1);
method Test116 (line 758) | [Fact] public void Test116() => sin(-5 * Pi / 2).AssertEqTo(-1);
method Test117 (line 759) | [Fact] public void Test117() => sin(-3 * Pi / 2).AssertEqTo(1);
method Test118 (line 760) | [Fact] public void Test118() => sin(-1 * Pi / 2).AssertEqTo(-1);
method Test119 (line 761) | [Fact] public void Test119() => sin(1 * Pi / 2).AssertEqTo(1);
method Test120 (line 762) | [Fact] public void Test120() => sin(3 * Pi / 2).AssertEqTo(-1);
method Test121 (line 763) | [Fact] public void Test121() => sin(5 * Pi / 2).AssertEqTo(1);
method Test122 (line 764) | [Fact] public void Test122() => sin(7 * Pi / 2).AssertEqTo(-1);
method Test123 (line 766) | [Fact] public void Test123() => sin(-4 * Pi / 3).AssertEqTo(sqrt(3) / 2);
method Test124 (line 767) | [Fact] public void Test124() => sin(-2 * Pi / 3).AssertEqTo(-sqrt(3) /...
method Test125 (line 768) | [Fact] public void Test125() => sin(-1 * Pi / 3).AssertEqTo(-sqrt(3) /...
method Test126 (line 769) | [Fact] public void Test126() => sin(1 * Pi / 3).AssertEqTo(sqrt(3) / 2);
method Test127 (line 770) | [Fact] public void Test127() => sin(2 * Pi / 3).AssertEqTo(sqrt(3) / 2);
method Test128 (line 771) | [Fact] public void Test128() => sin(4 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
method Test129 (line 772) | [Fact] public void Test129() => sin(5 * Pi / 3).AssertEqTo(-sqrt(3) / 2);
method Test130 (line 773) | [Fact] public void Test130() => sin(7 * Pi / 3).AssertEqTo(sqrt(3) / 2);
method Test131 (line 775) | [Fact] public void Test131() => sin(-3 * Pi / 4).AssertEqTo(-1 / sqrt(...
method Test132 (line 776) | [Fact] public void Test132() => sin(-1 * Pi / 4).AssertEqTo(-1 / sqrt(...
method Test133 (line 777) | [Fact] public void Test133() => sin(1 * Pi / 4).AssertEqTo(1 / sqrt(2));
method Test134 (line 778) | [Fact] public void Test134() => sin(3 * Pi / 4).AssertEqTo(1 / sqrt(2));
method Test135 (line 779) | [Fact] public void Test135() => sin(5 * Pi / 4).AssertEqTo(-1 / sqrt(2));
method Test136 (line 780) | [Fact] public void Test136() => sin(7 * Pi / 4).AssertEqTo(-1 / sqrt(2));
method Test137 (line 781) | [Fact] public void Test137() => sin(9 * Pi / 4).AssertEqTo(1 / sqrt(2));
method Test138 (line 782) | [Fact] public void Test138() => sin(11 * Pi / 4).AssertEqTo(1 / sqrt(2));
method Test139 (line 784) | [Fact] public void Test139() => sin(-5 * Pi / 6).AssertEqTo(-half);
method Test140 (line 785) | [Fact] public void Test140() => sin(-1 * Pi / 6).AssertEqTo(-half);
method Test141 (line 786) | [Fact] public void Test141() => sin(1 * Pi / 6).AssertEqTo(half);
method Test142 (line 787) | [Fact] public void Test142() => sin(5 * Pi / 6).AssertEqTo(half);
method Test143 (line 788) | [Fact] public void Test143() => sin(7 * Pi / 6).AssertEqTo(-half);
method Test144 (line 789) | [Fact] public void Test144() => sin(11 * Pi / 6).AssertEqTo(-half);
method Test145 (line 790) | [Fact] public void Test145() => sin(13 * Pi / 6).AssertEqTo(half);
method Test146 (line 791) | [Fact] public void Test146() => sin(17 * Pi / 6).AssertEqTo(half);
method Test147 (line 795) | [Fact] public void Test147() => sin(15 * Pi / 7).AssertEqTo(sin(1 * Pi...
method Test148 (line 796) | [Fact] public void Test148() => sin(8 * Pi / 7).AssertEqTo(-sin(1 * Pi...
method Test149 (line 797) | [Fact] public void Test149() => sin(4 * Pi / 7).AssertEqTo(sin(3 * Pi ...
method Test150 (line 801) | [Fact] public void Test150() => sin(x - 3 * Pi).AssertEqTo(sin(x + Pi));
method Test151 (line 802) | [Fact] public void Test151() => sin(x - 2 * Pi).AssertEqTo(sin(x));
method Test152 (line 803) | [Fact] public void Test152() => sin(x + 2 * Pi).AssertEqTo(sin(x));
method Test153 (line 804) | [Fact] public void Test153() => sin(x + 3 * Pi).AssertEqTo(sin(x + Pi));
method Test154 (line 805) | [Fact] public void Test154() => sin(x + 7 * Pi / 2).AssertEqTo(sin(x +...
method Test155 (line 809) | [Fact] public void Test155() => sin(x - 3 * Pi / 2).AssertEqTo(cos(x));
method Test156 (line 810) | [Fact] public void Test156() => sin(x - 1 * Pi / 2).AssertEqTo(-cos(x));
method Test157 (line 811) | [Fact] public void Test157() => sin(x + 1 * Pi / 2).AssertEqTo(cos(x));
method Test158 (line 812) | [Fact] public void Test158() => sin(x + 3 * Pi / 2).AssertEqTo(-cos(x));
method Test159 (line 814) | [Fact] public void Test159() => sin(Pi + x).AssertEqTo(-sin(x));
method Test160 (line 816) | [Fact] public void Test160() => sin(Pi + x + y).AssertEqTo(-sin(x + y));
method Test161 (line 819) | [Fact] public void Test161() => cos(Pi + x).AssertEqTo(-cos(x));
method Test162 (line 821) | [Fact] public void Test162() => cos(Pi + x + y).AssertEqTo(-cos(x + y));
method Test163 (line 827) | [Fact] public void Test163() => cos(0).AssertEqTo(1);
method Test164 (line 829) | [Fact] public void Test164() => cos(Pi).AssertEqTo(-1);
method Test165 (line 831) | [Fact] public void Test165() => cos(-10).AssertEqTo(cos(10));
method Test166 (line 833) | [Fact] public void Test166() => cos(-10 * x).AssertEqTo(cos(10 * x));
method Test167 (line 835) | [Fact] public void Test167() => cos(3 * Pi).AssertEqTo(-1);
method Test168 (line 837) | [Fact] public void Test168() => cos(2 * Pi * 3 / 4).AssertEqTo(0);
method Test169 (line 841) | [Fact] public void Test169() => cos(x - 3 * Pi).AssertEqTo(cos(x + Pi));
method Test170 (line 842) | [Fact] public void Test170() => cos(x + 3 * Pi).AssertEqTo(cos(x + Pi));
method Test171 (line 844) | [Fact] public void Test171() => cos(x - 2 * Pi).AssertEqTo(cos(x));
method Test172 (line 845) | [Fact] public void Test172() => cos(x + 2 * Pi).AssertEqTo(cos(x));
method Test173 (line 847) | [Fact] public void Test173() => cos(x + Pi * 7 / 2).AssertEqTo(cos(x +...
method Test174 (line 851) | [Fact] public void Test174() => cos(x - Pi * 3 / 2).AssertEqTo(-sin(x));
method Test175 (line 852) | [Fact] public void Test175() => cos(x - Pi * 1 / 2).AssertEqTo(sin(x));
method Test176 (line 853) | [Fact] public void Test176() => cos(x + Pi * 1 / 2).AssertEqTo(-sin(x));
method Test177 (line 854) | [Fact] public void Test177() => cos(x + Pi * 3 / 2).AssertEqTo(sin(x));
method Test178 (line 860) | [Fact] public void Test178() => Assert.True(a.Has(elt => elt == a), "a...
method Test179 (line 862) | [Fact] public void Test179() => Assert.True(a.Has(elt => elt == b) == ...
method Test180 (line 864) | [Fact] public void Test180() => Assert.True((a == b).Has(elt => elt ==...
method Test181 (line 866) | [Fact] public void Test181() => Assert.True((a == b).Has(elt => elt ==...
method Test182 (line 868) | [Fact] public void Test182() => Assert.True(((a + b) ^ c).Has(elt => e...
method Test183 (line 870) | [Fact] public void Test183() => Assert.True(((a + b) ^ c).Has(elt => (...
method Test184 (line 872) | [Fact] public void Test184() => Assert.True((x * (a + b + c)).Has(elt ...
method Test185 (line 874) | [Fact] public void Test185() => Assert.True((x * (a + b + c)).Has(elt ...
method Test186 (line 876) | [Fact] public void Test186() => Assert.True((x * (a + b + c)).Has(elt ...
method Test187 (line 882) | [Fact] public void Test187() => Assert.True((a + b).FreeOf(b) == false...
method Test188 (line 883) | [Fact] public void Test188() => Assert.True((a + b).FreeOf(c) == true,...
method Test189 (line 884) | [Fact] public void Test189() => Assert.True(((a + b) * c).FreeOf(a + b...
method Test190 (line 885) | [Fact] public void Test190() => Assert.True((sin(x) + 2 * x).FreeOf(si...
method Test191 (line 886) | [Fact] public void Test191() => Assert.True(((a + b + c) * d).FreeOf(a...
method Test192 (line 887) | [Fact] public void Test192() => Assert.True(((y + 2 * x - y) / x).Free...
method Test193 (line 888) | [Fact] public void Test193() => Assert.True(((x * y) ^ 2).FreeOf(x * y...
method Test194 (line 894) | [Fact] public void Test194() => Assert.True((x ^ -1).Numerator() == 1);
method Test195 (line 896) | [Fact] public void Test195() => Assert.True((x ^ -half).Numerator() ==...
method Test196 (line 902) | [Fact]
method Test197 (line 910) | [Fact]
method Test198 (line 918) | [Fact]
method Test199 (line 924) | [Fact]
method Test200 (line 933) | [Fact]
method Test201 (line 942) | [Fact]
method Test202 (line 960) | [Fact]
method Test203 (line 966) | [Fact]
method Test204 (line 972) | [Fact]
method Test205 (line 982) | [Fact]
method Test206 (line 992) | [Fact]
method Test207 (line 997) | [Fact]
method Test208 (line 1002) | [Fact]
method Test209 (line 1007) | [Fact]
method Test210 (line 1016) | [Fact] public void Test210() => Assert.True((a * (x ^ 2) + b * x + c)....
method Test211 (line 1018) | [Fact] public void Test211() => Assert.True((3 * x * (y ^ 2) + 5 * (x ...
method Test212 (line 1020) | [Fact] public void Test212() => Assert.True((3 * x * (y ^ 2) + 5 * (x ...
method Test213 (line 1022) | [Fact]
method Test214 (line 1031) | [Fact]
method Test215 (line 1037) | [Fact]
method Test216 (line 1050) | [Fact]
method Test217 (line 1056) | [Fact]
method Test218 (line 1062) | [Fact]
method Test219 (line 1069) | [Fact]
method Test220 (line 1075) | [Fact]
method Test221 (line 1085) | [Fact] public void Test221() => (x + y + z == 0).IsolateVariable(a).As...
method Test222 (line 1089) | [Fact]
method Test223 (line 1094) | [Fact]
method Test224 (line 1099) | [Fact]
method Test225 (line 1104) | [Fact] public void Test225() => Assert.True((0 == x - y).IsolateVariab...
method Test226 (line 1108) | [Fact]
method Test227 (line 1131) | [Fact]
method Test228 (line 1155) | [Fact]
method Test229 (line 1175) | [Fact] public void Test229() => (sqrt(x + y) == z).IsolateVariable(x)....
method Test230 (line 1177) | [Fact]
method Test231 (line 1182) | [Fact]
method Test232 (line 1187) | [Fact]
method Test233 (line 1192) | [Fact]
method Test234 (line 1197) | [Fact]
method Test235 (line 1202) | [Fact]
method Test236 (line 1207) | [Fact]
method Test237 (line 1212) | [Fact]
method Test238 (line 1217) | [Fact]
method Test239 (line 1226) | [Fact]
method Test241 (line 1231) | [Fact]
method Test242 (line 1238) | [Fact] public void Test242() => and(x + y == z, x / y == 0, x != 0).Ch...
method Test243 (line 1244) | [Fact]
method Test244 (line 1260) | [Fact]
method Test245 (line 1270) | [Fact]
method Test246 (line 1284) | [Fact]
method Test247 (line 1295) | [Fact]
method Test248 (line 1304) | [Fact]
method Test249 (line 1315) | [Fact]
method Test250 (line 1325) | [Fact]
method Test251 (line 1341) | [Fact]
method Test252 (line 1355) | [Fact]
method Test253_a (line 1369) | [Fact]
method Test253_b (line 1389) | [Fact]
method Test253 (line 1419) | [Fact]
method Kinematic (line 1453) | And Kinematic(Symbol s, Symbol u, Symbol v, Symbol a, Symbol t) =>
method PSE_Example_2_6 (line 1459) | [Fact]
method PSE_Example_2_7 (line 1496) | [Fact]
method PSE_Example_2_8 (line 1529) | [Fact]
method Kinematic (line 1581) | And Kinematic(Symbol sA, Symbol sB, Symbol vA, Symbol vB, Symbol a, Sy...
method PSE_Example_2_12 (line 1586) | [Fact]
method PSE_Example_4_3 (line 1640) | [Fact]
method PSE_Example_4_3_KinematicObjectABC (line 1720) | [Fact]
method PSE_5E_Example_4_5 (line 1812) | [Fact]
method PSE_5E_Example_4_6 (line 1909) | [Fact]
method PSE_5E_Example_4_7 (line 2026) | [Fact]
method PSE_5E_P4_9 (line 2173) | [Fact]
method SumDifferenceFormulaFuncTest (line 2308) | [Fact]
method SumDifferenceFormulaAFuncTest (line 2361) | [Fact]
method SinCosToTanFuncTest (line 2445) | [Fact]
method PSE_5E_P4_11 (line 2466) | [Fact]
method PSE_5E_P4_13 (line 2592) | [Fact]
method PSE_5E_P4_15 (line 2670) | [Fact]
method PSE_5E_P4_17 (line 2759) | [Fact]
method PSE_5E_P4_19 (line 2869) | [Fact]
method PSE_5E_P4_21 (line 2973) | [Fact]
method PSE_5E_P4_23 (line 3054) | [Fact]
method PSE_5E_E5_1 (line 3286) | [Fact]
method PSE_5E_E5_4 (line 3477) | [Fact]
method PSE_5E_E5_6 (line 3591) | [Fact]
method PSE_5E_E5_9 (line 3780) | [Fact]
method PSE_5E_E5_10 (line 3872) | [Fact]
method PSE_5E_E5_10_Obj3 (line 4082) | [Fact]
method PSE_5E_E5_12 (line 4197) | [Fact]
method PSE_5E_E5_13 (line 4310) | [Fact]
method PSE_5E_E5_14 (line 4458) | [Fact]
method PSE_5E_E5_14_Obj5 (line 4644) | [Fact]
method PSE_5E_P5_25 (line 4745) | [Fact]
method PSE_5E_P5_25_Obj (line 4863) | [Fact]
method PSE_5E_P5_31 (line 4920) | [Fact]
method PSE_5E_P5_31_Obj (line 5115) | [Fact]
method PSE_5E_P5_55 (line 5235) | [Fact]
method PSE_5E_P5_59 (line 5388) | [Fact]
method PSE_5E_P5_69 (line 5494) | [Fact]
method PSE_5E_E7_7 (line 5591) | [Fact]
method PSE_5E_E7_8 (line 5662) | [Fact]
method PSE_5E_E7_11 (line 5739) | [Fact]
method PSE_6E_P7_3 (line 5829) | [Fact]
method PSE_5E_P7_23 (line 5881) | [Fact]
method PSE_5E_P7_33 (line 5925) | [Fact]
method PSE_5E_P7_35 (line 6036) | [Fact]
method PSE_5E_P7_39 (line 6169) | [Fact]
method PSE_5E_P7_41 (line 6237) | [Fact]
method PSE_5E_P7_55 (line 6326) | [Fact]
method PSE_5E_E8_2 (line 6361) | [Fact]
method PSE_5E_E8_3 (line 6447) | [Fact]
method PSE_5E_E8_4 (line 6578) | [Fact]
method PSE_5E_Example_8_5 (line 6671) | [Fact]
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (359K chars).
[
{
"path": ".gitattributes",
"chars": 483,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs diff=csharp\n*.sln"
},
{
"path": ".gitignore",
"chars": 5646,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": "Examples/pse-example-5.10-Obj.md",
"chars": 4389,
"preview": "\n# Classes for representing forces on objects \n\nIn [this walkthrough](https://gist.github.com/dharmatech/a14d1a29a7d4c07"
},
{
"path": "Examples/symbolism-linux.md",
"chars": 3770,
"preview": "\nThis is a tutorial on how to build and run a simple Symbolism program on Linux.\n\nThe following instructions have been t"
},
{
"path": "Examples/unit-test-index.md",
"chars": 3052,
"preview": "\nIndex of examples in unit tests.\n\n# Physics Examples\n\n## Motion in Two Dimensions\n\n* [PSE 5E E4.3](https://github.com/d"
},
{
"path": "README.md",
"chars": 1917,
"preview": "\n# Symbolism - A Computer Algebra Library for C#\n\nLibrary that implements automatic simplification of algebraic expressi"
},
{
"path": "Symbolism/AlgebraicExpand.cs",
"chars": 1705,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.ExpandProduct;\nu"
},
{
"path": "Symbolism/CoefficientGpe.cs",
"chars": 2219,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Numerics;\nusing System.Text;\n\nusing Sym"
},
{
"path": "Symbolism/DeepSelect.cs",
"chars": 1437,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism\n{\n namesp"
},
{
"path": "Symbolism/DegreeGpe.cs",
"chars": 1210,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Numerics;\nusing System.Text;\n\nusing Sym"
},
{
"path": "Symbolism/EliminateVariable.cs",
"chars": 6134,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.Substitute;\nusin"
},
{
"path": "Symbolism/ExpandPower.cs",
"chars": 1506,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing System.Numerics;\n\nusing Sy"
},
{
"path": "Symbolism/ExpandProduct.cs",
"chars": 601,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism\n{\n namesp"
},
{
"path": "Symbolism/Has.cs",
"chars": 1607,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism\n{\n namesp"
},
{
"path": "Symbolism/IsolateVariable.cs",
"chars": 9452,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.Has;\n\nusing Symb"
},
{
"path": "Symbolism/LeadingCoefficientGpe.cs",
"chars": 402,
"preview": "using System.Collections.Generic;\n\nusing Symbolism.CoefficientGpe;\nusing Symbolism.DegreeGpe;\n\nnamespace Symbolism\n{\n "
},
{
"path": "Symbolism/LogicalExpand.cs",
"chars": 1279,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism.LogicalExpan"
},
{
"path": "Symbolism/PolynomialDivision.cs",
"chars": 1156,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.DegreeGpe;\nusing"
},
{
"path": "Symbolism/PolynomialGcd.cs",
"chars": 832,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.LeadingCoefficie"
},
{
"path": "Symbolism/RationalExpand.cs",
"chars": 684,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing Symbolism.AlgebraicExpand;"
},
{
"path": "Symbolism/RationalizeExpression.cs",
"chars": 1593,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism\n{\n namesp"
},
{
"path": "Symbolism/SimplifyEquation.cs",
"chars": 1424,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism.SimplifyEqua"
},
{
"path": "Symbolism/SimplifyLogical.cs",
"chars": 1279,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism.SimplifyLogi"
},
{
"path": "Symbolism/Substitute.cs",
"chars": 2671,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nnamespace Symbolism\n{\n namesp"
},
{
"path": "Symbolism/Symbolism.cs",
"chars": 48040,
"preview": "/* Copyright 2013 Eduardo Cavazos\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not us"
},
{
"path": "Symbolism/Symbolism.csproj",
"chars": 827,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n\n <Package"
},
{
"path": "Symbolism/Trigonometric.cs",
"chars": 14282,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing static Symbolism.ListConst"
},
{
"path": "Symbolism/Utils.cs",
"chars": 1266,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace Symbolism.Utils\n{\n public static class"
},
{
"path": "Symbolism.sln",
"chars": 1569,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2892"
},
{
"path": "Tests/Tests.cs",
"chars": 221650,
"preview": "/* Copyright 2013 Eduardo Cavazos\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not us"
},
{
"path": "Tests/Tests.csproj",
"chars": 507,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp2.2</TargetFramework>\n\n <IsPackab"
}
]
About this extraction
This page contains the full source code of the dharmatech/Symbolism GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 31 files (336.5 KB), approximately 91.1k tokens, and a symbol index with 566 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.