三体社区泛科幻大本营

注册

只看楼主

三体中黑暗森林的程序实现(脱代码版)【转自豆瓣】

吴颜 发表于 2015-4-8 15:51:50 [ 上一主题] [下一主题]

看过小说《三体》的人应该对黑暗森林这个概念不会陌生。它讲的是在宇宙中文明如果想存活下来,必须对遇到的任何文明发动攻击,并认为这是宇宙的唯一准则。

这个理论争论很大。支持的人认为能想出来黑暗森林的大刘实在是太伟大了。
反对的人认为这不过是科幻小说家的胡思乱想罢了。
我认为两者都不对,黑暗森林不过是博弈的一般性推论之一而已。
它即切实存在,也不是唯一的存在。

为了说明这一点,我将用程序来模拟实际的情况。

一、文明的种类

文明的三种外交策略
1、进攻的文明,战争解决一切(进攻)
2、友好的文明,提倡互相帮助(友好)
3、以牙还牙的文明,遇到进攻则反击,遇到帮助则互助(反击)

文明的两种探索策略
1、保守的文明,被动等待其他星球的文明来联系(保守)
2、好奇的文明,主动访问其他文明(好奇)

由以上策略排列组合出六种类型的文明:
1、保守进攻型文明
2、保守友好型文明
3、保守反击型文明
4、好奇进攻型文明
5、好奇友好型文明
6、好奇反击型文明

二、规则
每个文明初始都是1000000点文明值,当受到攻击时,文明倒退,文明值减少;当受到其他文明帮助时,文明加速进步,文明值增加。当文明值减少到0时,文明消失。

三、参数
文明会随时间发展,每经过一轮,文明会增长d%。

高文明对低文明有高攻击力,好像拿着长矛的军队无论无何也打不过拿着枪的军队。
高文明对低文明也有更多的帮助,发达国家对落后国家不仅有金钱的投资还会带动他们的科技发展。
所以设定:
对其他文明的攻击力 = 自身文明 * a%
对其他文明的帮助力 = 自身文明 * h%
由于文明会随时间按百分比成长,所以这样的简单设定,低文明对高文明影响的百分比会比较小,和上面的要求一致。


回复 点赞(1)

吴颜 发表于 2015-4-8 15:54:05

3

地板

七、总结
由上面我们可以看出根据不同的参数就会有不同的博弈方式。不管是黑暗森林、乌龟文明,还是互助文明,都是只需要满足一定条件就会成立的法则。坚持其中一个无疑是迂腐的。到底应该何时使用何种策略,具体看当时相互间的利害参数而定。

八、以下为程序代码:

