Skip to content

Commit

Permalink
PSE P4.11 - DeepSelect(DoubleAngleFormulaFunc)
Browse files Browse the repository at this point in the history
  • Loading branch information
dharmatech committed Jul 6, 2015
1 parent f111f05 commit f0f9dd0
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 0 deletions.
47 changes: 47 additions & 0 deletions Symbolism/DeepSelect.cs
@@ -0,0 +1,47 @@
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
(result as Equation).a.DeepSelect(proc) ==
(result as Equation).b.DeepSelect(proc);

if (result is Sum)
return
new Sum() { elts = (result as Sum).elts.Select(elt => elt.DeepSelect(proc)).ToList() }.Simplify();

if (result is Product)
return
new Product() { elts = (result as Product).elts.Select(elt => elt.DeepSelect(proc)).ToList() }.Simplify();

return result;
}
}
}

}
13 changes: 13 additions & 0 deletions Symbolism/Symbolism.cs
Expand Up @@ -827,6 +827,19 @@ public And(params MathObject[] ls)
}

public And() { name = "And"; args = new List<MathObject>(); proc = AndProc; }

public MathObject Add(MathObject obj)
{
var ls = new List<MathObject>(args);

ls.Add(obj);

var and = new And();

and.args = ls;

return and.Simplify();
}
}

public class Or : Function
Expand Down
1 change: 1 addition & 0 deletions Symbolism/Symbolism.csproj
Expand Up @@ -48,6 +48,7 @@
<ItemGroup>
<Compile Include="AlgebraicExpand.cs" />
<Compile Include="CoefficientGpe.cs" />
<Compile Include="DeepSelect.cs" />
<Compile Include="EliminateVariable.cs" />
<Compile Include="ExpandPower.cs" />
<Compile Include="ExpandProduct.cs" />
Expand Down
180 changes: 180 additions & 0 deletions Tests/Tests.cs
Expand Up @@ -29,6 +29,7 @@
using Symbolism.AlgebraicExpand;
using Symbolism.IsolateVariable;
using Symbolism.EliminateVariable;
using Symbolism.DeepSelect;

namespace Tests
{
Expand Down Expand Up @@ -124,6 +125,8 @@ static void Main(string[] args)
Func<MathObject, MathObject> cos = obj => Trig.Cos(obj);
Func<MathObject, MathObject> tan = obj => new Tan(obj).Simplify();

Func<MathObject, MathObject> asin = obj => new Asin(obj).Simplify();

{
var a = new Symbol("a");
var b = new Symbol("b");
Expand Down Expand Up @@ -1501,6 +1504,183 @@ static void Main(string[] args)

#endregion

#region DoubleAngleFormulaFunc

Func<MathObject, MathObject> DoubleAngleFormulaFunc =
elt =>
{
if (elt is Product)
{
var items = new List<MathObject>();
foreach (var item in (elt as Product).elts)
{
if (item is Sin)
{
var sym = (item as Sin).args.First();
if (items.Any(obj => (obj is Cos) && (obj as Cos).args.First() == sym))
{
items = items.Where(obj => ((obj is Cos) && (obj as Cos).args.First() == sym) == false).ToList();
items.Add(sin(2 * sym) / 2);
}
else items.Add(item);
}
else if (item is Cos)
{
var sym = (item as Cos).args.First();
if (items.Any(obj => (obj is Sin) && (obj as Sin).args.First() == sym))
{
items = items.Where(obj => ((obj is Sin) && (obj as Sin).args.First() == sym) == false).ToList();
items.Add(sin(2 * sym) / 2);
}
else items.Add(item);
}
else items.Add(item);
}
return new Product() { elts = items }.Simplify();
}
return elt;
};

#endregion

#region PSE 5E P4.11

{
// One strategy in a snowball fight is to throw a first snowball
// at a high angle over level ground. While your opponent is watching
// the first one, you throw a second one at a low angle and timed
// to arrive at your opponent before or at the same time as the first one.

// Assume both snowballs are thrown with a speed of 25.0 m/s.

// The first one is thrown at an angle of 70.0° with respect to the horizontal.

// (a) At what angle should the second (lowangle)
// snowball be thrown if it is to land at the same
// point as the first?

// (b) How many seconds later should the second snowball
// be thrown if it is to land at the same time as the first?

Func<MathObject, MathObject> sqrt = obj => obj ^ (new Integer(1) / 2);

var xA = new Symbol("xA");
var yA = new Symbol("yA");

var vxA = new Symbol("vxA");
var vyA = new Symbol("vyA");

var vA = new Symbol("vA");

var thA = new Symbol("thA");

var xB = new Symbol("xB");
var yB = new Symbol("yB");

var vxB = new Symbol("vxB");
var vyB = new Symbol("vyB");

var tAB = new Symbol("tAB");
var tAC = new Symbol("tAC");

var ax = new Symbol("ax");
var ay = new Symbol("ay");

var Pi = new Symbol("Pi");

var eqs = new And(

vxA == vA * cos(thA),
vyA == vA * sin(thA),

vxB == vxA + ax * tAB,
vyB == vyA + ay * tAB,

xB == xA + vxA * tAB + ax * (tAB ^ 2) / 2,
yB == yA + vyA * tAB + ay * (tAB ^ 2) / 2
);

DoubleFloat.tolerance = 0.00001;

{
var vals = new List<Equation>() { xA == 0, yA == 0, /* vxA vyA */ vA == 25.0, /* thA == 70.0, */ /* xB == 20.497, */ /* yB */ /* vxB */ vyB == 0, /* tAB */ ax == 0, ay == -9.8, Pi == Math.PI };

var zeros = vals.Where(eq => eq.b == 0).ToList();

{
// thA = ... || thA = ...

var expr = eqs
.SubstituteEqLs(zeros)
.EliminateVariables(yB, vxA, vyA, vxB, tAB)
.DeepSelect(DoubleAngleFormulaFunc)
.IsolateVariable(thA);

// th_delta = ...

var th1 = ((expr as Or).args[0] as Equation).b;
var th2 = ((expr as Or).args[1] as Equation).b;

var th_delta = new Symbol("th_delta");

eqs
.Add(th_delta == (th1 - th2).AlgebraicExpand())
.SubstituteEqLs(zeros)

.EliminateVariables(yB, vxA, vyA, vxB, tAB)

.DeepSelect(DoubleAngleFormulaFunc)
.EliminateVariable(xB)

.AssertEqTo(th_delta == asin(sin(2 * thA)) - Pi / 2)

.SubstituteEq(thA == (70).ToRadians())
.SubstituteEq(Pi == Math.PI)

.AssertEqTo(th_delta == -0.87266462599716454)
;
}

{
// tAB = ...

var tAB_eq = eqs
.SubstituteEqLs(zeros)
.EliminateVariables(yB, vxA, vyA, vxB, xB)
.IsolateVariable(tAB);

new And(
new Or(thA == (20).ToRadians(), thA == (70).ToRadians()),
tAB_eq,
tAC == tAB * 2)
.LogicalExpand()
.EliminateVariables(thA, tAB)

.AssertEqTo(new Or(
tAC == -2 * sin(Pi / 9) * vA / ay,
tAC == -2 * sin(7 * Pi / 18) * vA / ay))

.SubstituteEqLs(vals)
.AssertEqTo(
new Or(
tAC == 1.7450007312534115,
tAC == 4.794350106050552));
}
}

DoubleFloat.tolerance = null;
}

#endregion

#endregion

#region PSE 5E Example 4.3
Expand Down

0 comments on commit f0f9dd0

Please sign in to comment.