Exemplo n.º 1
0
 private ESection ProcessClusterOrConstraints(string currentLine, ESection currentSection, ref EClusterState currentClusterState)
 {
     if (currentLine.StartsWith(
             TestFileStrings.BeginCluster, StringComparison.OrdinalIgnoreCase))
     {
         currentSection         = ESection.Cluster;
         currentClusterState    = EClusterState.Id;
         this.currentClusterDef = new ClusterDef(this.MinClusterSizeX, this.MinClusterSizeY);
         return(currentSection);
     }
     if (currentLine.StartsWith(
             TestFileStrings.BeginConstraintsX, StringComparison.OrdinalIgnoreCase))
     {
         currentSection             = ESection.Constraints;
         this.currentConstraintDefs = this.ConstraintDefsX;
         return(currentSection);
     }
     if (currentLine.StartsWith(
             TestFileStrings.BeginConstraintsY, StringComparison.OrdinalIgnoreCase))
     {
         currentSection             = ESection.Constraints;
         this.currentConstraintDefs = this.ConstraintsDefY;
         return(currentSection);
     }
     if (currentLine.StartsWith(
             TestFileStrings.BeginConstraints, StringComparison.OrdinalIgnoreCase))
     {
         currentSection             = ESection.Constraints;
         this.currentConstraintDefs = this.ConstraintDefsX;
         return(currentSection);
     }
     return(currentSection);
 }
Exemplo n.º 2
0
 private void InitializeMembers()
 {
     SolverX              = null;
     SolverY              = null;
     SolutionX            = null;
     SolutionY            = null;
     MinPaddingX          = InitialMinPaddingX;
     MinPaddingY          = InitialMinPaddingY;
     AllowDeferToVertical = InitialAllowDeferToVertical;
     ClusterDef.Reset();
 }
Exemplo n.º 3
0
 internal void AddClusterDef(ClusterDef clusDef)
 {
     this.clusterDefs.Add(clusDef);
     clusDef.ParentClusterDef = this;
 }
Exemplo n.º 4
0
        private void VerifyClustersDoNotOverlapWithNonChildNodesInTheirOwnHierarchy(double epsilon, KeyValuePair <List <ClusterDef>, List <VariableDef> > kvpCurHier, ClusterDef[] localClusDefs, ref bool succeeded)
        {
            int idxStartVar = 0;

            foreach (ClusterDef clusCur in localClusDefs)
            {
                if (clusCur.IsEmpty)
                {
                    continue;
                }

                VariableDef[] localVarDefs = kvpCurHier.Value.OrderBy(varDef => varDef.Top).ToArray();
                for (int jj = idxStartVar; jj < localVarDefs.Length; ++jj)
                {
                    VariableDef varCheck = localVarDefs[jj];

                    // Minimize variable-list traversal.
                    if (varCheck.Top < (clusCur.Top - epsilon))
                    {
                        idxStartVar = jj;
                    }

                    // If the variable ends before the cluster starts, there's no overlap.
                    if ((clusCur.Top - varCheck.Bottom - this.MinPaddingY) > -epsilon)
                    {
                        continue;
                    }

                    // Rounding error may leave these calculations slightly greater or less than zero.
                    // Since margin is calculated only for inner edges and here we are testing for
                    // sibling rather than nested nodes, we don't use margin here.
                    // Name is <relativeToVarCur><RelativeToVarCheck>
                    double bottomTopOverlap = varCheck.Top - clusCur.Bottom - this.MinPaddingY;
                    if (bottomTopOverlap >= -epsilon)
                    {
                        // Out of range of clusCur's size, so we're done with clusCur.
                        break;
                    }

                    // Does varCheck's left or right border overlap?  Negative overlap means yes.
                    // Again, margins are only cluster-internal and we're testing external boundaries
                    // here; so the cluster size should have been calculated large enough and we only
                    // look at padding.
                    double xa = varCheck.Left - clusCur.Right - this.MinPaddingX;
                    double xb = clusCur.Left - varCheck.Right - this.MinPaddingX;

                    if ((xa < -epsilon) && (xb < -epsilon))
                    {
                        // Let's see if it's an ancestor.
                        bool hasSideOverlap = true;
                        foreach (ClusterDef clusDefParent in varCheck.ParentClusters)
                        {
                            for (ClusterDef clusDefAncestor = clusDefParent; null != clusDefAncestor; clusDefAncestor = clusDefAncestor.ParentClusterDef)
                            {
                                if (clusDefAncestor == clusCur)
                                {
                                    hasSideOverlap = false;
                                    break;
                                }
                            }
                            if (!hasSideOverlap)
                            {
                                break;
                            }
                        }

                        if (hasSideOverlap)
                        {
                            // Uh oh.
                            this.WriteLine("Error {0}: Overlap exists between Cluster '{1}' and non-child Node '{2}'", FailTag("OlapClusNode"),
                                           clusCur.ClusterId, varCheck.IdString);
                            this.WriteLine("   Cluster {0}: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}", clusCur.ClusterId,
                                           clusCur.Left, clusCur.Right, clusCur.Top, clusCur.Bottom);
                            this.WriteLine("      Node {0}: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}", varCheck.IdString,
                                           varCheck.Left, varCheck.Right, varCheck.Top, varCheck.Bottom);
                            succeeded = false;
                        }
                    } // endif overlap within epsilon
                }     // endfor each non-child variable
            }
        }
