C# 如何从表达式中获得所有最小真条件

C# 如何从表达式中获得所有最小真条件,c#,logic,expression,puzzle,discrete-mathematics,C#,Logic,Expression,Puzzle,Discrete Mathematics,我需要帮助从表达式中提取所有最小真条件(如sql中的where子句) 假设我有这样一个表达式: 例1: 例2: 例3: 注意:“|”表示”或“和”&“表示”和“”,因此要将大条件分解为所有可能的最小真条件 请建议…据我所知,您要求的是一组表达式,每个表达式都暗示输入。也就是说,如果这些表达式中的任何一个为真,则输入为真 这样说,我们可以看到我们正在做的是将输入改写成一个大的析取,然后列出术语。换句话说,您希望将您的输入重写为一个。维基百科告诉我们,“所有逻辑公式都可以转换为析取范式。然而,在某些

我需要帮助从表达式中提取所有最小真条件(如sql中的where子句)

假设我有这样一个表达式:

例1:

例2:

例3:

注意:
“|”表示”或“
”&“表示”和“
”,因此要将大条件分解为所有可能的最小真条件


请建议…

据我所知,您要求的是一组表达式,每个表达式都暗示输入。也就是说,如果这些表达式中的任何一个为真,则输入为真

这样说,我们可以看到我们正在做的是将输入改写成一个大的析取,然后列出术语。换句话说,您希望将您的输入重写为一个。维基百科告诉我们,“所有逻辑公式都可以转换为析取范式。然而,在某些情况下,转换为DNF可能导致公式的指数级爆炸。”

因此:如果在顶部有一个“或”,则返回一组所有子项(您可以递归地将此算法应用于每个子项)。如果顶部有一个“and”,则对每个子项递归运行该命令,然后返回“and”的所有组合,并为每个子项指定一个选项

例如,如果你有(A | B | C)给你A,B,C作为答案。 如果你有(A&(B | C)),那么左边的孩子只得到A,右边的孩子得到B,C。把它们放在一起,你会得到两个答案:A&B和A&C

如果你有一个“不”,你可以用德摩根定律来推它,所以你可以继续使用上面的两条规则


另外,我的回答是“如何获得所有答案”,这是你的文本所要求的,而不是“如何获得最小的答案”,这是标题所要求的。这是一个简单的步骤来考虑所有的答案,选择最小的一个。

< P>这样看来,帮助你的方法是把你的表达简化成一个产品的总和。通过将其放在乘积和形式中,您将有一系列不同的选项,如果它包含的所有值都为真,则每个选项都将是唯一正确的选项

处理这个问题的一种方法是使用复合模式。我们将从我们的
IExpression
界面开始:

public interface IExpression<T>
{
    int NumberOfPossibilities();

    IEnumerable<IEnumerable<ValueExpression<T>>> Possibilities();
    IEnumerable<ValueExpression<T>> GetNthPossibility(int n);
}
And表达式有点复杂。AND表达式的可能性数是被AND的可能性数的乘积

要获得第n种可能性,您可以这样想:

从0开始;对于0,结果要求将每个子表达式的第一个可能性相加。对于第一种可能性,我们在第一个子表达式中添加一个。每次n增加,我们增加从第一个子表达式得到的排列。当我们传递它的count时,它返回到零,下一个子表达式上升1。这基本上类似于计数,但其中每个数字代表一个子表达式,该数字的基数是该子表达式的可能性计数

public class AndExpression<T> : IExpression<T>
{
    private IList<IExpression<T>> expressions;
    public AndExpression(IList<IExpression<T>> expressions)
    {
        this.expressions = expressions;
    }

    public int NumberOfPossibilities()
    {
        return expressions.Aggregate(1,
            (acc, expression) => acc * expression.NumberOfPossibilities());
    }

    IEnumerable<IEnumerable<ValueExpression<T>>> IExpression<T>.Possibilities()
    {
        return Enumerable.Range(0, NumberOfPossibilities())
            .Select(n => GetNthPossibility(n));
    }

