private static void SetVariableExpectedPositions(VariableDef[] variableDefs, double[] expectedPositions) { for (uint id = 0; id < variableDefs.Length; ++id) { variableDefs[id].SetExpected(id, expectedPositions[id]); } }
internal bool CheckResult(VariableDef[] variableDefs, ConstraintDef[] constraintDefs, NeighborDef[] neighborDefs, double[] expectedPositions, bool checkResults) { SetVariableExpectedPositions(variableDefs, expectedPositions); int violationCount; return CheckResult(variableDefs, constraintDefs, neighborDefs, checkResults, out violationCount); }
// These overloads work with the local Test*()... internal bool CheckResult(VariableDef[] variableDefs, ConstraintDef[] constraintDefsX, ConstraintDef[] constraintDefsY, double[] expectedPositionsX, double[] expectedPositionsY, bool checkResults) { return CheckResult(variableDefs, /*clusterDefs:*/ null, constraintDefsX, constraintDefsY, expectedPositionsX, expectedPositionsY, checkResults); }
// // These overloads work with the local Test*() routines. // bool CheckResult(VariableDef[] variableDefs, ConstraintDef[] constraintDefs , NeighborDef[] rgNeighborDefs, double[] expectedPositionsX, bool fCheckResults) { for (uint id = 0; id < variableDefs.Length; ++id) { variableDefs[id].SetExpected(id, expectedPositionsX[id]); } return CheckResult(variableDefs, constraintDefs, rgNeighborDefs, fCheckResults); }
public ConstraintDef(VariableDef leftVariableDef, VariableDef rightVariableDef, double dblGap, bool isEquality) { this.LeftVariableDef = leftVariableDef; this.RightVariableDef = rightVariableDef; this.Gap = dblGap; this.IsEquality = isEquality; if (isEquality) { // For autogeneration, to avoid infeasible transitions such as a+3=b, b+3=c, a+9=b. this.LeftVariableDef.IsInEqualityConstraint = true; this.RightVariableDef.IsInEqualityConstraint = true; } leftVariableDef.LeftConstraints.Add(this); }
// meaning that we would like position i at "position" static void AddNodeWithIdealPosition(VariableDef varDef) { double weight = varDef.WeightX; double position = varDef.DesiredPosX; SfServ.Decision x = GetOrCreateDecision(varDef); //adding the term (ix-pos)^2; workaround for bug processing x(x - 2*position) SfServ.Term term = weight * (x * x - 2 * position * x); //model.AddConstraint(varDef.Ordinal.ToString() + "ttt", x >= -100000.0); // TODO: hack to make the solver happy - fix it later!!!! AddTermToGoalTerm(term); return; }
private static void Setup__Test_Cluster_Pad0_Sibling9_Nest1_MinSize(int width, int height, out VariableDef[] variableDefs, out ClusterDef[] clusterDefs) { variableDefs = new[] { //ordinal posXY sizeXY There is only one cluster, with 'b' vars; 'a' is root /* 0 */ new VariableDef(1.0, 1.0, 3.0, 3.0), /* 1 */ new VariableDef(2.0, 1.0, 3.0, 3.0), /* 2 */ new VariableDef(3.0, 1.0, 3.0, 3.0), /* 3 */ new VariableDef(1.0, 2.0, 3.0, 3.0), /* 4 */ new VariableDef(2.0, 2.0, 3.0, 3.0), /* 5 */ new VariableDef(3.0, 2.0, 3.0, 3.0), /* 6 */ new VariableDef(1.0, 3.0, 3.0, 3.0), /* 7 */ new VariableDef(2.0, 3.0, 3.0, 3.0), /* 8 */ new VariableDef(3.0, 3.0, 3.0, 3.0), }; clusterDefs = new ClusterDef[10]; clusterDefs[0] = new ClusterDef(); // Parent cluster for (int ii = 1; ii <= 9; ++ii) { // 1-based to skip the parent cluster. clusterDefs[ii] = new ClusterDef(width, height); clusterDefs[ii].AddVariableDef(variableDefs[ii - 1]); // 0-based clusterDefs[0].AddClusterDef(clusterDefs[ii]); } }
public ConstraintDef(VariableDef leftVariableDef, VariableDef rightVariableDef, double dblGap) : this(leftVariableDef, rightVariableDef, dblGap, /*isEquality:*/ false) { }
public ConstraintDef(VariableDef leftVariableDef, VariableDef rightVariableDef, double dblGap) : this(leftVariableDef, rightVariableDef, dblGap, /*isEquality:*/ false) { }
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(); }
static void GetNodeResolvedPosition(VariableDef varDef) { ((SfVariable)varDef.VariableX).GetResolvedPosition(); }
//// //// These overloads work with the local Test*() routines. //// internal bool CheckResult(VariableDef[] variableDefs, ConstraintDef[] constraintDefs, double[] expectedPositions, bool checkResults) { return CheckResult(variableDefs, constraintDefs, null, expectedPositions, checkResults); }
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 } }
internal bool SolveRegap(string tag, VariableDef[] variableDefs, ConstraintDef[] constraintDefs, double[] expectedPositionsX) { if (TestGlobals.VerboseLevel >= 1) { this.WriteLine("... ReGapping ({0})...", tag); } SetVariableExpectedPositions(variableDefs, expectedPositionsX); int numViolations = 0; var sw = new Stopwatch(); sw.Start(); this.SolutionX = this.SolverX.Solve(this.SolverParameters); sw.Stop(); bool succeeded = true; if (!VerifySolutionMembers(this.SolutionX, /*iterNeighbourDefs:*/ null)) { succeeded = false; } if (!VerifyConstraints(/*cRep:*/ 0, constraintDefs, /*succeeded:*/ true, ref numViolations, /*checkResults:*/ true)) { succeeded = false; } if (!PostCheckResults(variableDefs, this.SolutionX.GoalFunctionValue, double.NaN, sw, /*checkResults:*/ true)) { succeeded = false; } DisplayVerboseResults(); return succeeded; }
private ESection ProcessVariables(int lineNumber, string currentLine, ESection currentSection) { if (currentLine.StartsWith(TestFileStrings.EndVariables, StringComparison.OrdinalIgnoreCase)) { currentSection = ESection.PreClusterOrConstraints; return currentSection; } Match m; if (this.isTwoDimensional) { m = TestFileStrings.ParseVariable2D.Match(currentLine); if (m.Success) { this.VariableDefs.Add(new VariableDef( uint.Parse(m.Groups["ord"].ToString()), double.Parse(m.Groups["posX"].ToString()), double.Parse(m.Groups["posY"].ToString()), double.Parse(m.Groups["sizeX"].ToString()), double.Parse(m.Groups["sizeY"].ToString()), double.Parse(m.Groups["weightX"].ToString()), double.Parse(m.Groups["weightY"].ToString()))); } } else { m = TestFileStrings.ParseVariable1D.Match(currentLine); double scale = 1.0; if (!m.Success) { m = TestFileStrings.ParseVariable1DScale.Match(currentLine); scale = m.Success ? double.Parse(m.Groups["scale"].ToString()) : scale; } if (m.Success) { var varDef = new VariableDef( uint.Parse(m.Groups["ord"].ToString()), double.Parse(m.Groups["pos"].ToString()), double.Parse(m.Groups["size"].ToString()), double.Parse(m.Groups["weight"].ToString())) { ScaleX = scale }; this.VariableDefs.Add(varDef); } } if (!m.Success) { Validate.Fail(string.Format("Unparsable VARIABLE line {0}: {1}", lineNumber, currentLine)); } // Verify the variables in the file are sorted. This makes it easier for the results // reading to be in sync. Validate.AreEqual(this.VariableDefs[this.VariableDefs.Count - 1].Ordinal, (uint)(this.VariableDefs.Count - 1), "Out of order VARIABLE ordinal"); return currentSection; }
internal bool CheckResult(VariableDef[] variableDefs, ClusterDef[] clusterDefs, ConstraintDef[] constraintDefsX, ConstraintDef[] constraintDefsY, double[] expectedPositionsX, double[] expectedPositionsY, bool checkResults) { for (uint id = 0; id < variableDefs.Length; ++id) { variableDefs[id].SetExpected(id, expectedPositionsX[id], expectedPositionsY[id]); } return CheckResult(variableDefs, clusterDefs, constraintDefsX, constraintDefsY, checkResults); }
static void GetNodeResolvedPosition(VariableDef varDef) { ((SFVariable)varDef.m_varX).ActualPos = (double)solver.GetValue(GetOrCreateVar(varDef)); }
static int GetOrCreateVar(VariableDef varDef) { if (null == (object)varDef.m_varX) { int d; if (!solver.AddVariable((int)varDef.Ordinal, out d)) { throw new ApplicationException("Cannot Create SF Variable"); } solver.SetBounds(d, -10000000.0, 10000000.0); // TODO a hack - to make the solver happy - should be fixed later varDef.m_varX = new SFVariable(d); System.Diagnostics.Debug.Assert(d >= 0, "expected: d >= 0"); return d; } return ((SFVariable)varDef.m_varX).Id; }
// (i-j)*(i-j)*coefficient is added to the goal static void AddGoalTwoNodesAreClose(VariableDef i, VariableDef j, double weight) { int x = GetOrCreateVar(i); int y = GetOrCreateVar(j); // weight * (x * x - 2 * x * y + y * y) SetGoalCoefficient(weight, x, x); SetGoalCoefficient(-2 * weight, x, y); // Apparently this handles y,x as well SetGoalCoefficient(weight, y, y); }
// leftNode+gap leq RightNode static void AddLeftRightSeparationConstraint(VariableDef leftNode, VariableDef rightNode, double gap, bool isEquality) { var left = GetOrCreateVar(leftNode); var right = GetOrCreateVar(rightNode); int rightMinusLeft; solver.AddRow( numOfRows--, out rightMinusLeft); // Constraints have negative row numbers // TODO: Equality constraints? solver.SetCoefficient(rightMinusLeft, right, 1); //right-left>=gap solver.SetCoefficient(rightMinusLeft, left, -1); solver.SetLowerBound(rightMinusLeft, gap); }
// trying to position a node at a certain place static void AddNodeWithIdealPosition(VariableDef node) { int x = GetOrCreateVar(node); //adding the term weight*(x-position)^2 SetGoalCoefficient(node.WeightX, x, x); // Apparently multiplying by 2 is not necessary SetGoalCoefficient(x, -2 * node.WeightX * node.m_dblDesiredPosX); }
// leftNode+gap leq RightNode static void AddLeftRightSeparationConstraint(VariableDef leftNode, VariableDef rightNode, double gap, bool isEquality) { SfServ.Decision leftDecision = GetOrCreateDecision(leftNode); SfServ.Decision rightDecision = GetOrCreateDecision(rightNode); SfServ.Term term; if (isEquality) { term = (leftDecision * leftNode.ScaleX) + gap == (rightDecision * rightNode.ScaleX); } else { term = (leftDecision * leftNode.ScaleX) + gap <= (rightDecision * rightNode.ScaleX); } Constraints.Add(model.AddConstraint(Constraints.Count.ToString(), term)); }
// (i-j)*(i-j)*coefficient is added to the goal static void AddGoalTwoNodesAreClose(VariableDef i, VariableDef j, double weight) { SfServ.Decision x = GetOrCreateDecision(i); SfServ.Decision y = GetOrCreateDecision(j); SfServ.Term term = weight * (x * x - 2 * x * y + y * y); AddTermToGoalTerm(term); }
internal static void WriteFile(int seed, double maxGenWeight, double maxGenScale, Solution solution, List <VariableDef> lstVarDefs, List <ConstraintDef> lstCstDefs, List <NeighborDef> lstNbourDefs, StreamWriter outputFileWriter, int violationCount) { // TODO_cleanup: make shared strings; regenerate test files to verify // Add the summary information as comments. @@ allows findstr etc. scans of the file metadata. outputFileWriter.WriteLine("// @@Variables: {0}", lstVarDefs.Count); outputFileWriter.WriteLine("// @@Constraints: {0}", lstCstDefs.Count); outputFileWriter.WriteLine("// @@Neighbours: {0}", lstNbourDefs.Count); outputFileWriter.WriteLine(); // Values we want to read back in. outputFileWriter.WriteLine("Seed 0x{0}", seed.ToString("X")); outputFileWriter.WriteLine("Weight {0:F5}", maxGenWeight); outputFileWriter.WriteLine("Scale {0:F5}", maxGenScale); outputFileWriter.WriteLine("Goal {0}", solution.GoalFunctionValue); if (0 != violationCount) { outputFileWriter.WriteLine("UnsatisfiableConstraints {0}", violationCount); } outputFileWriter.WriteLine(); outputFileWriter.WriteLine(TestFileStrings.BeginVariables); for (int idxVar = 0; idxVar < lstVarDefs.Count; ++idxVar) { VariableDef varDef = lstVarDefs[idxVar]; Validate.IsTrue(varDef.WeightX >= 0.01, "varDef.WeightX is less than expected"); outputFileWriter.WriteLine( TestFileStrings.WriteVariable1D, idxVar, varDef.DesiredPosX, varDef.SizeX, varDef.WeightX, varDef.ScaleX); } outputFileWriter.WriteLine(TestFileStrings.EndVariables); outputFileWriter.WriteLine(); outputFileWriter.Flush(); outputFileWriter.WriteLine(TestFileStrings.BeginConstraints); foreach (ConstraintDef cstDef in lstCstDefs) { outputFileWriter.WriteLine( TestFileStrings.WriteConstraint, cstDef.LeftVariableDef.IdString, cstDef.RightVariableDef.IdString, cstDef.IsEquality ? "=" : string.Empty, cstDef.Gap); } outputFileWriter.WriteLine(TestFileStrings.EndConstraints); outputFileWriter.WriteLine(); outputFileWriter.Flush(); if (lstNbourDefs.Count > 0) { outputFileWriter.WriteLine(TestFileStrings.BeginNeighbours); foreach (NeighborDef nbourDef in lstNbourDefs) { outputFileWriter.WriteLine( TestFileStrings.WriteNeighbour, nbourDef.LeftVariableDef.IdString, nbourDef.RightVariableDef.IdString, nbourDef.Weight); } outputFileWriter.WriteLine(TestFileStrings.EndNeighbours); outputFileWriter.WriteLine(); outputFileWriter.Flush(); } // Now write the expected output - it won't be correct if an exception was thrown // but at least we printed a message to the screen and file. outputFileWriter.WriteLine(TestFileStrings.BeginResults); foreach (VariableDef varDef in lstVarDefs) { outputFileWriter.WriteLine(TestFileStrings.WriteResults1D, varDef.IdString, varDef.VariableX.ActualPos); } outputFileWriter.WriteLine(TestFileStrings.EndResults); // Done. outputFileWriter.Flush(); outputFileWriter.Close(); }
static SfServ.Decision GetOrCreateDecision(VariableDef varDef) { if (null == varDef.VariableX) { var d = new SfServ.Decision(SfServ.Domain.Real, varDef.Ordinal.ToString()); varDef.VariableX = new SfVariable(d); model.AddDecision(d); return d; } return ((SfVariable)varDef.VariableX).Decision; }
internal void AddVariableDef(VariableDef varDef) { this.variableDefs.Add(varDef); varDef.ParentClusters.Add(this); }
internal void StartAtZeroWorker(int numVarsPerBlock, int numBlocks) { var expectedPositionsXNotUsed = new double[numVarsPerBlock * numBlocks]; var variableDefs = new VariableDef[numVarsPerBlock * numBlocks]; var constraintDefs = new ConstraintDef[(numVarsPerBlock - 1) * numBlocks]; for (int idxBlock = 0; idxBlock < numBlocks; ++idxBlock) { int varOffset = numVarsPerBlock * idxBlock; int cstOffset = (numVarsPerBlock - 1) * idxBlock; for (int idxVar = 0; idxVar < numVarsPerBlock; ++idxVar) { int varIndex = varOffset + idxVar; variableDefs[varIndex] = new VariableDef(0.0, ValueNotUsed); if (idxVar > 0) { constraintDefs[cstOffset + idxVar - 1] = new ConstraintDef( variableDefs[varIndex - 1], variableDefs[varIndex], 1.0); } } } Validate.IsTrue( CheckResult(variableDefs, constraintDefs, expectedPositionsXNotUsed, false /* fCheckResults */), FailureString); }