package blackforest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class BlackForest {

//        public static void main(String[] args) {
//                Culture c1 = new Culture(VisitType.active, ForeignType.attack);
//                Culture c2 = new Culture(VisitType.active, ForeignType.friend);
//                for (int i = 0; i < 10000; i++) {
//                        try {
//                                c1.develop();
//                        } catch (RuntimeException e) {
//                                System.out.println(i);
//                                throw e;
//                        }
//                }
//                foreign(c1, c2);
//                System.out.println(c1.toString2() + ":" + c2.toString2());
//        }

        public static void main(String[] args) {
                // 随机建造10000个文明
                Random random = new Random();
                VisitType[] visitTypes = VisitType.values();
                ForeignType[] foreignTypes = ForeignType.values();

                List<Culture> activeCultures = new ArrayList<Culture>();
                List<Culture> allCultures = new ArrayList<Culture>();
                for (int i = 0; i < 10000; i++) {
                        VisitType visitType = visitTypes[random.nextInt(visitTypes.length)];
                        ForeignType foreignType = foreignTypes[random
                                        .nextInt(foreignTypes.length)];
                        Culture c = new Culture(visitType, foreignType);
                        allCultures.add(c);
                        if (visitType == VisitType.active)
                                activeCultures.add(c);
                }
                result(allCultures);

                // 经过500次的轮回
                for (int j = 0; j < 500; j++) {
                        // for (int j = 0; j < 10; j++) {
                        // 每个文明都能自己发展
                        for (Culture c : allCultures) {
                                c.develop();
                        }
                        // 激进的文明开始探索
                        for (Culture c1 : activeCultures) {
                                if (!c1.isExist())
                                        break;
                                Culture c2;
                                while (true) {
                                        c2 = allCultures.get(random.nextInt(allCultures.size()));
                                        if (c2 != c1 && c2.isExist())
                                                break;
                                }
                                foreign(c1, c2);
                        }
                        // 清除消失的文明
                        allCultures = delete(allCultures);
                        activeCultures = delete(activeCultures);
                        if (j % 50 == 0) {
                                System.out.print("第" + j + "轮:");
                                result(allCultures);
                        }
                        // 只有一个文明时,进化结束
                        if (allCultures.size() == 1) {
                                System.out.print("仅存一个文明,第" + j + "轮:");
                                result(allCultures);
                                break;
                        }
                        // 所有好奇的文明消失,进化结束
                        if (activeCultures.size() == 0) {
                                System.out.print("主动的文明全灭,第" + j + "轮:");
                                result(allCultures);
                                break;
                        }
                }
                result(allCultures);

        }

        private static List<Culture> delete(List<Culture> allCultures) {
                List<Culture> temp = new ArrayList<Culture>();
                for (Culture c : allCultures)
                        if (c.isExist())
                                temp.add(c);
                return temp;

        }

        // 文明间交流
        private static void foreign(Culture c1, Culture c2) {
                // long cc1 = c1.getCulture();
                // long cc2 = c2.getCulture();
                if (c1.foreignType == ForeignType.revenge) {
                        // 必须等别人进攻自己后才能报复
                        c2.foreignType.visit(c2, c1);
                        c1.foreignType.visit(c1, c2);
                } else {
                        c1.foreignType.visit(c1, c2);
                        c2.foreignType.visit(c2, c1);
                }
                // if (c1.getCulture() < 0 || c2.getCulture() < 0)
                // System.out.println("c1=" + cc1 + ":" + c1.toString2() + " c2="
                // + cc2 + ":" + c2.toString2());
        }

        // 統計結果
        private static void result(List<Culture> allCultures) {
                Map<Culture, Integer> result = new HashMap<Culture, Integer>();
                for (Culture c : allCultures) {
                        if (result.containsKey(c)) {
                                Integer a = result.get(c);
                                a++;
                                result.put(c, a);
                        } else {
                                result.put(c, 1);
                        }
                }
                System.out.println(result);

        }
}

// 探索策略:主动探索,被动等待
enum VisitType {
        active, passive
}

// 外交策略:进攻,友好,以牙还牙
enum ForeignType {
        attack {
                public void visit(Culture c1, Culture c2) {
                        if (c1.getCulture() > 0 && c2.getCulture() > 0) {
                                // 进攻这个文明
                                long s = (c1.getCulture() * Culture.a / 100);
                                if (s < 0)
                                        throw new IllegalStateException("s=" + s + " c1="
                                                        + c1.toString2());
                                c2.setCulture(c2.getCulture() - s);
                                // System.out.println(c1 + "把" + c2 + "消灭了"
                                // + (c1.culture * Culture.a / 100));
                        }
                }
        },
        friend {
                public void visit(Culture c1, Culture c2) {
                        if (c1.getCulture() > 0 && c2.getCulture() > 0) {
                                // 帮助这个文明
                                long s = (c1.getCulture() * Culture.h / 100);
                                if (s < 0)
                                        throw new IllegalStateException("s=" + s + " c1="
                                                        + c1.toString2());
                                // System.out.println("s=" + s + " c1=" + c1.toString2());
                                c2.setCulture(c2.getCulture() + s);
                                // System.out.println(c1 + "把" + c2 + "帮助了"
                                // + (c1.culture * Culture.h / 100));
                        }
                }
        },
        revenge {
                public void visit(Culture c1, Culture c2) {
                        if (c2.foreignType == attack)
                                attack.visit(c1, c2);
                        else
                                friend.visit(c1, c2);
                }
        };

        // c1对c2进行作用
        public abstract void visit(Culture c1, Culture c2);

}

class Culture {
        public final static int a = 1;
        public final static int h = 1;
        public final static int d = 0;