    public IEnumerable<ValueExpression<T>> GetNthPossibility(int n)
    {
        for (int i = 0; i < expressions.Count; i++)
        {
            int count = expressions[i].NumberOfPossibilities();
            foreach (var value in expressions[i].GetNthPossibility(n % count))
                yield return value;

            n /= count;
        }
    }
}
public类和表达式:IExpression
{
私人语言表达;
公共和表达式(IList表达式)
{
这个表达式=表达式;
}
公共整数
{
返回表达式。聚合(1,
(acc,expression)=>acc*expression.numberOfPoabilities());
}
IEnumerable IExpression.posabilities()
{
返回可枚举的.Range(0,numberOfPoabilities())
.选择(n=>getn可能性(n));
}
公共IEnumerable(int n)
{
for(int i=0;i
对于OR表达式,它与AND版本类似,但仍然不同

可能性的数量是内部表达式计数的总和,而不是乘积

为了得到第n个可能性,我们只返回其中一个子表达式的一个可能性中的项,而不是从每个as和do中返回一个

public class OrExpression<T> : IExpression<T>
{
    private IList<IExpression<T>> expressions;
    public OrExpression(IList<IExpression<T>> expressions)
    {
        this.expressions = expressions;
    }

    public int NumberOfPossibilities()
    {
        return expressions.Sum(expression => expression.NumberOfPossibilities());
    }

    public IEnumerable<IEnumerable<ValueExpression<T>>> Possibilities()
    {
        return Enumerable.Range(0, NumberOfPossibilities())
            .Select(n => GetNthPossibility(n));
    }

    public IEnumerable<ValueExpression<T>> GetNthPossibility(int n)
    {
        for (int i = 0; i < expressions.Count; i++)
        {
            int count = expressions[i].NumberOfPossibilities();
            if (n < count)
                return expressions[i].GetNthPossibility(n);
            else
                n -= count;
        }

        throw new ArgumentOutOfRangeException();
    }
}
public类或表达式:IExpression
{
私人语言表达;
公共或表达式(IList表达式)
{
这个表达式=表达式;
}
公共整数
{
返回expressions.Sum(expression=>expression.numberOfPoabilities());
}
公共数字可能性
{
返回可枚举的.Range(0,numberOfPoabilities())
.选择(n=>getn可能性(n));
}
公共IEnumerable(int n)
{
for(int i=0;i
下面是一个将表达式打印为字符串的简单函数:

public static void PrintPossibilities<T>(IExpression<T> expression)
{
    Console.WriteLine(string.Join(" + ", expression.Possibilities()
            .Select(possibility =>
                string.Concat(possibility.Select(value => value.Value)))));
}
publicstaticvoid打印可能性(IExpression表达式)
{
Console.WriteLine(string.Join(“+”,expression.Possibilities()
.选择(可能性=>
string.Concat(可能性.Select(value=>value.valueщщ));
}
请注意,这不会处理表达式的解析,只会在解析后对其进行处理

下面是对第一个示例的测试:

var AB = new AndExpression<string>(new[]{
    new ValueExpression<string>("A"),
    new ValueExpression<string>("B")});

var CD = new OrExpression<string>(new[]{
    new ValueExpression<string>("C"),
    new ValueExpression<string>("D")});

var exp = new AndExpression<string>(new IExpression<string>[] { AB, CD });

PrintPossibilities(exp);
var AB=new和expression(new[]{
新价值表达式(“A”),
新值表达式(“B”)};
var CD=新的或表达式(新[]{
新值表达式(“C”),
新值表达式(“D”)};
var exp=新的AndExpression(新的IEExpression[]{AB,CD});
印刷可能性(exp);
其中打印:

ABC+ABD

AB更改为OR表达式(您的第二个示例)打印:

A
public class AndExpression<T> : IExpression<T>
{
    private IList<IExpression<T>> expressions;
    public AndExpression(IList<IExpression<T>> expressions)
    {
        this.expressions = expressions;
    }

    public int NumberOfPossibilities()
    {
        return expressions.Aggregate(1,
            (acc, expression) => acc * expression.NumberOfPossibilities());
    }

    IEnumerable<IEnumerable<ValueExpression<T>>> IExpression<T>.Possibilities()
    {
        return Enumerable.Range(0, NumberOfPossibilities())
            .Select(n => GetNthPossibility(n));
    }

    public IEnumerable<ValueExpression<T>> GetNthPossibility(int n)
    {
        for (int i = 0; i < expressions.Count; i++)
        {
            int count = expressions[i].NumberOfPossibilities();
            foreach (var value in expressions[i].GetNthPossibility(n % count))
                yield return value;

            n /= count;
        }
    }
}
public class OrExpression<T> : IExpression<T>
{
    private IList<IExpression<T>> expressions;
    public OrExpression(IList<IExpression<T>> expressions)
    {
        this.expressions = expressions;
    }

    public int NumberOfPossibilities()
    {
        return expressions.Sum(expression => expression.NumberOfPossibilities());
    }

    public IEnumerable<IEnumerable<ValueExpression<T>>> Possibilities()
    {
        return Enumerable.Range(0, NumberOfPossibilities())
            .Select(n => GetNthPossibility(n));
    }

    public IEnumerable<ValueExpression<T>> GetNthPossibility(int n)
    {
        for (int i = 0; i < expressions.Count; i++)
        {
            int count = expressions[i].NumberOfPossibilities();
            if (n < count)
                return expressions[i].GetNthPossibility(n);
            else
                n -= count;
        }

        throw new ArgumentOutOfRangeException();
    }
}
public static void PrintPossibilities<T>(IExpression<T> expression)
{
    Console.WriteLine(string.Join(" + ", expression.Possibilities()
            .Select(possibility =>
                string.Concat(possibility.Select(value => value.Value)))));
}
var AB = new AndExpression<string>(new[]{
    new ValueExpression<string>("A"),
    new ValueExpression<string>("B")});

var CD = new OrExpression<string>(new[]{
    new ValueExpression<string>("C"),
    new ValueExpression<string>("D")});

var exp = new AndExpression<string>(new IExpression<string>[] { AB, CD });

PrintPossibilities(exp);
var third = new OrExpression<string>(new[]{
    new ValueExpression<string>("A"),
    new ValueExpression<string>("B"),
    new ValueExpression<string>("C")});