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); }
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); }); }
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()); }
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()); }
public void CreateWithPossibilities_ConnectsCorrectly(int numPossibilities, int numToSatisfy) { var possibilities = Possibilities.CreatePossibilities(new Coordinate(), numPossibilities); var concreteObjective = OptionalObjective.CreateWithPossibilities(possibilities, numToSatisfy); IObjective objective = concreteObjective; Assert.Equal(numToSatisfy, concreteObjective.TotalCountToSatisfy); Assert.Equal(NodeState.UNKNOWN, concreteObjective.State); Assert.False(objective.IsRequired); Assert.Equal( new HashSet <IPossibility>(possibilities), new HashSet <IPossibility>(objective.GetUnknownDirectPossibilities())); }
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)); }
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)); }
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()); }
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())); }