//Stripped down method for simpler testing
        public double[] SolveTest(AD.Term equation, AD.Variable[] args, double[,] limits)
        {
            lastSeed             = null;
            probeCount           = 0;
            successProbeCount    = 0;
            intervalCount        = 0;
            successIntervalCount = 0;
            fevalsCount          = 0;
            runCount             = 0;

            //this.FEvals = 0;
            double util = 0;

            this.begin = RosCS.RosSharp.Now();
#if (GSOLVER_LOG)
            InitLog();
#endif
            //ft.Reset();
            rResults.Clear();

            currentArgs = args;

            this.dim            = args.Length;
            this.limits         = limits;
            this.ranges         = new double[dim];
            this.rpropStepWidth = new double[dim];
            this.rpropStepConvergenceThreshold = new double[dim];


            equation = equation.AggregateConstants();



            ss = new CNSAT.CNSat();

            ss.UseIntervalProp = this.UseIntervalProp;
            //Console.WriteLine(cu.Constraint);
            LinkedList <CNSAT.Clause> cnf = ft.TransformToCNF(equation, ss);

            /*Console.WriteLine("Atoms: {0}, Occurrence: {1}",ft.Atoms.Count,ft.AtomOccurrence);
             * Console.WriteLine("Clauses: {0}",cnf.Count);
             * foreach(AD.Term atom in ft.Atoms.Keys) {
             *      Console.WriteLine("-------");
             *      Console.WriteLine(atom);
             *      Console.WriteLine("-------");
             * }*/
            /*
             * int litc=1;
             * List<AD.Term> terms = new List<AD.Term>(ft.Atoms);
             *
             * currentAtoms = new Dictionary<int, Term>();
             *
             * foreach(AD.Term t in terms) {
             *      foreach(Literal l in ft.References[t]) {
             *              l.Id = litc;
             *      }
             *      currentAtoms.Add(litc,t);
             *      litc++;
             * }*/


            ip.SetGlobalRanges(args, limits, ss);


            foreach (CNSAT.Clause c in cnf)
            {
                if (!c.IsTautologic)
                {
                    if (c.Literals.Count == 0)
                    {
                        util = Double.MinValue;
                        double[] ret = new double[dim];
                        for (int i = 0; i < dim; i++)
                        {
                            ret[i] = (this.limits[i, 1] + this.limits[i, 0]) / 2.0;
                        }
                        return(ret);
                    }
                    //Post Clause Here
                    //Console.Write("\nAdding Clause with "+c.Literals.Count+" Literals\n");
                    //c.Print();

                    ss.addBasicClause(c);
                }
            }
            ss.CNSMTGSolver = this;

            ss.Init();
            //PRE-Propagation:
#if DO_PREPROPAGATION
            if (!ip.PrePropagate(ss.Variables))
            {
                Console.WriteLine("Unsatisfiable (unit propagation)");
                //return null;
            }
#endif
            //END-PrePropagation
            //Console.WriteLine("Variable Count: " + ss.Variables.Count);

            bool solutionFound = false;


            solutionFound = ss.solve();
            //Console.WriteLine("Solution Found!!!!!");

            if (!solutionFound && r1.finalUtil > 0)
            {
                r1.finalUtil = -1;
            }
            util = r1.finalUtil;
            //if(util>this.utilitySignificanceThreshold) return r1.finalValue;
            return(r1.finalValue);
        }
        public double[] Solve(AD.Term equation, AD.Variable[] args, double[,] limits, double[][] seeds, out double util)
        {
            lastSeed             = null;
            probeCount           = 0;
            successProbeCount    = 0;
            intervalCount        = 0;
            successIntervalCount = 0;
            fevalsCount          = 0;
            runCount             = 0;
            this.begin           = RosCS.RosSharp.Now();

            //this.FEvals = 0;
            util = 0;
#if (GSOLVER_LOG)
            InitLog();
#endif
            //ft.Reset();
            rResults.Clear();

            currentArgs = args;

            this.dim            = args.Length;
            this.limits         = limits;
            this.ranges         = new double[dim];
            this.rpropStepWidth = new double[dim];
            this.rpropStepConvergenceThreshold = new double[dim];


            equation = equation.AggregateConstants();

            AD.ConstraintUtility cu   = (AD.ConstraintUtility)equation;
            bool utilIsConstant       = (cu.Utility is AD.Constant);
            bool constraintIsConstant = (cu.Constraint is AD.Constant);
            if (constraintIsConstant)
            {
                if (((AD.Constant)cu.Constraint).Value < 0.25)
                {
                    util = ((AD.Constant)cu.Constraint).Value;
                    double[] ret = new double[dim];
                    for (int i = 0; i < dim; i++)
                    {
                        ret[i] = (this.limits[i, 1] + this.limits[i, 0]) / 2.0;
                        //this.ranges[i]/2.0+this.limits[i,0];
                    }
                    return(ret);
                }
            }
            ss = new CNSAT.CNSat();

            ss.UseIntervalProp = this.UseIntervalProp;
            //Console.WriteLine(cu.Constraint);
            LinkedList <CNSAT.Clause> cnf = ft.TransformToCNF(cu.Constraint, ss);

            /*Console.WriteLine("Atoms: {0}, Occurrence: {1}",ft.Atoms.Count,ft.AtomOccurrence);
             * Console.WriteLine("Clauses: {0}",cnf.Count);
             * foreach(AD.Term atom in ft.Atoms.Keys) {
             *      Console.WriteLine("-------");
             *      Console.WriteLine(atom);
             *      Console.WriteLine("-------");
             * }*/
            /*
             * int litc=1;
             * List<AD.Term> terms = new List<AD.Term>(ft.Atoms);
             *
             * currentAtoms = new Dictionary<int, Term>();
             *
             * foreach(AD.Term t in terms) {
             *      foreach(Literal l in ft.References[t]) {
             *              l.Id = litc;
             *      }
             *      currentAtoms.Add(litc,t);
             *      litc++;
             * }*/

            if (UseIntervalProp)
            {
                ip.SetGlobalRanges(args, limits, ss);
            }


            foreach (CNSAT.Clause c in cnf)
            {
                if (!c.IsTautologic)
                {
                    if (c.Literals.Count == 0)
                    {
                        util = Double.MinValue;
                        double[] ret = new double[dim];
                        for (int i = 0; i < dim; i++)
                        {
                            ret[i] = (this.limits[i, 1] + this.limits[i, 0]) / 2.0;
                        }
                        return(ret);
                    }
                    //Post Clause Here
                    //Console.Write("\nAdding Clause with "+c.Literals.Count+" Literals\n");
                    //c.Print();

                    ss.addBasicClause(c);
                }
            }
            ss.CNSMTGSolver = this;

            ss.Init();
            //PRE-Propagation:
            if (UseIntervalProp)
            {
#if DO_PREPROPAGATION
                if (!ip.PrePropagate(ss.Variables))
                {
                    Console.WriteLine("Unsatisfiable (unit propagation)");
                    return(null);
                }
#endif
            }
            //END-PrePropagation
            //Console.WriteLine("Variable Count: " + ss.Variables.Count);

            bool solutionFound = false;

            ss.UnitDecissions = ss.Decisions.Count;

            do
            {
                if (!solutionFound)
                {
                    ss.EmptySATClause();
                    ss.EmptyTClause();
                    ss.backTrack(ss.UnitDecissions);
                }
                solutionFound = ss.solve();
                if (Optimize)
                {
                    r1 = RPropOptimizeFeasible(ss.Decisions, ((AD.ConstraintUtility)equation).Utility, args, r1.finalValue, false);
                }
                if (!solutionFound && r1.finalUtil > 0)
                {
                    r1.finalUtil = -1;
                }
                util = r1.finalUtil;
                if (!Optimize && solutionFound)
                {
                    return(r1.finalValue);
                }
                else if (Optimize)
                {
                    //optimization case
                    rResults.Add(r1);
                    CNSAT.Clause c = new Alica.Reasoner.CNSAT.Clause();
                    foreach (CNSAT.Var v in ss.Decisions)
                    {
                        c.Add(new CNSAT.Lit(v, v.Assignment == CNSAT.Assignment.True ? CNSAT.Assignment.False : CNSAT.Assignment.True));
                    }
                    //ss.addBasicClause(c);
                    ss.addIClause(c);
                    ss.backTrack(ss.Decisions[ss.Decisions.Count - 1].DecisionLevel);
                    solutionFound = false;
                }
            } while (!solutionFound && this.begin + this.maxSolveTime > RosCS.RosSharp.Now() /*&& this.runCount < this.MaxFEvals*/);

            //Console.WriteLine("Probes: {0}/{1}\tIntervals: {2}/{3}",successProbeCount,probeCount,successIntervalCount,intervalCount);
            //ip.PrintStats();
            //Console.WriteLine("Rprop Runs: {0}\t FEvals {1}\t Solutions Found: {2}",this.runCount,this.fevalsCount, rResults.Count);

            //return best result
            if (rResults.Count > 0)
            {
                foreach (RpropResult rp in rResults)
                {
                    if (rp.finalUtil > util)
                    {
                        util = rp.finalUtil;
                        r1   = rp;
                    }
                }
                return(r1.finalValue);
            }
            Console.WriteLine("Unsatisfiable");

            return(null);
        }