/// <summary> /// This method is looking for a subset that contains values that /// the outer set does not contain /// </summary> /// <param name="outerSet"></param> /// <param name="space"></param> /// <returns></returns> public IPossible ReducedSetValues(IEnumerable <TKey> outerSet, ISpace <TKey> space) { Keys <TKey> oSet = new Keys <TKey>(outerSet); oSet.ExceptWith(this); IPossible reducedValues = space.AllValuesAt(this); // Get all values in subset combination foreach (TKey keyInner in this) { Possible innerValues = new Possible(space[keyInner]); foreach (TKey keyOuter in oSet) { innerValues.FilterOut(space[keyOuter]); } // Each innerKey must have an exclusive value not in the outer set if (innerValues.Count > 0) { reducedValues.IntersectPossible(innerValues); } else { reducedValues.Clear(); break; } } return(reducedValues); }
public bool SetValues(IPossible possible) { if (!this.innerValue.SetEquals(possible)) { this.innerValue = new HashSet <int>(possible.Values); HasChanged = true; return(true); } return(false); }
/// <summary> /// If combined values are equal to the spaces then its a complete set /// e.g. 1-3,1-3,1-3,1-9,1-9,1-9,1-9,1-9,1-9 (Keys1,2,3 are complete) /// e.g. 1-2,2-3,1:3,1-9,1-9,1-9,1-9,1-9,1-9 (Keys1,2,3 are complete) /// e.g. 1-9,1-9,1-9,4-9,4-9,4-9,4-9,4-9,4-9 (Keys4-9 are complete) /// </summary> public bool CompleteSet(IList <TKey> set) { IPossible allValues = Space.AllValuesAt(set); if (allValues.Values.Count == set.Count) { return(true); } return(false); }
public bool CompleteSet2(IList <TKey> set) { set.Add(this.SourceKey); IPossible allValues = Space.AllValuesAt(set); if (allValues.Values.Count == set.Count) { return(true); } return(false); }
// Test public bool IntersectPossible(IPossible possible) { int oldCount = innerValue.Count; innerValue.IntersectWith(possible.Values); if (innerValue.Count != oldCount) { HasChanged = true; return(true); } return(false); }
public void RunAlgorithmTest() { // Initialise Space ISpace <int> space = new Space <int>(new Possible() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); for (int i = 1; i < 82; i++) { space.Add(i, new Possible() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); } // Initialise one group (top row) Keys <int> group = new Keys <int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; IPuzzle <int> puzzle = new PuzzleBase <int>(space); IPuzzleEngine <int> engine = new PuzzleEngine <int>(puzzle); // Action space[1].SetValue(1); Keys <int> keysInner = new Keys <int>() { 1 }; int jobsAdded = ConstraintMutuallyExclusive <int> .CreateCompleteSetActions(keysInner, group, engine); // Test Keys <int> expectedK = new Keys <int>() { 2, 3, 4, 5, 6, 7, 8, 9 }; Possible expectedV = new Possible() { 1 }; IJobFilter <int> job = engine.Peek() as IJobFilter <int>; Keys <int> actual = job.Keys; IPossible filter = job.Filter; // Check the algorithm returned 8 changes Assert.AreEqual(8, actual.Count(), "Algorithm Eliminate did not return 8 changes"); Assert.IsTrue(expectedK.SetEquals(actual)); Assert.AreEqual(1, filter.Count, "Filter value incorrect"); Assert.IsTrue(expectedV.SetEquals(filter), "Filter values incorrect"); }
/// <summary> /// This method is looking for a subset that contains values that /// the outer set does not contain. /// E.g. 1-9,2-9,2-9,2-9,2-9,2-9,2-9,2-9,2-9 (Only Key1 is a reduced set9) /// or 1-9,1-9,1-9,2-9,2-9,2-9,2-9,2-9,2-9 (Only Keys1-3 contain 1) /// </summary> /// <param name="set"></param> /// <returns></returns> public bool ReducedSet(IEnumerable <TKey> set) { Keys <TKey> inner = new Keys <TKey>(set); IPossible allValues = inner.ReducedSetValues(OuterSet, Space); if (allValues.Count > 0) { IRegion <TKey> reduced = new Region <TKey>(set, allValues); this.Regions.Add(reduced); return(true); } return(false); }
private void textBlock1_LostFocus(object sender, RoutedEventArgs e) { IPossible possibleOriginal = solver.Puzzle.Space[key]; ISpace <int> space = new Space <int>(new Possible() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); IPossible p = new Possible(); foreach (char c in textBlock1.Text) { if (c.CompareTo('1') == 0) { p.Add(1); } else if (c.CompareTo('2') == 0) { p.Add(2); } else if (c.CompareTo('3') == 0) { p.Add(3); } else if (c.CompareTo('4') == 0) { p.Add(4); } else if (c.CompareTo('5') == 0) { p.Add(5); } else if (c.CompareTo('6') == 0) { p.Add(6); } else if (c.CompareTo('7') == 0) { p.Add(7); } else if (c.CompareTo('8') == 0) { p.Add(8); } else if (c.CompareTo('9') == 0) { p.Add(9); } } space.Add(key, p); solver.Engine.SetInitialValues(space); }
public Keys <TKey> Eliminate(Keys <TKey> keys, IPossible valuesToRemove) { Keys <TKey> keysChanged = new Keys <TKey>(); foreach (TKey k in keys) { // only add to changed if the keys that have changed if (this[k].FilterOut(valuesToRemove)) { keysChanged.Add(k); } } return(keysChanged); }
/// <summary> /// This method creates eliminate actions for each complete set /// it finds in our constraint. /// </summary> /// <param name="keysChangedIn">This is the last change</param> /// <param name="engine">The engine and the puzzle data</param> protected int CreateActions1(IEnumerable <TKey> keysChangedIn, IPuzzleEngine <TKey> engine) { int added = 0; foreach (TKey kSource in keysChangedIn) { if (added == 0) { // Get the values at this point IPossible kPossible = engine.Puzzle.Space[kSource]; // single value - no need to find combinations if (kPossible.Count == 1) { Keys <TKey> useKeys = new Keys <TKey>() { kSource }; added += CreateCompleteSetActions(useKeys, Keys, engine); } // multi value - get all combinations in our set else if ((kPossible.Count > 1)) { Keys <TKey> combinationSet = new Keys <TKey>(Keys); combinationSet.Remove(kSource); int iUpper = combinationSet.Count; int iLower = kPossible.Count - 1; for (int search = iLower; search < iUpper && added == 0; search++) { CompleteSetTester <TKey> tester = new CompleteSetTester <TKey>(kSource, engine.Puzzle.Space); CombinationValues <TKey> combi = new CombinationValues <TKey>(search, combinationSet); combi.Test = tester.CompleteSet2; combi.FindOne = true; if (combi.CalcCombinations() > 0) { foreach (IList <TKey> combination in combi.Combinations) { Keys <TKey> completeSet = new Keys <TKey>(combination); added += CreateCompleteSetActions(completeSet, Keys, engine); } } } } } } return(added); }
// Returns the actual values filtered // e.g. 1-9 filter 1-3 (result = 4-9) return 1-3 // e.g. 2-9 filter 1-3 (result = 4-9) return 2-3 public bool FilterOut(IPossible possible) { int oldCount = innerValue.Count; innerValue.ExceptWith(possible.Values); if (innerValue.Count != oldCount) { HasChanged = true; if (innerValue.Count == 0) { if (NoValuesLeft != null) { NoValuesLeft(this); } } return(true); } return(false); }
/// <summary> /// This elimination works out if there is an intersection between mutually exclusive sets /// that contains any values that are in the intersection and not in the outersection of one set. /// If this is so, (and both sets must contain that value) then the values can be eliminated from /// the other set also. Only need - in addition to above, used when intersecting points > 1. /// </summary> static public int CreateCompleteIntersectActions(Keys <TKey> group1, Keys <TKey> group2, IPuzzleEngine <TKey> engine) { int added = 0; Keys <TKey> keysIntersection = new Keys <TKey>(group1); keysIntersection.IntersectWith(group2); if (keysIntersection.Count > 1) { Keys <TKey> keysOuter1 = new Keys <TKey>(group1); keysOuter1.ExceptWith(keysIntersection); Keys <TKey> keysOuter2 = new Keys <TKey>(group2); keysOuter2.ExceptWith(keysIntersection); IPossible valuesIntersect = engine.Puzzle.Space.AllValuesAt(keysIntersection); IPossible valuesOuter1 = engine.Puzzle.Space.AllValuesAt(keysOuter1); IPossible valuesOuter2 = engine.Puzzle.Space.AllValuesAt(keysOuter2); Possible filter2 = new Possible(valuesIntersect); filter2.FilterOut(valuesOuter1); if (filter2.Count > 0) { engine.Add(new JobFilter <TKey>("Intersection", keysOuter2, filter2)); added++; } // find each value that is present in the intersection (and not in outer1) // and eliminate it from the set2 // find each value that is present in the intersection (and not in outer) // and eliminate it from the set1 Possible filter1 = new Possible(valuesIntersect); filter1.FilterOut(valuesOuter2); if (filter1.Count > 0) { engine.Add(new JobFilter <TKey>("Intersection", keysOuter1, filter1)); added++; } } return(added); }
static public int CreateCompleteSetActions(Keys <TKey> group1, Keys <TKey> group2, IPuzzleEngine <TKey> engine) { int added = 0; // This works out possibleInner (go to space and union all values); IPossible possibleInner = engine.Puzzle.Space.AllValuesAt(group1); // If the values in the set are equal to the // available spaces in the solution then we consider this set // complete and can eliminate it from the rest of the group // (e.g. 1 value in 1 cell, or 8 values in 8 cells) if (possibleInner.Values.Count == group1.Count()) { // This finds the working group of locations (excludes the changed set) Keys <TKey> workingGroup = new Keys <TKey>(group2); workingGroup.ExceptWith(group1); IJob <TKey> job = new JobFilter <TKey>("CompleteSet", workingGroup, possibleInner); engine.Add(job); added++; // Get all the possible values from key and filter them out of the group } return(added); }
public JobFilter(string name, Keys <TKey> keys, IPossible filter) : base(name, JobType.Filter, 1) { this.Keys = keys; this.Filter = filter; }
void Value_NoValuesLeft(IPossible possible) { throw new Exception("No Values Left"); }
public Region(IEnumerable <TKey> keys, IPossible value) : base(value) { Keys = new Keys <TKey>(keys); }
public bool IsSupersetOf(IPossible possible) { return(innerValue.IsSupersetOf(possible)); }
public void RunAlgorithmEliminateTest1() { // Initialise Possible IPossible possibleAll = new Possible() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Initialise Space ISpace <int> space = new Space <int>(new Possible() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }); for (int i = 1; i < 82; i++) { space.Add(i, new Possible(possibleAll)); } // Initialise one group (top row) Keys <int> group = new Keys <int>(); for (int i = 1; i < 10; i++) { group.Add(i); } IPuzzle <int> puzzle = new PuzzleBase <int>(space); IPuzzleEngine <int> engine = new PuzzleEngine <int>(puzzle); // Action Possible values2To9 = new Possible(possibleAll); values2To9.Remove(1); Keys <int> keysInner = new Keys <int>(); for (int j = 2; j < 10; j++) { keysInner.Add(j); space[j] = new Possible(values2To9); } int jobsAdded = ConstraintMutuallyExclusive <int> .CreateCompleteSetActions(keysInner, group, engine); Assert.AreEqual(1, engine.Count); // Test Keys <int> expectedK = new Keys <int>() { 1 }; IPossible expectedV = new Possible() { 2, 3, 4, 5, 6, 7, 8, 9 }; IJobFilter <int> job = engine.Peek() as IJobFilter <int>; Keys <int> actual = job.Keys; IPossible filter = job.Filter; Assert.AreEqual(1, actual.Count(), "Algorithm Eliminate did not return 8 changes"); Assert.IsTrue(expectedK.SetEquals(actual)); Assert.AreEqual(8, filter.Count, "Filter value incorrect"); Assert.IsTrue(expectedV.SetEquals(filter), "Filter values incorrect"); }
public bool Equals(IPossible other) { return(this.SetEquals(other)); }
public RegionBase(IPossible value) { Value = new Possible(value); }
public Space(IPossible defaultValue) { DefaultValue = defaultValue; }