示例#1
0
        public void TrySelectAndDeselectPossibility_WithOneRequired_Works()
        {
            var puzzle        = new Puzzle(4);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var selectedPossibility = possibilities[0];
            var droppedPossibility  = possibilities[1];
            var objective           = Objective.CreateFullyConnected(matrix, possibilities, 1);

            Assert.NotEqual(NodeState.SELECTED, objective.State);
            ((IObjective)objective).TrySelectPossibility(selectedPossibility.AttachedObjectives.First());
            Assert.Equal(NodeState.SELECTED, objective.State);
            Assert.DoesNotContain(objective, matrix.GetUnsatisfiedRequiredObjectives());
            Assert.Empty(((IObjective)objective).GetUnknownDirectPossibilities());
            Assert.Empty(selectedPossibility.DroppedFromObjectives);
            Assert.Single(droppedPossibility.DroppedFromObjectives);

            ((IObjective)objective).DeselectPossibility(selectedPossibility.AttachedObjectives.First());
            Assert.NotEqual(NodeState.SELECTED, objective.State);
            Assert.Contains(objective, matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());
            Assert.Empty(selectedPossibility.DroppedFromObjectives);
            Assert.Empty(droppedPossibility.DroppedFromObjectives);
            Assert.Contains(selectedPossibility, ((IObjective)objective).GetUnknownDirectPossibilities());
            Assert.Contains(droppedPossibility, ((IObjective)objective).GetUnknownDirectPossibilities());
        }
