protected override Expression VisitMethodCall(MethodCallExpression m) { if (m.Object != null && m.Object.NodeType == ExpressionType.Parameter) { var p = (ParameterExpression)m.Object; if (_paramWhere.Contains(p)) { if (m.Method.Name != "get_Item" || m.Arguments[0].NodeType != ExpressionType.Constant) { _nonConstant = true; return(m); } var paramVar = _paramVar[p.Name]; var index = (int)((ConstantExpression)m.Arguments[0]).Value; if (index < 0 || index >= paramVar.ListCount) { _indexOutOfLength = true; return(m); } var kvp = IntExt.CreateLong(paramVar.Index, index); if (!_paramId.Contains(kvp)) { _paramId.Add(kvp); } return(makeListParam(_param, _methods, kvp, m.Type)); } } return(base.VisitMethodCall(m)); }
bool tryAppendAllDifferent(ReadOnlyCollection <Expression> exps) { var list = new HashSet <long>(); foreach (var exp in exps) { switch (exp.NodeType) { case ExpressionType.Call: var m = (MethodCallExpression)exp; if (m.Method.Name == "get_Item" && m.Object.NodeType == ExpressionType.Parameter && m.Arguments[0].NodeType == ExpressionType.Constant) { list.Add(IntExt.CreateLong(_paramVar[((ParameterExpression)m.Object).Name].Index, (int)((ConstantExpression)m.Arguments[0]).Value)); } else { return(false); } break; case ExpressionType.Parameter: list.Add(IntExt.CreateLong(0, _paramVar[((ParameterExpression)exp).Name].Index)); break; default: return(false); } } _exp = Expression.Call(_exp, "AppendAllDifferent", null, Expression.Constant(list)); return(true); }
protected override Expression VisitParameter(ParameterExpression p) { if (_paramWhere.Contains(p) && !_paramVar[p.Name].IsList) { var kvp = IntExt.CreateLong(0, _paramVar[p.Name].Index); if (!_paramId.Contains(kvp)) { _paramId.Add(kvp); } return(makeVarParam(_param, _methods, kvp.GetLowInt(), p.Type)); } return(p); }
//public methods public virtual IEnumerable <List <ReadOnlyCollection <T> > > LookAhead() { if (_noSolution) { return(Enumerable.Empty <List <ReadOnlyCollection <T> > >()); } var data = _variables.Select(a => a.Select(b => b.ToList()).ToList() ).ToList(); return(lookAhead( data, _variables.SelectMany((a, i) => a.Select((b, j) => IntExt.CreateLong(i, j)) ).ToArray(), new HashSet <long>() ).Select(s => s.GroupBy(a => a.Item1.GetHighInt()).OrderBy(a => a.Key).Select(a => a.OrderBy(b => b.Item1.GetLowInt()).Select(b => b.Item2).ToList().AsReadOnly() ).ToList() )); }
//local methods IEnumerable <IEnumerable <Tuple <long, T> > > lookAhead(List <List <List <T> > > data, long[] unsolved, HashSet <long> solved) { //all solved, return empty if (unsolved.Length == 0) { yield return(Tuple.Create(IntExt.CreateLong(0, _variables[0].Count), default(T)).ToEnumerable()); yield break; } //do on first time if (solved.Count == 0) { var newData = data.Select(d => d.ToList()).ToList(); foreach (var node in _nodeConstraints) { filterData(newData, node.Key, node.Value.PredicateAll(), null); } unsolved = unsolved.OrderBy(x => getData(newData, x).Count).ToArray(); data = newData; } //pull out first unsolve var index = unsolved[0]; var candidate = getData(data, index); var newUnsolve = new long[unsolved.Length - 1]; Array.Copy(unsolved, 1, newUnsolve, 0, newUnsolve.Length); var newSolved = new HashSet <long>(solved) { index }; //get predicate List <Tuple <HashSet <long>, Func <List <List <List <T> > >, bool> > > arc; _arcConstraints.TryGetValue(index, out arc); List <Tuple <HashSet <long>, Func <List <List <List <T> > >, bool> > > pair; _pairConstraints.TryGetValue(index, out pair); List <HashSet <long> > diff; _allDifferents.TryGetValue(index, out diff); foreach (var t in candidate) { //create new data set var newData = data.Select(d => d.ToList()).ToList(); setData(newData, index, new List <T> { t }); //find minimum scope var minValue = int.MaxValue; var minUnSolve = 0; //set occurrents List <Dictionary <T, int> > valueCheck = null; if (_occurrents.Count > 0) { valueCheck = new List <Dictionary <T, int> >(_occurrents.Count); for (var i = 0; i < _occurrents.Count; i++) { valueCheck.Add(new Dictionary <T, int>(tComparer)); } } //for each unsolve for (var j = 0; j < newUnsolve.Length; j++) { var prediList = Enumerable.Empty <Func <List <List <List <T> > >, bool> >(); var k = newUnsolve[j]; //apply predicate if (diff != null) { prediList = diff.Where(a => a.Contains(k)) .Take(1) .Select(a => new Func <List <List <List <T> > >, bool>(x => !tComparer.Equals(x[k.GetHighInt()][k.GetLowInt()][0], t))); } if (pair != null) { prediList = prediList.Concat(pair.Where(a => a.Item1.Contains(k)) .Take(1) .Select(a => a.Item2)); } if (arc != null) { prediList = prediList.Concat(arc.Where(a => a.Item1.All(b => b == k || newSolved.Contains(b))) .Select(a => a.Item2)); } var predicate = prediList.PredicateAll(); //if predicate is not empty if (!Equals(predicate, emptyPredicate)) { filterData(newData, k, predicate, val => setValueCheck(valueCheck, val, j, newUnsolve[j])); } else if (_occurrents.Count > 0) { var oldList = getData(newData, k); foreach (var item in oldList) { setValueCheck(valueCheck, item, j, newUnsolve[j]); } } //set minimum scope if (j == 0 || getData(newData, k).Count < minValue) { minUnSolve = j; minValue = getData(newData, k).Count; } } //apply occurents if (_occurrents.Count > 0) { foreach (var c in valueCheck) { foreach (var kvp in c) { if (kvp.Value == -1) { continue; } var k = newUnsolve[kvp.Value]; setData(newData, k, new List <T> { kvp.Key }); if (minValue > 1) { minValue = 1; minUnSolve = kvp.Value; } } } } //swop item based on minimum scope if (minUnSolve > 0) { var tmp = newUnsolve[0]; newUnsolve[0] = newUnsolve[minUnSolve]; newUnsolve[minUnSolve] = tmp; } //iterate next item foreach (var r in lookAhead(newData, newUnsolve, newSolved)) { yield return(Tuple.Create(index, t).ToEnumerable().Concat(r)); } } }