Skip to content

Commit

Permalink
Merge pull request #101 from corywalker/corywalker
Browse files Browse the repository at this point in the history
Memory allocation fixes. Can now load Rubi in ~15 seconds.
  • Loading branch information
corywalker committed Sep 7, 2017
2 parents b563d68 + 8a4c575 commit 32ed3cf
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 81 deletions.
6 changes: 4 additions & 2 deletions examples/test_rubi.m
@@ -1,5 +1,7 @@
testproblems = ReadList["/Users/cwalker32/Code/gocode/src/github.com/corywalker/expreduce/test_rubi/test_rubi.m"];
testproblems = DeleteCases[testproblems, Null];
(*testproblems = ReadList["/Users/cwalker32/Code/gocode/src/github.com/corywalker/expreduce/test_rubi/test_rubi.m"];*)
(*testproblems = DeleteCases[testproblems, Null];*)
testproblems = ReadList["/Users/cwalker32/Downloads/test.m"][[1]];
Print[Length[testproblems]];

testi = 1;

Expand Down
6 changes: 6 additions & 0 deletions expreduce.go
Expand Up @@ -8,10 +8,13 @@ import (
"log"
"os"
"runtime/pprof"
"net/http"
_ "net/http/pprof"
)

var debug = flag.Bool("debug", false, "Debug mode. No initial definitions.")
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var netprofile = flag.Bool("netprofile", false, "Enable live profiling at http://localhost:8080/debug/pprof/")

