Punnett Squares, Flowers and Bayesian Networks
Here’s a simple science puzzle from Brilliant.org that I am working on.
Punnett Squares, Flowers and Bayesian Networks
Here’s a simple science puzzle from Brilliant.org that I am working on.

P is a dominant trait for round petal while p is a recessive trait for long petal
The alleles correspond to these traits:

Dominant and recessive traits
We are given the following choices:

If you look carefully at the parental alleles you will know the tricky answer immediately!
To some extent, this is a trick question and only asks that you pay careful attention to the parental alleles. But we are here to learn more than just tricks!
Suppose you didn’t see the trick. You could instead work out how to model this with a Bayesian network, which is really very well adapted to modeling this kind of genotype problem.
Let’s first model a generic Punnett Square, the typical representation for showing how dominant and recessive traits cross over in simple Mendelian genetics.

https://en.wikipedia.org/wiki/Punnett_square
Below is a (small) typical generic Punnett square where B is the dominant allele and b is the recessive allele. The child is equally likely to inherit B or b from each parent, generating this genotype pattern. This is a micro-Punnett square:

Child genotype has 25% of being BB, 50% of being Bb, and 25% of being bb. Allele B is dominant in 75% of cases.
Once the genotype is in place, the revealed traits (the phenotype) become manifest.
Let’s do this more dynamically with a Bayesian network. Let’s start with a generic network with two parent nodes and a child node with their possible alleles as states.

The generic network with uniform probabilities across the board
This is the child node table to fill in to determine the probabilities of the child inheriting various possible genotypes:

We could fill the relevant % in the table manually
But you can also just enter a raw count as unnormalized and let Netica figure out the %. You can get the count by constructing a micro-punnett square (as above) for each line. The total must equal 4 (there are 4 squares), and this will be normalized and converted to % by Netica.
We derive the count this way: for example:

The count must always sum to 4
Let’s watch how this works in action:

The manual entry of the child’s possible genotype given the parent’s genotype.
This was tedious to do manually!
Netica normalizes and converts to %:

After normalization and converted to %
Once the table is filled in, we have this updated network. We will update the phenotype as well, where A is dominant, so AA and Aa yield A for the phenotype.

The updated child genotype and phenotype
But we want to generalize this process and write an equation for this task. I’ve become very fond of the select function in Netica to speed things up, so let’s use it. What do we need? I asked Claude:

We can accomplish this with state numbers for AA, Aa and aa

Our generic network before compiling equation to table but with state numbers 1, 0.5 and 0
It’s crucial to understand that these state numbers will function as probabilities that will be used in our equations:

This is the clue showing us how to build our CPT table
And now for the moment of truth: We accomplish this calculation with this equation. The select0 function acts like a “for” loop over the index numbers 0, 1, 2, but crucially uses the state numbers as probabilities in our formula above:
P (Child_genotype | Mother_genotype, Father_genotype) =
select0 (Child_genotype,
Mother_genotype * Father_genotype, // p1 * p2
Mother_genotype * (1 - Father_genotype) + // p1 (1 - p2) +
(1 - Mother_genotype) * Father_genotype , // (1 - p1) p2
( 1 - Mother_genotype) * (1 - Father_genotype) ) // (1 - p1)(1 - p2)
Once we compile the equation into a table, we get this updated table:

This is identical to our manually entered table
And we get this updated network:

This reproduces the result we did manually above
Notice that we left the priors for the parental genotypes as uniform distributions. But we don’t need to. We can change them to standard values:

we have updated the parental priors for their phenotype but it makes no difference!
We are now ready to tackle our original problem, which we started with. The network structure is the same as above, except that we have four genotypes to worry about, one for each flower trait. (I have specially arranged the nodes!) The outer layer are the parent nodes and the inner layer (in teal) are the child nodes:

The network of parent node and child node for the flower puzzle
We don’t need to rehearse the equations needed since they are the same style as discussed above, but here they are anyway (four equations):
P(Color3 | Color1, Color2) =
select0(Color3,
Color1 * Color2,
Color1 * (1 - Color2) + (1 - Color1) * Color2,
(1 - Color1) * (1 - Color2)
)
P(Fragrance3 | Fragrance1, Fragrance2) =
select0(Fragrance3,
Fragrance1 * Fragrance2,
Fragrance1 * (1 - Fragrance2) + (1 - Fragrance1) * Fragrance2,
(1 - Fragrance1) * (1 - Fragrance2)
)
P (Petal3 | Petal1, Petal2) =
select0 (Petal3,
Petal1 * Petal2 ,
Petal1 * (1 - Petal2) +
(1 - Petal1) * Petal2 ,
( 1 - Petal1 ) * (1 - Petal2) )
P(Stem3 | Stem1, Stem2) =
select0(Stem3,
Stem1 * Stem2,
Stem1 * (1 - Stem2) + (1 - Stem1) * Stem2,
(1 - Stem1) * (1 - Stem2)
)
The equation needed for “no dominant” traits is simple. There will be no dominant traits if ALL the child node genotypes only have recessive alleles, pp, cc, ff, and ss.

No Dominant trait if and only ALL alleles are recessive
Once compiled, we have this updated network:

At 0.39% there is very little chance indeed. But we are not done!
Recall that we were given the Alleles for the parent genotypes: One has alleles Pp Cc FF ss, and the other has alleles Pp cc Ff Ss. So we need to enter that as observations in our network: Watch what happens and see exactly where the no_dominant node goes to zero:

Watch carefully for when no_dominant goes to zero
If you missed it, the blue node went to zero with the Fragrance1 node, which has alleles FF and cannot produce anything but a dominant trait!

The no_dominant trait goes to zero probability because of Fragrance1 node

Are not these brilliant flowers beautiful!
SOURCES & REFERENCES
Brilliantiums Are Lovely Flowers | Brilliant

메타데이터
- post_id
- b92ccd17a366
- slug
- punnett-squares-flowers-and-bayesian-networks-b92ccd17a366
- url
- https://medium.com/@pbercker/punnett-squares-flowers-and-bayesian-networks-b92ccd17a366
- canonical_url
- https://medium.com/@pbercker/punnett-squares-flowers-and-bayesian-networks-b92ccd17a366
- author_url
- https://medium.com/@pbercker
- status
- ok
- fetched_at
- 2026-06-09 15:37:30