// this == var が成立するような expression を返す // (this == 1 && var == 1) || (this == 2 && var == 2) || ... public IExpression EqualCondition(VariableInteger var) { Debug.Assert(var.lowerbound == lowerbound); Debug.Assert(var.variables.Count == variables.Count); var ret = new ExpressionOr(); for (int i = 0; i < variables.Count; i++) { var item = new ExpressionAnd(); for (int j = 0; j < variables.Count; j++) { if (i == j) { item.children.Add(new ExpressionInteger(variables[j], true)); item.children.Add(new ExpressionInteger(var.variables[j], true)); } else { item.children.Add(new ExpressionInteger(variables[j], false)); item.children.Add(new ExpressionInteger(var.variables[j], false)); } } ret.children.Add(item); } return(ret); }
public override IExpression Negate() { var expr = new ExpressionOr(); foreach (var child in children) { expr.children.Add(child.Negate()); } return(expr); }
// expr を簡約した結果を返す // 新規変数を追加する時に生じた制約は、 newExpr に入れる public IExpression TseitinTranslate(IExpression expr, ExpressionAnd newExpr) { var ret = expr.Empty(); foreach (var child in expr.children) { // 簡約の必要がない if (child.GetType() == typeof(ExpressionInteger)) { ret.children.Add(child); } else { // 再帰的に簡約 var childExpr = TseitinTranslate(child, newExpr); // childExpr を newId の変数で置き換え var newId = generator.GenerateId(); ret.children.Add(new ExpressionInteger(newId, true)); // childExpr == newId の制約 var newChildExpr = new ExpressionInteger(newId, false); if (childExpr.GetType() == typeof(ExpressionAnd)) { foreach (var subexpr in childExpr.children) { var newSubExpr = new ExpressionOr(); newSubExpr.children.Add(newChildExpr.Clone()); newSubExpr.children.Add(subexpr); newExpr.children.Add(newSubExpr); } } else // childExpr.GetType() == typeof (ExpressionOr) { childExpr.children.Add(newChildExpr); newExpr.children.Add(childExpr); } } } return(ret); }
public override IExpression Flatten() { var ret = new ExpressionOr(); foreach (var child in children) { var flatten = child.Flatten(); if (GetType() == child.GetType()) { foreach (var child2 in flatten.children) { ret.children.Add(child2); } } else { ret.children.Add(flatten); } } return(ret); }
// 値域の中のどれか一つは取れるという制約を出力 public IExpression AssignAny() { var ret = new ExpressionOr(); for (int i = 0; i < variables.Count; i++) { var item = new ExpressionAnd(); // 下から i 番目の値が採用されるような割当て for (int j = 0; j < variables.Count; j++) { if (i == j) { item.children.Add(new ExpressionInteger(variables[j], true)); } else { item.children.Add(new ExpressionInteger(variables[j], false)); } } ret.children.Add(item); } return(ret); }