如何实现无限集类?

时间:2012-07-25 22:33:22

标签: c# set set-theory

我正在为离散数学设计一个类库,我想不出实现infinite set的方法。

到目前为止我所拥有的是:我有一个抽象基类Set,它实现了接口ISet。对于有限集,我派生出一个有限集类,它实现了每个集合方法。我可以这样使用它:

FiniteSet<int> set1 = new FiniteSet<int>(1, 2, 3);
FiniteSet<int> set2 = new FiniteSet<int>(3, 4, 5);
Console.WriteLine(set1); //{1, 2, 3}
Console.WriteLine(set2); //{3, 4, 5}

set1.UnionWith(set2);
Console.WriteLine(set1); //{1, 2, 3, 4, 5}

现在我想代表一个无限集。我有从set,InfiniteSet派生另一个抽象类的想法,然后使用该库的开发人员必须从InfiniteSet派生来实现他们自己的类。我会提供常用的集合,例如N,Z,Q和R.

但是我不知道我是如何实现像Subset和GetEnumerator这样的方法 - 我甚至开始认为这是不可能的。如何以实际方式枚举无限集,以便可以将它与另一个无限集相交/联合?如何在代码中检查N是R的子集?至于基数问题..那么,这可能是一个单独的问题。

这一切使我得出的结论是,我实现无限集的想法可能是错误的方法。我非常感谢你的意见:)。

编辑:为了清楚起见,我也想代表无数的无限集。

Edit2:我认为重要的是要记住最终目标是实现ISet,这意味着任何解决方案都必须提供(应该)实现所有ISet's methods的方法,其中最有问题的是枚举方法和IsSubsetOf方法。

5 个答案:

答案 0 :(得分:6)

无法完全实现ISet<T>无数无限集。

这是一个证据(由Bertrand Russell提供):

假设您已经创建了一个类MySet<T>,它可以表示无数的无限集。现在让我们考虑一些MySet<object>个对象。

我们标记了一个特定的MySet<object>,称之为instance,“异常”如果:

instance.Contains(instance)返回true。

同样,如果符合以下条件,我们会将instance标记为“ normal ”:

instance.Contains(instance)返回false。

请注意,这种区别是针对所有instance明确定义的。

现在考虑一个名为MySet<MySet<object>>的{​​{1}}实例。

我们将paradox定义为paradox,其中包含MySet<MySet<object>>的所有普通实例。

MySet<object>应该返回什么?

如果它返回paradox.Contains(paradox),则true 异常,并且在自行调用时应该返回paradox

如果它返回false,那么false 正常,并且在自己调用时应该返回paradox

无法实施true来解决此悖论,因此无法为所有可能的不可数集合全面实施Contains


现在,如果您将ISet<T>的基数限制为等于或小于连续体(| R |)的基数,那么您将能够绕过这个悖论。

即使这样,你也无法实现MySet<T>或类似的方法,因为这样做会等同于解决暂停问题。 (请记住,所有Contains程序的集合的基数等于| Z |&lt; | R |。)

修改

为了更加彻底,这里是对我的断言的解释,“这样做将等同于解决停止问题。”

考虑由所有C#程序(作为字符串)组成的C#,它在有限的时间内停止(假设它们为任何输入停止,确切地说)。称之为MySet<string>。该集合是*递归可枚举的“,这意味着你可以在其上实现paradox2(不容易,但它是可能的。)这也意味着它被很好地定义。但是,这个集合不是”可判定的“,因为它补语不是递归可枚举的。

按如下方式定义C#程序:

GetEnumerator

编译上述程序,并将其作为输入传递给自己。会发生什么?

如果您的using ... //Everything; public static class Decider { private MySet<string> _haltingSet = CreateHaltingSet(); static void Main(string [] args) { Console.WriteLine(_haltingSet.Contains(args[0])); } } 方法已正确实施,那么您已解决了暂停问题。但是,我们知道这是不可能的,因此我们只能得出结论,即使对于可数无限的集合,也无法正确实现Contains

您可以限制Contains班级适用于所有decidable sets.但是,您仍然会遇到各种问题从不停止有限的时间。

