func TestMaxent(t *testing.T) {

	const json = `
	[
		{
			"A": ["a"],
			"B": ["b"],
			"__label__": "A"
		},
		{
			"A": ["b"],
			"B": ["a"],
			"__label__": "B"
		}
	]
	`
	c := FromJson([]byte(json))

	opt := gd.GradientDescent{1, 0.01, -1, 1}

	start := make(gd.NDimensionalValue, c.DimCnt())
	weights := opt.Optimize(c, start)

	if math.Abs(weights[0]+weights[1]) > 0.01 {
		t.Errorf("%v=>%v\n%v=>%v", c.FeatureMap[0], weights[0], c.FeatureMap[1], weights[1])
	}
}
func main() {

	var raw []byte
	if len(os.Args) < 3 {
		raw, _ = ioutil.ReadAll(os.Stdin)
	} else {
		raw, _ = ioutil.ReadFile(os.Args[1])
	}

	// read in the training data
	maxent := cloglik.FromJson(raw)

	// initialize gradient descent parameters
	grad_descent := gd.GradientDescent{}
	grad_descent.LearningRate = 0.1
	grad_descent.Threshold = 0.01
	grad_descent.MaxIter = -1

	// parallelism
	//threads,_ := strconv.ParseInt(os.Args[3],0,0)
	//fmt.Println("Threads: ",threads)
	threads := runtime.NumCPU()
	runtime.GOMAXPROCS(threads)
	grad_descent.Threads = threads
	maxent.Threads = threads

	// starting point
	x0 := make(gd.NDimensionalValue, maxent.DimCnt()) // x0 = [0,...,0]

	// minimize
	xmin := grad_descent.Optimize(maxent, x0)

	fmt.Fprintln(os.Stderr, "Loglikelihood: ", maxent.Val(xmin))

	// prepare the result for JSON output
	rs := make(map[string]float64)
	for i, v := range xmin {
		rs[maxent.FeatureMap[i]] = v
	}

	// output
	json_out, _ := json.Marshal(rs)
	if len(os.Args) < 3 {
		os.Stdout.Write(json_out)
	} else {
		ioutil.WriteFile(os.Args[2], json_out, 0666)
	}
}