        private long culture = 1000000;
        VisitType visitType;
        ForeignType foreignType;//

        Culture(VisitType visitType, ForeignType foreignType) {
                this.visitType = visitType;
                this.foreignType = foreignType;
        }

        public boolean isExist() {
                return culture > 0;
        }

        public long getCulture() {
                return culture;
        }

        public static long max = Long.MAX_VALUE / 10000;

        public void setCulture(long culture) {
                // System.out.println("culture="+culture);
                if (culture > max)
                        throw new IllegalStateException();

                this.culture = culture;
        }

        @Override
        public int hashCode() {
                return visitType.ordinal() * 10 + foreignType.ordinal();
        }

        @Override
        public boolean equals(Object o) {
                Culture c = (Culture) o;
                return c.visitType == visitType && c.foreignType == foreignType;
        }

        @Override
        public String toString() {
                // return visitType + ":" + foreignType + ":" + culture;
                return visitType + ":" + foreignType;
        }

        public String toString2() {
                return visitType + ":" + foreignType + ":" + culture;

        }

        public void develop() {
                setCulture(culture * d / 100 + culture);
        }
}

点评 引用回复 点赞(3)

吴颜 发表于 2015-4-8 15:52:10

1

沙发

四、猜想
当文明间攻击力a相对比较高的时候,进攻的文明更有优势,黑暗森林成立。当文明间帮助力h相对比较高的时候,互助的文明更有优势。当文明增长d相对比较高时,保守的文明更有优势。

五、程序运行结果
1、由于按百分比的成长是非常快速的。单纯考虑发展时,当将发展参数d设为1%,经过2074轮文明值会超出计算机可正常运算的范围。d设为7%,仅经过305轮文明值会超过计算机的正常运算范围。
考虑到文明还有互相帮助增加发展速度,为了程序能稳定运行500轮左右,将d和h都设为1%。

2、文明的负面效应都是大于正面效应。比如有了刀以后,可能打猎方便了,但刀也能轻易把人杀死。有了核能以后,靠核电站能提供一些电能,但核武器已经足够把地球毁灭多少次了。
所以进攻参数a我设为150%,因为每个文明都拥有足以摧毁自己的力量。

(参数:a=150, d=1, h=1),运行结果如下:

仅存一个文明,第175轮:{好奇:进攻=1}

开始时,基本每种类型的文明都会随机到一千七左右的数量:(请参考最开始说的三种外交策略和两种探索策略,排列组合后一共有6种类型的文明)
运行一段时间后,各类文明都均匀地减少,到175轮时,只剩下一个主动进攻的文明。
这就是黑暗森林的结果,文明只能存在一个。主动进攻的文明未必能比别人活得久,但不主动进攻的文明生存的可能性是0。

3、如果攻击力减少,受到攻击的文明不被一轮秒杀,就能有机会反击了。黑暗森林应该就不成立了。
将攻击参数a由150%降低到100%,(参数:a=100, d=1, h=1)运行结果如下:

主动的文明全灭,第201轮:{保守:进攻=111, 保守:友好=115, 保守:反击=126}

果然,有机会反击后,主动探索宇宙的文明锐减,最后全部消失。只剩下安于在自己星球的文明生存下来。此时黑暗森林法则不成立。安于在自己星球生存的文明更容易存活的情况,我们暂且称之为乌龟文明。记得霍金就警告过人们不要随便探索宇宙寻找其他文明,看来他是比较同意这种看法的。

4、自身发展d减少,文明主要靠互相帮助来进行进化时(闭关锁国的发展一定是很慢的,所以推测闭星锁球的文明发展也比较慢)
进攻参数a调为1%,发展参数d调为0%,帮助参数h仍为1%,运行结果如下:(参数:a=1, d=0, h=1)

第500轮:{好奇:进攻=210, 好奇:友好=1680, 好奇:反击=1648, 保守:进攻=834, 保守:友好=1701, 保守:反击=1653}

到500轮运行结束时,所有类型的文明都存在,主动进攻的文明最惨,只存活了210个;被动进攻的文明第二惨,存活了834个;其他文明都和开始时没变,存在1700左右的数量。互助的文明胜出。
这称为互助文明,基本就是人类社会的现况吧。光靠自己根本就不能活下去,想要活下去必须靠别人的帮助。和别人交流知识,交易物品,互爱互助。这就是人类社会的准则吧。

