March Library中的Multiboolean——多值逻辑实现

(附前文)习惯上我们在应用系统中一直使用两值逻辑:非 True 即 False 。两值逻辑的运算体系已经相当成熟,与、或、非以及衍生的异或、与非等等。但是在实际应用中,我们会有机会遇到三值逻辑。

三值逻辑通常包含可选的 True 、 False 、 NULL 。如何在完备的两值逻辑运算体系中加入这个 NULL ,使之满足我们的需要,并且不会引发逻辑矛盾,就是我们要在这里讨论的。

NULL 参与逻辑运算时,实际上存在着不同的算法。按 NULL 值在运算中的“优先级”分为三种。

通常我们在数据库中使用的三值逻辑,遵循 NULL 最优的原则。有 NULL 值参与二值运算时,返回结果为 NULL ,其它与二值逻辑相同。这一原则基于关系型数据库将 NULL 视为“无意义( Nil )”。由于其内容无意义,则任何逻辑值与之进行运算的结果都是无意义值,这也与许多数据关系型数据库对 NULL 的处理一致。

另一方面,可能有些朋友没有注意到,事实上常见的权限体系也是一种三值逻辑,这个体系里 NULL 值处于最低优先级,两个权限值进行合并时, False (否定)高于一切,没有否定值时,肯定值( True )高于 NULL ,只有两个值均为 NULL 时,结果才为 NULL 。实际上我们可以将它看作是一个三值与运算,那么出于数学上的对称,很容易可以构造出对应的逻辑或运算。这种运算规则视 NULL 为“未赋值( Undefine )”。

最后一种规定 NULL 值的优先级介于 True 和 False 之间,与运算,二者有一为 False 时,返回 False ,否则二者有一为 NULL 时,返回 NULL ,二者均为 True 时返回 True ;或运算,二者有一为 True 时返回 True ,否则二者有一为 NULL 时返回 NULL ,二者均为 False 时返回 False 。这等于分别承认 True 和 False 在或和与运算中的最高优先级。它基于 NULL 值为“未知”的理念。这种规则下,对 NULL 值严格视为未知的 True 或 False ( Unknown )。也有一些数据库的三值逻辑是基于这个体系的, MSDN 中给出了一个基于此规则的 DBBool 示例。

关于 NULL 值的学术讨论其实一直没有休止过,这期间还出现过四元逻辑等理论。实践也证明,“真实”世界中客观存在着不止一种三值逻辑体系。在实用中应当依据具体情况选择最适合的规则。

我不想隐瞒,写下这一章的时候,我心里很自豪。对于真正的高手,那些创造了强大的虚拟机、框架和优雅类库的大师来讲, MultiBoolean 这样的小东西确实不算什么。但是,这确是第一个可以让我自己满意的作品。虽然这个设计还不能作到完美,但是它已经可以满足我当前对多值逻辑的应用需求。

长期以来,困扰我的最大问题莫过于多值逻辑中不同的空值如何兼容。当然,从数学意义来讲,不同的空值代表了不同的逻辑空间,它们之间不应该存在交叉。所以理想状态应该是根据某种标记来区分不同的逻辑,并将它们分隔开。但是在实用中,一个可以在不影响各自的逻辑算法、不引发异常的前提下处理多种空值逻辑的多值逻辑类型,似乎更为完美。毕竟它是一个基础类型,应该使用尽可能简单——我的 Blog 上记载了另一种多值逻辑实现,在实用中,我感觉它确实过于复杂了。一个只有几种状态的逻辑类型,居然需要工厂方法来构造……

引起这种复杂结构的直接原因,即是我一直试图用 -1 , 0 , 1 三个整型来表达逻辑三态。也许对于某一种逻辑来讲,这样作是合适的,但是如果想要用一个 0 来表达多个逻辑空值,未免太过苛求了。

用多个整数来表达?这种方式我也想过,比如将 Nil 设为最小值, UnKnown 设为最大值。然而很难实现一个简单优雅的算法来兼容这些值,本来 UnKnown 本身的算法很简洁漂亮,而其它另两种虽然不够直观,但是足以内洽。当把它们放在一起的时候,不应该产生任何冲突。

在一个偶然的机会,我想到了复数。是的,复数正是我需要的表达形式!如果将有效逻辑值表达为实数,将空值表达为虚数,这正是我所需要的效果。在形式上,由于 Unknown 的含义,恰恰可以将它视为“真正的空值”或“可能的逻辑值”两种体系的一个交叉点,也就是说,它正是那个实虚轴交叉的原点—— 0 。而这也与 MSDN 中的空值算法兼容。

