Beispiel #1
0
        /// <summary>
        /// Add a <see cref="ConstraintHeader"/> connecting all the
        /// <see cref="PossibleValue"/>s at the given <paramref name="valueIndex"/> on the
        /// given <paramref name="squares"/>. Skips null squares, null possible values, and any
        /// possible values in a known state (i.e. dropped or selected).
        /// </summary>
        /// <param name="squares">The squares to add possible square values from.</param>
        /// <param name="valueIndex">
        /// The value index of the possible value within the squares.
        /// </param>
        /// <param name="matrix">The matrix for the current puzzle being solved.</param>
        public static void AddConstraintHeadersForValueIndex(
            ReadOnlySpan <Square?> squares, int valueIndex, ExactCoverMatrix matrix)
        {
            var possibleSquares    = new PossibleValue[squares.Length];
            int numPossibleSquares = 0;

            for (int i = 0; i < squares.Length; i++)
            {
                Square?square = squares[i];
                if (square is null)
                {
                    continue;
                }
                PossibleValue?possibleSquare = square.GetPossibleValue(valueIndex);
                if (possibleSquare is null ||
                    possibleSquare.State != PossibleSquareState.UNKNOWN)
                {
                    continue;
                }
                possibleSquares[numPossibleSquares++] = possibleSquare;
            }
            ConstraintHeader.CreateConnectedHeader(
                matrix,
                new ReadOnlySpan <PossibleValue>(possibleSquares, 0, numPossibleSquares));
        }
Beispiel #2
0
        public void CreateConnectedLink_WithExistingLinks_ConnectsCorrectly()
        {
            var puzzle           = new Puzzle(4);
            var matrix           = new ExactCoverMatrix(puzzle);
            var square           = new Square(new Coordinate(0, 0), 2);
            var possibleSquare   = new PossibleValue(square, 1);
            var constraintHeader = new ConstraintHeader(matrix);

            var firstLink = Link.CreateConnectedLink(possibleSquare, constraintHeader);
            var link      = Link.CreateConnectedLink(possibleSquare, constraintHeader);

            Assert.Same(firstLink, link.Up);
            Assert.Same(firstLink, link.Down);
            Assert.Same(firstLink, link.Right);
            Assert.Same(firstLink, link.Left);
            Assert.Same(link, firstLink.Up);
            Assert.Same(link, firstLink.Down);
            Assert.Same(link, firstLink.Right);
            Assert.Same(link, firstLink.Left);
            Assert.Same(possibleSquare, link.PossibleSquare);
            Assert.Same(constraintHeader, link.Constraint);
            Assert.Equal(2, constraintHeader.Count);
            Assert.Same(firstLink, constraintHeader.FirstLink);
            Assert.Same(firstLink, possibleSquare.FirstLink);
        }
        public void TrySelect_DropsConstraintConnectedSquareValues()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int           valueIndex    = 0;
            PossibleValue possibleValue = matrix.GetSquare(new Coordinate(0, 1)).GetPossibleValue(valueIndex);

            Assert.True(possibleValue.TrySelect());

            ConstraintHeader constraintA = possibleValue.FirstLink.Constraint;
            ConstraintHeader constraintB = possibleValue.FirstLink.Right.Constraint;

            Assert.Equal(4, constraintA.GetLinks().Count());
            Assert.Equal(4, constraintB.GetLinks().Count());
            foreach (Link link in constraintA.GetLinks())
            {
                if (link.PossibleSquare == possibleValue)
                {
                    continue;
                }
                Assert.Equal(PossibleSquareState.DROPPED, link.PossibleSquare.State);
            }
            foreach (Link link in constraintB.GetLinks())
            {
                if (link.PossibleSquare == possibleValue)
                {
                    continue;
                }
                Assert.Equal(PossibleSquareState.DROPPED, link.PossibleSquare.State);
            }
        }
        public void Return_WithSatisfiedConstraint_UndropsTheRowAsExpected()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int              valueIndex    = 0;
            Square           square        = matrix.GetSquare(new Coordinate(0, 0));
            PossibleValue    possibleValue = square.GetPossibleValue(valueIndex);
            Link             linkA         = possibleValue.FirstLink;
            Link             linkB         = linkA.Right;
            ConstraintHeader constraintA   = linkA.Constraint;
            ConstraintHeader constraintB   = linkB.Constraint;

            Assert.True(constraintB.TrySatisfyFrom(possibleValue.FirstLink.Right.Up));
            possibleValue.Return();

            Assert.Equal(4, square.NumPossibleValues);
            Assert.Equal(PossibleSquareState.UNKNOWN, possibleValue.State);
            Assert.Equal(4, constraintA.Count);
            Assert.Equal(4, constraintB.Count);
            Assert.Contains(linkA, constraintA.GetLinks());
            Assert.Contains(linkB, constraintB.GetLinks());
        }
        public void TryDrop_LeavesUnchangedOnFailure()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int valueIndex = 0;

            Assert.True(matrix.GetSquare(new Coordinate(0, 0)).GetPossibleValue(valueIndex).TryDrop());
            Assert.True(matrix.GetSquare(new Coordinate(0, 1)).GetPossibleValue(valueIndex).TryDrop());
            Assert.True(matrix.GetSquare(new Coordinate(0, 2)).GetPossibleValue(valueIndex).TryDrop());
            Square           square        = matrix.GetSquare(new Coordinate(0, 3));
            PossibleValue    possibleValue = square.GetPossibleValue(valueIndex);
            Link             linkA         = possibleValue.FirstLink;
            Link             linkB         = linkA.Right;
            ConstraintHeader constraintA   = linkA.Constraint;
            ConstraintHeader constraintB   = linkB.Constraint;

            Assert.False(possibleValue.TryDrop());

            Assert.Equal(4, square.NumPossibleValues);
            Assert.Equal(PossibleSquareState.UNKNOWN, possibleValue.State);
            Assert.Equal(1, constraintA.Count);
            Assert.Equal(4, constraintB.Count);
            Assert.Same(linkA, constraintA.FirstLink);
            Assert.Contains(linkB, constraintB.GetLinks());
        }