六、总结
1、由上面我们可以看出根据不同的参数就会有不同的博弈方式。不管是黑暗森林、乌龟文明,还是互助文明,都是只需要满足一定条件就会成立的法则。坚持其中一个无疑是迂腐的。到底应该何时使用何种策略,具体看当时相互间的利害参数而定。

2、运行结果最出乎意料的是黑暗森林下,所有的文明都死的很快,就算是你看到什么文明就消灭什么文明,但对别的文明探索并消灭你的概率基本没影响。黑暗森林只是保证最后幸存的文明一定是主动进攻型的文明而已。

3、对费米悖论的解释。在人类还没有探索宇宙的时候,我们认为火星上面都是有文明存在的。但探索了以后才发现,原来宇宙里面文明存在概率那么低,低到到目前为止一个都没发现。
为什么宇宙中文明存在如此之少?目前想到的原因是文明的存在条件非常苛刻,所以只有地球上偶然有了文明。
但有没有人想过另外一种可能性:黑暗森林。如果我们附近有其他文明的话,地球就不存在了。这也是基于人择定理的一种推论。也是对费米悖论的一种合理的解释。

4、我们目前最可能存在于何种宇宙规则下的推测:
如果我们存在于互助文明中,宇宙中应该存在大量的文明,我们广播后应该早就被发现,或者干脆还没广播,我们就被其他文明访问了。这也是费米悖论。
如果我们存在于乌龟文明中,广播是最危险的,被保守的好战文明发现,我们就是个死。
如果我们存在于黑暗森林中,宇宙中几乎没有文明,而我们广播暴露自己的可能性就很小了。

事实上我们也正在宇宙中广播自己,并且我们还好好地活着,所以我们存在于黑暗森林的可能性非常大。

5、为什么程序会如此简单?你的模型是否过于简单?面对这样的问题我引用原作中的一句话来作为答复:
“星星都是一个个的点,宇宙中各个文明社会的复杂结构,其中的混沌和随机的因素,都被这样巨大的距离滤去了。那些文明在我们看来就是一个个拥有参数的点,这在数学上就比较容易处理了。”——《三体II 黑暗森林》

6、遗漏的条件。
原作中认为黑暗森林的存在条件是:
i、生存是文明的第一需要
ii、文明不断增长和扩张,但宇宙中的物质总量保持不变
iii、技术爆炸
iv、猜疑链

为什么我的程序中只考虑了第一点。因为我觉得黑暗森林只需要第一点就能实现了。把其他因素考虑进去也能实现黑暗森林,不考虑也能实现黑暗森林的话,按剃刀原理就去除了。
另外猜疑链不是一种实现,而是一个概念,它只代表你无法在事先确认别人的行动而已。其实日常生活中一样存在猜疑链,我们的思维全都自动简化了,所以你没感觉而已。

点评 引用回复 点赞(1)

吴颜 发表于 2015-4-8 15:53:45

板凳

看过小说《三体》的人应该对黑暗森林这个概念不会陌生,它讲的是在宇宙中文明如果想存活下来,必须对遇到的任何文明发动攻击,并认为这是宇宙的唯一准则。

这个理论争论很大。支持的人认为能想出来黑暗森林实在是太伟大了。反对的人认为这不过是科幻小说家的胡思乱想罢了。
我认为两者都不对,黑暗森林不过是博弈的一般性推论之一而已。它即切实存在,也不是唯一的存在。

为了说明这一点,我将用程序来模拟实际的情况。

一、文明的外交策略
1、进攻的文明,战争解决一切(attack)
2、友好的文明,提倡互相帮助(friend)
3、以牙还牙的文明,遇到进攻则反击,遇到帮助则互助(revenge)

二、文明的探索策略
1、保守的文明,被动等待其他星球的文明来联系(passive)
2、好奇的文明,主动访问其他文明(active)

三、规则
每个文明初始都是1000000点文明值,当受到攻击时,文明倒退,文明值减少;当受到其他文明帮助时,文明加速进步,文明值增加。当文明值减少到0时,文明消失。