Exemplo n.º 5
0
        private void VerifyClustersDoNotOverlapWithNonParentClustersInTheirOwnHierarchy(double epsilon, out ClusterDef[] localClusDefs, KeyValuePair <List <ClusterDef>, List <VariableDef> > kvpCurHier, ref bool succeeded)
        {
            localClusDefs = kvpCurHier.Key.OrderBy(clusDef => clusDef.Top).ToArray();
            for (int ii = 0; ii < localClusDefs.Length; ++ii)
            {
                ClusterDef clusCur = localClusDefs[ii];
                if (clusCur.IsEmpty || clusCur.IsNewHierarchy)
                {
                    continue;
                }
                for (int jj = ii + 1; jj < localClusDefs.Length; ++jj)
                {
                    ClusterDef clusCheck = localClusDefs[jj];
                    if (clusCheck.IsEmpty || clusCheck.IsNewHierarchy)
                    {
                        continue;
                    }

                    // Rounding error may leave these calculations slightly greater or less than zero.
                    // Since margin is calculated only for inner edges and here we are testing for
                    // sibling rather than nested nodes, we don't use margin here.
                    // Name is <relativeToVarCur><RelativeToVarCheck>
                    double bottomTopOverlap = clusCheck.Top - clusCur.Bottom - this.MinPaddingY;
                    if (bottomTopOverlap >= -epsilon)
                    {
                        // Out of range of clusCur's size, so we're done with clusCur.
                        break;
                    }

                    // Does clusCheck's left or right border overlap?  Negative overlap means yes.
                    // Again, margins are only cluster-internal and we're testing external boundaries
                    // here; so the cluster size should have been calculated large enough and we only
                    // look at padding.
                    double xa = clusCheck.Left - clusCur.Right - this.MinPaddingX;
                    double xb = clusCur.Left - clusCheck.Right - this.MinPaddingX;

                    if ((xa < -epsilon) && (xb < -epsilon))
                    {
                        // Let's see if it's a parent.
                        bool hasSideOverlap = true;
                        for (ClusterDef clusDefParent = clusCheck.ParentClusterDef; null != clusDefParent; clusDefParent = clusDefParent.ParentClusterDef)
                        {
                            if (clusDefParent == clusCur)
                            {
                                hasSideOverlap = false;
                                break;
                            }
                        }

                        // Note: This test may fail if clusCheck is a parent of clusCur, but in that case
                        // clusCheck should be outside clusCur - which means we had another error before this,
                        // that cluster {clusCheck} is outside the bounds of parent cluster {clusCur}.
                        if (hasSideOverlap)
                        {
                            // Uh oh.
                            this.WriteLine("Error {0}: Overlap exists between sibling Clusters '{1}' and '{2}'", FailTag("OlapSibClus"),
                                           clusCur.ClusterId, clusCheck.ClusterId);
                            this.WriteLine("   Cluster {0}: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}", clusCur.ClusterId,
                                           clusCur.Left, clusCur.Right, clusCur.Top, clusCur.Bottom);
                            this.WriteLine("   Cluster {0}: L/R T/B {1:F5}/{2:F5} {3:F5}/{4:F5}", clusCheck.ClusterId,
                                           clusCheck.Left, clusCheck.Right, clusCheck.Top, clusCheck.Bottom);
                            succeeded = false;
                        }
                    } // endif overlap within epsilon
                }     // endfor localClusDefs[jj]
            }
        }