这是一个令我激动的发现。很快,我着手寻找合适的复数实现。由于 .net CLR 中没有提供内置的复数类型,我参考 STL 中的复数实现编写了一个 C# 版本的 Complex 类型。后面的事,就是怎样把这个想法具体化了。

以下就是实现代码,在代码的文档注释中,有各个主要功能的详细介绍:

using System;

using System.Data;

using March.Math;

namespace March.VBoolean

{

///

 1<summary>
 2
 3/// MultiBoolean  是  VBoolean  命名空间中最后加入的一个成 
 4
 5///  员,从结构来讲,可能也是多值离散逻辑的最终类型了。相比 
 6
 7///  同一空间内的  VarBoolean  和  Boolw3  ,它在数学上统一了三种空 
 8
 9///  值规则,成为一个完备实用的数据类型。后两者今后将只作为 
10
11///  向下兼容而存在,并且在以后的版本中可能会去掉这两个类型。 
12
13/// </summary>

public struct MultiBoolean

{

private Complex __value;

private static readonly Complex TrueValue = new Complex(1, 0);

private static readonly Complex FalseValue = new Complex(-1, 0);

private static readonly Complex UnknownValue = new Complex(0, 0);

private static readonly Complex UndefineValue = new Complex(0, 1);

private static readonly Complex NilValue = new Complex(0, -1);

///

1<summary>
2
3///  真值 
4
5/// </summary>

public static readonly MultiBoolean True = new MultiBoolean(new Complex(1, 0));

///

1<summary>
2
3///  假值 
4
5/// </summary>

public static readonly MultiBoolean False = new MultiBoolean(new Complex(-1, 0));

///

1<summary>
2
3/// MultiBoolean  支持的空值类型之一,表示该值是真或假中 
4
5///  的一种,但是不能确定。 
6
7/// </summary>

public static readonly MultiBoolean Unknown = new MultiBoolean(new Complex(0, 0));

///

1<summary>
2
3/// MultiBoolean  支持的空值类型之一,表示未定义的逻辑值。 
4
5///  如果限定逻辑状态为  True  ,  False  ,  Undefine  中的一种,那么与运算即为权限管 
6
7///  理体系中的权限校验操作。 
8
9/// </summary>

public static readonly MultiBoolean Undefine = new MultiBoolean(new Complex(0, 1));

///

1<summary>
2
3/// MultiBoolean  支持的空值类型之一,表示无意义的逻辑值。 
4
5/// </summary>

public static readonly MultiBoolean Nil = new MultiBoolean(new Complex(0, -1));

///

1<summary>
2
3/// MultiBoolean  内部以复数表示逻辑状态,通过这个内部的 
4
5///  构造函数生成指定状态的逻辑值。 
6
7/// </summary>

///

1<param name="value"/>

代表状态的复数值,可能值为 1 ,- 1 , i , -i , 0

private MultiBoolean(Complex value)

{

this.__value = value;

}

public bool IsTrue{get{return __value == TrueValue;}}

public bool IsFalse{get{return __value == FalseValue;}}

public bool IsUnknown{get{return __value == UnknownValue;}}

public bool IsUndefine{get{return __value == UndefineValue;}}

public bool IsNil{get{return __value == NilValue;}}

///

 1<summary>
 2
 3///  两值逻辑向  MultiBoolean  转型的隐式转型函数。 
 4
 5///  因为  MultiBoolean  中定义了多种可选的空值,  CLR  的  DBNull  并未定义 
 6
 7///  与二值逻辑的转型规则,所以在这里不定义  DBNull  向  MultiBoolean  的隐式 
 8
 9///  转换。需要进行转换的用户可以根据自己的应用逻辑定义自己的类型转换。 
10
11/// </summary>

///

1<param name="x"/>

逻辑值

///

1<returns> 转换后的  MultiBoolean </returns>

public static implicit operator MultiBoolean(bool x)

{

return x? True: False;

}

///

