Example #1
0
        static bool Solve(ISolverShell solver, ProjSolv.Parameters parameters)
        {
            bool executionLimitExceeded = false, retval = true;

            if (!solver.Solve(parameters, out executionLimitExceeded))
            {
                System.Console.WriteLine("  Error - Solve failed");
                ++s_cExecutionFailed;
                retval = false;
            }
            if (executionLimitExceeded)
            {
                System.Console.WriteLine("  Warning - one or more execution limits were exceeded");
                ++s_cExecutionLimitExceeded;
            }
            return(retval);
        }
Example #2
0
        private static void Test_dummy_ideal_position()
        {
            //just test for equation (x-500)^2 -> min
            ISolverShell solver = new SolverShell();

            solver.AddVariableWithIdealPosition(0, 10, 0.000001);
            solver.AddFixedVariable(1, 500);

            solver.AddGoalTwoVariablesAreClose(0, 1, 100000.0);

            // The default parameters have too large a QpscConvergenceQuotient and too
            // small an OuterProjectIterationsLimit (we don't add constraints here so the
            // inner iterations do nothing and all movement is done by the QPSC step adjustments
            // in the outer iterations).
            ProjSolv.Parameters parameters = new ProjSolv.Parameters();
            parameters.QpscConvergenceQuotient     = 1e-14;
            parameters.OuterProjectIterationsLimit = 0; // no limit

            Solve(solver, parameters);

            System.Console.WriteLine(solver.GetVariableResolvedPosition(0));
            System.Console.WriteLine(solver.GetVariableResolvedPosition(1));
        }
        internal Qpsc(Parameters solverParameters, int cVariables)
        {
            this.solverParameters = solverParameters;

            this.matrixQ = new MatrixCell[cVariables][];
            this.vectorWiDi = new double[cVariables];
            this.vectorQpscVars = new QpscVar[cVariables];

            this.gradientVector = new double[cVariables];
            this.vectorQg = new double[cVariables];
            this.vectorPrevY = new double[cVariables];
            this.vectorCurY = new double[cVariables];
        }
        /// <summary>
        /// Sets Variable.ActualPos to the positions of the Variables that minimally satisfy the constraints
        /// along this axis.  This overload takes a parameter specification.
        /// </summary>
        /// <param name="solverParameters">Solution-generation options.</param>
        /// <returns>The only failure condition is if there are one or more unsatisfiable constraints, such as cycles
        ///         or mutually exclusive equality constraints; if these are encountered, a list of lists of these 
        ///         constraints is returned, where each list contains a single cycle, which may be of length one for
        ///         unsatisfiable equality constraints.  Otherwise, the return value is null.</returns>
        public Solution Solve(Parameters solverParameters)
        {
            if (null != solverParameters)
            {
                this.solverParams = (Parameters)solverParameters.Clone();
            }

            // Reset some parameter defaults to per-solver-instance values.
            if (this.solverParams.OuterProjectIterationsLimit < 0)
            {
                // If this came in 0, it stays that way, and there is no limit.  Otherwise, set it to a value
                // reflecting the expectation of convergence roughly log-linearly in the number of variables.
#if SHARPKIT //https://github.com/SharpKit/SharpKit/issues/4 integer rounding issue
                this.solverParams.OuterProjectIterationsLimit = 100 * (((int)Math.Log(this.numberOfVariables, 2.0)) + 1);
#else
                this.solverParams.OuterProjectIterationsLimit = 100 * ((int)Math.Log(this.numberOfVariables, 2.0) + 1);
#endif
            }
            if (this.solverParams.InnerProjectIterationsLimit < 0)
            {
                // If this came in 0, it stays that way, and there is no limit.  Otherwise, assume that for
                // any pass, each constraint may be violated (most likely this happens only on the first pass),
                // and add some extra based upon constraint count.  Now that we split and retry on unsatisfied
                // constraints, assume that any constraint may be seen twice on a pass.
#if SHARPKIT //https://github.com/SharpKit/SharpKit/issues/4 integer rounding issue
                this.solverParams.InnerProjectIterationsLimit = (this.numberOfConstraints * 2) + (100 * (((int)Math.Log(this.numberOfConstraints, 2.0)) + 1));
#else
                this.solverParams.InnerProjectIterationsLimit = (this.numberOfConstraints * 2) + (100 * ((int)Math.Log(this.numberOfConstraints, 2.0) + 1));
#endif
            }

            // ReSolving can be done for updated constraints.
            bool isReSolve = !this.allConstraints.IsEmpty;
            CheckForUpdatedConstraints();

            this.solverSolution = new Solution { MinInnerProjectIterations = int.MaxValue };
            this.allConstraints.MaxConstraintTreeDepth = 0;
            this.allConstraints.SolverParameters = this.solverParams;

            //
            // First set up all the internal stuff we'll use for solutions.
            //
#if CACHE_STATS
            cacheStats.Clear();
#endif // CACHE_STATS

            // If no constraints have been loaded, there's nothing to do.  Two distinct variables
            // are required to create a constraint, so this also ensures a minimum number of variables.
            if (0 == this.numberOfConstraints)
            {
                // For Qpsc, we may have neighbours but no constraints.
                if (!this.IsQpsc)
                {
                    return (Solution)this.solverSolution.Clone();
                }
            }
            else if (!isReSolve)
            {
                SetupConstraints();
            }

            // This is the number of unsatisfiable constraints encountered.
            this.allConstraints.NumberOfUnsatisfiableConstraints = 0;

            // Merge Equality constraints first.  These do not do any constraint-splitting, and thus
            // remain in the same blocks, always satisfied, regardless of whether we're solving the full
            // Qpsc or the simpler loop.
            MergeEqualityConstraints();

            // Prepare for timeout checking.
            if (this.solverParams.TimeLimit > 0)
            {
                this.timeoutStopwatch = new Stopwatch();
                this.timeoutStopwatch.Start();
            }

            //
            // Done with initial setup.  Now if we have neighbour pairs, we do the full SolveQpsc logic
            // complete with Gradient projection.  Otherwise, we have a much simpler Project/Split loop.
            //
            if (this.IsQpsc)
            {
                this.SolveQpsc();
            }
            else
            {
                this.SolveByStandaloneProject();
                this.CalculateStandaloneProjectGoalFunctionValue();
            }

            // We initialized this to int.MaxValue so make sure it's sane if we didn't complete a Project iteration.
            if (this.solverSolution.MinInnerProjectIterations > this.solverSolution.MaxInnerProjectIterations)
            {
                // Probably this is 0.
                this.solverSolution.MinInnerProjectIterations = this.solverSolution.MaxInnerProjectIterations;
            }

#if CACHE_STATS
            cacheStats.Print();
            Console.WriteLine("  NumFinalBlocks = {0}, MinCacheBlocks = {1}, MaxCacheSize = {2}",
                                allBlocks.Count, violationCacheMinBlockCutoff, ViolationCache.MaxConstraints);
#endif // CACHE_STATS

            // Done.  Caller will copy each var.ActualPos back to the Nodes.  If we had any unsatisfiable
            // constraints, copy them back out to the caller.
            this.solverSolution.NumberOfUnsatisfiableConstraints = this.allConstraints.NumberOfUnsatisfiableConstraints;
#if BLOCK_STATS
            int minBlockVars = this.numberOfVariables;
            int maxBlockVars = 0;
            foreach (Block block in allBlocks.Vector) {
                if (minBlockVars > block.Variables.Count) {
                    minBlockVars = block.Variables.Count;
                }
                if (maxBlockVars < block.Variables.Count) {
                    maxBlockVars = block.Variables.Count;
                }
            } // endforeach block

            Console.WriteLine("Num final Blocks: {0}, Min Block Vars: {1}, Max Block Vars: {2}",
                    allBlocks.Count, minBlockVars, maxBlockVars);
#endif // BLOCK_STATS
            this.solverSolution.MaxConstraintTreeDepth = this.allConstraints.MaxConstraintTreeDepth;
            return (Solution)this.solverSolution.Clone();
        } // end Solve()
 internal bool VerifyConstraint(Parameters solverParameters, Constraint cst, bool isHorizontal, ref bool violationsSeen)
 {
     if (cst.IsUnsatisfiable)
     {
         return true;
     }
     bool hasViolation = cst.Violation > solverParameters.GapTolerance;
     if (cst.IsEquality)
     {
         hasViolation = Math.Abs(cst.Violation) > solverParameters.GapTolerance;
     }
     if (hasViolation)
     {
         if (!violationsSeen)
         {
             WriteLine("  {0} Violation(s) of Constraint(s) that were not marked Unsatisfiable:", isHorizontal ? "X" : "Y");
             violationsSeen = true;
         }
         if (TestGlobals.VerboseLevel >= 1)
         {
             WriteLine("    {0}", cst);
         }
     }
     return !hasViolation;
 }
        private static void Test_dummy_ideal_position() {
            //just test for equation (x-500)^2 -> min
            ISolverShell solver = new SolverShell();

            solver.AddVariableWithIdealPosition(0, 10, 0.000001);
            solver.AddFixedVariable(1, 500);

            solver.AddGoalTwoVariablesAreClose(0, 1, 100000.0);

            // The default parameters have too large a QpscConvergenceQuotient and too
            // small an OuterProjectIterationsLimit (we don't add constraints here so the
            // inner iterations do nothing and all movement is done by the QPSC step adjustments
            // in the outer iterations).
            ProjSolv.Parameters parameters = new ProjSolv.Parameters();
            parameters.QpscConvergenceQuotient = 1e-14;
            parameters.OuterProjectIterationsLimit = 0; // no limit
            
            Solve(solver, parameters);

            System.Console.WriteLine(solver.GetVariableResolvedPosition(0));
            System.Console.WriteLine(solver.GetVariableResolvedPosition(1));
        }
 /// <summary>
 /// Constructor taking OverlapRemoval parameter and solver parameters.
 /// </summary>
 /// <param name="allowDeferToVertical"></param>
 /// <param name="solverParameters"></param>
 public OverlapRemovalParameters(bool allowDeferToVertical, Parameters solverParameters)
 {
     this.AllowDeferToVertical = allowDeferToVertical;
     this.SolverParameters = solverParameters;
 }
 /// <summary>
 /// Constructor taking solver parameters.
 /// </summary>
 /// <param name="solverParameters"></param>
 public OverlapRemovalParameters(Parameters solverParameters)
 {
     this.SolverParameters = solverParameters;
     AllowDeferToVertical = true;
 }