示例#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 TrySelectPossibility_WhenRejectedByParent_LeavesUnchanged()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var childOptional = OptionalObjective.CreateWithPossibilities(
                Possibilities.CreatePossibilities(new(), 2), 1);
            var optional            = OptionalObjective.CreateWithPossibilities(fakePossibilities, 1);
            var linkToChildOptional = Link.CreateConnectedLink(childOptional, optional);
            var parent = new FakeObjective(isRequired: true);

            parent.CanSelectPossibilities = false;
            var          linkToParent = Link.CreateConnectedLink(optional, parent);
            IPossibility possibility  = optional;
            IObjective   objective    = optional;

            Assert.False(objective.TrySelectPossibility(fakePossibilities[0].AttachedObjectives.First()));
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.SelectedPossibilities);
        }
示例#3
0
        public void TryDropAndReturnPossibility_WhenOkWithParent_Succeeds()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var          optional     = OptionalObjective.CreateWithPossibilities(fakePossibilities, 1);
            var          parent       = new FakeObjective(isRequired: true);
            IPossibility possibility  = optional;
            IObjective   objective    = optional;
            var          linkToParent = Link.CreateConnectedLink(possibility, parent);
            var          childToDrop  = fakePossibilities[0];

            Assert.True(objective.TryDropPossibility(childToDrop.AttachedObjectives.First()));
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.DroppedPossibilities);

            Assert.True(objective.TryDropPossibility(fakePossibilities[1].AttachedObjectives.First()));
            Assert.Equal(NodeState.DROPPED, optional.State);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Single(parent.DroppedPossibilities, linkToParent);

            objective.ReturnPossibility(fakePossibilities[1].AttachedObjectives.First());
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.DroppedPossibilities);

            objective.ReturnPossibility(childToDrop.AttachedObjectives.First());
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.DroppedPossibilities);
        }
示例#4
0
        public void TryDropPossibility_WhenRejectedByParent_LeavesUnchanged()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var childOptional = OptionalObjective.CreateWithPossibilities(
                Possibilities.CreatePossibilities(new(), 2), 1);
            var possibilities = fakePossibilities.Cast <IPossibility>().Append(childOptional).ToArray();
            var optional      = OptionalObjective.CreateWithPossibilities(possibilities, 3);
            var parent        = new FakeObjective(isRequired: true);

            parent.CanDropPossibilities = false;
            IPossibility possibility = optional;
            IObjective   objective   = optional;

            Link.CreateConnectedLink(possibility, parent);
            var childToDrop = fakePossibilities[0];

            Assert.False(objective.TryDropPossibility(childToDrop.AttachedObjectives.First()));

            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Empty(parent.DroppedPossibilities);
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
        }
示例#5
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);
        }
示例#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 TryDropAndReturnFromObjective_CascadesToOtherParents_DropsThenReturns()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var childOptional = OptionalObjective.CreateWithPossibilities(
                Possibilities.CreatePossibilities(new(), 2), 1);
            var optional = OptionalObjective.CreateWithPossibilities(
                fakePossibilities.Cast <IPossibility>().Prepend(childOptional).ToArray(), 1);
            var parentToDropFrom = OptionalObjective.CreateWithPossibilities(
                new IPossibility[] {
                new FakePossibility(),
            }, 1);
            var linkToParent        = Link.CreateConnectedLink(optional, parentToDropFrom);
            var parentToCascadeDrop = OptionalObjective.CreateWithPossibilities(
                new IPossibility[] {
                new FakePossibility(),
                optional,
            }, 2);
            var required = new FakeObjective(isRequired: true);

            Link.CreateConnectedLink(parentToDropFrom, required);
            Link.CreateConnectedLink(parentToCascadeDrop, required);
            IPossibility possibility = optional;

            Assert.True(possibility.TryDropFromObjective(linkToParent));
            Assert.Equal(NodeState.DROPPED, optional.State);
            Assert.Equal(NodeState.DROPPED, parentToCascadeDrop.State);

            possibility.ReturnFromObjective(linkToParent);
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, parentToCascadeDrop.State);
        }
示例#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
        private List <Link> CreateThreeLinksWithSamePossibility()
        {
            var possibility = new FakePossibility();

            return(new List <Link> {
                Link.CreateConnectedLink(possibility, new FakeObjective()),
                Link.CreateConnectedLink(possibility, new FakeObjective()),
                Link.CreateConnectedLink(possibility, new FakeObjective()),
            });
        }
示例#10
0
        public void TrySelectAndDeselectPossibility_Succeeds()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var childOptional = OptionalObjective.CreateWithPossibilities(
                Possibilities.CreatePossibilities(new(), 2), 1);
            var          optional            = OptionalObjective.CreateWithPossibilities(fakePossibilities, 2);
            var          linkToChildOptional = Link.CreateConnectedLink(childOptional, optional);
            var          parent       = new FakeObjective(isRequired: true);
            var          linkToParent = Link.CreateConnectedLink(optional, parent);
            IPossibility possibility  = optional;
            IObjective   objective    = optional;

            Assert.True(objective.TrySelectPossibility(fakePossibilities[0].AttachedObjectives.First()));
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.SelectedPossibilities);

            Assert.True(objective.TrySelectPossibility(fakePossibilities[1].AttachedObjectives.First()));
            Assert.Equal(NodeState.SELECTED, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Single(parent.SelectedPossibilities, linkToParent);
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);

            objective.DeselectPossibility(fakePossibilities[1].AttachedObjectives.First());
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.SelectedPossibilities);

            objective.DeselectPossibility(fakePossibilities[0].AttachedObjectives.First());
            Assert.Equal(NodeState.UNKNOWN, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
            Assert.Empty(parent.SelectedPossibilities);
        }