Exemplo n.º 6
0
        private static void UnflattenEachClusterHierarchy(IEnumerable <ClusterDef> iterClusterDefs, IEnumerable <VariableDef> iterVariableDefs, Dictionary <int, KeyValuePair <List <ClusterDef>, List <VariableDef> > > dictHierarchies)
        {
            var kvpCurrentHierarchy = new KeyValuePair <List <ClusterDef>, List <VariableDef> >(new List <ClusterDef>(), new List <VariableDef>());

            dictHierarchies[0] = kvpCurrentHierarchy;
            foreach (VariableDef varDef in iterVariableDefs)
            {
                // If no parent, or a child of cluster 0 (which is implicit and not added to a test datafile's
                // cluster specifications), add it to the DefaultClusterHierarchy.
                if (0 == varDef.ParentClusters.Count)
                {
                    kvpCurrentHierarchy.Value.Add(varDef);
                }
                else
                {
                    foreach (ClusterDef clusDef in varDef.ParentClusters)
                    {
                        if (0 == clusDef.ClusterId)
                        {
                            kvpCurrentHierarchy.Value.Add(varDef);
                        }
                    }
                }
            }

            // Now if there are explicit clusters and/or hierarchies, add them and their variables to their hierarchy.
            if (null != iterClusterDefs)
            {
                foreach (ClusterDef clusDef in iterClusterDefs)
                {
                    Validate.IsTrue(clusDef.ClusterId > 0, "Explicit clusters must have ID > 0");
                    if (clusDef.IsNewHierarchy)
                    {
                        // Create a new hierarchy.
                        kvpCurrentHierarchy = new KeyValuePair <List <ClusterDef>, List <VariableDef> >(new List <ClusterDef>(), new List <VariableDef>());
                        dictHierarchies[clusDef.ClusterId] = kvpCurrentHierarchy;
                    }
                    else
                    {
                        // Find the root cluster of the hierarchy.  Default to the DefaultClusterHierarchy.
                        int rootId = 0;
                        for (ClusterDef clusDefParent = clusDef.ParentClusterDef; null != clusDefParent; clusDefParent = clusDefParent.ParentClusterDef)
                        {
                            if (clusDefParent.IsNewHierarchy)
                            {
                                rootId = clusDefParent.ClusterId;
                                Validate.IsNull(clusDefParent.ParentClusterDef, "IsNewHierarchy cluster's parent must be null");
                                break;
                            }
                        }
                        kvpCurrentHierarchy = dictHierarchies[rootId];
                        kvpCurrentHierarchy.Key.Add(clusDef);
                    } // endifelse IsNewHierarchy

                    foreach (VariableDef varDef in clusDef.Variables)
                    {
                        kvpCurrentHierarchy.Value.Add(varDef);
                    }
                } // endfor each cluster
            }
        }
