Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Corywalker #188

Merged
merged 5 commits into from Nov 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 11 additions & 1 deletion expreduce/builtin.go
Expand Up @@ -45,7 +45,16 @@ func toTestInstructions(tc expreduceapi.ExpressionInterface) []TestInstruction {
continue
}
instructions = append(instructions, &SameTestEx{
st.GetParts()[1], st.GetParts()[2]})
st.GetParts()[1], st.GetParts()[2], 0})
continue
}
if st, isSt := atoms.HeadAssertion(tiEx, "System`ENearlySameTest"); isSt {
if len(st.GetParts()) != 3 {
log.Fatalf("Invalid test case: %v\n", tiEx)
continue
}
instructions = append(instructions, &SameTestEx{
st.GetParts()[1], st.GetParts()[2], .01})
continue
}
if st, isSt := atoms.HeadAssertion(tiEx, "System`EStringTest"); isSt {
Expand Down Expand Up @@ -207,6 +216,7 @@ func GetAllDefinitions() (defs []NamedDefSet) {
defs = append(defs, NamedDefSet{"stats", getStatsDefinitions()})
defs = append(defs, NamedDefSet{"manip", getManipDefinitions()})
defs = append(defs, NamedDefSet{"rubi", getRubiDefinitions()})
defs = append(defs, NamedDefSet{"tests", getTestsDefinitions()})

// Check for duplicate definitions
definedNames := make(map[string]bool)
Expand Down
11 changes: 11 additions & 0 deletions expreduce/builtin_power.go
Expand Up @@ -134,6 +134,16 @@ func getPowerDefinitions() (defs []Definition) {
return true, fmt.Sprintf("Sqrt[%v]", this.GetPart(1).StringForm(nextParams))
}
}
if atoms.IsSameQ(this.GetPart(2), atoms.NewRational(big.NewInt(-1), big.NewInt(2))) {
nextParams := params
nextParams.PreviousHead = "<TOPLEVEL>"
if params.Form == "TeXForm" {
return true, fmt.Sprintf("\\frac{1}{\\sqrt{%v}}", this.GetPart(1).StringForm(nextParams))
}
if params.Form == "InputForm" {
return true, fmt.Sprintf("(1/Sqrt[%v])", this.GetPart(1).StringForm(nextParams))
}
}
}
return toStringInfixAdvanced(this.GetParts()[1:], "^", "System`Power", false, "", "", params)
},
Expand Down Expand Up @@ -381,5 +391,6 @@ func getPowerDefinitions() (defs []Definition) {
Name: "Exp",
legacyEvalFn: mathFnOneParam(math.Exp),
})
defs = append(defs, Definition{Name: "Conjugate"})
return
}
7 changes: 7 additions & 0 deletions expreduce/builtin_system.go
Expand Up @@ -664,6 +664,13 @@ func getSystemDefinitions() (defs []Definition) {
Bootstrap: true,
Attributes: []string{"HoldAll", "SequenceHold"},
})
defs = append(defs, Definition{
Name: "ENearlySameTest",
OmitDocumentation: true,
expreduceSpecific: true,
Bootstrap: true,
Attributes: []string{"HoldAll", "SequenceHold"},
})
defs = append(defs, Definition{
Name: "Hash",
legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex {
Expand Down
10 changes: 10 additions & 0 deletions expreduce/builtin_tests.go
@@ -0,0 +1,10 @@
package expreduce

func getTestsDefinitions() (defs []Definition) {
defs = append(defs, Definition{
Name: "ExpreduceMiscTests",
OmitDocumentation: true,
expreduceSpecific: true,
})
return
}
1 change: 1 addition & 0 deletions expreduce/evalstate.go
Expand Up @@ -122,6 +122,7 @@ func (es *EvalState) Init(loadAllDefs bool) {
es.MarkSeen("System`EKnownFailures")
es.MarkSeen("System`EKnownDangerous")
es.MarkSeen("System`ESameTest")
es.MarkSeen("System`ENearlySameTest")
es.MarkSeen("System`EStringTest")
es.MarkSeen("System`EExampleOnlyInstruction")
es.MarkSeen("System`EComment")
Expand Down
39 changes: 31 additions & 8 deletions expreduce/resources.go

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion expreduce/resources/arithmetic.m
Expand Up @@ -238,6 +238,7 @@
Abs[Infinity] := Infinity;
Abs[ComplexInfinity] := Infinity;
Abs[-a_] := Abs[a];
Abs[a_?((!FreeQ[#,I|_Complex])&)] := Sqrt[Total[ReIm[a]^2]] ;/ (FreeQ[ReIm[a], Re] && FreeQ[ReIm[a], Im]);
Attributes[Abs] = {Listable, NumericFunction, Protected, ReadProtected};
Tests`Abs = {
ESimpleExamples[
Expand All @@ -251,7 +252,8 @@
ESameTest[True, Abs[-5.2] > 0],
ESameTest[0, Abs[0]],
ESameTest[Abs[x^a], Abs[-x^a]],
ESameTest[Abs[x^(a + b)], Abs[-x^(a + b)]]
ESameTest[Abs[x^(a + b)], Abs[-x^(a + b)]],
ESameTest[1/2, Abs[1/2 E^(\[ImaginaryJ]*\[Pi]/4)]],
]
};

Expand Down
11 changes: 11 additions & 0 deletions expreduce/resources/atoms.m
Expand Up @@ -111,6 +111,8 @@
realNumberQ[x_Integer] := True;
realNumberQ[x_Real] := True;
realNumberQ[x_Rational] := True;
realNumberQ[(b_Integer?Positive)^Rational[-1, n_Integer?Positive]] := True;
realNumberQ[(b_Integer?Positive)^Rational[1, 2]] := True;
realNumberQ[x_] := Which[
x === Pi, True,
True, False
Expand All @@ -122,6 +124,9 @@
Im[Complex[_,im_]] := im;
Im[x_?realNumberQ + rest__] := Im[Plus[rest]];
Im[x_?realNumberQ * rest__] := x * Im[Times[rest]];
Im[I * rest__] := Re[Times[rest]];
Im[Complex[a_, b_] * rest__] := Im[a rest] + Re[b rest];
Im[Complex[a_, b_] * c__ + d__] := Im[a c + d] + Re[b c];
Im[E^(x_?NumericQ)] := E^Re[x] Sin[Im[x]];
Attributes[Im] = {Listable, NumericFunction, Protected};
Tests`Im = {
Expand All @@ -131,6 +136,11 @@
ESameTest[0, Im[2/3]],
ESameTest[1, Im[2 + I]],
ESameTest[1/(2 Sqrt[2]), Im[1/2 E^(I*\[Pi]/4)]],
ESameTest[-1/Sqrt[2], Im[(-I)/Sqrt[2]]],
ESameTest[Re[a*b], Im[a*I*b]],
ESameTest[-(1/(2 Sqrt[2])), Im[-(I/Sqrt[2])+1/2 E^((I \[Pi])/4)]],
], EKnownFailures[
ESameTest[Im[a c]+Re[b c], Im[a c + I b c]],
]
};

Expand All @@ -140,6 +150,7 @@
Re[Complex[0, 1] + rest__] := Re[Plus[rest]];
Re[x_?realNumberQ + rest__] := x + Re[Plus[rest]];
Re[x_?realNumberQ * rest__] := x * Re[Times[rest]];
Re[Complex[0, 1] * rest__] := -Im[Times[rest]];
Re[E^(x_?NumericQ)] := E^Re[x] Cos[Im[x]];
Attributes[Re] = {Listable, NumericFunction, Protected};
Tests`Re = {
Expand Down
5 changes: 5 additions & 0 deletions expreduce/resources/plot.m
Expand Up @@ -55,3 +55,8 @@
PlotRangePadding -> {{Scaled[0.02], Scaled[0.02]}, {Scaled[0.05],
Scaled[0.05]}}, Ticks -> {Automatic, Automatic}};
Graphics[lines, displayOptions]];
Tests`Plot = {
ETests[
ESameTest[Graphics, Plot[2*Cos[10 t + 1] - Sin[4 t - 1], {t, 0, 10}] // Head],
]
};
17 changes: 17 additions & 0 deletions expreduce/resources/power.m
Expand Up @@ -845,6 +845,23 @@
Arg::usage = "`Arg[x]` computes the argument of `x`.";
Attributes[Arg] = {Listable, NumericFunction, Protected};
Arg[a_?NumberQ] := ArcTan[Re[a], Im[a]];
Arg[a_] := ArcTan[Re[a], Im[a]] ;/ (FreeQ[ReIm[a], Re] && FreeQ[ReIm[a], Im]);
Tests`Arg = {
ESimpleExamples[
ESameTest[Pi/4, Arg[1/2 E^(I*Pi/4)]],
]
};

Conjugate::usage = "`Conjugate[x]` computes the complex conjugate of `x`.";
Conjugate[a_] := a - 2 Im[a] I ;/ (FreeQ[Im[a], Re] && FreeQ[Im[a], Im]);
Attributes[Conjugate] = {Listable, NumericFunction, Protected, ReadProtected};
Tests`Conjugate = {
ESimpleExamples[
ESameTest[4-4I, Conjugate[4+4I]],
ESameTest[-4I, Conjugate[4I]],
ESameTest[4, Conjugate[4]],
]
};

ComplexExpand::usage = "`ComplexExpand[e]` returns a complex expansion of `e`.";
Attributes[ComplexExpand] = {Protected};
Expand Down
41 changes: 41 additions & 0 deletions expreduce/resources/tests.m
@@ -0,0 +1,41 @@

Tests`ExpreduceMiscTests = {
ETests[
ESameTest[1/2 E^((I Pi)/4), z=1/2 E^(\[ImaginaryJ]*Pi/4)],
ESameTest[1/(2 Sqrt[2]), Re[z]],
ESameTest[1/(2 Sqrt[2]), 1/2*Cos[Pi/4]],
ESameTest[1/(2 Sqrt[2]), Im[z]],
ESameTest[1/(2 Sqrt[2]), 1/2*Sin[Pi/4]],
ESameTest[1/2, Abs[z]],
ESameTest[Pi/4, Arg[z]],
ESameTest[-(1/(2 Sqrt[2])), Conjugate[z]//Im],
ESameTest[1/Sqrt[2], z+Conjugate[z]//FullSimplify],
ESameTest[1/Sqrt[2], Cos[Pi/4]],
ESameTest[{-(1/2),0}, ReIm[1/2 E^(\[ImaginaryJ]*Pi)]],
ESameTest[{-(1/2),0}, ReIm[1/2 E^(-\[ImaginaryJ]*Pi)]],
ESameTest[{0,1}, ReIm[E^(\[ImaginaryJ]*Pi/2)]],
ESameTest[{0,-1}, ReIm[E^(-\[ImaginaryJ]*Pi/2)]],
ESameTest[{0,1}, ReIm[E^(\[ImaginaryJ]*5Pi/2)]],
ESameTest[{5,0}, ReIm[5*E^(\[ImaginaryJ](0))]],
ESameTest[{-2,0}, ReIm[2*E^(\[ImaginaryJ](Pi))]],
ESameTest[{0,-3}, ReIm[3*E^(\[ImaginaryJ](-Pi/2))]],
ESameTest[{1/2,-(Sqrt[3]/2)}, ReIm[1*E^(\[ImaginaryJ](-2Pi/6))]],
ESameTest[{1,1}, ReIm[Sqrt[2]*E^(\[ImaginaryJ](Pi/4))]],
(* a,b,c *)
ESameTest[{-Im[E^(10 I t)],Re[E^(10 I t)]}, ReIm[\[ImaginaryJ]*E^(\[ImaginaryJ]*10*t)]],
(* Period: .6283 *)
ENearlySameTest[0.628319, 2Pi/10//N],
ESameTest[Null, myf[t_]:=E^((-1+\[ImaginaryJ])t);],
ESameTest[True, myf[t]==E^-t*E^(\[ImaginaryJ]*t)],
(* Always decreasing, not periodic *)
(* Period: .285*)
ENearlySameTest[0.285714, 2Pi/(7Pi)//N],
(* Period: 3.167 (maybe pi) *)
ENearlySameTest[0.628319, 2Pi/10//N],
ENearlySameTest[1.5708, 2Pi/4//N],
ENearlySameTest[3.14159, LCM[2/10,2/4]*Pi//N],
ENearlySameTest[3.14159, LCM[1/5,1/2]*Pi//N],

ESameTest[Null, ClearAll[z, myf]],
]
};
40 changes: 28 additions & 12 deletions expreduce/testing.go
Expand Up @@ -2,6 +2,7 @@ package expreduce

import (
"bytes"
"math"
"testing"

"github.com/corywalker/expreduce/expreduce/atoms"
Expand Down Expand Up @@ -65,23 +66,18 @@ func (test *TestComment) run(t *testing.T, es expreduceapi.EvalStateInterface, t
type SameTestEx struct {
Out expreduceapi.Ex
In expreduceapi.Ex
// The pecent difference we are willing to tolerate.
floatTolerance float64
}

func (test *SameTestEx) run(t *testing.T, es expreduceapi.EvalStateInterface, td testDesc) bool {
stringParams := ActualStringFormArgsFull("InputForm", es)
succ, s := casTestInner(es, es.Eval(test.In), es.Eval(test.Out), test.In.StringForm(stringParams), true, td.desc)
succ, s := casTestInner(es, es.Eval(test.In), es.Eval(test.Out), test.In.StringForm(stringParams), true, td.desc, test.floatTolerance)
assert.True(t, succ, s)
return succ
}

func casTestInner(es expreduceapi.EvalStateInterface, inTree expreduceapi.Ex, outTree expreduceapi.Ex, inStr string, test bool, desc string) (succ bool, s string) {
theTestTree := atoms.NewExpression([]expreduceapi.Ex{
atoms.NewSymbol("System`SameQ"),
atoms.NewExpression([]expreduceapi.Ex{atoms.NewSymbol("System`Hold"), inTree}),
atoms.NewExpression([]expreduceapi.Ex{atoms.NewSymbol("System`Hold"), outTree}),
})

theTest := es.Eval(theTestTree)
func casTestInner(es expreduceapi.EvalStateInterface, inTree expreduceapi.Ex, outTree expreduceapi.Ex, inStr string, test bool, desc string, floatTolerance float64) (succ bool, s string) {

context, contextPath := definitionComplexityStringFormArgs()
var buffer bytes.Buffer
Expand All @@ -101,6 +97,26 @@ func casTestInner(es expreduceapi.EvalStateInterface, inTree expreduceapi.Ex, ou
buffer.WriteString(desc)
}

outFloat, outIsFloat := outTree.(*atoms.Flt)
inFloat, inIsFloat := inTree.(*atoms.Flt)
if floatTolerance > 0 && outIsFloat && inIsFloat {
if outFloat.Val.Sign() == inFloat.Val.Sign() && outFloat.Val.Sign() != 0 {
inVal, _ := inFloat.Val.Float64()
outVal, _ := outFloat.Val.Float64()
pctDiff := (inVal - outVal) / ((inVal + outVal) / 2)
pctDiff = math.Abs(pctDiff) * 100
return pctDiff < floatTolerance, buffer.String()
}
}

theTestTree := atoms.NewExpression([]expreduceapi.Ex{
atoms.NewSymbol("System`SameQ"),
atoms.NewExpression([]expreduceapi.Ex{atoms.NewSymbol("System`Hold"), inTree}),
atoms.NewExpression([]expreduceapi.Ex{atoms.NewSymbol("System`Hold"), outTree}),
})

theTest := es.Eval(theTestTree)

resSym, resIsSym := theTest.(*atoms.Symbol)
if !resIsSym {
return false, buffer.String()
Expand All @@ -112,19 +128,19 @@ func casTestInner(es expreduceapi.EvalStateInterface, inTree expreduceapi.Ex, ou
}

func casAssertSame(t *testing.T, es expreduceapi.EvalStateInterface, out string, in string) bool {
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, true, "")
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, true, "", 0)
assert.True(t, succ, s)
return succ
}

func casAssertDiff(t *testing.T, es expreduceapi.EvalStateInterface, out string, in string) bool {
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, false, "")
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, false, "", 0)
assert.True(t, succ, s)
return succ
}

func casAssertDescSame(t *testing.T, es expreduceapi.EvalStateInterface, out string, in string, desc string) bool {
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, true, desc)
succ, s := casTestInner(es, es.Eval(parser.Interp(in, es)), es.Eval(parser.Interp(out, es)), in, true, desc, 0)
assert.True(t, succ, s)
return succ
}
2 changes: 1 addition & 1 deletion expreduce/testing_test.go
Expand Up @@ -14,7 +14,7 @@ func TestTesting(t *testing.T) {
es := NewEvalState()

casAssertSame(t, es, " 1 ", " 1")
succ, s := casTestInner(es, es.Eval(parser.Interp(" 1. ", es)), es.Eval(parser.Interp("1 ", es)), " 1. ", true, "")
succ, s := casTestInner(es, es.Eval(parser.Interp(" 1. ", es)), es.Eval(parser.Interp("1 ", es)), " 1. ", true, "", 0)
assert.False(t, succ, s)
casAssertSame(t, es, "5.5", "1+1.5+3")
casAssertDiff(t, es, "5.6", "1+1.5+3")
Expand Down