コード例 #1
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);
        }
コード例 #2
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);
        }
コード例 #3
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);
        }
コード例 #4
0
        public void CreateWithPossibilities_NeedsMoreThanPossible_Throws()
        {
            var possibilities = Possibilities.CreatePossibilities(new Coordinate(), 1);

            Assert.Throws <ArgumentException>(
                () => OptionalObjective.CreateWithPossibilities(possibilities, 2));
        }
コード例 #5
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);
        }
コード例 #6
0
        internal static OptionalObjective[] CreateIndependentOptionalObjectives(int objectivesCount, int countToSatisfy)
        {
            var objectives = new OptionalObjective[objectivesCount];

            for (--objectivesCount; objectivesCount >= 0; --objectivesCount)
            {
                objectives[objectivesCount] = OptionalObjective.CreateWithPossibilities(
                    Possibilities.CreatePossibilities(new Coordinate(objectivesCount, 0), 3), countToSatisfy);
            }
            return(objectives);
        }
コード例 #7
0
        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()));
        }
コード例 #8
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);
        }
コード例 #9
0
ファイル: ObjectiveTest.cs プロジェクト: MorganR/SudokuSpice
        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()));
        }
コード例 #10
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);
        }
コード例 #11
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));
        }
コード例 #12
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);
        }
コード例 #13
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);
        }