在做《抽象代数的代码实现》这一专题时,我碰到数学概念难以用代码表达的问题,而这又很大程度上是由于数学上各种杂七杂八的存在性问题引起的,所以我想探究一下存在性问题到底是什么。在存在性问题解决之前先把这个专题暂停掉,因为以我现在的能力基本上挖掘不出什么东西,我需要先学习编译器,程序设计语言原理,范畴论等很多相关知识。

还是以最简单的存在性问题抽屉原理为例,把4个苹果放进3个抽屉,证明至少有一个抽屉里的苹果不少于2个。先来看一个最简单粗暴的方法,直接遍历所有的放法,这里使用递归,把这个程序记为A:

//程序A
int TraversalBox(int *aBox, int index,int nBox,int nApple)
{int i;int rc = 0;for(i=0;i<nBox;i++){if( index<nApple-1 ){aBox[i]++;rc = TraversalBox(aBox,index+1,nBox,nApple);aBox[i]--;if( rc ){break;}}else{aBox[i]++;     //所有苹果放完后,统计每个盒子里苹果的数量if( aBox[0]<2 && aBox[1]<2 && aBox[2]<2 ){rc = 1;break;}aBox[i]--;}}assert(!rc);return rc;
}
int PigeonholePrinciple(void)
{int nBox = 3;int nApple = 4;int aBox[3] = {0};int rc;//遍历4个苹果,每个苹果有3种放法rc = TraversalBox(aBox,0,nBox,nApple);return rc;
}

这里有一个问题,程序A所包含的信息就是描述需求的最小信息吗,如果不是,那么有没有一种描述需求的最小信息的语言,而且用这个语言编写需求的难度不会难于用文字表达,然后有一个需求解析器根据输入的需求信息生成程序A,示意图如下

事实上人用文字表达的需求信息是不完全的,很多信息都是人们的共识不需要表达,而这一部分信息在需求解析器中是不存在的,所以需要提前添加。想做一个通用的需求解析器的难度基本上已经约等于做一个通用人工智能(AGI)了,但是我的关注焦点不在这上面,这里顺便提一下。

再回来重新分析程序A,为了证明至少有一个抽屉里的苹果不少于2个,遍历后用了3^4=81次计算,当规模增大时,计算量将指数增大,甚至很多场景中的数量都是无穷的,不可能通过遍历所有情况来完成判断。显然人不是这么做的,直觉上是先挖掘一些既定的事实信息,通过这些信息再进行推理得到最后的结论。

比如我们可以在程序中添加assert来表达一些既定的事实,在每一次放完苹果后,所有盒子的苹果总数为4,出现满足条件的情形时,则每个盒子里的苹果数小于2,3个盒子里苹果总数小于4,这个程序记为B,代码如下

//程序B
int TraversalBox(int *aBox, int index,int nBox,int nApple)
{int i;int sum;int rc = 0;for(i=0;i<nBox;i++){if( index<nApple-1 ){aBox[i]++;rc = TraversalBox(aBox,index+1,nBox,nApple);aBox[i]--;if( rc ){break;}}else{aBox[i]++;sum = aBox[0]+aBox[1]+aBox[2];//新增代码assert( sum==4 );//苹果总数为4if( aBox[0]<2 && aBox[1]<2 && aBox[2]<2 ){//新增代码assert( aBox[0]<=1 );assert( aBox[1]<=1 );assert( aBox[2]<=1 );assert( sum == aBox[0]+aBox[1]+aBox[2] );assert( sum<4 );//苹果总数小于4rc = 1;break;}aBox[i]--;}}return rc;
}

看到上面的代码,在判断条件前我们已经断言了苹果总数为4,进入判断条件后,我们得出苹果总数小于4这个错误结论,也就是说明这个条件是进不去的。现在我们需要一个代码结构分析器对程序A的代码进行分析,进而挖掘出各种各样的断言。

这个东西也特别难做,代码的结构有千万种,对应各种不同的断言,你不知道哪些断言是最关键的,所以最后还需要人工添加,甚至需要先确定目标后再重新去寻找有用的断言。

其实我最关心的还是,在获得程序B的各种断言后,怎么进行推理,根据结合需求来优化程序效率,并给出相应的结论。在程序B中,if( aBox[0]<2 && aBox[1]<2 && aBox[2]<2 )这个条件是永远进不去的,因为里面的断言会和之前的断言产生矛盾,这样rc就不会置1,也就是说明不可能有每个抽屉的苹果个数都小于2的放法,从而在得出结论后直接跳出循环,本来要执行81次的代码现在就执行一次,最后产生的效果是一样的,程序记为C,代码如下

//程序C
int TraversalBox(int *aBox, int index,int nBox,int nApple)
{int i;int sum;int rc = 0;for(i=0;i<nBox;i++){if( index<nApple-1 ){aBox[i]++;rc = TraversalBox(aBox,index+1,nBox,nApple);aBox[i]--;//新增代码assert( !rc );break;}else{aBox[i]++;sum = aBox[0]+aBox[1]+aBox[2];assert( sum==4 );//苹果总数为4if( aBox[0]<2 && aBox[1]<2 && aBox[2]<2 ){assert( aBox[0]<=1 );assert( aBox[1]<=1 );assert( aBox[2]<=1 );assert( sum == aBox[0]+aBox[1]+aBox[2] );assert( sum<4 );//苹果总数小于4rc = 1;break;}else{//新增代码break;}aBox[i]--;}}//新增代码assert( !rc );return rc;
}

这个推理机的示意图如下,推理机甚至可以根据推理的进程让程序B生成更多的断言,有时候推理还需要和外界交互来提供更详细的需求信息

这个推理机的难度也是无比巨大,现在我要做的就是把研究的焦点放在推理机的一小部分功能上,假如程序B的断言都给你了,怎么推出有价值的结论,如上根据assert( sum==4 )和assert( sum<4 );利用反证法可推出assert( !rc ),这样事实上就得到了一个非常有说服力的对存在性的证明,这个问题我觉得结合数理逻辑的知识还是有希望解决的。

关于存在性问题的本质思考相关推荐

  1. 《本质思考 · 从底层思维构建解决问题的支点》读书笔记分享

    <本质思考 · 从底层思维构建解决问题的支点>这本书由日本庆应义塾大学研究生院教授.全球咨询巨头埃森哲原董事总经理--米泽创一所著,它聚焦人人都应规避的9大思考陷阱,教你更快.更深.更持久 ...

  2. [机缘参悟-89]:《本质思考》- 本质思考的7种习惯

    目录 一.精准性思考(精确:表面词语要精确) 二.非歧义思考(深度:明确表面词语背后的动机) 三.多维度思考(广度:全方面思考) 四.反馈式思考(确认:反复确认) 五.适应性思考(变化:因环境变化而变 ...

  3. Atitit 设计模式的本质思考】

    Atitit 设计模式的本质思考] 1. 世界就是有模式构建的1 1.1. 多次模式与偶然模式1 1.2. 模式就是在一种场合下对某个问题的一个解决方案."1 1.3. 模式需要三样东西.  ...

  4. php代码的健壮性,代码健壮性的几点思考 - 逍遥客 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

    自动化一直如火如荼的发展的,但同时,很多从业者在经历了最初的热情.激进之后,也会陷入了冷静的思考:那就是投入产出比问题,那就是自动化测试是否真的给测试工作带来了质的改变. 在诸多的引起思考,带来彷徨的 ...

  5. 业务和技术的本质思考

    业务技术定义 现在IT技术,基本都是需要和业务打交道,但是你真正理解业务.技术的本质吗?怎么利用各自的优势? 业务,是指某种有目的的工作或工作项目 技术,是指人类对机器.硬件或人造器皿的运用,也包含更 ...

  6. [机缘参悟-90]:《本质思考》- 本质思考的9个陷阱

    目录 01.思维惰性:少思考是大脑的本能 02.认知扭曲:心理防御机制的副作用 03.盲区:紧急状态下人的视野会收缩 04.局限:只基于自己掌控的范围寻找方案 05.孤立:忽视各个问题之间的关联 06 ...

  7. 当微信遇上众筹——颠覆性创业背后的思考

    春节前后,微信除了红包满天飞以外,我的朋友圈也被几条很有意思的文章反复刷屏,那是关于众筹与颠覆性创业的话题.我和几个创业圈的朋友边围观边思考,于是有了下面这些文字,更多是记录,列位看官请轻拍. 事件: ...

  8. c++对象回收string类型成员时coredump_本体技术视点 | 虚拟机中引用性动态语言对象模型思考...

    1 引言 Ontology 的 NeoVM 虚拟机新增加了 DCALL.HAS_KEY.KEYS 以及 VALUES 等几条新的指令.因此,基于 NeoVM 的引用性动态语言对象的设计理论上可行,这可 ...

  9. 成为架构师系列: 怎样画系统架构图? 背后的本质是对问题的本质思考

    开发人员必须钻研领域以获取业务知识.他们必须磨砺其建模技巧,并精通领域设计. Eric<Domain-Driven Design> 所谓的领域建模,是一种通过日常不断实践,来强化开发人员思 ...

最新文章

  1. 密钥生成并配置_基于密钥的SSH认证流程
  2. SQL Server 2008还原数据库时出现“备份集中的数据库备份与现有的数据库不同”的解决方法
  3. linux shell脚本中调用另一个shell脚本
  4. 47. Leetcode 107 - 二叉树的层次遍历 ii (二叉树-二叉树遍历)
  5. python中的类和对象
  6. 【云炬大学生创业基础笔记】第1章第2节测试
  7. 08-百度ai语音合成
  8. matlab仿真生成信号程序,信号与系统的MATLAB仿真
  9. 自己在UWP程序上调用usb转串口的路程
  10. r中如何求变量的对数转换_对数转换以求阳性。
  11. 如何查看服务器数据库修改密码,如何查看服务器数据库密码
  12. SQLServer 事务、锁、阻塞
  13. Hibernate-01-API及环境搭建
  14. 查看前端页面请求的文件地址_前端性能优化方法
  15. MatConvnet工具箱文档翻译理解五
  16. aria2最新tracker服务器,【无灯+Hiboy】padavan下自动更新aria2的BT tracker 服务器列表...
  17. Java设置excel单元格锁定状态
  18. 2021-01-16
  19. 单片机笔记(江科大自化协)
  20. ACM进阶大一到大三

热门文章

  1. LeetCode-Valid Palindrome
  2. 2023年最新,Win11+Tensorflow+CUDA部署,用显卡加速训练模型
  3. 现代语音信号处理-胡航(part 1 - 语音信号处理主要研究内容)
  4. 右键实现打开对应的软件
  5. idea设置中文版(详细)
  6. 各种软件开源协议是什么意思
  7. JavaScript 使用newArray()替换Uint8Array(),Uint16Array(),Uint64Array(),Float64Array()等方法
  8. nimble 2 蓝牙开发API
  9. 散列算法(也叫:摘要算法)
  10. css画三角形和箭头