Exemplo n.º 7
0
        private ESection ProcessCluster(int lineNumber, string currentLine, ESection currentSection, ref EClusterState currentClusterState)
        {
            if (currentLine.StartsWith(
                    TestFileStrings.EndCluster, StringComparison.OrdinalIgnoreCase))
            {
                if (EClusterState.Variable != currentClusterState)
                {
                    Validate.Fail(string.Format("Unexpected END CLUSTER line {0}: {1}", lineNumber, currentLine));
                }
                currentSection = ESection.PreClusterOrConstraints;
                this.ClusterDefs.Add(this.currentClusterDef);
                this.currentClusterDef = null;
                return(currentSection);
            }
            if (EClusterState.Id == currentClusterState)
            {
                Match m = TestFileStrings.ParseClusterId.Match(currentLine);
                if (m.Success)
                {
                    // Verify the Clusters in the file are sorted on ID.  This makes it easier for the results
                    // reading to be in sync, as we'll index ClusterDefs by [Parent - 1].
                    var id = int.Parse(m.Groups["id"].ToString());
                    Validate.IsTrue(this.currentClusterDef.ClusterId == id, "Out of order CLUSTER id");
                }
                else
                {
                    Validate.Fail(string.Format("Unparsable CLUSTER ID line {0}: {1}", lineNumber, currentLine));
                }
                currentClusterState = EClusterState.Parent;
            }
            else if (EClusterState.Parent == currentClusterState)
            {
                Match m = TestFileStrings.ParseClusterParent.Match(currentLine);
                if (m.Success)
                {
                    int parentId = int.Parse(m.Groups["parent"].ToString());

                    // Cluster IDs are 1-based because we use 0 for the "root cluster".
                    if (0 != parentId)
                    {
                        ClusterDef clusParent = this.ClusterDefs[parentId - 1];
                        Validate.AreEqual(clusParent.ClusterId, parentId, "clusParent.ClusterId mismatch with idParent");
                        clusParent.AddClusterDef(this.currentClusterDef);
                    }
                }
                else
                {
                    Validate.Fail(string.Format("Unparsable CLUSTER Parent line {0}: {1}", lineNumber, currentLine));
                }
                currentClusterState = EClusterState.LeftBorder;
            }
            else if (EClusterState.LeftBorder == currentClusterState)
            {
                // Older files didn't have MinSize.
                Match m = TestFileStrings.ParseClusterMinSize.Match(currentLine);
                if (m.Success)
                {
                    this.currentClusterDef.MinimumSizeX = double.Parse(m.Groups["X"].ToString());
                    this.currentClusterDef.MinimumSizeY = double.Parse(m.Groups["Y"].ToString());
                    return(currentSection);
                }
                if (0 == string.Compare("NewHierarchy", currentLine, StringComparison.OrdinalIgnoreCase))
                {
                    // NewHierarchy is optional.
                    this.currentClusterDef.IsNewHierarchy = true;
                    return(currentSection);
                }
                this.currentClusterDef.LeftBorderInfo = ParseBorderInfo("Left", currentLine, lineNumber);
                currentClusterState = EClusterState.RightBorder;
            }
            else if (EClusterState.RightBorder == currentClusterState)
            {
                this.currentClusterDef.RightBorderInfo = ParseBorderInfo("Right", currentLine, lineNumber);
                currentClusterState = EClusterState.TopBorder;
            }
            else if (EClusterState.TopBorder == currentClusterState)
            {
                this.currentClusterDef.TopBorderInfo = ParseBorderInfo("Top", currentLine, lineNumber);
                currentClusterState = EClusterState.BottomBorder;
            }
            else if (EClusterState.BottomBorder == currentClusterState)
            {
                this.currentClusterDef.BottomBorderInfo = ParseBorderInfo("Bottom", currentLine, lineNumber);
                currentClusterState = EClusterState.Variable;
            }
            else if (EClusterState.Variable == currentClusterState)
            {
                Match m = TestFileStrings.ParseClusterVariable.Match(currentLine);
                if (m.Success)
                {
                    int variableId = int.Parse(m.Groups["var"].ToString());
                    this.currentClusterDef.AddVariableDef(this.VariableDefs[variableId]);
                }
                else
                {
                    Validate.Fail(string.Format("Unparsable CLUSTER Variable line {0}: {1}", lineNumber, currentLine));
                }
            }
            return(currentSection);
        }