示例#2
0
        public void TryConstrain_ConstrainsCorrectly()
        {
            var puzzle = new Puzzle(new int?[][] {
                new int?[] { null, null, 9, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 5, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var boxesToConstrain = new Box[] {
                new Box(new Coordinate(0, 0), 3),
            };
            var constraint = new MagicSquaresConstraint(
                _CreateStandardPossibleValues(9),
                boxesToConstrain, includeDiagonals: false);
            var graph = ExactCoverGraph.Create(puzzle);

            Assert.True(constraint.TryConstrain(puzzle, graph));

            _AssertPossibleValuesAtSquare(new(0, 0), new int[] { 1, 2, 4, 5 }, graph);
            _AssertPossibleValuesAtSquare(new(0, 1), new int[] { 4, 5 }, graph);
            _AssertPossibleValuesAtSquare(new(1, 0), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, graph);
            _AssertPossibleValuesAtSquare(new(1, 1), new int[] { 4, 5, 7, 8 }, graph);
            _AssertPossibleValuesAtSquare(new(1, 2), new int[] { 1 }, graph);
            _AssertPossibleValuesAtSquare(new(2, 0), new int[] { 7 }, graph);
            _AssertPossibleValuesAtSquare(new(3, 0), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, graph);
        }
示例#3
0
        public void TryConstrain_WithUniqueValuesInDiagonals_Succeeds()
        {
            var puzzle = new Puzzle(new int?[][] {
                new int?[] { 1, null, null, null },
                new int?[] { null, null, 2, null },
                new int?[] { null, 3, 3, null },
                new int?[] { 4, null, null, null },
            });
            var graph      = ExactCoverGraph.Create(puzzle);
            var constraint = new DiagonalUniquenessConstraint();

            Assert.True(constraint.TryConstrain(puzzle, graph));

            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(0, 1), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(0, 2), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(1, 0), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(1, 3), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(2, 0), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(2, 3), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(3, 1), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(3, 2), new int[] { 1, 2, 3, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(1, 1), new int[] { 2, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(3, 3), new int[] { 2, 4 }, graph);
            ExactCoverGraphs.AssertPossibleValuesAtSquare(new(0, 3), new int[] { 1 }, graph);
            ExactCoverGraphs.AssertNoPossibleValuesAtSquare(new(0, 0), graph);
            ExactCoverGraphs.AssertNoPossibleValuesAtSquare(new(2, 2), graph);
            ExactCoverGraphs.AssertNoPossibleValuesAtSquare(new(1, 2), graph);
            ExactCoverGraphs.AssertNoPossibleValuesAtSquare(new(2, 1), graph);
            ExactCoverGraphs.AssertNoPossibleValuesAtSquare(new(3, 0), graph);
        }
示例#4
0
        public void CreateFullyConnected_ConnectsCorrectly(int numPossibilities, int numRequired, bool asConcrete)
        {
            int size          = 4;
            var puzzle        = new Puzzle(size);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = Possibilities.CreatePossibilities(new Coordinate(), numPossibilities);

            Objective objective;

            if (asConcrete)
            {
                objective = Objective.CreateFullyConnected(matrix,
                                                           new ReadOnlySpan <Possibility>(possibilities),
                                                           numRequired);
            }
            else
            {
                objective = Objective.CreateFullyConnected(matrix,
                                                           new ReadOnlySpan <IPossibility>(possibilities),
                                                           numRequired);
            }

            Assert.True(objective.AllUnknownPossibilitiesAreConcrete);
            Assert.True(((IObjective)objective).IsRequired);
            Assert.Equal(numPossibilities == numRequired, objective.AllUnknownPossibilitiesAreRequired);
            Assert.NotEqual(NodeState.SELECTED, objective.State);
            Assert.Equal(possibilities.Length, objective.CountUnknown);
            Assert.Equal(numRequired, objective.TotalCountToSatisfy);
            Assert.All(possibilities,
                       p => Assert.Contains(p, ((IObjective)objective).GetUnknownDirectPossibilities()));
            Assert.All(((IObjective)objective).GetUnknownDirectPossibilities(),
                       p => Assert.Contains(p, possibilities));
            Assert.Contains(objective, matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());
        }
示例#5
0
        public void Create_ConfiguresSquareObjectives()
        {
            var puzzle = new Puzzle(4);
            var graph  = ExactCoverGraph.Create(puzzle);

            var objectives = graph.GetUnsatisfiedRequiredObjectives();

            Assert.Equal(puzzle.Size * puzzle.Size, objectives.Count());

            var seenCoordinates    = new HashSet <Coordinate>();
            var possibilityIndices = new HashSet <int>()
            {
                0, 1, 2, 3
            };

            Assert.All(objectives,
                       concreteObjective =>
            {
                IObjective objective = concreteObjective;
                var possibilities    = objective.GetUnknownDirectPossibilities().Cast <Possibility>().ToArray();
                // Assert that each square links every possibility at that coordinate.
                Assert.Equal(puzzle.Size, possibilities.Length);
                Assert.Equal(possibilityIndices, new HashSet <int>(possibilities.Select(p => p.Index)));
                var firstCoord = possibilities.First().Coordinate;
                Assert.All(possibilities,
                           p =>
                {
                    Assert.Equal(firstCoord, p.Coordinate);
                    Assert.Equal(NodeState.UNKNOWN, p.State);
                });
                // Assert an objective is made for each square.
                Assert.DoesNotContain(firstCoord, seenCoordinates);
                seenCoordinates.Add(firstCoord);
            });
        }
示例#6
0
        public void TryDropAndReturnPossibility_Succeeds()
        {
            var puzzle        = new Puzzle(4);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
                new FakePossibility(),
            };
            var        toDrop            = possibilities[0];
            var        concreteObjective = Objective.CreateFullyConnected(matrix, possibilities, 2);
            IObjective objective         = concreteObjective;

            Assert.True(objective.TryDropPossibility(toDrop.AttachedObjectives.First()));
            Assert.Equal(2, concreteObjective.CountUnknown);
            Assert.Equal(2, objective.GetUnknownDirectPossibilities().Count());
            Assert.Contains(possibilities[1], objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[2], objective.GetUnknownDirectPossibilities());
            Assert.Empty(toDrop.DroppedFromObjectives);

            objective.ReturnPossibility(toDrop.AttachedObjectives.First());
            Assert.Equal(3, concreteObjective.CountUnknown);
            Assert.Equal(3, objective.GetUnknownDirectPossibilities().Count());
            Assert.Contains(toDrop, objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[1], objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[2], objective.GetUnknownDirectPossibilities());
        }
示例#7
0
        public void TrySelectAndDeselectPossibility_WithMultipleRequired_Works()
        {
            var puzzle        = new Puzzle(4);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var        firstSelected     = possibilities[0];
            var        secondSelected    = possibilities[1];
            var        concreteObjective = Objective.CreateFullyConnected(matrix, possibilities, 2);
            IObjective objective         = concreteObjective;

            Assert.True(objective.TrySelectPossibility(firstSelected.AttachedObjectives.First()));
            Assert.NotEqual(NodeState.SELECTED, concreteObjective.State);
            Assert.Equal(1, concreteObjective.CountUnknown);
            Assert.Single(objective.GetUnknownDirectPossibilities(), secondSelected);
            Assert.Contains(concreteObjective, matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());

            Assert.True(objective.TrySelectPossibility(secondSelected.AttachedObjectives.First()));
            Assert.Equal(NodeState.SELECTED, concreteObjective.State);
            Assert.Equal(0, concreteObjective.CountUnknown);
            Assert.True(!matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities().Contains(concreteObjective) ||
                        matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities().Count() == 1);

            objective.DeselectPossibility(secondSelected.AttachedObjectives.First());
            Assert.NotEqual(NodeState.SELECTED, concreteObjective.State);
            Assert.Equal(1, concreteObjective.CountUnknown);
            Assert.Single(objective.GetUnknownDirectPossibilities(), secondSelected);
            Assert.Contains(concreteObjective, matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());

            objective.DeselectPossibility(firstSelected.AttachedObjectives.First());
            Assert.Equal(2, concreteObjective.CountUnknown);
        }
示例#8
0
 public void CascadingDropUpDownUpWithDropAtMidpoint()
 {
     var puzzle          = new Puzzle(4);
     var matrix          = ExactCoverGraph.Create(puzzle);
     var possibilities   = Possibilities.CreatePossibilities(new Coordinate(), 3);
     var required        = Objective.CreateFullyConnected(matrix, new ReadOnlySpan <Possibility>(possibilities), 1);
     var fakePossibility = new FakePossibility();
     var optional        = OptionalObjective.CreateWithPossibilities(
         possibilities[1..3], 2);
示例#9
0
        public void GetPossibilitiesOnRow_ReturnsExpectedSquares()
        {
            var puzzle = new Puzzle(4);
            var graph  = ExactCoverGraph.Create(puzzle);

            int rowIndex = 1;
            var row      = graph.GetPossibilitiesOnRow(rowIndex);

            Assert.Equal(4, row.Length);
            Assert.Equal(new Coordinate(rowIndex, 0), row[0] ![0] !.Coordinate);
示例#10
0
        public void TryConstrain_IncludingDiagonals_ConstrainsCorrectly()
        {
            var puzzle = new Puzzle(new int?[][] {
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, 6, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, 3, 8, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var boxesToConstrain = new Box[] {
                new Box(new Coordinate(3, 3), 3),
            };
            var constraint = new MagicSquaresConstraint(
                _CreateStandardPossibleValues(9),
                boxesToConstrain, includeDiagonals: true);
            var graph = ExactCoverGraph.Create(puzzle);

            Assert.True(constraint.TryConstrain(puzzle, graph));

            // rows: 18, 27, 45
            // rows: all
            // rows: 4

            // cols: all
            // cols: 84 75
            // cols: 1

            // 124578    | 4578 | x
            // 123456789 | 4578 | 1
            // 4         | x    | x

            // diagonals \: 16 25 34 -> Has to be 25 when combining top left and middle possibles.
            // diagonals /: 18 27 45 -> Has to be 45 when combining bottom left and middle possibles.

            // 25        | 4578 | x
            // 123456789 | 5    | 1
            // 4         | x    | x

            // Note this doesn't filter further because failed optional objectives can't drop
            // possiblities.

            _AssertPossibleValuesAtSquare(new(3, 3), new int[] { 2, 5 }, graph);
            _AssertPossibleValuesAtSquare(new(3, 4), new int[] { 4, 5, 7, 8 }, graph);
            _AssertPossibleValuesAtSquare(new(4, 3), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, graph);
            _AssertPossibleValuesAtSquare(new(4, 4), new int[] { 5 }, graph);
            _AssertPossibleValuesAtSquare(new(4, 5), new int[] { 1 }, graph);
            _AssertPossibleValuesAtSquare(new(5, 3), new int[] { 4 }, graph);
            _AssertPossibleValuesAtSquare(new(6, 3), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, graph);
        }
示例#11
0
        public void TryConstrain_WithNonUniqueValuesInDiagonals_Fails()
        {
            var puzzle = new Puzzle(new int?[][] {
                new int?[] { 1, null, null, null },
                new int?[] { null, null, null, null },
                new int?[] { null, 3, 1, null },
                new int?[] { null, null, null, null },
            });
            var graph      = ExactCoverGraph.Create(puzzle);
            var constraint = new DiagonalUniquenessConstraint();

            Assert.False(constraint.TryConstrain(puzzle, graph));
        }
        public void Constrain_ReturnsExpectedConstraints()
        {
            int size = 4;

            int[] possibleValues   = new int[] { 1, 3, 5, 7 };
            var   puzzle           = new Puzzle(size);
            var   matrix           = ExactCoverGraph.Create(puzzle);
            var   squareObjectives = new HashSet <Objective>(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());

            Assert.True(new ColumnUniquenessConstraint().TryConstrain(puzzle, matrix));

            Assert.Equal(
                size * possibleValues.Length + squareObjectives.Count,
                matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities().Count());
            Dictionary <int, HashSet <int> > columnsToValues = new();

            for (int i = 0; i < size; ++i)
            {
                columnsToValues[i] = new HashSet <int>();
            }
            var expectedRows = new int[] { 0, 1, 2, 3 };

            Assert.All(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities(),
                       concreteObjective =>
            {
                if (squareObjectives.Contains(concreteObjective))
                {
                    return;
                }
                IObjective objective = concreteObjective;
                var possibilities    = objective.GetUnknownDirectPossibilities().Cast <Possibility>().ToArray();
                int column           = possibilities[0].Coordinate.Column;
                int value            = possibilities[0].Index;
                Assert.DoesNotContain(value, columnsToValues[column]);
                columnsToValues[column].Add(value);
                var expectedCoordinates = expectedRows.Select(row => new Coordinate(row, column)).ToArray();
                Assert.Equal(expectedCoordinates.Length, possibilities.Length);
                Assert.All(possibilities, p =>
                {
                    Assert.Contains(p.Coordinate, expectedCoordinates);
                    Assert.Equal(value, p.Index);
                });
                Assert.All(expectedCoordinates, c => Assert.NotNull(possibilities.SingleOrDefault(p => p.Coordinate == c)));
            });
            Assert.All(
                columnsToValues.Values,
                values => Assert.Equal(new HashSet <int> {
                0, 1, 2, 3
            }, values));
        }
示例#13
0
        public void Constrain_GroupsConstraintsAsExpected()
        {
            int size    = 4;
            int boxSize = 2;

            int[] possibleValues   = new int[] { 1, 3, 5, 7 };
            var   puzzle           = new Puzzle(size);
            var   matrix           = ExactCoverGraph.Create(puzzle);
            var   squareObjectives = new HashSet <Objective>(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());

            Assert.True(new BoxUniquenessConstraint().TryConstrain(puzzle, matrix));

            Assert.Equal(
                size * possibleValues.Length + squareObjectives.Count,
                matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities().Count());
            Dictionary <int, HashSet <int> > boxIndicesToValues = new();

            for (int i = 0; i < size; ++i)
            {
                boxIndicesToValues[i] = new HashSet <int>();
            }
            Assert.All(matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities(),
                       concreteObjective =>
            {
                if (squareObjectives.Contains(concreteObjective))
                {
                    return;
                }
                IObjective objective = concreteObjective;
                var possibilities    = objective.GetUnknownDirectPossibilities().Cast <Possibility>().ToArray();
                int boxIndex         = Boxes.CalculateBoxIndex(possibilities[0].Coordinate, boxSize);
                int value            = possibilities[0].Index;
                Assert.DoesNotContain(value, boxIndicesToValues[boxIndex]);
                boxIndicesToValues[boxIndex].Add(value);
                var boxCoordinates = Boxes.YieldUnsetCoordsForBox(boxIndex, boxSize, puzzle).ToArray();
                Assert.Equal(boxCoordinates.Length, possibilities.Length);
                Assert.All(possibilities, p =>
                {
                    Assert.Contains(p.Coordinate, boxCoordinates);
                    Assert.Equal(value, p.Index);
                });
                Assert.All(boxCoordinates, c => Assert.NotNull(possibilities.SingleOrDefault(p => p.Coordinate == c)));
            });
            Assert.All(
                boxIndicesToValues.Values,
                values => Assert.Equal(new HashSet <int> {
                0, 1, 2, 3
            }, values));
        }
示例#14
0
        public void CreateFullyConnected_WithOptionalObjectives_ConnectsCorrectly()
        {
            var puzzle             = new Puzzle(4);
            var matrix             = ExactCoverGraph.Create(puzzle);
            var optionalObjectives = new OptionalObjective[] {
                OptionalObjective.CreateWithPossibilities(Possibilities.CreatePossibilities(new Coordinate(), 2), 1),
                OptionalObjective.CreateWithPossibilities(Possibilities.CreatePossibilities(new Coordinate(), 2), 1),
            };
            var        concreteObjective = Objective.CreateFullyConnected(matrix, optionalObjectives, 1);
            IObjective objective         = concreteObjective;

            Assert.Equal(
                new HashSet <IPossibility>(optionalObjectives),
                new HashSet <IPossibility>(objective.GetUnknownDirectPossibilities()));
        }
示例#15
0
        public void GetAllPossibilitiesAt_ForUnsetCoordinate_ReturnsExpectedPossibilities()
        {
            var             puzzle = new Puzzle(4);
            ExactCoverGraph graph  = ExactCoverGraph.Create(puzzle);

            var possibilities = graph.GetAllPossibilitiesAt(new Coordinate());

            Assert.NotNull(possibilities);
            Assert.Equal(puzzle.Size, possibilities !.Length);
            for (int i = 0; i < puzzle.Size; ++i)
            {
                Assert.NotNull(possibilities[i]);
                Assert.Equal(i, possibilities[i] !.Index);
            }
        }
示例#16
0
        public void TrySelectAndDeselect_WhenSharedByOpposingObjectives_Fails()
        {
            var puzzle = new Puzzle(4);
            var matrix = ExactCoverGraph.Create(puzzle);
            var concretePossibility = new Possibility(new(), 1);
            var possibilities       = new IPossibility[] { concretePossibility };
            var parentA             = OptionalObjective.CreateWithPossibilities(possibilities, 1);
            var parentB             = OptionalObjective.CreateWithPossibilities(possibilities.Append(new FakePossibility()).ToArray(), 1);
            var required            = Objective.CreateFullyConnected(
                matrix,
                new IPossibility[] { parentA, parentB },
                1);

            Assert.False(concretePossibility.TrySelect());
            Assert.Equal(NodeState.UNKNOWN, parentA.State);
            Assert.Equal(NodeState.UNKNOWN, parentB.State);
            Assert.NotEqual(NodeState.SELECTED, required.State);
        }
示例#17
0
        public void AllUnknownPossibilitiesAreConcrete_UpdatesWhenPossibilitiesChange()
        {
            var puzzle          = new Puzzle(4);
            var matrix          = ExactCoverGraph.Create(puzzle);
            var fakePossibility = new FakePossibility(isConcrete: false);
            var possibilities   = new IPossibility[] {
                new Possibility(new Coordinate(), 0),
                fakePossibility,
            };

            var objective = Objective.CreateFullyConnected(matrix, possibilities, 1);

            Assert.Single(fakePossibility.AttachedObjectives);
            Assert.False(objective.AllUnknownPossibilitiesAreConcrete);

            Assert.True(((IObjective)objective).TryDropPossibility(fakePossibility.AttachedObjectives.First()));
            Assert.True(objective.AllUnknownPossibilitiesAreConcrete);
        }
示例#18
0
        public void TryDropPossibility_WhenRequired_Fails()
        {
            var puzzle        = new Puzzle(4);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
                new FakePossibility(),
            };
            var        toDrop            = possibilities[0];
            var        concreteObjective = Objective.CreateFullyConnected(matrix, possibilities, 3);
            IObjective objective         = concreteObjective;

            Assert.False(objective.TryDropPossibility(toDrop.AttachedObjectives.First()));
            Assert.Equal(3, concreteObjective.CountUnknown);
            Assert.Equal(3, objective.GetUnknownDirectPossibilities().Count());
            Assert.Contains(toDrop, objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[1], objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[2], objective.GetUnknownDirectPossibilities());
        }
示例#19
0
        public void CascadingDropUpDownUp()
        {
            var puzzle          = new Puzzle(4);
            var matrix          = ExactCoverGraph.Create(puzzle);
            var possibilities   = Possibilities.CreatePossibilities(new Coordinate(), 2);
            var required        = Objective.CreateFullyConnected(matrix, new ReadOnlySpan <Possibility>(possibilities), 1);
            var fakePossibility = new FakePossibility();
            var optional        = OptionalObjective.CreateWithPossibilities(
                possibilities.Cast <IPossibility>().ToArray(), 2);
            var fakeLinkToOptional = Link.CreateConnectedLink(fakePossibility, optional);
            var separateRequired   = Objective.CreateFullyConnected(matrix, new IPossibility[] { optional }, 1);


            // Additionally try one where optional ends up dropped before the cascade somehow... maybe add one to possibilities and to optional's countToSatisfy.

            Assert.True(possibilities[0].TrySelect());
            Assert.Equal(NodeState.SELECTED, possibilities[0].State);
            Assert.Equal(NodeState.DROPPED, possibilities[1].State);
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(fakePossibility.DroppedFromObjectives);
            Assert.Equal(NodeState.SELECTED, required.State);
            Assert.NotEqual(NodeState.SELECTED, separateRequired.State);

            Assert.True(((IObjective)optional).TrySelectPossibility(fakeLinkToOptional));
            Assert.Equal(NodeState.SELECTED, possibilities[0].State);
            Assert.Equal(NodeState.DROPPED, possibilities[1].State);
            Assert.Equal(NodeState.SELECTED, optional.State);
            Assert.Equal(NodeState.SELECTED, required.State);
            Assert.Equal(NodeState.SELECTED, separateRequired.State);

            ((IObjective)optional).DeselectPossibility(fakeLinkToOptional);
            Assert.Equal(NodeState.SELECTED, possibilities[0].State);
            Assert.Equal(NodeState.DROPPED, possibilities[1].State);
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(fakePossibility.DroppedFromObjectives);
            Assert.Equal(NodeState.SELECTED, required.State);
            Assert.NotEqual(NodeState.SELECTED, separateRequired.State);

            Assert.False(((IObjective)optional).TryDropPossibility(fakeLinkToOptional));
        }
示例#20
0
        public void CreateFullyConnected_NeedsMoreThanPossible_Throws(bool asConcrete)
        {
            int size          = 4;
            var puzzle        = new Puzzle(size);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = Possibilities.CreatePossibilities(new Coordinate(), 1);

            Assert.Single(possibilities);

            Assert.Throws <ArgumentException>(
                () =>
            {
                if (asConcrete)
                {
                    Objective.CreateFullyConnected(matrix, new ReadOnlySpan <Possibility>(possibilities), possibilities.Length + 1);
                }
                else
                {
                    Objective.CreateFullyConnected(matrix, new ReadOnlySpan <IPossibility>(possibilities), possibilities.Length + 1);
                }
            });
        }
示例#21
0
        public void TryConstrain_NotPossible_Fails()
        {
            var puzzle = new Puzzle(new int?[][] {
                new int?[] { null, null, 6, null, null, null, null, null, null },
                new int?[] { 1, null, null, null, null, null, null, null, null },
                new int?[] { null, 3, 8, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
                new int?[] { null, null, null, null, null, null, null, null, null },
            });
            var boxesToConstrain = new Box[] {
                new Box(new Coordinate(0, 0), 3),
            };
            var constraint = new MagicSquaresConstraint(
                _CreateStandardPossibleValues(9),
                boxesToConstrain, includeDiagonals: false);
            var graph = ExactCoverGraph.Create(puzzle);

            Assert.False(constraint.TryConstrain(puzzle, graph));
        }
示例#22
0
        public void TrySelectPossibility_WithUndetachablePossibility_Fails()
        {
            var puzzle        = new Puzzle(4);
            var matrix        = ExactCoverGraph.Create(puzzle);
            var possibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
                new FakePossibility(),
            };
            var toSelect     = possibilities[0];
            var undetachable = possibilities[2];

            undetachable.CanBeDetached = false;
            var        concreteObjective = Objective.CreateFullyConnected(matrix, possibilities, 1);
            IObjective objective         = concreteObjective;

            Assert.False(objective.TrySelectPossibility(toSelect.AttachedObjectives.First()));
            Assert.Empty(possibilities[1].DroppedFromObjectives);
            Assert.Empty(undetachable.DroppedFromObjectives);
            Assert.Contains(objective, matrix.GetUnsatisfiedRequiredObjectivesWithConcretePossibilities());
            Assert.Contains(toSelect, objective.GetUnknownDirectPossibilities());
            Assert.Contains(possibilities[1], objective.GetUnknownDirectPossibilities());
            Assert.Contains(undetachable, objective.GetUnknownDirectPossibilities());
        }
示例#23
0
        public void TrySelectPossibility_CausesCascadingDrop_SelectsAndDeselectsCorrectly()
        {
            var puzzle            = new Puzzle(4);
            var matrix            = ExactCoverGraph.Create(puzzle);
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var optional = OptionalObjective.CreateWithPossibilities(fakePossibilities, 1);
            var fakesOnParentToSelect = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var parentToSelect = OptionalObjective.CreateWithPossibilities(
                fakesOnParentToSelect.Cast <IPossibility>().Prepend(optional).ToArray(), 2);
            var fakeOnParentToDrop = new FakePossibility();
            var parentToDrop       = OptionalObjective.CreateWithPossibilities(
                new IPossibility[] {
                fakeOnParentToDrop,
                optional,
            }, 2);
            var required = Objective.CreateFullyConnected(
                matrix,
                new IPossibility[] { parentToSelect, parentToDrop },
                1);
            IObjective objective = optional;

            ;
            // Select one fake on parentToSelect so that selecting this optional will satisfy the
            // objective.
            Assert.True(((IObjective)parentToSelect).TrySelectPossibility(fakesOnParentToSelect[0].AttachedObjectives.First()));
            Assert.True(objective.TrySelectPossibility(fakePossibilities[0].AttachedObjectives.First()));
            Assert.Equal(NodeState.SELECTED, optional.State);
            Assert.Equal(NodeState.SELECTED, parentToSelect.State);
            Assert.Empty(fakesOnParentToSelect[1].DroppedFromObjectives);
            Assert.Equal(NodeState.SELECTED, required.State);
            Assert.Equal(NodeState.DROPPED, parentToDrop.State);
            Assert.Empty(fakeOnParentToDrop.DroppedFromObjectives);

            objective.DeselectPossibility(fakePossibilities[0].AttachedObjectives.First());
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, parentToSelect.State);
            Assert.Empty(fakesOnParentToSelect[1].DroppedFromObjectives);
            Assert.Equal(NodeState.UNKNOWN, required.State);
            Assert.Equal(NodeState.UNKNOWN, parentToDrop.State);
            Assert.Empty(fakeOnParentToDrop.DroppedFromObjectives);

            // Select a possibility on parentToDrop first. This should result in no change overall.
            Assert.True(((IObjective)parentToDrop).TrySelectPossibility(fakeOnParentToDrop.AttachedObjectives.First()));

            // Selecting the objective would satisfy both optional parents, which violates the
            // required objective.
            Assert.False(objective.TrySelectPossibility(fakePossibilities[0].AttachedObjectives.First()));

            // Deselect a possibility from parentToSelect so that we can now select parentToDrop.
            ((IObjective)parentToSelect).DeselectPossibility(fakesOnParentToSelect[0].AttachedObjectives.First());
            Assert.True(objective.TrySelectPossibility(fakePossibilities[0].AttachedObjectives.First()));
            Assert.Equal(NodeState.SELECTED, optional.State);
            Assert.Equal(NodeState.DROPPED, parentToSelect.State);
            Assert.Empty(fakesOnParentToSelect[1].DroppedFromObjectives);
            Assert.Equal(NodeState.SELECTED, required.State);
            Assert.Equal(NodeState.SELECTED, parentToDrop.State);
            Assert.Empty(fakeOnParentToDrop.DroppedFromObjectives);
        }