管中窥豹
2023-04-03陈凯
陈凯
《世说新语》中有这样一个故事:王羲之的几个门生在玩棋,王羲之只有几岁的儿子王献之在一旁观看,说其中一方将要输了。门生觉得那么小年龄的孩子,恐怕只是懂那么一点点就乱说话,于是有点嘲笑地评价说:“管中窥豹,时见一斑。”王献之有没有说准呢?大概是说准了吧,不过,故事里只是提到了王献之颇为不高兴地回应:“远惭荀奉倩,近愧刘真长。”“管中窥豹”是一个常用的成语,不过其具体的运用别有一番奥妙:当人们只说“管中窥豹”的时候,通常是指难以从局部现象了解全局,而当人们说“管中窥豹,可见一斑”的时候,却往往是想说,即便从局部现象中也能了解到全局的状况。这种看似矛盾的用法体现了语言文化的复杂性。在一个复杂的计算系统中,也常能发现类似“管中窥豹”的现象,可以将“斑”视作局部的计算现象,而“豹”则是整体的计算现象,有时可由局部了解全局,有时却不能。利用局部的计算现象达成全局的计算目标,是构造计算模型的一种重要思维方式。
管窥之斑或可见豹
假设一个列表中存储有若干数字,要求找出其中最大的数字并将其移至列表最后,可以采用怎样的方法呢?方法很多,不妨将这个列表想象成一个长条的存储槽,而数字是槽上大小不一的盒子,有一只机械手臂可以同时观察两个盒子的状况并针对这两个盒子做出某种动作,那么,当某人观察到这只机械手臂从槽左侧开始向右移动,并同时实施将两个盒子中更大的那个交换到另一个盒子右侧这样的行为时,就能判定,当机械手臂移至槽右侧末端时,那里最终一定会摆放下槽中最大的盒子。扩展想象一下,如果机械手臂可以同时观察三个盒子的情况,并能将其中最大的盒子交换到另两个盒子的最右侧,那么可以推断,这个装置整体的作用和刚才的装置类似,也能够在存储槽中找出最大的盒子并放置到整个槽右侧末端。一个使用列表的演示程序代码及运行结果如图1所示。在这个例子中,局部的功能和全局的功能是一致的,所以比较容易借助局部变化的现象推演出整体变化的情况,用管窥之豹来比喻的话,局部的最大数的交换是斑,整体的最大数的交换是豹。
在简单的逻辑运算中,也能发现“管中窥豹,可见一斑”的例子,如三个人投票,规则是一票否决,这时候可以用与的逻辑运算来获知投票结果。如果扩展到十个人或更多人投票,那么全局的与运算的结果还是很容易判断出来的:只要有一张否决票,那么整个表决都不会通过,在与的逻辑运算中,局部与整体的计算现象是一致的。
管窥之斑或难见豹
接下来看一个稍微复杂一些的例子,某存储槽中有很多黑色盒子和白色盒子随机相间排列。但在存储槽的左侧最前端放着一个特殊的盒子,它向前正面是黑色的,向后反面是白色的。机械手臂总是实施将此两色盒子和其右侧盒子交换的动作,如果其右侧盒子是黑色的,则交换的同时还要将此两色盒子正反颠倒,如果其右侧盒子是白色的,则只是交换位置而不对两色盒子实施正反颠倒的动作。那么,当这只机械手臂顺槽移动到最右侧末端时,这个两色盒子到底是黑色还是白色,则提示着存储槽中的黑色盒子数量是奇数还是偶数。一个演示程序代码及运行结果如图2所示。代码中用“b”和“w”代表黑色和白色的盒子,用“-1”和“1”代表两色盒子的黑色正面和白色反面。在这个例子中,局部的行为是交换盒子并判断及实施两色盒正反颠倒的动作,但在系统运行的整体上,却实现了奇偶判断的任务。局部动作虽然和整体任务有密切的关系,但在行为表现上是不一致的。
将以上任务再做修改,假设机械手臂总是处于存储槽左侧开端处,而存储槽的传送带会将其余右侧的若干盒子向左移动靠拢,当机械手臂观察到两色盒与黑盒左右排列的状态时,就扔掉黑盒,同时将两色盒翻面,当机械臂观察到白色反面向前的两色盒与白盒左右排列的状态时,就扔掉白盒,否则就不做任何事。这样一个局部的规则,到底可以用来实现怎样的整体功能呢?这个问题的推理要比刚才的例子费劲得多,虽然管窥见斑,但豹的整体的样子就更难想象了。大家不妨直接看如图3所示的程序代码的演示。跟踪运行过程可知,在程序初始列表中,“b”的数量代表将要被判断奇偶的数字,“w”是标志符,如程序运行最后所有的“w”都消失了,则说明被判断的所有数字都是奇数,否则,就说明连续摆放的“b”盒子用来表示的数量中,至少有一个偶数。在这个例子中,局部发生变化的位置只有一处,想象一下,若列表中多处位置都在按规则发生局部的变化,那么整体的变化现象就更难以揣摩了。
在逻辑運算中也有类似的例子,如果对多个数字做一种叫做与非的运算(对两个逻辑值的与运算的结果取反),哪怕这个局部变化规则非常简单,也还是不能根据这个局部变化现象直观地推演出全局的变化现象,下页图4所示的是对8个逻辑值进行逻辑运算的程序代码。如果是进行与的逻辑运算,那么很容易推测出整体的结果,如果是与非的逻辑运算,那就只有一步一步地计算才能得出全局的结果。所以说,有时通过管窥之斑是很难见到豹的。
斑豹之变
在一个计算模型中,斑和豹的地位是会发生变化的,以冒泡排序算法为例,对于长度为x的数列,数列中两两数字比对交换是斑,数列中最大数放置到最右侧的现象是豹。同时,也可以将第n次在长度x-n+1的数列中实现最大数放置到最右侧的这一现象视作斑,而长度为x的数列最终实现排序的这一现象视作豹。
哪怕局部的规则很简单,若一个系统中多个局部都并发地应用规则,整体上就有可能产生出混沌的现象,单凭人脑的能力,是难以把握局部规则运用于全局后的变化状态的,但对于某些特定的数据集合,局部规则的并发应用,也能呈现出全局层面在混沌变化的同时涌现出部分有规则变化的现象。用语言描述这种现象是十分困难的,借助元胞自动机的例子更容易说明这种现象。WireWorld是一种正方形网格元胞自动机,它的运行规则是:每个格子允许有四种颜色,在每个变化的时刻,黑色总是保持黑色,红色总是变成蓝色,蓝色总是变成黄色,黄色保持黄色的状态,但只要黄色的格子周围的八个格子里有一个或两个红色,黄色就变成红色。虽然局部规律不难理解,但对于稍微复杂一些的Wireworld图样,绝大部分人如果只用头脑推理和想象是很难判断出运行结果的。这种针对全局状态预测的困难,也是复杂系统的一个特征。例如,下页图5所示的图案A在若干步变化后陆续出现B、C、D等图案变化的现象,不得不用计算机才能逐步模拟出全局的图样变化状况。
但令人惊讶的是,虽然图5所示的系统在运作过程中是混沌的,可它的初始时刻(如图A所示的时刻)的信号状态和若干时刻后(如图D所示的时刻)的信号状态,这两者间是存在明确的规律的。这里勉强比喻一下,在局部范围内可以看出有规律的“斑”,但很多“斑”组合在一起,大多数情况下是一片混沌,只有某些特别的“斑”偶尔以某种特别的方式组合起来后,能显现出某种“豹”的样子。如图5所示的图样,它的行为很像一个能进行与逻辑运算的装置。一旦有了这样的领悟,就能够将这个特殊组合的“豹”当作为了组合出更大规模的“豹”的“斑”来使用了。下页图6是利用Wireworld元胞自动机实现奇偶校验的例子,如果说整体的奇偶校验任务是豹,那么这个系统中重要的组成部分就是如图5所示的图样的变化状态,就成为整体的豹的斑(注意,这里的斑不是图样而是图样的变化)。本文在这里只是试图说明这种现象的存在,但除非读者亲自运行并观察这个系统的运作过程,只依靠阅读这里的文字描述,是很难明白这些图样变化是如何实现奇偶校验的功能的。
系统科学对此现象是这样描述的:局域耦合可以产生出信号传递的现象,使得整体系统在不具備中心控制能力的情况下,在宏观的尺度涌现出动力学行为。不过对于复杂系统,系统科学的研究目标主要是结构和功能的关系以及系统演化的规律,而计算机科学在于如何利用这种演化规律,或者是如何为创设出一种具有实用价值的演化规律来设计特定的结构。
“用斑绘豹”的教学设计
从上述较为艰深和抽象的讨论回归到日常教学,这里介绍一个可以在教学中引发讨论的有趣问题:假设有一个长长的存储槽,槽内排列大小不一的盒子,槽的左侧末端是某A,槽的右侧末端是某B。某只机械手臂在槽的侧面左右来回随机游走,机械手臂会观察槽内盒子,它每次检查三个盒子,然后将最大的盒子取出,放置在另两个盒子的右面,假如遇见的三个盒子都是一样的,则不做任何事继续随机游走。例如,机械手臂看到的是“635”,就将“6”交换到另两个数最右侧,成为“356”。可以将这个情况以某种编码展现出来:
A26352627282738244758473B
R
-->
A26352627282738244758473B
R
容易猜出,编码中数字代表不同大小的盒子,数字越大盒子越大,R是机械手臂。现在,某A要和某B通过在纸盒子上写字的方式来传输信息,但某A和某B不能离开自己的位置,为了实现通信的需求,某A和某B使用了一种充气变为9、放气变为1的变化盒,在通信时可将变化盒放置在自己身边的槽末端(为避免复杂性,变化盒传达到对方阅后即毁),这里要问的是:为了实现相互通信,在A和B的身边,需要准备多少变化盒?
①A和B各需要1个变化盒给对方发消息;
②A和B各需要2个变化盒给对方发消息;
③A需要2个变化盒能发出消息给B,B需要1个变化盒能发出消息;
④A需要1个变化盒能发出消息给B,B需要2个变化盒能发出消息。
问题描述的盒子位置在变化过程中,很清晰地体现出局域耦合所产生的信号传递现象,而且,系统整体的功能依赖于规则引发的局部变化,但整体的功能又和局部行为不相一致,希望读者在领悟到这一点后,能进一步尝试用局部的“斑”来建构出整体的“豹”,解决更复杂一些的问题。