四、参数
文明会随时间发展,每经过一轮,文明会增长d%。

高文明对低文明有高攻击力,好像拿着长矛的军队无论无何也打不过拿着枪的军队。
高文明对低文明也有更多的帮助,发达国家对落后国家不仅有金钱的投资还会带动他们的科技发展。
所以设定:
对其他文明的攻击力 = 自身文明 * a%
对其他文明的帮助力 = 自身文明 * h%
由于文明会随时间按百分比成长,所以这样的简单设定,低文明对高文明影响的百分比会比较小,和上面的要求一致。


五、猜想
当文明间攻击力a相对比较高的时候,进攻的文明更有优势,黑暗森林成立。当文明间帮助力h相对比较高的时候,互助的文明更有优势。当文明增长d相对比较高时,保守的文明更有优势。

六、程序运行
1、由于按百分比的成长是非常快速的。单纯考虑发展时,当将发展参数d设为1%,经过2074轮文明值会超出计算机可正常运算的范围。d设为7%,仅经过305轮文明值会超过计算机的正常运算范围。
考虑到文明还有互相帮助增加发展速度,为了程序能稳定运行500轮左右,将d和h都设为1%。

2、文明的负面效应都是大于正面效应。比如有了刀以后,可能打猎方便了,但刀也能轻易把人杀死。有了核能以后,靠核电站能提供一些电能,但核武器已经足够把地球毁灭多少次了。
所以进攻参数a我设为150%,因为每个文明都拥有足以摧毁自己的力量。

运行结果如下:(参数:a=150, d=1, h=1)
第0轮:{active:attack=1659, active:friend=1604, active:revenge=1643, passive:attack=1681, passive:friend=1668, passive:revenge=1688}
第50轮:{active:attack=831, active:friend=699, active:revenge=713, passive:attack=871, passive:friend=833, passive:revenge=867}
第100轮:{active:attack=328, active:friend=245, active:revenge=245, passive:attack=352, passive:friend=301, passive:revenge=344}
第150轮:{active:attack=50, active:friend=22, active:revenge=17, passive:attack=49, passive:friend=43, passive:revenge=44}
仅存一个文明,第175轮:{active:attack=1}

开始时,基本每种类型的文明都会随机到一千七左右的数量:(请参考最开始说的三种外交策略和两种探索策略,排列组合后一共有6种类型的文明)
运行一段时间后,各类文明都均匀地减少,到175轮时,只剩下一个主动进攻的文明。
这就是黑暗森林的结果,文明只能存在一个。主动进攻的文明未必能比别人活得久,但不主动进攻的文明生存的可能性是0。

3、如果攻击力减少,受到攻击的文明不被一轮秒杀,就能有机会反击了。黑暗森林应该就不成立了。
将攻击参数a由150%降低到100%,运行结果如下:(参数:a=100, d=1, h=1)
第0轮:{active:attack=1675, active:friend=1631, active:revenge=1620, passive:attack=1702, passive:friend=1642, passive:revenge=1637}
第50轮:{active:attack=847, active:friend=777, active:revenge=772, passive:attack=1034, passive:friend=1081, passive:revenge=1063}
第100轮:{active:attack=286, active:friend=280, active:revenge=244, passive:attack=536, passive:friend=616, passive:revenge=621}
第150轮:{active:attack=31, active:friend=31, active:revenge=18, passive:attack=197, passive:friend=248, passive:revenge=264}
第200轮:{active:attack=2, passive:attack=111, passive:friend=115, passive:revenge=126}
主动的文明全灭,第201轮:{passive:attack=111, passive:friend=115, passive:revenge=126}

果然,有机会反击后,主动探索宇宙的文明锐减,最后全部消失。只剩下安于在自己星球的文明生存下来。此时黑暗森林法则不成立。安于在自己星球生存的文明更容易存活的情况,我们暂且称之为乌龟文明。记得霍金就警告过人们不要随便探索宇宙寻找其他文明,看来他是比较同意这种看法的。

