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()); }
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); }
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); }
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); }
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 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 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); }
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);
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()), }); }
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); }
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()); }
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()); }
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); }
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); }
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 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)); }
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); }
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); }
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 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); }