private IEnumerable <IFilter> GenerateFilters(IEnumerable <string> queries) { foreach (var s in queries) { FilterCluster cluster = null; try { cluster = QueryCompiler.ToFilter(s); } catch (Exception e) { ExceptionStorage.Register(e, ExceptionCategory.ConfigurationError, "フィルタ クエリを読み取れません: " + s); } if (cluster != null) { if (cluster.Filters.Count() == 1) { var filter = cluster.Filters.First(); if (cluster.Negate) { filter.Negate = !filter.Negate; } yield return(filter); } else { yield return(cluster); } } } }
public FilterClusterViewModel(FilterEditorViewModel root, FilterClusterViewModel parent, FilterCluster cluster) : base(root, parent) { if (cluster == null) { throw new ArgumentNullException("cluster"); } this.cluster = cluster; }
private static IEnumerable <IFilter> OptimizeCo(IFilter filter, FilterCluster parent) { System.Diagnostics.Debug.WriteLine("Current focus: " + filter.ToQuery() + " / on " + parent.ToQuery()); if (filter is FilterCluster) { return(OptimizeCoCluster((FilterCluster)filter, parent)); } else { return new[] { filter } }; }
private static IEnumerable <IFilter> OptimizeCoCluster(FilterCluster cluster, FilterCluster parent) { if (parent == null) { throw new ArgumentNullException("parent"); } var items = (cluster.Filters ?? new IFilter[0]) .SelectMany(f => OptimizeCo(f, cluster)) .ToArray(); if (items.Length == 0) { // 要素無しのフィルタ return(new[] { new FilterCluster() { ConcatenateAnd = false, // 常に AND 結合 Negate = cluster.ConcatenateAnd != cluster.Negate } }); // AND => U false false // NAND => Φ false true // OR => Φ true false // NOR => U true true // ANDかNANDに集約, つまり Negate を U なら false, Φ なら trueにセットする } else if (items.Length == 1) { // 要素が1つしかない場合、このクラスタをスルーする // このクラスタがNegateであれば、直下アイテムのNegate値を変更する if (cluster.Negate) { System.Diagnostics.Debug.WriteLine("Inverse"); items[0].Negate = !items[0].Negate; // 多重処理されないようにNegateをリセットする cluster.Negate = false; } // 所属を変更する return(OptimizeCo(items[0], parent)); } else if (cluster.Negate == false && cluster.ConcatenateAnd == parent.ConcatenateAnd) { // このクラスタがNegateでなく、直上のクラスタと同じ結合である場合 // 直上のクラスタに合成する return(items.SelectMany(f => OptimizeCo(f, parent))); } else { // クラスタのアイテムを更新 cluster.Filters = items; return(new[] { cluster.Contraction() }); } }
/// <summary> /// フィルタの最適化 /// </summary> public static FilterCluster Optimize(FilterCluster cluster) { // ルートフィルタクラスタの最適化 var items = cluster.Filters.SelectMany(f => OptimizeCo(f, cluster)); if (items.Count() == 1 && items.First() is FilterCluster) { var rc = items.First() as FilterCluster; if (cluster.Negate) rc.Negate = !rc.Negate; return rc.Contraction(); } else { cluster.Filters = items.ToArray(); return cluster.Contraction(); } }
/// <summary> /// フィルタの最適化 /// </summary> public static FilterCluster Optimize(FilterCluster cluster) { // ルートフィルタクラスタの最適化 var items = cluster.Filters.SelectMany(f => OptimizeCo(f, cluster)); if (items.Count() == 1 && items.First() is FilterCluster) { var rc = items.First() as FilterCluster; if (cluster.Negate) { rc.Negate = !rc.Negate; } return(rc.Contraction()); } else { cluster.Filters = items.ToArray(); return(cluster.Contraction()); } }
/// <summary> /// フィルタを縮約化します。 /// </summary> private static FilterCluster Contraction(this FilterCluster cluster) { // クラスタ内の全空フィルタクラスタを取得する var emptyClusters = cluster.Filters.OfType <FilterCluster>().Where(f => f.Filters.Count() == 0).ToArray(); // [全ての空フィルタクラスタはORかNORである] if (emptyClusters.FirstOrDefault(f => f.ConcatenateAnd) != null) { throw new ArgumentException("All empty filters must be OR or NOR."); } // フィルタと非空フィルタクラスタを待避 var filters = cluster.Filters.Except(emptyClusters).ToArray(); // 1 : U [全ツイートの抽出: !() [NOR(Φ)]] // 0 : F [一つだけ含まれるフィルタ] // -1 : Φ [抽出されるツイート無し: () [OR(Φ)] int resultValue = 0; if (cluster.ConcatenateAnd) { // AND 結合モード // OR 空フィルタが含まれていたら resultvalue = -1 (Φ) if (emptyClusters.FirstOrDefault(f => !f.Negate) != null) { resultValue = -1; } // そうでない場合は、フィルタが存在すればresultValue = 0, でなければ 1 else if (filters.Length > 0) { resultValue = 0; } else { resultValue = 1; } } else { // OR 結合モード // NOR 空フィルタが含まれていたら resultvalue = 1 (U) if (emptyClusters.FirstOrDefault(f => f.Negate) != null) { resultValue = 1; } // そうでない場合は、フィルタが存在すればresultValue = 0, でなければ -1 else if (filters.Length > 0) { resultValue = 0; } else { resultValue = -1; } } if (resultValue == 1) // U { return new FilterCluster() { ConcatenateAnd = true, Negate = cluster.Negate } } ; else if (resultValue == 0) // F { return new FilterCluster() { ConcatenateAnd = cluster.ConcatenateAnd, Filters = filters, Negate = cluster.Negate } } ; else if (resultValue == -1) // Φ { return new FilterCluster() { ConcatenateAnd = false, Negate = !cluster.Negate } } ; else { throw new InvalidOperationException("resultValue is invalid:" + resultValue.ToString()); } }
private static IEnumerable<IFilter> OptimizeCoCluster(FilterCluster cluster, FilterCluster parent) { if (parent == null) throw new ArgumentNullException("parent"); var items = (cluster.Filters ?? new IFilter[0]) .SelectMany(f => OptimizeCo(f, cluster)) .ToArray(); if (items.Length == 0) { // 要素無しのフィルタ return new[]{new FilterCluster(){ ConcatenateAnd = false, // 常に AND 結合 Negate = cluster.ConcatenateAnd != cluster.Negate} }; // AND => U false false // NAND => Φ false true // OR => Φ true false // NOR => U true true // ANDかNANDに集約, つまり Negate を U なら false, Φ なら trueにセットする } else if (items.Length == 1) { // 要素が1つしかない場合、このクラスタをスルーする // このクラスタがNegateであれば、直下アイテムのNegate値を変更する if (cluster.Negate) { System.Diagnostics.Debug.WriteLine("Inverse"); items[0].Negate = !items[0].Negate; // 多重処理されないようにNegateをリセットする cluster.Negate = false; } // 所属を変更する return OptimizeCo(items[0], parent); } else if (cluster.Negate == false && cluster.ConcatenateAnd == parent.ConcatenateAnd) { // このクラスタがNegateでなく、直上のクラスタと同じ結合である場合 // 直上のクラスタに合成する return items.SelectMany(f => OptimizeCo(f, parent)); } else { // クラスタのアイテムを更新 cluster.Filters = items; return new[] { cluster.Contraction() }; } }
private static IEnumerable<IFilter> OptimizeCo(IFilter filter, FilterCluster parent) { System.Diagnostics.Debug.WriteLine("Current focus: " + filter.ToQuery() + " / on " + parent.ToQuery()); if (filter is FilterCluster) return OptimizeCoCluster((FilterCluster)filter, parent); else return new[] { filter }; }
/// <summary> /// フィルタ クラスタを走査し、構築します。 /// </summary> /// <returns>フィルタ クラスタ</returns> private static FilterCluster AnalyzeCluster() { var cluster = new FilterCluster(); bool endPoint = false; while (!endPoint) { if (cursor + 1 >= query.Length) throw new QueryException("クエリが不適切です。オブジェクトが終了していません。"); Next(); switch (Tokenize()) { // 無視する文字 case TokenType.Space: break; case TokenType.Tab: break; case TokenType.CarriageReturn: break; case TokenType.LineFeed: break; case TokenType.OpenBracket: var childCluster = AnalyzeCluster(); childCluster.Parent = cluster; cluster.Add(childCluster); break; case TokenType.CloseBracket: endPoint = true; break; case TokenType.Sharp: Next(); switch (Tokenize()) { case TokenType.OpenBracket: var childCalculator = AnalyzeCalculator(); childCalculator.Parent = cluster; cluster.Add(childCalculator); break; } break; case TokenType.ConcatenatorAnd: // and cluster.Filters.Last().Operator = LogicalOperator.And; break; case TokenType.ConcatenatorOr: // or cluster.Filters.Last().Operator = LogicalOperator.Or; break; case TokenType.ConcatenatorXor: // xor cluster.Filters.Last().Operator = LogicalOperator.Xor; break; default: cluster.Add(AnalyzeFilter()); break; } } return cluster; }
private static IEnumerable<IFilter> OptimizeCo(IFilter filter, FilterCluster parent) { if (filter is FilterCluster) return OptimizeCoCluster((FilterCluster)filter, parent); else return new[] { filter }; }
private static FilterCluster AnalysisExpression(ExpressionTuple expressionTuple) { var retcluster = new FilterCluster() { ConcatenateOR = expressionTuple.ConcatOr.GetValueOrDefault(false) }; if (expressionTuple.Expression == null) { retcluster.Filters = new[] { AnalysisExpressionBody(expressionTuple.ExpressionBody) }; } else { if (!expressionTuple.ConcatOr.HasValue) throw new InvalidOperationException("内部エラー: ExpressionTupleはチェーンを構成しますが、接続情報がありません。"); retcluster.Filters = new[] { AnalysisExpressionBody(expressionTuple.ExpressionBody), AnalysisExpression(expressionTuple.Expression) }; } return retcluster; }