Beispiel #6
0
        internal static Link CreateConnectedLink(PossibleValue possibleSquare, ConstraintHeader header)
        {
            var squareLink = new Link(possibleSquare, header);

            possibleSquare.Attach(squareLink);
            header.Attach(squareLink);
            return(squareLink);
        }
Beispiel #7
0
        public static void AssertPossibleValueIsOnConstraint(
            PossibleValue possibleValue, ConstraintHeader constraint)
        {
            Link link = constraint.FirstLink;

            do
            {
                if (link.PossibleSquare == possibleValue)
                {
                    return;
                }
                link = link.Down;
            } while (link != constraint.FirstLink);
            Assert.True(false, "No matching possible square value found.");
        }
        public void TrySelect_SelectsSquare()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int           valueIndex    = 0;
            Square        square        = matrix.GetSquare(new Coordinate(0, 1));
            PossibleValue possibleValue = square.GetPossibleValue(valueIndex);

            Assert.True(possibleValue.TrySelect());

            Assert.Equal(PossibleSquareState.SELECTED, possibleValue.State);
        }
        public void Deselect_WithSelectedValue_SetsStateAndSquareCountCorrectly()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int           valueIndex    = 0;
            Square        square        = matrix.GetSquare(new Coordinate(0, 1));
            PossibleValue possibleValue = square.GetPossibleValue(valueIndex);

            Assert.True(possibleValue.TrySelect());
            possibleValue.Deselect();

            Assert.Equal(PossibleSquareState.UNKNOWN, possibleValue.State);
            Assert.Equal(4, square.NumPossibleValues);
        }
        public void Deselect_WithSelectedValue_ReturnsDroppedRows()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int           valueIndex    = 0;
            Square        square        = matrix.GetSquare(new Coordinate(0, 1));
            PossibleValue possibleValue = square.GetPossibleValue(valueIndex);

            Assert.True(possibleValue.TrySelect());
            possibleValue.Deselect();

            Link             linkA       = possibleValue.FirstLink;
            Link             linkB       = linkA.Right;
            ConstraintHeader constraintA = linkA.Constraint;
            ConstraintHeader constraintB = linkB.Constraint;

            Assert.False(constraintA.IsSatisfied);
            Assert.False(constraintB.IsSatisfied);
            Assert.Equal(4, constraintA.Count);
            Assert.Equal(4, constraintB.Count);
            foreach (Link link in constraintA.GetLinks())
            {
                if (link != linkA)
                {
                    Assert.Equal(PossibleSquareState.UNKNOWN, link.PossibleSquare.State);
                }
            }
            foreach (Link link in constraintB.GetLinks())
            {
                if (link != linkB)
                {
                    Assert.Equal(PossibleSquareState.UNKNOWN, link.PossibleSquare.State);
                }
            }
        }
        public void TrySelect_SatisfiesConstraints()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int           valueIndex    = 0;
            PossibleValue possibleValue = matrix.GetSquare(new Coordinate(0, 1)).GetPossibleValue(valueIndex);

            Assert.True(possibleValue.TrySelect());

            ConstraintHeader constraintA = possibleValue.FirstLink.Constraint;
            ConstraintHeader constraintB = possibleValue.FirstLink.Right.Constraint;

            Assert.True(constraintA.IsSatisfied);
            Assert.True(constraintB.IsSatisfied);
            Assert.Equal(4, constraintA.Count);
            Assert.Equal(4, constraintB.Count);
            Assert.DoesNotContain(constraintA, matrix.GetUnsatisfiedConstraintHeaders());
            Assert.DoesNotContain(constraintB, matrix.GetUnsatisfiedConstraintHeaders());
        }
        public void TryDrop_DropsOnSuccess()
        {
            var puzzle = new Puzzle(4);
            var matrix = new ExactCoverMatrix(puzzle);

            new RowUniquenessConstraint().Constrain(puzzle, matrix);
            new ColumnUniquenessConstraint().Constrain(puzzle, matrix);

            int              valueIndex    = 1;
            Square           square        = matrix.GetSquare(new Coordinate(1, 0));
            PossibleValue    possibleValue = square.GetPossibleValue(valueIndex);
            Link             linkA         = possibleValue.FirstLink;
            Link             linkB         = linkA.Right;
            ConstraintHeader constraintA   = linkA.Constraint;
            ConstraintHeader constraintB   = linkB.Constraint;

            Assert.True(possibleValue.TryDrop());
            Assert.Equal(3, square.NumPossibleValues);
            Assert.Equal(PossibleSquareState.DROPPED, possibleValue.State);
            Assert.Equal(3, constraintA.Count);
            Assert.Equal(3, constraintB.Count);
            Assert.DoesNotContain(linkA, constraintA.GetLinks());
            Assert.DoesNotContain(linkB, constraintB.GetLinks());
        }
        internal PipelineVariable(XmlNode node)
        {
            id = node.Attributes["id"].Value.Trim();
            name = Banshee.Base.Localization.SelectSingleNode(node, "name").InnerText.Trim();
            control_type = StringToControlType(node.SelectSingleNode("control-type").InnerText.Trim());

            XmlAttribute enables_attr = node.Attributes["enables"];
            if(enables_attr != null && enables_attr.Value != null) {
                string [] vars = enables_attr.Value.Split(',');
                if(vars != null && vars.Length > 0) {
                    enables = new string[vars.Length];
                    for(int i = 0; i < vars.Length; i++) {
                        enables[i] = vars[i].Trim();
                    }
                }
            }

            XmlAttribute disables_attr = node.Attributes["disables"];
            if(disables_attr != null && disables_attr.Value != null) {
                string [] vars = disables_attr.Value.Split(',');
                if(vars != null && vars.Length > 0) {
                    disables = new string[vars.Length];
                    for(int i = 0; i < vars.Length; i++) {
                        disables[i] = vars[i].Trim();
                    }
                }
            }

            try {
                XmlNode unit_node = node.SelectSingleNode("unit");
                if(unit_node != null) {
                    unit = node.SelectSingleNode("unit").InnerText.Trim();
                }
            } catch {
            }

            try {
                XmlNode advanced_node = node.SelectSingleNode("advanced");
                if(advanced_node != null) {
                    advanced = ParseAdvanced(advanced_node.InnerText);
                }
            } catch {
            }

            default_value = ReadValue(node, "default-value");
            min_value = ToDouble(ReadValue(node, "min-value"));
            max_value = ToDouble(ReadValue(node, "max-value"));
            min_label = ReadValue(node, "min-label", true);
            max_label = ReadValue(node, "max-label", true);

            string step_value_str = ReadValue(node, "step-value");
            if(step_value_str != null) {
                bool zeros = true;
                step_precision = step_value_str.IndexOf(".") + 1;

                for(int i = step_precision; i > 0 && i < step_value_str.Length; i++) {
                    if(step_value_str[i] != '0') {
                        zeros = false;
                        break;
                    }
                }

                step_precision = zeros ? 0 : step_value_str.Length - step_precision;
                step_value = ToDouble(step_value_str);
            }

            if(default_value != null && default_value != String.Empty && (current_value == null ||
                current_value == String.Empty)) {
                current_value = default_value;
            }

            foreach(XmlNode possible_value_node in Banshee.Base.Localization.SelectNodes(node, "possible-values/value")) {
                try {
                    string value = possible_value_node.Attributes["value"].Value.Trim();
                    string display = possible_value_node.InnerText.Trim();

                    PossibleValue possible_value = new PossibleValue(value, display);

                    XmlAttribute attr = possible_value_node.Attributes["enables"];
                    if(attr != null && attr.Value != null) {
                        string [] vars = attr.Value.Split(',');
                        if(vars != null && vars.Length > 0) {
                            possible_value.Enables = new string[vars.Length];
                            for(int i = 0; i < vars.Length; i++) {
                                possible_value.Enables[i] = vars[i].Trim();
                            }
                        }
                    }

                    attr = possible_value_node.Attributes["disables"];
                    if(attr != null && attr.Value != null) {
                        string [] vars = attr.Value.Split(',');
                        if(vars != null && vars.Length > 0) {
                            possible_value.Disables = new string[vars.Length];
                            for(int i = 0; i < vars.Length; i++) {
                                possible_value.Disables[i] = vars[i].Trim();
                            }
                        }
                    }

                    if(!possible_values.ContainsKey(value)) {
                        possible_values.Add(value, possible_value);
                        possible_values_keys.Add(value);
                    }
                } catch {
                }
            }
        }