示例#11
0
        public void PopFromObjective_OnlyUpdatesLinkReferences()
        {
            var poppedPossibility = new FakePossibility();
            var secondPossibility = new FakePossibility();
            var objective         = new FakeObjective();
            var poppedLink        = Link.CreateConnectedLink(poppedPossibility, objective);
            var secondLink        = Link.CreateConnectedLink(secondPossibility, objective);

            poppedLink.PopFromObjective();

            Assert.Same(secondLink, poppedLink.NextOnObjective);
            Assert.Same(secondLink, poppedLink.PreviousOnObjective);
            Assert.Same(secondLink, secondLink.NextOnObjective);
            Assert.Same(secondLink, secondLink.PreviousOnObjective);
            Assert.Same(poppedLink, objective.AttachedPossibilities.First());
        }
示例#12
0
        public void ReinsertToObjective_UndoesPop()
        {
            var poppedPossibility = new FakePossibility();
            var secondPossibility = new FakePossibility();
            var objective         = new FakeObjective();
            var poppedLink        = Link.CreateConnectedLink(poppedPossibility, objective);
            var secondLink        = Link.CreateConnectedLink(secondPossibility, objective);

            poppedLink.PopFromObjective();
            poppedLink.ReinsertToObjective();

            Assert.Same(secondLink, poppedLink.NextOnObjective);
            Assert.Same(secondLink, poppedLink.PreviousOnObjective);
            Assert.Same(poppedLink, secondLink.NextOnObjective);
            Assert.Same(poppedLink, secondLink.PreviousOnObjective);
            Assert.Same(poppedLink, objective.AttachedPossibilities.First());
        }
示例#13
0
        public void CreateConnectedLink_ConnectsCorrectly()
        {
            var possibility = new FakePossibility();
            var objective   = new FakeObjective();

            var link = Link.CreateConnectedLink(possibility, objective);

            Assert.Single(possibility.AttachedObjectives, link);
            Assert.Single(objective.AttachedPossibilities, link);
            Assert.Same(link, link.NextOnObjective);
            Assert.Same(link, link.PreviousOnObjective);
            Assert.Same(link, link.NextOnPossibility);
            Assert.Same(link, link.PreviousOnPossibility);
            Assert.Same(possibility, link.Possibility);
            Assert.Same(objective, link.Objective);
            Assert.Single(link.GetLinksOnObjective(), link);
            Assert.Single(link.GetLinksOnPossibility(), link);
        }
示例#14
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);
        }
示例#15
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());
        }
示例#16
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));
        }
示例#17
0
        public void CreateConnectedLink_WithExistingLinksOnPossibility_ConnectsCorrectly()
        {
            var possibility = new FakePossibility();
            var objective   = new FakeObjective();

            var firstLink = Link.CreateConnectedLink(possibility, new FakeObjective());
            var link      = Link.CreateConnectedLink(possibility, objective);

            Assert.Same(link, link.PreviousOnObjective);
            Assert.Same(link, link.NextOnObjective);
            Assert.Same(firstLink, link.NextOnPossibility);
            Assert.Same(firstLink, link.PreviousOnPossibility);
            Assert.Same(firstLink, firstLink.PreviousOnObjective);
            Assert.Same(firstLink, firstLink.NextOnObjective);
            Assert.Same(link, firstLink.NextOnPossibility);
            Assert.Same(link, firstLink.PreviousOnPossibility);
            Assert.Same(possibility, link.Possibility);
            Assert.Same(objective, link.Objective);
            Assert.Equal(2, link.GetLinksOnPossibility().Count());
            Assert.Contains(link, link.GetLinksOnPossibility());
            Assert.Contains(firstLink, link.GetLinksOnPossibility());
            Assert.Single(link.GetLinksOnObjective(), link);
            Assert.Single(firstLink.GetLinksOnObjective(), firstLink);
        }
示例#18
0
        public void TryDropFromObjective_LeavesPossibilitiesUnchanged()
        {
            var fakePossibilities = new FakePossibility[] {
                new FakePossibility(),
                new FakePossibility(),
            };
            var childOptional = OptionalObjective.CreateWithPossibilities(
                Possibilities.CreatePossibilities(new(), 2), 1);
            var optional = OptionalObjective.CreateWithPossibilities(
                fakePossibilities.Cast <IPossibility>().Prepend(childOptional).ToArray(), 1);
            var          parent       = new FakeObjective(isRequired: true);
            var          linkToParent = Link.CreateConnectedLink(optional, parent);
            IPossibility possibility  = optional;
            IObjective   objective    = optional;

            Assert.True(possibility.TryDropFromObjective(linkToParent));
            Assert.Equal(NodeState.DROPPED, optional.State);
            Assert.Equal(NodeState.UNKNOWN, childOptional.State);
            Assert.All(((IObjective)childOptional).GetUnknownDirectPossibilities().Cast <Possibility>(),
                       p => Assert.Equal(NodeState.UNKNOWN, p.State));
            Assert.Empty(parent.SelectedPossibilities);
            Assert.Empty(fakePossibilities[0].DroppedFromObjectives);
            Assert.Empty(fakePossibilities[1].DroppedFromObjectives);
        }
示例#19
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());
        }
示例#20
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);
        }