Пример #1
0
// 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
}
Пример #2
0
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
}
Пример #3
0
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
}
Пример #4
0
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
}
Пример #5
0
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
}
Пример #6
0
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
}
Пример #7
0
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
}
Пример #8
0
// 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
}
Пример #9
0
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
}
Пример #10
0
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
}
Пример #11
0
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
}
Пример #12
0
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
}
Пример #13
0
// 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
}
Пример #14
0
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
}