我正在为离散数学设计一个类库,我想不出一种实现方法的方法 无限集。
到目前为止我所拥有的是:我有一个抽象基类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的方法,最有问题的是枚举方法和IsSubsetOf方法。
无法完全实施 ISet<T>
无数无限集。
这是一个证明(由Bertrand Russell提供):
假设您已经创建了一个类 MySet<T>
这可以代表一个无数无限的集合。现在让我们考虑一些 MySet<object>
对象。
我们标注一个特定的 MySet<object>
, 叫它 instance
,“不正常“如果:
instance.Contains(instance)
返回true。
同样,我们会标记 instance
作为“正常“如果:
instance.Contains(instance)
返回false。
请注意,这种区别是为所有人明确定义的 instance
。
现在考虑一个实例 MySet<MySet<object>>
叫 paradox
。
我们定义 paradox
作为 MySet<MySet<object>>
其中包含所有可能的 正常 的实例 MySet<object>
。
什么应该 paradox.Contains(paradox)
返回?
如果它返回 true
, 然后 paradox
是 不正常 应该已经回来了 false
当被召唤时。
如果它返回 false
然后 paradox
是 正常,应该已经返回了 true
当被召唤时。
没有办法实施 Contains
解决这个矛盾,所以没有办法完全实现 ISet<T>
对于所有可能的无数集。
现在,如果你限制了基数 MySet<T>
等于或小于连续体(| R |)的基数,那么你就能解决这个矛盾。
即使这样,你也无法实现 Contains
或类似的方法,因为这样做相当于解决停止问题。 (记住所有的一套 C#
程序的基数等于| Z | <| R |。)
编辑
为了更加彻底,这里是对我的断言的解释,“这样做将等同于解决停止问题。”
考虑一下 MySet<string>
它包含所有C#程序(作为字符串),它们在有限的时间内停止(假设它们停止输入任何输入,确切地说)。叫它 paradox2
。该集合是*递归可枚举的“,这意味着您可以实现 GetEnumerator
在它上面(不容易,但有可能)。这也意味着它定义明确。但是,这个集合不是“可判定的”,因为它的补码不是递归可枚举的。
定义C#程序如下:
using ... //Everything;
public static class Decider {
private MySet<string> _haltingSet = CreateHaltingSet();
static void Main(string [] args) {
Console.WriteLine(_haltingSet.Contains(args[0]));
}
}
编译上面的程序,并将其作为输入传递给自己。怎么了?
如果你的 Contains
方法正确实施,然后你已经解决了暂停问题。但是,我们知道这是不可能的,因此我们只能得出结论认为无法正确实施 Contains
, 即使是可数无限的集合。
你可以限制你的 MySet<T>
为所有人工作的课程 可判定的集合。 但是,您仍然会遇到函数的各种问题 决不 在有限的时间内停止。
举个例子,让我们假装我们有一个叫做的任意精度实数类型 Real
,让我们来吧 nonHalting
是一个实例 MySet<Real>
其中包括Riemann Zeta函数的所有非平凡零点(这是一个可判定的集合)。如果你能正确实施 IsProperSubsetOf
上 nonHalting
当通过所有复数的集合与实部1/2(也是一个可判定的集合)时,在有限的时间内返回,那么你将赢得一个 千禧奖。
你将不得不概括Set的意思。
如果您将拥有无限集,则无法对其进行有意义的枚举,因此您不会使用枚举操作来定义集合运算。
如果你定义一个 Set<f>
就...而言 bool IsMember(f obj)
方法,它可以用于无限集。
您可以将两个集合的并集或交集定义为两个集合的逻辑和/或IsMember方法。
代表无数的无限集
让我们在实践中如何完成这一陈述。例如,当询问天气时,集合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种,您可以在无限范围内专门定义它们的交互,然后使用更简单的有限实现比较。
你究竟打算用它做什么
你无法枚举它。
我认为我将它当作普遍集的后代。
我想我会从另一端开始
定义一个通用集,其中Ismember始终为true
然后是IsMember为真的后代,如果它是自然数的表示
{1,2,3,4}是N的进一步限制
无论如何一个想法
这可能有很多限制,就像符号表达式处理一样。
这是一个小例子:
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;
}
}
}