Exemplo n.º 8
0
        internal static void WriteFile(int seed,
                                       double maxWeightToGenerate,
                                       Solver solverX,
                                       Solver solverY,
                                       Solution solutionX,
                                       Solution solutionY,
                                       double minPaddingX,
                                       double minPaddingY,
                                       double minClusterSizeX,
                                       double minClusterSizeY,
                                       double maxMargin,
                                       List <VariableDef> lstVarDefs,
                                       List <ClusterDef> lstClusDefs,
                                       StreamWriter outputFileWriter)
        {
            // TODO_cleanup: make shared strings; regenerate test files to verify

            // Add the summary information as comments. @@ (high-level) and @# (low-level) allow
            // findstr etc. scans of the file metadata; @[@#] gets both.
            outputFileWriter.WriteLine("// @@Variables: {0}", lstVarDefs.Count);
            outputFileWriter.WriteLine("// @@Clusters: {0}", (null == lstClusDefs) ? 0 : lstClusDefs.Count);
            outputFileWriter.WriteLine("// @@Constraints_X: {0}", solverX.Constraints.Count());
            outputFileWriter.WriteLine("// @@Constraints_Y: {0}", solverY.Constraints.Count());
            outputFileWriter.WriteLine();

            // Values we want to read back in.
            outputFileWriter.WriteLine("Seed 0x{0}", seed.ToString("X"));
            outputFileWriter.WriteLine("Weight {0:F5}", maxWeightToGenerate);
            outputFileWriter.WriteLine("Padding {0:F5} {1:F5}", minPaddingX, minPaddingY);
            outputFileWriter.WriteLine("MinClusterSize {0:F5} {1:F5}", minClusterSizeX, minClusterSizeY);
            outputFileWriter.WriteLine("Margin {0}", maxMargin);
            outputFileWriter.WriteLine("Goal {0} {1}", solutionX.GoalFunctionValue, solutionY.GoalFunctionValue);
            outputFileWriter.WriteLine();

            outputFileWriter.WriteLine(TestFileStrings.BeginVariables);
            for (int idxVar = 0; idxVar < lstVarDefs.Count; ++idxVar)
            {
                VariableDef varDef = lstVarDefs[idxVar];
                outputFileWriter.WriteLine(
                    TestFileStrings.WriteVariable2D,
                    idxVar,
                    varDef.DesiredPosX,
                    varDef.DesiredPosY,
                    varDef.SizeX,
                    varDef.SizeY,
                    varDef.WeightX,
                    varDef.WeightY);
            }
            outputFileWriter.WriteLine(TestFileStrings.EndVariables);
            outputFileWriter.WriteLine();
            outputFileWriter.Flush();

            if (null != lstClusDefs)
            {
                // Write out the clusters, starting at 1 to skip the root.  Since we populate the
                // clusterdefs left-to-right we'll always print out the parents before the children.
                foreach (ClusterDef clusDef in lstClusDefs)
                {
                    outputFileWriter.WriteLine(TestFileStrings.BeginCluster);

                    // Write the current cluster definition.
                    outputFileWriter.WriteLine(TestFileStrings.WriteClusterId, clusDef.ClusterId);
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterParent,
                        null == clusDef.ParentClusterDef ? 0 : clusDef.ParentClusterDef.ClusterId);
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterMinSize, clusDef.MinimumSizeX, clusDef.MinimumSizeY);
                    if (clusDef.IsNewHierarchy)
                    {
                        outputFileWriter.WriteLine("NewHierarchy");
                    }
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterBorder,
                        "Left",
                        clusDef.LeftBorderInfo.InnerMargin,
                        ClusterDef.IsFixedString(clusDef.LeftBorderInfo),
                        clusDef.LeftBorderInfo.Weight);
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterBorder,
                        "Right",
                        clusDef.RightBorderInfo.InnerMargin,
                        ClusterDef.IsFixedString(clusDef.RightBorderInfo),
                        clusDef.RightBorderInfo.Weight);
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterBorder,
                        "Top",
                        clusDef.TopBorderInfo.InnerMargin,
                        ClusterDef.IsFixedString(clusDef.TopBorderInfo),
                        clusDef.TopBorderInfo.Weight);
                    outputFileWriter.WriteLine(
                        TestFileStrings.WriteClusterBorder,
                        "Bottom",
                        clusDef.BottomBorderInfo.InnerMargin,
                        ClusterDef.IsFixedString(clusDef.BottomBorderInfo),
                        clusDef.BottomBorderInfo.Weight);
                    outputFileWriter.WriteLine("// @#ClusterVars: {0}", clusDef.Variables.Count);
                    foreach (VariableDef varDef in clusDef.Variables)
                    {
                        outputFileWriter.WriteLine(TestFileStrings.WriteClusterVariable, varDef.IdString);
                    }
                    outputFileWriter.WriteLine(TestFileStrings.EndCluster);
                    outputFileWriter.WriteLine();
                }
                outputFileWriter.Flush();
            } // endif clusters exist

            // Write the constraints.
            // TODOclus: This is outputting vars Lnn Rnn in DEBUG and an empty string in RELEASE; consider making the file
            //           output (with clusters, anyway) run in DEBUG-only and have TestFileReader.cs know how to decode them.
            outputFileWriter.WriteLine(TestFileStrings.BeginConstraintsX);
            foreach (Constraint cst in solverX.Constraints.OrderBy(cst => cst))
            {
                // There are no equality constraints in OverlapRemoval so pass an empty string.
                outputFileWriter.WriteLine(
                    TestFileStrings.WriteConstraint,
                    ((OverlapRemovalNode)cst.Left.UserData).UserData,
                    ((OverlapRemovalNode)cst.Right.UserData).UserData,
                    string.Empty,
                    cst.Gap);
            }
            outputFileWriter.WriteLine(TestFileStrings.EndConstraints);
            outputFileWriter.WriteLine();
            outputFileWriter.WriteLine(TestFileStrings.BeginConstraintsY);
            foreach (Constraint cst in solverY.Constraints.OrderBy(cst => cst))
            {
                // There are no equality constraints in OverlapRemoval so pass an empty string.
                outputFileWriter.WriteLine(
                    TestFileStrings.WriteConstraint,
                    ((OverlapRemovalNode)cst.Left.UserData).UserData,
                    ((OverlapRemovalNode)cst.Right.UserData).UserData,
                    string.Empty,
                    cst.Gap);
            }
            outputFileWriter.WriteLine(TestFileStrings.EndConstraints);
            outputFileWriter.WriteLine();

            // Now write the results.
            outputFileWriter.WriteLine(TestFileStrings.BeginResults);
            foreach (VariableDef varDef in lstVarDefs)
            {
                outputFileWriter.WriteLine(TestFileStrings.WriteResults2D, varDef.IdString, varDef.VariableX.ActualPos, varDef.VariableY.ActualPos);
            } // endforeach varDef
            outputFileWriter.WriteLine(TestFileStrings.EndResults);

            if (null != lstClusDefs)
            {
                outputFileWriter.WriteLine();
                outputFileWriter.WriteLine(TestFileStrings.BeginClusterResults);
                outputFileWriter.WriteLine("// (includes only clusters that are not IsNewHierarchy)");
                foreach (ClusterDef clusDef in lstClusDefs)
                {
                    // Clusters at the root of a hierarchy have no borders.
                    if (!clusDef.IsNewHierarchy)
                    {
                        outputFileWriter.WriteLine(
                            TestFileStrings.WriteClusterResults,
                            clusDef.ClusterId,
                            clusDef.Left,
                            clusDef.Right,
                            clusDef.Top,
                            clusDef.Bottom);
                    }
                }
                outputFileWriter.WriteLine(TestFileStrings.EndClusterResults);
            }

            // Done.
            outputFileWriter.Flush();
            outputFileWriter.Close();
        }