4、自身发展d减少,文明主要靠互相帮助来进行进化时(闭关锁国的发展一定是很慢的,所以推测闭星锁球的文明发展也比较慢)
进攻参数a调为1%,发展参数d调为0%,帮助参数h仍为1%,运行结果如下:(参数:a=1, d=0, h=1)
第0轮:{active:attack=1669, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第50轮:{active:attack=1669, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第100轮:{active:attack=1669, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第150轮:{active:attack=1643, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第200轮:{active:attack=1440, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第250轮:{active:attack=1192, active:friend=1680, active:revenge=1648, passive:attack=1649, passive:friend=1701, passive:revenge=1653}
第300轮:{active:attack=919, active:friend=1680, active:revenge=1648, passive:attack=1638, passive:friend=1701, passive:revenge=1653}
第350轮:{active:attack=675, active:friend=1680, active:revenge=1648, passive:attack=1559, passive:friend=1701, passive:revenge=1653}
第400轮:{active:attack=486, active:friend=1680, active:revenge=1648, passive:attack=1370, passive:friend=1701, passive:revenge=1653}
第450轮:{active:attack=327, active:friend=1680, active:revenge=1648, passive:attack=1086, passive:friend=1701, passive:revenge=1653}
第500轮:{active:attack=210, active:friend=1680, active:revenge=1648, passive:attack=834, passive:friend=1701, passive:revenge=1653}

到500轮运行结束时,所有类型的文明都存在,主动进攻的文明最惨,只存活了210个;被动进攻的文明第二惨,存活了834个;其他文明都和开始时没变,存在1700左右的数量。互助的文明胜出。
这称为互助文明,基本就是人类社会的现况吧。光靠自己根本就不能活下去,想要活下去必须靠别人的帮助。和别人交流知识,交易物品,互爱互助。这就是人类社会的准则吧。

点评 引用回复 点赞(1)

O5-13 发表于 2015-4-8 19:14:32

5#

啊哈,这玩意我写过

点评 引用回复 点赞(0)

冰蓝寂静 发表于 2015-4-10 17:05:57

6#

这是用数学模型求证黑暗森林的存在啊。可惜俺是文科生,这么长的推理过程,已经让我的脑细胞死亡大半,我该去吃药了,否则我的智商大概会回到原始人时代。

点评 引用回复 点赞(0)

中微子说 发表于 2015-6-8 13:13:25

7#

这程序貌似有问题啊,我执行不了

点评 引用回复 点赞(0)

不在乎 发表于 2015-6-8 17:45:47

8#

首先对于定量分析的同志表示敬仰。
其次对于四个前提条件:
i、生存是文明的第一需要
ii、文明不断增长和扩张,但宇宙中的物质总量保持不变
iii、技术爆炸
iv、猜疑链
个人觉得:
第一条是说文明要么主动攻击要么被动攻击,为了生存,不存在被动防御到死的文明
第二条可以考虑设定一个宇宙文明值的上限,到达上限后,强制将低于某一个文明值的文明清除掉
第三条应考虑一定概率给某个文明200%甚至更高的文明值增加机会
第四条应该体现在文明的分类中,所谓以牙还牙的文明其实是博弈论中的说法,而根据猜疑链,我觉得其实只存在两种文明,主动攻击的和被动攻击的,两两配对时,只有两个被动攻击的文明才可能建立帮助,而两个主动攻击文明或者主动攻击文明对被动攻击文明,都会形成攻击行为,也就是说接触中仅四分之一会形成帮助的结果

点评 引用回复 点赞(1)

安尘 发表于 2015-6-26 23:31:05

9#

没时间全部看完,不过很棒!

点评 引用回复 点赞(0)

提示:close

 

已赞!

 

提示:close

 

已关注!

 

您需要登录后才可以回帖 登录 | 立即注册

关注我们新浪微博微信 3

  

沪ICP备14049458号    网站地图

Powered by Discuz! X3.2@2001-2013, Comsenz Inc 版权信息

更多友情链接

钛度社区 3G小说网 磨铁中文网 创世中文网 网易原创 起点中文网 潇湘书院 红袖添香 小说阅读网
科幻世界 书海小说网 纵横中文网 科幻星云网

快速回复 返回顶部 返回列表
close