 1<summary>
 2
 3/// MultiBoolean  的与操作。 
 4
 5///  返回值按  Nil  ,  False  ,  Unknown  ,  True  ,  UnDefine  的优先级从两值中取一返回。 
 6
 7///  如果限定逻辑状态为  True  ,  False  ,  Undefine  中的一种,那么该与运算即为权限管 
 8
 9///  理体系中的权限校验操作。 
10
11/// </summary>

///

1<param name="x"/>

左值

///

1<param name="y"/>

右值

///

1<returns> 返回值  </returns>

public static MultiBoolean operator & (MultiBoolean x, MultiBoolean y)

{

if(x.IsNil || y.IsNil)

return Nil;

if(x.IsUndefine )

return y;

if(y.IsUndefine)

return x;

return new MultiBoolean(x.__value.real < y.__value.real ? x.__value : y.__value);

}

///

1<summary>
2
3/// MultiBoolean  的或操作。 
4
5///  返回值按  Nil  ,  True  ,  Unknown  ,  False  ,  UnDefine  的优先级从两值中取一返回。 
6
7/// </summary>

///

1<param name="x"/>

左值

///

1<param name="y"/>

右值

///

1<returns> 返回值  </returns>

public static MultiBoolean operator | (MultiBoolean x, MultiBoolean y)

{

if(x.IsNil || y.IsNil)

return Nil;

if(x.IsUndefine)

return new MultiBoolean(y.__value);

if(y.IsUndefine)

return new MultiBoolean(x.__value);

return new MultiBoolean(x.__value.real > y.__value.real ? x.__value : y.__value);

}

///

 1<summary>
 2
 3/// MultiBoolean  的非操作。  True  和  False  互为非值。 
 4
 5///  空值的非操作通常没有意义,仍返回空值本身。当且仅当 
 6
 7/// x  为  True  或  False  时,  !x=x&amp;False  (实际上  x==Nil  时也满足这个 
 8
 9///  规则,但其行为与  T/F  值的非不相同)。 
10
11/// </summary>

///

1<param name="x"/>

操作数

///

1<returns> 返回值  </returns>

public static MultiBoolean operator ! (MultiBoolean x)

{

return new MultiBoolean(new Complex(-x.__value.real, x.__value.imag));

}

///

 1<summary>
 2
 3/// MultiBoolean  对象的等值判断,需要指出的是,对于空 
 4
 5///  值,判断其是否相等没有意义,故两值中有至少一个为空时, 
 6
 7///  按以下规则判断: 
 8
 9///  只有一个为空值时,返回该空值状态; 
10
11///  两个都为空值时,返回优先级较高的一个。 
12
13///  定义这样的规则只是为了方便最常见的三值逻辑应用,我认为不应该出现不同空值 
14
15///  之间发生比较的场合,至少这样的运算非常罕见,而它的数学意义也模糊不清。 
16
17///  需要定义自己的判等规则时,可以调用对象的实例方法  Equals  或静态方法  Equals  。 
18
19/// </summary>

///

1<param name="x"/>

左值

///

1<param name="y"/>

右值

///

1<returns> 返回值  </returns>

public static MultiBoolean operator == (MultiBoolean x, MultiBoolean y)

{

if(x.__value.real == 0 && y.__value.real == 0)

return new MultiBoolean(new Complex(0, System.Math.Min(x.__value.imag, y.__value.imag)));

if(x.__value.real == 0 && y.__value.real != 0)

return new MultiBoolean(x.__value);

if(x.__value.real != 0 && y.__value.real == 0)

return new MultiBoolean(y.__value);

return x.__value.real == y.__value.real ? True : False;

}

///

 1<summary>
 2
 3/// MultiBoolean  对象的不等判断,需要指出的是,对于空 
 4
 5///  值,判断其是否相等没有意义,故两值中有至少一个为空时, 
 6
 7///  按以下规则判断: 
 8
 9///  只有一个为空值时,返回该空值状态; 
10
11///  两个都为空值时,返回优先级较高的一个。 
12
13///  定义这样的规则只是为了方便最常见的三值逻辑应用,我认为不应该出现不同空值 
14
15///  之间发生比较的场合,至少这样的运算非常罕见,而它的数学意义也模糊不清。 
16
17///  需要定义自己的判等规则时,可以调用对象的实例方法  Equals  或静态方法  Equals  。 
18
19/// </summary>

///

1<param name="x"/>

左值

///

1<param name="y"/>

右值

///

1<returns> 返回值  </returns>

public static MultiBoolean operator != (MultiBoolean x, MultiBoolean y)

{

if(x.__value.real == 0 && y.__value.real == 0)

return new MultiBoolean(new Complex(0, System.Math.Min(x._

Published At
Categories with Web编程
Tagged with
comments powered by Disqus