作为一个例子,让我们假装我们有一个名为MySet<T>的任意精度实数类型,让我们让Real成为nonHalting的一个实例,其中包含所有非平凡的零。 Riemann Zeta函数(这是一个可判定的集合)。如果你能够在MySet<Real>上正确实现IsProperSubsetOf以在有限的时间内返回,当通过所有复数的集合与实部1/2(也是可判定集)时,那么你将获胜一个Millennium Prize.

答案 1 :(得分:2)

你将不得不概括Set的意思。

如果您将拥有无限集,则无法对其进行有意义的枚举,因此您不会使用枚举操作来定义集合运算。

如果您根据Set<f>方法定义bool IsMember(f obj),则可以将其用于无限集。

您可以将两个集合的并集或交集定义为两个集合的逻辑和/或IsMember方法。

答案 2 :(得分:2)

代表无数无限集

让我们在实践中如何完成这一陈述。例如,当询问天气时,集合A是集合Z(正整数)的子集,主题不是Z.Z中的每个数字都不被分析。分析的是有问题的集合A.因为没有办法比较Ak(一个子k,其中k是1和| A |之间的数字)与Z(无限)的每个值,所以A的每个值必须是与构成Z的属性相比较。如果A中的每个值都满足Z的属性,则A是Z的子集。

如何在代码R union N

中表示

与上述相同的过程。 R的属性是“任何实数” - 在代码中,这可能是“任何不会抛出异常的双重”(显然Math.Pow(-1,.5)会产生问题,因此不会出现在R中)。 N的属性是“任何整数” - 在代码中,这可以是Math.Floor!= Math.Ceiling的任何数字。这两者的结合是它们的属性的结合。任何符合R或N属性的数字 - 在代码中,这将是任何不会抛出异常的数字,以创建,其中Math.Floor!= Math.Ceiling。

<强>摘要

要表示不可数的无限集,请使用它们的属性而不是它们的值。


编辑

N⊆R?

让我们回到属性的想法,因为这是我追求的主题。 N是R的子集吗?要使N成为R的子集,则N的属性必须满足R的属性的所有。属性列表需要准确。为了表示无穷大的数值,我建议使用一个包含可空int数和普通int符号的类。

public class Infinite
{
 public int? Number { get; set; }
 public int Sign { get; set; }
}

这些方面的东西。 Number.Value == null意味着无限。符号可用于显示负(-1),+ - (0)或正(1)。

回到R情境的N子集。除了前面列出的属性之外,N还将Infinite.Number == null和Infinite.Sign == 0作为其属性的边界。就像R.所以,N能够满足边界属性。接下来将是上面定义的属性。我实际上被困在这里。我不知道如何在代码中证明.Floor == .Ceiling的每个数字都不会导致异常。然而,由于这些类型的超集(Rational,Irrational,Integer,Real,Complex,Imaginary,Transcendental,Algebraic,Natural)中只有9种,你可以在无限范围内专门定义它们的相互作用,然后使用更简单的有限实现比较。

答案 3 :(得分:0)

你究竟打算用它做什么。 你无法枚举它。

我认为我将其视为普遍集的后代。

我想我会从另一端开始

定义一个通用集,其中Ismember始终为true 然后是IsMember为真的后代,如果它是自然数的表示 {1,2,3,4}是N的进一步限制

无论如何想到

答案 4 :(得分:0)

这可能有很多限制,就像符号表达式处理一样。

这是一个小例子:

class IntSet
{
    int m_first;
    int m_delta;

    public IntSet(int first, int delta)
    {
        m_first = first;
        m_delta = delta;
    }

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();

        sb.Append('[');
        sb.Append(m_first);
        sb.Append(',');
        sb.Append(m_first + m_delta);
        sb.Append(',');
        sb.Append("...");
        sb.Append(']');

        return sb.ToString();
    }

    public IEnumerable<int> GetNumbers()
    {
        yield return m_first;

        int next = m_first;

        while (true)
        {
            next += m_delta;

            yield return next;
        }
    }
}