基于合情推理的基因推测 一不涉及合情推理的基因推测高考生物都是不涉及合情推理的。也就是说都是把父辈的基因推出来然后再推子辈的基因。例如这一题现实生活中情况更复杂就需要合情推理了。二本文讨论范围1本文只讨论单基因的情况不讨论多组的情况2本文只讨论AA和Aa一定是正常的aa一定是遗传病的情况。3本文只讨论遗传病一定是一出生就知道了不考虑没观测到的情况。4本文只讨论非伴性遗传的情况。5本文只讨论每个人都有已知的唯一的亲生父母的情况不考虑基因编辑、克隆等各种技术。三合情推理基本假设如果医生已经推出了父亲是Aa母亲是AA或者Aa那即将出生的孩子的概率怎么算显然我们需要基于基因比例A和a的比例去做合理推算。但是更复杂的情况来了如果还有个已出生的孩子是AA或Aa那么母亲和这个孩子都要基于基因比例去推算然后又互相影响则会变得非常复杂。最复杂的点不在于计算复杂度而在于现实复杂度比如父辈和子辈的基因统计比例可能本来就不一样考虑到致死率、致弃婴导致的存活率、影响婚配等各种现实因素很可能每一代的比例就是不一样的。言归正传这些偏离了本文的主题所以我们做一个假设我们只能拿到一个常数x表示A的比例是xa的比例是1-x忽略各种现实因素。x的使用方法就是基于增广族谱的合情推理。四基于增广族谱的合情推理1拓扑排序一个有限的族谱S一定是有向无环图先做拓扑排序得到S的子集S1{r属于S | r的亲生父亲或亲生母亲都不在S中}2族谱增广基于S1进行增广对于S1中的每个可能是正常的个体可能是AA或Aa其父母若不在S中则设定成x/(2-x)的概率是AA(2-2x)/(2-x)的概率是Aa对于S1中的每个遗传病个体aa无需做增广。PS这里出现的2个常数已经是基于条件概率推导的结果。3全族谱合情推理只根据客观的已知信息和族谱增广的结果后续不再使用x推导出所有人的基因概率。这一步不能基于拓扑排序的结果进行按序处理因为涉及根据子辈的信息往父辈反推的场景。例如系谱分析中概率问题的贝叶斯分析一例代码残卷enum FinalType : int{ A, //AA Aa a, //aa U // unknown }; struct Person { int id; //每个人的编号0,1,2,3... bool flag; //是否在集合S中 int faId; //-1表示不在集合S中 int maId; //-1表示不在集合S中 FinalType type; }; //每个人是AA的概率 mapint, double solve(vectorPerson vp, float ratioA) { int id vp.size(); //增广族谱 for (int i id - 1; i 0; i--) { if (vp[i].type A) { if (vp[i].faId -1) { vp[i].faId id; vp.push_back(Person{ id,false,-1,-1,U }); } if (vp[i].maId -1) { vp[i].maId id; vp.push_back(Person{ id,false,-1,-1,U }); } } if (vp[i].type U) { if (vp[i].faId -1 vp[i].maId ! -1){ vp[i].faId id; vp.push_back(Person{ id,false,-1,-1,U }); } if (vp[i].faId ! -1 vp[i].maId -1) { vp[i].maId id; vp.push_back(Person{ id,false,-1,-1,U }); } } } mapint, double pAA; mapint, double pAa; } int main2() { vectorPersonvp{ Person{0,true,-1, - 1,A}, Person{1,true,-1,-1,A}, Person{2,true,0,1,a}, Person{3,true,0,1,A}, Person{4,true,-1,-1,a}, Person{5,true,3,4,A} }; float ratioA 0.99; return 0; }