Beispiel #14
0
 private Link(PossibleValue possibleSquare, ConstraintHeader constraint)
 {
     PossibleSquare = possibleSquare;
     Constraint     = constraint;
     Up             = Down = Right = Left = this;
 }
Beispiel #15
0
        internal PipelineVariable(XmlNode node)
        {
            id           = node.Attributes["id"].Value.Trim();
            name         = Banshee.Base.Localization.SelectSingleNode(node, "name").InnerText.Trim();
            control_type = StringToControlType(node.SelectSingleNode("control-type").InnerText.Trim());

            XmlAttribute enables_attr = node.Attributes["enables"];

            if (enables_attr != null && enables_attr.Value != null)
            {
                string [] vars = enables_attr.Value.Split(',');
                if (vars != null && vars.Length > 0)
                {
                    enables = new string[vars.Length];
                    for (int i = 0; i < vars.Length; i++)
                    {
                        enables[i] = vars[i].Trim();
                    }
                }
            }

            XmlAttribute disables_attr = node.Attributes["disables"];

            if (disables_attr != null && disables_attr.Value != null)
            {
                string [] vars = disables_attr.Value.Split(',');
                if (vars != null && vars.Length > 0)
                {
                    disables = new string[vars.Length];
                    for (int i = 0; i < vars.Length; i++)
                    {
                        disables[i] = vars[i].Trim();
                    }
                }
            }

            try {
                XmlNode unit_node = node.SelectSingleNode("unit");
                if (unit_node != null)
                {
                    unit = node.SelectSingleNode("unit").InnerText.Trim();
                }
            } catch {
            }

            try {
                XmlNode advanced_node = node.SelectSingleNode("advanced");
                if (advanced_node != null)
                {
                    advanced = ParseAdvanced(advanced_node.InnerText);
                }
            } catch {
            }

            default_value = ReadValue(node, "default-value");
            min_value     = ToDouble(ReadValue(node, "min-value"));
            max_value     = ToDouble(ReadValue(node, "max-value"));
            min_label     = ReadValue(node, "min-label", true);
            max_label     = ReadValue(node, "max-label", true);

            string step_value_str = ReadValue(node, "step-value");

            if (step_value_str != null)
            {
                bool zeros = true;
                step_precision = step_value_str.IndexOf(".") + 1;

                for (int i = step_precision; i > 0 && i < step_value_str.Length; i++)
                {
                    if (step_value_str[i] != '0')
                    {
                        zeros = false;
                        break;
                    }
                }

                step_precision = zeros ? 0 : step_value_str.Length - step_precision;
                step_value     = ToDouble(step_value_str);
            }

            if (default_value != null && default_value != String.Empty && (current_value == null ||
                                                                           current_value == String.Empty))
            {
                current_value = default_value;
            }

            foreach (XmlNode possible_value_node in Banshee.Base.Localization.SelectNodes(node, "possible-values/value"))
            {
                try {
                    string value   = possible_value_node.Attributes["value"].Value.Trim();
                    string display = possible_value_node.InnerText.Trim();

                    PossibleValue possible_value = new PossibleValue(value, display);

                    XmlAttribute attr = possible_value_node.Attributes["enables"];
                    if (attr != null && attr.Value != null)
                    {
                        string [] vars = attr.Value.Split(',');
                        if (vars != null && vars.Length > 0)
                        {
                            possible_value.Enables = new string[vars.Length];
                            for (int i = 0; i < vars.Length; i++)
                            {
                                possible_value.Enables[i] = vars[i].Trim();
                            }
                        }
                    }

                    attr = possible_value_node.Attributes["disables"];
                    if (attr != null && attr.Value != null)
                    {
                        string [] vars = attr.Value.Split(',');
                        if (vars != null && vars.Length > 0)
                        {
                            possible_value.Disables = new string[vars.Length];
                            for (int i = 0; i < vars.Length; i++)
                            {
                                possible_value.Disables[i] = vars[i].Trim();
                            }
                        }
                    }

                    if (!possible_values.ContainsKey(value))
                    {
                        possible_values.Add(value, possible_value);
                        possible_values_keys.Add(value);
                    }
                } catch {
                }
            }
        }