func main() {
flag.Parse()
Expand All @@ -23,6 +26,9 @@ func main() {
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if *netprofile {
go http.ListenAndServe(":8080", nil)
}

rl, err := readline.NewEx(&readline.Config{
HistoryFile: "/tmp/readline.tmp",
Expand Down
1 change: 1 addition & 0 deletions expreduce/blank.go
Expand Up @@ -56,6 +56,7 @@ func IsBlankTypeCapturing(e Ex, target Ex, head Ex, pm *PDManager, cl *CASLogger
toMatch, ispd := pm.patternDefined[sAsSymbol.Name]
if !ispd {
toMatch = target
pm.LazyMakeMap()
pm.patternDefined[sAsSymbol.Name] = target
}
if !IsSameQ(toMatch, target, cl) {
Expand Down
3 changes: 2 additions & 1 deletion expreduce/builtin_system.go
Expand Up @@ -184,7 +184,7 @@ func applyModuleFn(this *Expression, es *EvalState) (Ex, bool) {
es.defined[pl.uniqueName] = Def{
downvalues: []DownValue{
DownValue{
rule: *NewExpression([]Ex{
rule: NewExpression([]Ex{
&Symbol{"System`Rule"},
&Symbol{pl.uniqueName},
rhs,
Expand All @@ -195,6 +195,7 @@ func applyModuleFn(this *Expression, es *EvalState) (Ex, bool) {
} else {
es.defined[pl.uniqueName] = Def{}
}
pm.LazyMakeMap()
pm.patternDefined[pl.sym.Name] = &Symbol{pl.uniqueName}
}
toReturn = ReplacePD(toReturn, es, pm)
Expand Down
25 changes: 25 additions & 0 deletions expreduce/cas_test.go
Expand Up @@ -110,6 +110,31 @@ func TestLowLevel(t *testing.T) {

es := NewEvalState()

lhs := NewExpression([]Ex{
&Symbol{"System`Power"},
NewExpression([]Ex{
&Symbol{"System`Plus"},
&Symbol{"Global`a"},
&Symbol{"Global`b"},
&Symbol{"Global`c"},
}),
NewInt(0),
})
rule := NewExpression([]Ex{
&Symbol{"System`Rule"},
NewExpression([]Ex{
&Symbol{"System`Power"},
NewExpression([]Ex{
&Symbol{"System`Blank"},
}),
NewInt(0),
}),
NewInt(99),
})
for numi := 0; numi < 700000; numi++ {
Replace(lhs, rule, es)
}

// Test basic float functionality
var f *Flt = &Flt{big.NewFloat(5.5)}
assert.Equal(t, "5.5", f.String())
Expand Down
4 changes: 2 additions & 2 deletions expreduce/definition.go
Expand Up @@ -3,7 +3,7 @@ package expreduce
import "bytes"

type DownValue struct {
rule Expression
rule *Expression
specificity int
}

Expand All @@ -22,7 +22,7 @@ func CopyDefs(in map[string]Def) map[string]Def {
newDef := Def{}
for _, dv := range v.downvalues {
newDv := DownValue{
rule: *dv.rule.DeepCopy().(*Expression),
rule: dv.rule.DeepCopy().(*Expression),
specificity: dv.specificity,
}
newDef.downvalues = append(newDef.downvalues, newDv)
Expand Down
47 changes: 31 additions & 16 deletions expreduce/evalstate.go
Expand Up @@ -207,6 +207,17 @@ func (this *EvalState) GetDef(name string, lhs Ex) (Ex, bool, *Expression) {
if !this.IsDef(name) {
return nil, false, nil
}
// Special case for checking simple variable definitions like "a = 5".
// TODO: Perhaps split out single var values into the Definition to avoid
// iterating over every one.
if _, lhsIsSym := lhs.(*Symbol); lhsIsSym {
for _, def := range this.defined[name].downvalues {
if _, symDef := def.rule.Parts[1].(*Symbol); symDef {
return def.rule.Parts[2], true, def.rule
}
}
return nil, false, nil
}
this.Debugf("Inside GetDef(\"%s\",%s)", name, lhs)
for i := range this.defined[name].downvalues {
def := this.defined[name].downvalues[i].rule
Expand All @@ -219,7 +230,7 @@ func (this *EvalState) GetDef(name string, lhs Ex) (Ex, bool, *Expression) {
started = time.Now().UnixNano()
}

res, replaced := Replace(lhs, &def, this)
res, replaced := Replace(lhs, def, this)

if this.isProfiling {
elapsed := float64(time.Now().UnixNano()-started) / 1000000000
Expand All @@ -228,7 +239,7 @@ func (this *EvalState) GetDef(name string, lhs Ex) (Ex, bool, *Expression) {
}

if replaced {
return res, true, &def
return res, true, def
}
}
return nil, false, nil
Expand Down Expand Up @@ -276,7 +287,10 @@ func (this *EvalState) MarkSeen(name string) {

// Attempts to compute a specificity metric for a rule. Higher specificity rules
// should be tried first.
func ruleSpecificity(lhs Ex, rhs Ex) int {
func ruleSpecificity(lhs Ex, rhs Ex, name string) int {
if name == "Rubi`Int" {
return 100
}
// I define complexity as the length of the Lhs.String()
// because it is simple, and it works for most of the common cases. We wish
// to attempt f[x_Integer] before we attempt f[x_]. If LHSs map to the same
Expand Down Expand Up @@ -338,7 +352,7 @@ func (this *EvalState) Define(lhs Ex, rhs Ex) {
newDef := Def{
downvalues: []DownValue{
DownValue{
rule: *NewExpression([]Ex{
rule: NewExpression([]Ex{
&Symbol{"System`Rule"}, lhs, rhs,
}),
},
Expand All @@ -349,14 +363,14 @@ func (this *EvalState) Define(lhs Ex, rhs Ex) {
}

// Overwrite identical rules.
for i := range this.defined[name].downvalues {
existingRule := this.defined[name].downvalues[i].rule
for _, dv := range this.defined[name].downvalues {
existingRule := dv.rule
existingLhs := existingRule.Parts[1]
if IsSameQ(existingLhs, lhs, &this.CASLogger) {
existingRhsCond := maskNonConditional(existingRule.Parts[2])
newRhsCond := maskNonConditional(rhs)
if IsSameQ(existingRhsCond, newRhsCond, &this.CASLogger) {
this.defined[name].downvalues[i].rule.Parts[2] = rhs
dv.rule.Parts[2] = rhs
return
}
}
Expand All @@ -365,16 +379,17 @@ func (this *EvalState) Define(lhs Ex, rhs Ex) {
// Insert into definitions for name. Maintain order of decreasing
// complexity.
var tmp = this.defined[name]
newSpecificity := ruleSpecificity(lhs, rhs)
for i := range this.defined[name].downvalues {
if this.defined[name].downvalues[i].specificity == 0 {
this.defined[name].downvalues[i].specificity = ruleSpecificity(
this.defined[name].downvalues[i].rule.Parts[1],
this.defined[name].downvalues[i].rule.Parts[2],
newSpecificity := ruleSpecificity(lhs, rhs, name)
for i, dv := range this.defined[name].downvalues {
if dv.specificity == 0 {
dv.specificity = ruleSpecificity(
dv.rule.Parts[1],
dv.rule.Parts[2],
name,
)
}
if this.defined[name].downvalues[i].specificity < newSpecificity {
newRule := *NewExpression([]Ex{&Symbol{"System`Rule"}, lhs, rhs})
if dv.specificity < newSpecificity {
newRule := NewExpression([]Ex{&Symbol{"System`Rule"}, lhs, rhs})
tmp.downvalues = append(
tmp.downvalues[:i],
append(
Expand All @@ -389,7 +404,7 @@ func (this *EvalState) Define(lhs Ex, rhs Ex) {
return
}
}
tmp.downvalues = append(tmp.downvalues, DownValue{rule: *NewExpression([]Ex{&Symbol{"System`Rule"}, lhs, rhs})})
tmp.downvalues = append(tmp.downvalues, DownValue{rule: NewExpression([]Ex{&Symbol{"System`Rule"}, lhs, rhs})})
this.defined[name] = tmp
}

Expand Down
6 changes: 3 additions & 3 deletions expreduce/ex_expression.go
Expand Up @@ -31,7 +31,7 @@ func HeadAssertion(ex Ex, head string) (*Expression, bool) {
}
}
}
return NewEmptyExpression(), false
return nil, false
}

func headExAssertion(ex Ex, head Ex, cl *CASLogger) (*Expression, bool) {
Expand All @@ -41,7 +41,7 @@ func headExAssertion(ex Ex, head Ex, cl *CASLogger) (*Expression, bool) {
return expr, true
}
}
return NewEmptyExpression(), false
return nil, false
}

func OperatorAssertion(ex Ex, opHead string) (*Expression, *Expression, bool) {
Expand All @@ -57,7 +57,7 @@ func OperatorAssertion(ex Ex, opHead string) (*Expression, *Expression, bool) {
}
}
}
return NewEmptyExpression(), NewEmptyExpression(), false
return nil, nil, false
}

func tryReturnValue(e Ex) (Ex, bool) {
Expand Down

0 comments on commit 32ed3cf

Please sign in to comment.