// add complexity to a single multiplication term func (PS *PgeSearch) WidenTermInExprMethod1(O, E expr.Expr, pos int) (ret []expr.Expr) { ret = make([]expr.Expr, 0) // insert leafs f()*L for _, L := range PS.GenLeafs { l := L.Clone() C := O.Clone() P := pos e := C.GetExpr(&P) // fmt.Printf("pos(%d): %v\n", pos, e) M := e.(*expr.Mul) M.Insert(l) sort.Sort(M) C.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(C) if good { ret = append(ret, C) } } // insert node(L) : f() * c*node(L) for _, N := range PS.GenNodes { for _, L := range PS.GenLeafs { c := new(expr.Constant) c.P = -1 l := L.Clone() n := N.Clone() p := 1 n.SetExpr(&p, l) var E expr.Expr if N.ExprType() == expr.DIV { E = expr.NewDiv(c, l) } else { // mul it M := expr.NewMul() M.Insert(c) M.Insert(n) E = M } C := O.Clone() P := pos e := C.GetExpr(&P) // fmt.Printf("pos(%d): %v\n", pos, e) M := e.(*expr.Mul) M.Insert(E) sort.Sort(M) C.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(C) if good { ret = append(ret, C) } } } return ret }
func GenBenchData(e expr.Expr, vars []BenchmarkVar, samples int) (pts []Point) { pts = make([]Point, 0) if vars[0].Rtype == Uniform { for i := 0; i < samples; i++ { input := make([]float64, len(vars)) retry: for j, v := range vars { r := rand.Float64() input[j] = (r * (v.H - v.L)) + v.L } out := e.Eval(0, input, nil, nil) if math.IsNaN(out) || math.IsInf(out, 0) || math.Abs(out) > 100000.0 { goto retry } var pnt Point pnt.SetIndeps(input) pnt.SetDepnds([]float64{out}) pts = append(pts, pnt) } } else { // RangeType == Equal counter := make([]float64, len(vars)) for j, v := range vars { counter[j] = v.L } L1, L2 := len(vars)-1, vars[len(vars)-1].L for counter[L1] <= L2 { input := make([]float64, len(vars)) copy(input, counter) out := e.Eval(0, input, nil, nil) var pnt Point pnt.SetIndeps(input) pnt.SetDepnds([]float64{out}) pts = append(pts, pnt) // increment counter for j, v := range vars { counter[j] += v.S if counter[j] > v.H { counter[j] = v.L } else { break } } } } return }
func (tp *TreeParams) CheckExprTmp(e expr.Expr) bool { if e.Size() < tp.TmpMinSize || e.Size() > tp.TmpMaxSize || e.Height() < tp.TmpMinDepth || e.Height() > tp.TmpMaxDepth { return false } return true }
func scoreExpr(e expr.Expr, P *probs.ExprProblem, dataSets []*probs.PointSet, coeff []float64) (hitsL1, hitsL2, evalCnt, nanCnt, infCnt int, l1_err, l2_err float64) { var l1_sum, l2_sum float64 for _, PS := range dataSets { for _, p := range PS.Points() { y := p.Depnd(P.SearchVar) var out float64 if P.SearchType == probs.ExprBenchmark { out = e.Eval(0, p.Indeps(), coeff, PS.SysVals()) } else if P.SearchType == probs.ExprDiffeq { out = e.Eval(p.Indep(0), p.Indeps()[1:], coeff, PS.SysVals()) } if math.IsNaN(out) { nanCnt++ continue } else if math.IsInf(out, 0) { infCnt++ continue } else { evalCnt++ } diff := out - y l1_val := math.Abs(diff) l2_val := diff * diff l1_sum += l1_val l2_sum += l2_val if l1_val < P.HitRatio { hitsL1++ } if l2_val < P.HitRatio { hitsL2++ } } } if evalCnt == 0 { l1_err = math.NaN() l2_err = math.NaN() } else { fEvalCnt := float64(evalCnt + 1) l1_err = l1_sum / fEvalCnt l2_err = math.Sqrt(l2_sum / fEvalCnt) } return }
func LevmarExpr(e expr.Expr, searchDim int, task ExprProblemType, guess []float64, train, test []*PointSet) []float64 { ps := train[0].NumPoints() PS := len(train) * ps c := make([]float64, len(guess)) var cd callback_data cd.Train = train cd.Test = test cd.E = e cd.Coeff = c cd.Task = task cd.J = make([]expr.Expr, len(guess)) for i, _ := range cd.J { deriv := e.DerivConst(i) // simp := deriv.Simplify(expr.DefaultRules()) cd.J[i] = deriv } // c/levmar inputs coeff := make([]C.double, len(guess)) for i, g := range guess { coeff[i] = C.double(g) } y := make([]C.double, PS) for i1, T := range train { for i2, p := range T.Points() { i := i1*ps + i2 y[i] = C.double(p.Depnd(searchDim)) } } ya := (*C.double)(unsafe.Pointer(&y[0])) ca := (*C.double)(unsafe.Pointer(&coeff[0])) ni := C.int(PS) mi := C.int(len(c)) // C.levmar_dif(ya, ca, mi, ni, unsafe.Pointer(&cd)) C.levmar_der(ya, ca, mi, ni, unsafe.Pointer(&cd)) for i, _ := range coeff { c[i] = float64(coeff[i]) } return c }
func (PS *PgeSearch) ExpandMethod1(O expr.Expr) (ret []expr.Expr) { O.Sort() ret = make([]expr.Expr, 0) // fmt.Printf("Expanding expression: %v\n", O) for i := 0; i < O.Size(); i++ { I := i E := O.GetExpr(&I) switch E.ExprType() { case expr.ADD: tmp := PS.AddTermToExprMethod1(O, E, i) ret = append(ret, tmp[:]...) case expr.MUL: tmp := PS.WidenTermInExprMethod1(O, E, i) ret = append(ret, tmp[:]...) case expr.VAR: tmp := PS.DeepenTermInExprMethod1(O, E, i) ret = append(ret, tmp[:]...) default: // expr.DIV,expr.COS,expr.SIN,expr.EXP,expr.LOG,expr.ABS,expr.POW continue } } return ret }
func (tp *TreeParams) CheckExpr(e expr.Expr) bool { if e.Size() < tp.MinSize { // fmt.Printf( "Too SMALL: e:%v l:%v\n", e.Size(), tp.TmpMinSize ) return false } else if e.Size() > tp.MaxSize { // fmt.Printf( "Too LARGE: e:%v l:%v\n", e.Size(), tp.TmpMaxSize ) return false } else if e.Height() < tp.MinDepth { // fmt.Printf( "Too SHORT: e:%v l:%v\n", e.Height(), tp.TmpMinDepth ) return false } else if e.Height() > tp.MaxDepth { // fmt.Printf( "Too TALL: e:%v l:%v\n", e.Height(), tp.TmpMaxDepth ) return false } return true }
// change any term to something more complex... func (PS *PgeSearch) DeepenTermInExprMethod1(O, E expr.Expr, pos int) []expr.Expr { exprs := make([]expr.Expr, 0) // make into add A := expr.NewAdd() A.Insert(E.Clone()) OA := A.Clone() exprs = append(exprs, PS.AddTermToExprMethod1(OA, A, 0)[:]...) // make into mul M := expr.NewMul() M.Insert(E.Clone()) OM := M.Clone() exprs = append(exprs, PS.WidenTermInExprMethod1(OM, M, 0)[:]...) // // make into div // if E.ExprType() != expr.DIV { // D := new(expr.Div) // c := new(expr.Constant) // c.P = -1 // D.Numer = c // D.Denom = E.Clone() // exprs = append(exprs, D) // } // make inside of nodes for _, N := range PS.GenNodes { if N.ExprType() == expr.DIV { continue } T := N.Clone() P := 1 T.SetExpr(&P, E.Clone()) exprs = append(exprs, T) } ret := make([]expr.Expr, 0) for _, e := range exprs { C := O.Clone() P := pos C.SetExpr(&P, e) ret = append(ret, C) } return ret }
func (PS *PgeSearch) ExpandMethod3(O expr.Expr) (ret []expr.Expr) { O.Sort() ret = make([]expr.Expr, 0) // fmt.Printf("Expanding expression: %v\n", O) add := O.(*expr.Add) // adding term to addition for _, B := range PS.ffxBases { found := false for _, C := range add.CS { // fmt.Printf("checking %v in %v\n", B, add) if C.AmISame(B) { // fmt.Println("found\n\n") found = true break } } if !found { e := O.Clone() a := e.(*expr.Add) a.Insert(B.Clone()) sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n\n", a) // ret = append(ret, a) } } // extending terms in addition for _, B := range PS.ffxBases { for i, C := range add.CS { if C.ExprType() == expr.MUL { m := C.(*expr.Mul) if len(m.CS) > 3 { continue } } e := O.Clone() a := e.(*expr.Add) mul := expr.NewMul() mul.Insert(a.CS[i]) mul.Insert(B.Clone()) a.CS[i] = mul sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n\n", a) ret = append(ret, a) } } // fmt.Println("Len of ret = ", len(ret)) return ret }
func StackLevmarExpr(e expr.Expr, x_dims int, coeff []float64, c_ygiven, c_input []C_double) []float64 { // fmt.Printf("Entering Stack Levmar: \n") c_coeff := make([]C.double, len(coeff)) for i, c := range coeff { c_coeff[i] = C.double(c) } // c_ygiven := make([]C.double, len(ygiven)) // for i, c := range ygiven { // c_ygiven[i] = C.double(c) // } // c_input := make([]C.double, len(input)) // for i, c := range input { // c_input[i] = C.double(c) // } cp := (*C.double)(unsafe.Pointer(&c_coeff[0])) mi := C.int(len(coeff)) yp := (*C.double)(unsafe.Pointer(&c_ygiven[0])) ni := C.int(len(c_ygiven)) var sd *C.StackData sd = new(C.StackData) // fmt.Printf("x_len: %d x_dim: %d\n", len(input), x_dims) sd.x_len = C.int(len(c_input)) sd.x_dim = C.int(x_dims) sd.x_data = (*C.double)(unsafe.Pointer(&c_input[0])) serial := make([]int, 0) serial = e.StackSerial(serial) // fmt.Printf("StackSerial: %v\n", serial) c_serial := make([]C.int, len(serial)) for i, I := range serial { c_serial[i] = C.int(I) } sd.expr.serial = (*C.int)(unsafe.Pointer(&c_serial[0])) sd.expr.s_len = C.int(len(serial)) // fmt.Printf("GOT HERE: %v\n", serial) derivs := make([]C.StackExpr, len(coeff)) for i, _ := range coeff { deriv := e.DerivConst(i) dserial := make([]int, 0) dserial = deriv.StackSerial(dserial) d_serial := make([]C.int, len(dserial)) for i, I := range dserial { d_serial[i] = C.int(I) } derivs[i].serial = (*C.int)(unsafe.Pointer(&d_serial[0])) derivs[i].s_len = C.int(len(d_serial)) } sd.derivs = (*C.StackExpr)(unsafe.Pointer(&derivs[0])) sd.d_len = C.int(mi) // fmt.Printf("Going into stack_levmar_dif\n") C.stack_levmar_dif(yp, cp, mi, ni, unsafe.Pointer(sd)) // C.stack_levmar_der(yp, cp, mi, ni, unsafe.Pointer(sd)) // fmt.Printf("Returned from stack_levmar_dif\n") c := make([]float64, len(c_coeff)) for i, _ := range c_coeff { c[i] = float64(c_coeff[i]) } // fmt.Printf("C0: %f\n", c[0]) return c }
func (tp *TreeParams) CheckExprLog(e expr.Expr, log *bufio.Writer) bool { // if e.Size() < tp.TmpMinSize || e.Size() > tp.TmpMaxSize || // e.Height() < tp.TmpMinDepth || e.Height() > tp.TmpMaxDepth { // return false // } if e.Size() < tp.MinSize { fmt.Fprintf(log, "Too SMALL: e:%v l:%v\n", e.Size(), tp.MinSize) return false } else if e.Size() > tp.MaxSize { fmt.Fprintf(log, "Too LARGE: e:%v l:%v\n", e.Size(), tp.MaxSize) return false } else if e.Height() < tp.MinDepth { fmt.Fprintf(log, "Too SHORT: e:%v l:%v\n", e.Height(), tp.MinDepth) return false } else if e.Height() > tp.MaxDepth { fmt.Fprintf(log, "Too TALL: e:%v l:%v\n", e.Height(), tp.MaxDepth) return false } return true }
func (PS *PgeSearch) ExpandMethod2(O expr.Expr) (ret []expr.Expr) { O.Sort() ret = make([]expr.Expr, 0) // fmt.Printf("Expanding expression: %v\n", O) add := O.(*expr.Add) // adding term to addition for _, B := range PS.ffxBases { found := false for _, C := range add.CS { // fmt.Printf("checking %v in %v\n", B, add) if C.AmISame(B) { // fmt.Println("found\n\n") found = true break } } if !found { e := O.Clone() a := e.(*expr.Add) a.Insert(B.Clone()) sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n\n", a) // ret = append(ret, a) } } // extending terms in addition for _, B := range PS.ffxBases { for i, C := range add.CS { if C.ExprType() == expr.MUL { m := C.(*expr.Mul) if len(m.CS) > 3 { continue } } e := O.Clone() a := e.(*expr.Add) mul := expr.NewMul() mul.Insert(a.CS[i]) mul.Insert(B.Clone()) a.CS[i] = mul sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n\n", a) ret = append(ret, a) } } // deepening terms // if len(add.CS) < 2 { // return ret // } for i, C := range add.CS { if C.ExprType() == expr.MUL { m := C.(*expr.Mul) if len(m.CS) != 2 { continue } if m.CS[1].ExprType() == expr.ADD { continue } } else { continue } for _, B := range PS.ffxBases { e := O.Clone() a := e.(*expr.Add) m := a.CS[i].(*expr.Mul) n := m.CS[1] switch n.ExprType() { case expr.SQRT: A := expr.NewAdd() A.Insert(n.(*expr.Sqrt).C) A.Insert(B.Clone()) n.(*expr.Sqrt).C = A case expr.SIN: A := expr.NewAdd() A.Insert(n.(*expr.Sin).C) A.Insert(B.Clone()) n.(*expr.Sin).C = A case expr.COS: A := expr.NewAdd() A.Insert(n.(*expr.Cos).C) A.Insert(B.Clone()) n.(*expr.Cos).C = A case expr.TAN: A := expr.NewAdd() A.Insert(n.(*expr.Tan).C) A.Insert(B.Clone()) n.(*expr.Tan).C = A case expr.EXP: A := expr.NewAdd() A.Insert(n.(*expr.Exp).C) A.Insert(B.Clone()) n.(*expr.Exp).C = A case expr.LOG: A := expr.NewAdd() A.Insert(n.(*expr.Log).C) A.Insert(B.Clone()) n.(*expr.Log).C = A default: A := expr.NewAdd() A.Insert(m.CS[1]) A.Insert(B.Clone()) m.CS[1] = A } sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n", a) ret = append(ret, a) } } for i, C := range add.CS { if C.ExprType() == expr.MUL { m := C.(*expr.Mul) if len(m.CS) != 2 { continue } if m.CS[1].ExprType() == expr.ADD { continue } } else { continue } for _, B := range PS.ffxBases { e := O.Clone() a := e.(*expr.Add) m := a.CS[i].(*expr.Mul) n := m.CS[1] switch n.ExprType() { case expr.SQRT: M := expr.NewMul() M.Insert(n.(*expr.Sqrt).C) M.Insert(B.Clone()) n.(*expr.Sqrt).C = M case expr.SIN: M := expr.NewMul() M.Insert(n.(*expr.Sin).C) M.Insert(B.Clone()) n.(*expr.Sin).C = M case expr.COS: M := expr.NewMul() M.Insert(n.(*expr.Cos).C) M.Insert(B.Clone()) n.(*expr.Cos).C = M case expr.TAN: M := expr.NewMul() M.Insert(n.(*expr.Tan).C) M.Insert(B.Clone()) n.(*expr.Tan).C = M case expr.EXP: M := expr.NewMul() M.Insert(n.(*expr.Exp).C) M.Insert(B.Clone()) n.(*expr.Exp).C = M case expr.LOG: M := expr.NewMul() M.Insert(n.(*expr.Log).C) M.Insert(B.Clone()) n.(*expr.Log).C = M } sort.Sort(a) a.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(a) if good { ret = append(ret, a) } // fmt.Printf("grew %v\n", a) ret = append(ret, a) } } // fmt.Println("Len of ret = ", len(ret)) return ret }
// add another term to an add expr func (PS *PgeSearch) AddTermToExprMethod1(O, E expr.Expr, pos int) (ret []expr.Expr) { ret = make([]expr.Expr, 0) A := E.(*expr.Add) // f() + cL for _, L := range PS.GenLeafs { c := new(expr.Constant) c.P = -1 l := L.Clone() // mul it M := expr.NewMul() M.Insert(c) M.Insert(l) // skip if the same term already exists in the add skip := false for _, e := range A.CS { if e == nil { continue } // fmt.Printf("ACMP %v %v\n", M, e) if e.AmIAlmostSame(M) || M.AmIAlmostSame(e) { skip = true break } } if skip { continue } C := O.Clone() P := pos AM := C.GetExpr(&P).(*expr.Add) AM.Insert(M) sort.Sort(AM) C.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(C) if good { ret = append(ret, C) } } // f() + c*node(L) for _, N := range PS.GenNodes { for _, L := range PS.GenLeafs { c := new(expr.Constant) c.P = -1 l := L.Clone() n := N.Clone() p := 1 n.SetExpr(&p, l) var E expr.Expr if N.ExprType() == expr.DIV { E = expr.NewDiv(c, l) } else { // mul it M := expr.NewMul() M.Insert(c) M.Insert(n) E = M } // skip if the same term already exists in the add skip := false for _, e := range A.CS { if e == nil { continue } // fmt.Printf("ACMP %v %v\n", M, e) if e.AmIAlmostSame(E) || E.AmIAlmostSame(e) { skip = true break } } if skip { continue } // fmt.Println(E.String()) C := O.Clone() P := pos AM := C.GetExpr(&P).(*expr.Add) AM.Insert(E) sort.Sort(AM) C.CalcExprStats() good := PS.cnfg.treecfg.CheckExpr(C) if good { ret = append(ret, C) } } } return ret }
func RegressExpr(E expr.Expr, P *probs.ExprProblem) (R *probs.ExprReport) { guess := make([]float64, 0) guess, eqn := E.ConvertToConstants(guess) var coeff []float64 if len(guess) > 0 { // fmt.Printf("x_dims: %d %d\n", x_dim, x_dim2) // Callback version coeff = levmar.LevmarExpr(eqn, P.SearchVar, P.SearchType, guess, P.Train, P.Test) // Stack version // x_dim := P.Train[0].NumDim() // if c_input == nil { // ps := P.Train[0].NumPoints() // PS := len(P.Train) * ps // x_tot := PS * x_dim // c_input = make([]levmar.C_double, x_tot) // c_ygiven = make([]levmar.C_double, PS) // for i1, T := range P.Train { // for i2, p := range T.Points() { // i := i1*ps + i2 // c_ygiven[i] = levmar.MakeCDouble(p.Depnd(P.SearchVar)) // for i3, x_p := range p.Indeps() { // j := i1*ps*x_dim + i2*x_dim + i3 // c_input[j] = levmar.MakeCDouble(x_p) // } // } // } // } // coeff = levmar.StackLevmarExpr(eqn, x_dim, guess, c_ygiven, c_input) // serial := make([]int, 0) // serial = eqn.StackSerial(serial) // fmt.Printf("StackSerial: %v\n", serial) // fmt.Printf("%v\n%v\n%v\n\n", eqn, coeff, steff) } R = new(probs.ExprReport) R.SetExpr(eqn) /*.ConvertToConstantFs(coeff)*/ R.SetCoeff(coeff) R.Expr().CalcExprStats() // hitsL1, hitsL2, evalCnt, nanCnt, infCnt, l1_err, l2_err := scoreExpr(E, P, coeff) _, _, _, trnNanCnt, _, trn_l1_err, _ := scoreExpr(E, P, P.Train, coeff) _, _, tstEvalCnt, tstNanCnt, _, tst_l1_err, tst_l2_err := scoreExpr(E, P, P.Test, coeff) R.SetTrainScore(trnNanCnt) R.SetTrainError(trn_l1_err) R.SetPredScore(tstNanCnt) R.SetTestScore(tstEvalCnt) R.SetTestError(tst_l1_err) R.SetPredError(tst_l2_err) return R }