我正在构建一个脚本,用于计算一起繁殖的动物的遗传。每只动物都有一组基因(例如BbEeKk),程序应该计算后代的所有遗传可能性。但我不知道如何对字母进行方程式,因为整个解决方案只使用字母来处理乘法多项式。到目前为止,脚本是用PHP编写的。但是如果PHP无法处理这种类型的等式,它可以很容易地转移到另一个等式。
这是一个如何(在纸面上)你会找到BbEEKk和bbeeKk之间交叉的后代的例子:
// First we take the individual gene pairs and multiply them together
(B + b)(b + b) = 2Bb + 2bb
(E + E)(e + e) = 4Ee
(K + k)(K + k) = 1KK + 2Kk + 1kk
// Take those and form a polynomial
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
// Multiply first two expressions
(6BbEe + 6bbEe)(1KK + 2Kk + 1kk)
// Multiply remaining two expressions
(6BbEeKK + 12BbEeKk + 6BbEekk + 6bbEeKK + 12bbEeKk + 6bbEekk)
提取我们得到的最终值:
12/64 (18.75%) offspring as BbEeKk
12/64 (18.75%) offspring as bbEeKk
6/64 (9.375%) offspring as BbEeKK
6/64 (9.375%) offspring as BbEekk
6/64 (9.375%) offspring as bbEeKK
6/64 (9.375%) offspring as bbEekk
我似乎无法为PHP找到一种处理此类操作的方法,而且我不熟悉JavaScript以了解它是否可以。
答案 0 :(得分:3)
有趣:)
让数学与编程相结合。
首先,我认为你在例子中犯了一个错误,应该是
// First we take the individual gene pairs and multiply them together
(B + b)(b + b) = 2Bb + 2bb
(E + E)(e + e) = 4Ee
(K + k)(K + k) = 1KK + 2Kk + 1kk
// Take those and form a polynomial
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
// Multiply first two expressions
(8BbEe + 8bbEe)(1KK + 2Kk + 1kk)
// Multiply remaining two expressions
(8BbEeKK + 16BbEeKk + 8BbEekk + 8bbEeKK + 16bbEeKk + 8bbEekk)
这样,所有可能的弹簧总和为100%
这可以通过应用矩阵计算轻松解决,
第一步是将基因视为数字
bb ==> 0
bB ==> Bb ==> 1
BB ==> 2
任何字母都相同。
一旦你有以下等式:
(2Bb + 2bb)(4Ee)(1KK + 2Kk + 1kk)
您可以将其翻译为矩阵操作:
[2 2 0] * [0 4 0] * [1 2 1]
考虑对矩阵进行转置以进行尺寸匹配。结果矩阵将为您提供总和为64的数字。
答案 1 :(得分:2)
因此,如果我理解正确,那么首先我们必须分开" BbEEKk"进入" Bb"," EE",Kk",和" bbeeKk"相同。
之后,我们应该有" Bb"和" bb"。
我用这个摆弄了一点,我认为如果你把它们分开来解决第一部分,就像我写的一样:
function test($a,$b){
if ($a[0] == $a[1]) {
if ($b[0] == $b[1]) {
return "4" . $a[0] . $b[0];
}
return "2" . $b[0] . $a[0] . "+2" . $a[0] . $a[0];
} elseif ($b[0] == $b[1]) {
if ($a[0] == $a[1]) {
return "4" . $b[0] . $a[0];
}
return "2" . $a[0] . $b[0] . "+2" . $b[0] . $b[0];
} elseif ($a[0] != $a[1]) {
return "1" . $a[0] . $a[0] . "+2" . $a . "+1" . $a[1] . $a[1];
}
}
应该可以像我在这里做的那样做其他步骤。
答案 2 :(得分:0)
一种解决方案(它是一种“蛮力”解决方案而不是很漂亮):
<?php
$seqs = ["BbEEKk", "bbeeKk"];
// chunk them to parts of 2 chars
$seqs = array_map(function($el) {return str_split($el,2);}, $seqs);
echo "<pre>".print_r($seqs,true)."</pre>";
// cross the two sequence strings:
$step1 = [];
for($i=0;$i<count($seqs[0]);$i++)
$step1[] = multiplySequences([$seqs[0][$i], $seqs[1][$i]]);
echo "<pre>".print_r($step1,true)."</pre>";
// now multiply the result and sort them:
$step2 = multiplySequences($step1);
usort($step2, function($a, $b) {
return $b[0]-$a[0];
});
echo "<pre>".print_r($step2,true)."</pre>";
// takes an array of sequenzes. a sequenze is an array of sequenzeparts. a sequenzepart is an array [0=>number, 1=>the sequenz as chars]
function multiplySequences($seqs) {
foreach($seqs as &$seq)
multiplySequencesPrepare($seq);
// multiply them all:
$t = $seqs[0];
for($i=1;$i<count($seqs);$i++) {
$t = multiplySequencesHelper($t, $seqs[$i]);
$t = multiplySequencesPrepare($t);
}
return $t;
}
// prepare the data to process them. it defines the format from above: input can be a string "2Bb" or an array. if it's an array there are to possibilities: 1) [0=>number, 1=>sequence] or [[0=>number, 1=>sequence],[0=>number, 1=>sequence],...]
function multiplySequencesPrepare(&$seq) {
if(is_array($seq))
$seq = array_map(function($s) { if(is_array($s)) return $s; preg_match('/(\d*)(\w+)/', $s, $s); $s[1]=(int)$s[1]==0?1:(int)$s[1]; return array_slice($s,1);}, $seq);
else
$seq = call_user_func(function($s) {
preg_match('/(\d*)(\w+)/', $s, $s);
$s[2] = str_split($s[2]);
$s[1]=(int)$s[1]==0?1:(int)$s[1];
return array_map(function($sp) use($s) { return [$s[1], $sp]; }, $s[2]);
}, $seq);
return $seq;
}
// calculate the result of two sequences:
function multiplySequencesHelper($seq1, $seq2) {
$res = [];
$cnt = [];
foreach($seq1 as $s1)
foreach($seq2 as $s2) {
$c1 = $s1[1];
$c2 = $s2[1];
$res[] = $tcc = ($c1<$c2?$c1.$c2:$c2.$c1);
$cnt[$tcc] = $s1[0]*$s2[0];
}
$tmp = array_count_values($res);
return array_map(function($el) use($tmp,$cnt) { return ($cnt[$el]*$tmp[$el]).$el; }, array_unique($res));
}
代码中的测试注释应该解释它。