<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>KissYagni</title><link href="/" rel="alternate"/><link href="/feeds/all.atom.xml" rel="self"/><id>/</id><updated>2025-09-23T18:30:00+02:00</updated><subtitle>Keep It Simple Stupid, You Aren't Gonna Need It !</subtitle><entry><title>Quantum Processing – Creating Quantum circuit with qiskit.</title><link href="/quantum-processing-creating-quantum-circuit-with-qiskit.html" rel="alternate"/><published>2025-09-23T18:30:00+02:00</published><updated>2025-09-23T18:30:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-09-23:/quantum-processing-creating-quantum-circuit-with-qiskit.html</id><summary type="html">&lt;p&gt;Computing is about writing code. Whether it is with punched cards, assembly, Python, or vibe coding using prompts for retards, we need a way to tell the computer which algorithm we want to execute.&lt;/p&gt;
&lt;p&gt;I'm currently experimenting with &lt;a href="https://www.ibm.com/quantum/qiskit"&gt;qiskit&lt;/a&gt;, the IBM Python library for quantum computing.
I don't know if …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Computing is about writing code. Whether it is with punched cards, assembly, Python, or vibe coding using prompts for retards, we need a way to tell the computer which algorithm we want to execute.&lt;/p&gt;
&lt;p&gt;I'm currently experimenting with &lt;a href="https://www.ibm.com/quantum/qiskit"&gt;qiskit&lt;/a&gt;, the IBM Python library for quantum computing.
I don't know if it is good or bad; I just took the first one I found.&lt;/p&gt;
&lt;h2 id="installing-qiskit"&gt;Installing qiskit&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;qiskit&lt;span class="w"&gt; &lt;/span&gt;qiskit-aer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="first-program"&gt;First program&lt;/h2&gt;
&lt;p&gt;I won't details the code. I will just gives z small snippet to show how it look like.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;qiskit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;q&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;qiskit_aer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;qaer&lt;/span&gt;

&lt;span class="c1"&gt;# Create a quantum circuit with 2 qbit register and 1 classical register&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add Hadamard gate on qbit 0&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add CNOT Gate between qbit 0 and qbit 1&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# measure qbit0 into classical register 1&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# print the circuit on console&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# creating a simulator to execute quantum circuit&lt;/span&gt;
&lt;span class="n"&gt;simulator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qaer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AerSimulator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;statevector&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simulator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# execute circuit 100 times&lt;/span&gt;
&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simulator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shots&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# print result of execution&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_counts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;     ┌───┐     ┌─┐
q_0: ┤ H ├──■──┤M├
     └───┘┌─┴─┐└╥┘
q_1: ─────┤ X ├─╫─
          └───┘ ║
c: 1/═══════════╩═
                0
{&amp;#39;0&amp;#39;: 57, &amp;#39;1&amp;#39;: 43}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;— What does the &lt;code&gt;{'0': 57, '1': 43}&lt;/code&gt; means ?&lt;/p&gt;
&lt;p&gt;Quantum algorithms are intrinsically stochastic. A QBit in superposition state can have 2 different values once measured. So to simulate a measure, we have to run the algorithm several times.
Here, we ask the simulator to execute the circuit 100 times. And the result contains the number of times QBit has been measured as "0" and "1". Here, one can see it has been measured 57 times at "0" and 43 times at "1". Giving approximately a 50% chance for both values, which correspond to a QBit that has been put in a superposition state by an Hadamard gate.&lt;/p&gt;
&lt;h1 id="bernstein-vazirani-algorithm"&gt;Bernstein-Vazirani Algorithm&lt;/h1&gt;
&lt;p&gt;BV Problem is another quantum problem that can be solve with quantum circuit. Lets assume we have &lt;span class="math"&gt;\(s\)&lt;/span&gt; a binary string and oracle function &lt;span class="math"&gt;\(f_s: \{0, 1\}^n \rightarrow \{0, 1\}\)&lt;/span&gt;, so that &lt;span class="math"&gt;\(f(x)\)&lt;/span&gt; is the dot product &lt;span class="math"&gt;\(x.s\)&lt;/span&gt; module 2: &lt;span class="math"&gt;\(f_s(x) = x_1.s_1 \oplus x_2.s_2 \oplus ... \oplus x_n.s_n\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ex: &lt;span class="math"&gt;\(n=4, s=0101\)&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f_s(0000) = mod_2(0 * 0 + 0 * 1 + 0 * 0 + 0 * 1) = 0\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f_s(0001) = mod_2(0 * 0 + 0 * 1 + 0 * 0 + 1 * 1) = 1\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f_s(0010) = mod_2(0 * 0 + 0 * 1 + 1 * 0 + 0 * 1) = 0\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f_s(0011) = mod_2(0 * 0 + 0 * 1 + 1 * 0 + 1 * 1) = 1\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal is to find &lt;span class="math"&gt;\(s\)&lt;/span&gt; by requesting &lt;span class="math"&gt;\(f\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;— What the actual fuck O_O ???&lt;/p&gt;
&lt;p&gt;Please, don't force me to find an example involving &lt;a href="/the-deutsch-algorithm.html#the-deutsch-problem"&gt;HR and genre parity in a company...&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyway, classical algorithm may look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Indeed,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(0001)=s_0\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(0010)=s_1\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(0100)=s_2\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(1000)=s_3\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It require &lt;span class="math"&gt;\(n\)&lt;/span&gt; evaluation of &lt;span class="math"&gt;\(f\)&lt;/span&gt; to find &lt;span class="math"&gt;\(s\)&lt;/span&gt;. Lets implement this in qiskit:&lt;/p&gt;
&lt;h2 id="bernstein-vazirani-classical-algorithm"&gt;Bernstein-Vazirani Classical Algorithm&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;qiskit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;q&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;qiskit_aer&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;qaer&lt;/span&gt;


&lt;span class="c1"&gt;# Build our secret function.&lt;/span&gt;
&lt;span class="c1"&gt;# this function return a quantum circuit that, given an input x of N Qbits, return f(x) in N+1 QBit&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# WARNING: 1st value will be on 1st qbit, which is printed on the 1st line when drawing the circuit,&lt;/span&gt;
    &lt;span class="c1"&gt;# but it the &amp;quot;least significant value&amp;quot;, so right, when result is printed&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;qc&lt;/span&gt;

&lt;span class="c1"&gt;# create a curcuit to aks a question to the oracle, and get the oracle answer&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_qubits&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Question should have &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; values.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create a cricuit with n qbit and 1 classical bit. As the Oracle answere only with 0 or 1.&lt;/span&gt;
    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Create the question&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Plug the oracle&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Measure oracle answer&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;qc&lt;/span&gt;


&lt;span class="c1"&gt;# Helper function to execute given circuit&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;simulator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qaer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AerSimulator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;statevector&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transpile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simulator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simulator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shots&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;


&lt;span class="n"&gt;oracle_circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;build_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;ask_oracle_circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;build_ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we execute the circuit, we end up with this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;     &lt;/span&gt;┌───┐&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌───┐&lt;span class="w"&gt;      &lt;/span&gt;░
q_0:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;├─░─┤&lt;span class="w"&gt; &lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;├──────░────
&lt;span class="w"&gt;     &lt;/span&gt;├───┤&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└───┘&lt;span class="w"&gt;      &lt;/span&gt;░
q_1:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;├─░───■────────░────
&lt;span class="w"&gt;     &lt;/span&gt;├───┤&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt;        &lt;/span&gt;░
q_2:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;├─░───┼────■───░────
&lt;span class="w"&gt;     &lt;/span&gt;└───┘&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌─┴─┐┌─┴─┐&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌─┐
q_3:&lt;span class="w"&gt; &lt;/span&gt;──────░─┤&lt;span class="w"&gt; &lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;├┤&lt;span class="w"&gt; &lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;├─░─┤M├
&lt;span class="w"&gt;           &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└───┘└───┘&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└╥┘
c:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;/══════════════════════╩═
&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the left, we prepare our inputs. As we ask for &lt;code&gt;[0, 0, 0]&lt;/code&gt;, the 3 qbits are let as is.
On the middle is the oracle circuit. This part is supposed to be unknown.
On the right, we measure the oracle answer in register 0.&lt;/p&gt;
&lt;p&gt;Let's execute this circuit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_counts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This means that all 100 executions return '0'. Which is expected because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f([0, 0, 0]) = 0\)&lt;/span&gt; whatever &lt;span class="math"&gt;\(f\)&lt;/span&gt; secret key..&lt;/li&gt;
&lt;li&gt;We didn't put any qbits into superposition. So result will always be the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let's implement the classical algorithm to find the secret key.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oracle_circuit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_qubits&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
    &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# build circuit corresponding to question.&lt;/span&gt;
    &lt;span class="n"&gt;ask_oracle_circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;build_ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# execute and print&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ask_oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_counts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So, secret key is &lt;code&gt;[0, 1, 1]&lt;/code&gt;, with 100% confidence. Cool, we built a classical algorithm and execute it on a quantum computer.&lt;/p&gt;
&lt;p&gt;— Could you remind me the prices of a quantum computer ?&lt;/p&gt;
&lt;p&gt;A lot. Now, let's write a quantum algorithm that require only 1 evaluation of &lt;span class="math"&gt;\(f\)&lt;/span&gt;.&lt;/p&gt;
&lt;h2 id="bernstein-vazirani-quantum-algorithm"&gt;Bernstein-Vazirani Quantum Algorithm&lt;/h2&gt;
&lt;p&gt;I won't do the math, just write the program and try to explain it. Let's add this function to our code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_find_hidden_string_circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_qubits&lt;/span&gt;

    &lt;span class="c1"&gt;# build a quantum circuit with n qbits and n-1 classical bits&lt;/span&gt;
    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Create the question&lt;/span&gt;

    &lt;span class="c1"&gt;# add H gate to each qbit, so they are in 0/1 superposition&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# add Z gate on the last one, because of reasons&lt;/span&gt;
    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Plug the oracle&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ================================================&lt;/span&gt;
    &lt;span class="c1"&gt;# Measure oracle answer&lt;/span&gt;

    &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;measure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;qc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And execute it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;find_circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;build_find_hidden_string_circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oracle_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;find_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;     &lt;/span&gt;┌───┐&lt;span class="w"&gt;      &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌───┐&lt;span class="w"&gt;      &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌───┐┌─┐
q_0:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├──────░─┤&lt;span class="w"&gt; &lt;/span&gt;I&lt;span class="w"&gt; &lt;/span&gt;├──────░─┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├┤M├──────
&lt;span class="w"&gt;     &lt;/span&gt;├───┤&lt;span class="w"&gt;      &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└───┘&lt;span class="w"&gt;      &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;├───┤└╥┘┌─┐
q_1:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├──────░───■────────░─┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├─╫─┤M├───
&lt;span class="w"&gt;     &lt;/span&gt;├───┤&lt;span class="w"&gt;      &lt;/span&gt;░&lt;span class="w"&gt;   &lt;/span&gt;│&lt;span class="w"&gt;        &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;├───┤&lt;span class="w"&gt; &lt;/span&gt;║&lt;span class="w"&gt; &lt;/span&gt;└╥┘┌─┐
q_2:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├──────░───┼────■───░─┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├─╫──╫─┤M├
&lt;span class="w"&gt;     &lt;/span&gt;├───┤┌───┐&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;┌─┴─┐┌─┴─┐&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;├───┤&lt;span class="w"&gt; &lt;/span&gt;║&lt;span class="w"&gt;  &lt;/span&gt;║&lt;span class="w"&gt; &lt;/span&gt;└╥┘
q_3:&lt;span class="w"&gt; &lt;/span&gt;┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├┤&lt;span class="w"&gt; &lt;/span&gt;Z&lt;span class="w"&gt; &lt;/span&gt;├─░─┤&lt;span class="w"&gt; &lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;├┤&lt;span class="w"&gt; &lt;/span&gt;X&lt;span class="w"&gt; &lt;/span&gt;├─░─┤&lt;span class="w"&gt; &lt;/span&gt;H&lt;span class="w"&gt; &lt;/span&gt;├─╫──╫──╫─
&lt;span class="w"&gt;     &lt;/span&gt;└───┘└───┘&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└───┘└───┘&lt;span class="w"&gt; &lt;/span&gt;░&lt;span class="w"&gt; &lt;/span&gt;└───┘&lt;span class="w"&gt; &lt;/span&gt;║&lt;span class="w"&gt;  &lt;/span&gt;║&lt;span class="w"&gt;  &lt;/span&gt;║
c:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;/════════════════════════════════╩══╩══╩═
&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The middle part is still the oracle function, which is unknown. But we built a slightly different question by putting all QBits in a superposition state.
It's like if we asked all possible values to Oracle in a single question.
Then, instead of measuring the Oracle answer, we first apply an H gate on each qbits and measure the &lt;span class="math"&gt;\(n\)&lt;/span&gt; first. Because of quantum entanglement, their values depend on the Oracle answer. So their values may be influenced by the last qbit.&lt;/p&gt;
&lt;p&gt;Let's execute this circuit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;find_circuit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_counts&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;110&amp;#39;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;— Ah, you fail! The secret key is &lt;code&gt;011&lt;/code&gt;, not &lt;code&gt;110&lt;/code&gt; !&lt;/p&gt;
&lt;p&gt;Sorry, but no. The first value of the key is stored in the 1st qbit, i.e., the least significant bit, which is on the right. &lt;code&gt;[0, 1, 1]&lt;/code&gt; will be output as &lt;code&gt;110&lt;/code&gt;. It's just a formatting issue, not an algorithm issue.&lt;/p&gt;
&lt;p&gt;— Mkay.... Another point. In the classical algorithm, you measured only the last QBit. Whereas in Quantum One, you measured &lt;span class="math"&gt;\(n\)&lt;/span&gt; Qbits. Of course it's more efficient; you're trying to scam me!!!&lt;/p&gt;
&lt;p&gt;Still no. In classical algorithms, I know the first &lt;span class="math"&gt;\(n\)&lt;/span&gt; qbits are input qbits. So it's useless to measure them. Remember the &lt;a href="/quantum-processing-the-controled-gates.html#conservation-of-quantum-information"&gt;previous article&lt;/a&gt;. Information cannot be lost, so any multi-qbit gate must return the whole input in one way or another. With a classical algorithm, you could measure the first &lt;span class="math"&gt;\(n\)&lt;/span&gt; qbits, but it won't give you any useful information, and you would still have to do a for loop with &lt;span class="math"&gt;\(n\)&lt;/span&gt; iterations to get the secret key.&lt;/p&gt;
&lt;p&gt;The conclusion is we have a quantum circuit that can find the secret key of an oracle in a single evaluation. In the next article, we will try to understand how this algorithm works.&lt;/p&gt;
&lt;h1 id="takeaways"&gt;Takeaways&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;qiskit is a Python library to build and simulate quantum circuits on its computer.&lt;/li&gt;
&lt;li&gt;To simulate a quantum computer, several runs might be required because of quantum superposition.&lt;/li&gt;
&lt;li&gt;You can use a quantum computer to execute classical algorithms. But it's not really efficient.&lt;/li&gt;
&lt;/ul&gt;
&lt;script type="text/javascript"&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="misc"/></entry><entry><title>The Deutsch algorithm.</title><link href="/the-deutsch-algorithm.html" rel="alternate"/><published>2025-09-10T18:12:00+02:00</published><updated>2025-09-10T18:12:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-09-10:/the-deutsch-algorithm.html</id><summary type="html">&lt;p&gt;I continue this journey in quantum computing with a completly useless, however fundamental, quantum algorithm: &lt;strong&gt;The Deutsch Algorithm&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;– Hurray, yet another theorical tool that I will never use...&lt;/p&gt;
&lt;p&gt;Remember the last time you have to use a Turing machine ? Right. But without Turing Machine, there won't be any of todays …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I continue this journey in quantum computing with a completly useless, however fundamental, quantum algorithm: &lt;strong&gt;The Deutsch Algorithm&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;– Hurray, yet another theorical tool that I will never use...&lt;/p&gt;
&lt;p&gt;Remember the last time you have to use a Turing machine ? Right. But without Turing Machine, there won't be any of todays modern language.&lt;/p&gt;
&lt;h1 id="the-query-model"&gt;The Query Model&lt;/h1&gt;
&lt;p&gt;Before talking about quantum algorithm, I have to talk about &lt;strong&gt;The Query Model&lt;/strong&gt;. In traditional computing, you have input data,
that goes through a processing, and are transformed into output data:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Classical process model. Process take input data and transform them to output data." src="/images/2025/processModel.png"&gt;&lt;/p&gt;
&lt;p&gt;With Query model, we have a black box, called an &lt;strong&gt;Oracle&lt;/strong&gt;. This Oracle know something. For example, the airspeed velocity of an unladen swallow.
But you cannot ask it directly "What is the airspeed velocity of an unladen swallow?". You can only ask closed question, like "Is it a European swallow?",
or "Is it 10m/s?". And by asking all the possible speed, you will find the information hidden in the oracle.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Query model. Input is an Oracle function. Process ask question to this Oracle until it find the good answer." src="/images/2025/queryModel.png"&gt;&lt;/p&gt;
&lt;p&gt;– Mmm... This look like bruteforce with extra steps.&lt;/p&gt;
&lt;p&gt;Yes it is. In classical computing, you will have to ask all the possible values. This specific problem could be optimized using a binary search. This lower the complexity from &lt;span class="math"&gt;\(O(n)\)&lt;/span&gt; to &lt;span class="math"&gt;\(O(log(n))\)&lt;/span&gt;. But in the end, you will still have to do several queries to the oracle.&lt;/p&gt;
&lt;p&gt;Let's formalize this. We have an Oracle function &lt;span class="math"&gt;\(f\)&lt;/span&gt;, taking a binary value and return a binary answer:&lt;/p&gt;
&lt;div class="math"&gt;$$
f: \{0, 1\}^n \rightarrow \{0, 1\}^m
$$&lt;/div&gt;
&lt;p&gt;For our swallow example, we can encode velocity in &lt;em&gt;uint8&lt;/em&gt; and the oracle return true or false (&lt;span class="math"&gt;\(1\)&lt;/span&gt; or &lt;span class="math"&gt;\(0\)&lt;/span&gt;):&lt;/p&gt;
&lt;div class="math"&gt;$$
f: [0, 255] \rightarrow \{0, 1\}
$$&lt;/div&gt;
&lt;p&gt;Search algorithm would be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;for i in [0, 255]:
   if f(i) == 1
      return i
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One can see this algorithm complexity is &lt;span class="math"&gt;\(O(N)\)&lt;/span&gt;. &lt;strong&gt;BUT&lt;/strong&gt;, there is a small subtility. We can consider it &lt;span class="math"&gt;\(O(2^n)\)&lt;/span&gt;, &lt;span class="math"&gt;\(n\)&lt;/span&gt; being the number of &lt;em&gt;bits&lt;/em&gt; used to represent the input. So it has an exponential complexity.&lt;/p&gt;
&lt;p&gt;– This makes this algorithm much more scary !&lt;/p&gt;
&lt;p&gt;Yes. But when talking about complexity in quantum comlputing, it refer to number of qbits used. To do the parallel with classical algorithm, it's better to compute complexity using number of input bits, and not number of input values.&lt;/p&gt;
&lt;p&gt;Now comes the interesting part. In Quantum Computing, as you can put qbits in superposition states, you can ask several questions at the same time, in a single query.&lt;/p&gt;
&lt;p&gt;Instead of asking &lt;span class="math"&gt;\(f(00000000)?\)&lt;/span&gt;, &lt;span class="math"&gt;\(f(00000001)?\)&lt;/span&gt;, &lt;span class="math"&gt;\(f(00000010)?\)&lt;/span&gt;, etc... Couldn't we ask &lt;span class="math"&gt;\(f(\left| \psi_0 \psi_1 \psi_2 \psi_3 \psi_4 \psi_5 \psi_6 \psi_7 \right&amp;gt;)\)&lt;/span&gt;
only once where the &lt;span class="math"&gt;\(\psi_i\)&lt;/span&gt; are all both &lt;span class="math"&gt;\(0\)&lt;/span&gt; and &lt;span class="math"&gt;\(1\)&lt;/span&gt; ?&lt;/p&gt;
&lt;p&gt;Well, let's try to answer this question.&lt;/p&gt;
&lt;h1 id="the-deutsch-problem"&gt;The Deutsch Problem&lt;/h1&gt;
&lt;p&gt;We'll try to find if the parity is well respected in a company. This company has only 2 employees, and we want to see if there is one man and one woman in this company.
This company, as every companies, is a black box. You can only ask to HR if a given employee is a man or a woman.&lt;/p&gt;
&lt;p&gt;– What the hell is this problem ?&lt;/p&gt;
&lt;p&gt;Don't blame me, I never found any practical example of Deutsch algorithm, so I'm doing my best !&lt;/p&gt;
&lt;p&gt;Anyway, the company is the &lt;span class="math"&gt;\(f\)&lt;/span&gt; function. There are only 2 employees, so we need one bit to encode the input. Let's take &lt;span class="math"&gt;\(0\)&lt;/span&gt; for first employee, &lt;span class="math"&gt;\(1\)&lt;/span&gt; for second one.
For a question, the answer has 2 possibilities: man or woman. So we also need a single bit for the answer. Let's take &lt;span class="math"&gt;\(0\)&lt;/span&gt; for man and &lt;span class="math"&gt;\(1\)&lt;/span&gt; for woman. We end up with the function:&lt;/p&gt;
&lt;div class="math"&gt;$$
f: \{0, 1\} \rightarrow \{0, 1\}
$$&lt;/div&gt;
&lt;p&gt;To know if the parity is respected, we have to ask the question "Is employee &lt;span class="math"&gt;\(x\)&lt;/span&gt; a man ?" twice. If we know employee &lt;span class="math"&gt;\(0\)&lt;/span&gt; is a man, maybe the second is a man, maybe a woman. In the end, there are 4 possible cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both employee are men:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
  f(x) = 0 \quad \forall x
  $$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Both employee are women:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
  f(x) = 1 \quad \forall x
  $$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Employee 0 is a man, and employee 1 is a woman:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
  f(x) = x \quad \forall x
  $$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Employee 0 is a woman, and employee 1 is a man:
  &lt;div class="math"&gt;$$
  f(x) = !x \quad \forall x
  $$&lt;/div&gt;
&lt;em&gt;NOT&lt;/em&gt; &lt;span class="math"&gt;\(x\)&lt;/span&gt; can be seens as &lt;span class="math"&gt;\(1\)&lt;/span&gt; &lt;em&gt;XOR&lt;/em&gt; &lt;span class="math"&gt;\(x\)&lt;/span&gt;, or &lt;span class="math"&gt;\(1 $\oplus\)&lt;/span&gt; x&lt;span class="math"&gt;\(, $\oplus\)&lt;/span&gt; being binary addition without carry.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="the-query-gate"&gt;The Query Gate&lt;/h1&gt;
&lt;p&gt;One can draw the Query gate of arbitray &lt;span class="math"&gt;\(f\)&lt;/span&gt; function like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Query gate of f. Gate takes inputs, and return f(x)" src="/images/2025/queryGate.png"&gt;&lt;/p&gt;
&lt;p&gt;But in quantum computing, this pose a problem. Remember ? Any quantum gate must be invertible (and even unitary). From the gate output, we must be able to find what was the input.&lt;/p&gt;
&lt;p&gt;No problem, let's plug the input to the output:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Unitary Query gate use to create a quantum query gate. Gate takes x and y as input, and return x and y + f(x) Gate takes inputs, and return f(x)" src="/images/2025/QqueryGate.png"&gt;&lt;/p&gt;
&lt;p&gt;– Wait, why do we need to &lt;span class="math"&gt;\(\oplus\)&lt;/span&gt; the output ? We already know what was the input with the &lt;span class="math"&gt;\(\left| x \right&amp;gt;\)&lt;/span&gt; ?&lt;/p&gt;
&lt;p&gt;Yes, but tranformation must also be Unitary (whatever this means...). And the &lt;span class="math"&gt;\(y \oplus\)&lt;/span&gt; makes it unitary for any function &lt;span class="math"&gt;\(f\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;For any function &lt;span class="math"&gt;\(f\)&lt;/span&gt; we can build a quantum gate to query &lt;span class="math"&gt;\(f\)&lt;/span&gt;.&lt;/p&gt;
&lt;h1 id="the-deutsch-algorithm"&gt;The Deutsch Algorithm&lt;/h1&gt;
&lt;p&gt;Ladies and gentlemen, this is &lt;strong&gt;The Deutsch Algorithm&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Quantum circuits corresponding to Deutsch algorithm." src="/images/2025/deutsch.png"&gt;&lt;/p&gt;
&lt;p&gt;Let's analyse it step by step.&lt;/p&gt;
&lt;h2 id="left-psi_0-right"&gt;&lt;span class="math"&gt;\(\left| \Psi_0 \right&amp;gt;\)&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Initial state.&lt;/p&gt;
&lt;div class="math"&gt;$$
\left| \Psi_0 \right&amp;gt; = \left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; = \left| 0 1 \right&amp;gt;
$$&lt;/div&gt;
&lt;h2 id="left-psi_1-right"&gt;&lt;span class="math"&gt;\(\left| \Psi_1 \right&amp;gt;\)&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;We put the system in superposition state using 2 &lt;a href="/quantum-processing-the-quantum-gates-single-qbit.html#hadamard"&gt;Hadamard gates&lt;/a&gt;:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left| \Psi_1 \right&amp;gt; = \left&amp;lt; H | 0 \right&amp;gt; \otimes \left&amp;lt; H | 1 \right&amp;gt; =
\frac{\left| 0 \right&amp;gt; + \left| 1 \right&amp;gt;}{\sqrt{2}} \otimes  \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}}
$$&lt;/div&gt;
&lt;p&gt;To really understand what is a superposition state, let write this a bit diferently:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left| \Psi_1 \right&amp;gt; =
\underbrace{\left[ \frac{1}{\sqrt{2}} \left| 0 \right&amp;gt; + \frac{1}{\sqrt{2}} \left| 1 \right&amp;gt; \right]}_{\left| \psi_1 \right&amp;gt;=\alpha \left| 0 \right&amp;gt; + \beta \left| 1 \right&amp;gt;}
\otimes
\underbrace{\left[ \frac{1}{\sqrt{2}} \left| 0 \right&amp;gt; - \frac{1}{\sqrt{2}} \left| 1 \right&amp;gt; \right]}_{\left| \psi_2 \right&amp;gt;=\alpha \left| 0 \right&amp;gt; + \beta \left| 1 \right&amp;gt;}
$$&lt;/div&gt;
&lt;p&gt;This mean the first qbit &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; can be &lt;span class="math"&gt;\(0\)&lt;/span&gt; or &lt;span class="math"&gt;\(1\)&lt;/span&gt;, with probablity &lt;span class="math"&gt;\(1/2\)&lt;/span&gt;. Same for second qbit &lt;span class="math"&gt;\(\left| \psi_2 \right&amp;gt;\)&lt;/span&gt;. (Probability is the square, so &lt;span class="math"&gt;\(-1/\sqrt{2}\)&lt;/span&gt; still gives probability of &lt;span class="math"&gt;\(1/2\)&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;If we develop this equation, we can also see things differently:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_1 \right&amp;gt;
&amp;amp;=
\left[ \frac{1}{\sqrt{2}} \left| 0 \right&amp;gt; + \frac{1}{\sqrt{2}} \left| 1 \right&amp;gt; \right]
\otimes
\left[ \frac{1}{\sqrt{2}} \left| 0 \right&amp;gt; - \frac{1}{\sqrt{2}} \left| 1 \right&amp;gt; \right]
\\
&amp;amp;=
\frac{1}{2} \left| 0 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\frac{1}{2} \left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; +
\frac{1}{2} \left| 1 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\frac{1}{2} \left| 1 \right&amp;gt; \otimes \left| 1 \right&amp;gt;
\\
&amp;amp;=
\frac{1}{2} \left| 00 \right&amp;gt; -
\frac{1}{2} \left| 01 \right&amp;gt; +
\frac{1}{2} \left| 10 \right&amp;gt; -
\frac{1}{2} \left| 11 \right&amp;gt;
\end{align}
$$&lt;/div&gt;
&lt;p&gt;&lt;span class="math"&gt;\(\left| \Psi_1 \right&amp;gt;\)&lt;/span&gt; is the superposition of states &lt;span class="math"&gt;\(\left| 00 \right&amp;gt;\)&lt;/span&gt;, &lt;span class="math"&gt;\(\left| 01 \right&amp;gt;\)&lt;/span&gt;, &lt;span class="math"&gt;\(\left| 10 \right&amp;gt;\)&lt;/span&gt;, &lt;span class="math"&gt;\(\left| 11 \right&amp;gt;\)&lt;/span&gt;, which is the canonical base of a 2 qbit system. Each states having a probability of &lt;span class="math"&gt;\(1/4\)&lt;/span&gt; to be measured !&lt;/p&gt;
&lt;h2 id="left-psi_2-right"&gt;&lt;span class="math"&gt;\(\left| \Psi_2 \right&amp;gt;\)&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Ok, things get serious. That's where I get I didn't understood anything to Quantum Processing and I decided to start this series of articles.&lt;/p&gt;
&lt;p&gt;We have to apply &lt;span class="math"&gt;\(U_f\)&lt;/span&gt; gate to &lt;span class="math"&gt;\(\left| \Psi_1 \right&amp;gt;\)&lt;/span&gt;. The good news is that &lt;span class="math"&gt;\(U_f\)&lt;/span&gt; is linear, like any quantum gate. So&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= U_f(\frac{1}{2} \left| 00 \right&amp;gt; - \frac{1}{2} \left| 01 \right&amp;gt; + \frac{1}{2} \left| 10 \right&amp;gt; - \frac{1}{2} \left| 11 \right&amp;gt;)
\\
&amp;amp;= \frac{1}{2} [U_f(\left| 00 \right&amp;gt;) - U_f(\left| 01 \right&amp;gt;) + U_f(\left| 10 \right&amp;gt;) - U_f(\left| 11 \right&amp;gt;)]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus f(\left| 0 \right&amp;gt;)) -
\left| 0 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus f(\left| 0 \right&amp;gt;)) +
\left| 1 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus f(\left| 1 \right&amp;gt;)) -
\left| 1 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus f(\left| 1 \right&amp;gt;))
]
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Remember, &lt;span class="math"&gt;\(U_f(\left| x y \right&amp;gt;) = U_f(\left| x \right&amp;gt; \otimes \left| y \right&amp;gt;) = \left| x \right&amp;gt; \otimes (\left| y \right&amp;gt; \oplus f(\left| x \right&amp;gt;))\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;There were 4 possibilities for &lt;span class="math"&gt;\(f\)&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(x) = 0 \quad \forall x\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) -
\left| 0 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) +
\left| 1 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) -
\left| 1 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 0 \right&amp;gt;)
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; +
\left| 1 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\left| 1 \right&amp;gt; \otimes \left| 1 \right&amp;gt;
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 0 \right&amp;gt; -
\left| 0 1 \right&amp;gt; +
\left| 1 0 \right&amp;gt; -
\left| 1 1 \right&amp;gt;
]
\end{align}
$$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(x) = 1 \quad \forall x\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) -
\left| 0 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) +
\left| 1 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) -
\left| 1 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 1 \right&amp;gt;)
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; -
\left| 0 \right&amp;gt; \otimes \left| 0 \right&amp;gt; +
\left| 1 \right&amp;gt; \otimes \left| 1 \right&amp;gt; -
\left| 1 \right&amp;gt; \otimes \left| 0 \right&amp;gt;
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 1 \right&amp;gt; -
\left| 0 0 \right&amp;gt; +
\left| 1 1 \right&amp;gt; -
\left| 1 0 \right&amp;gt;
]
\end{align}
$$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(x) = x \quad \forall x\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) -
\left| 0 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) +
\left| 1 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) -
\left| 1 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 1 \right&amp;gt;)
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; +
\left| 1 \right&amp;gt; \otimes \left| 1 \right&amp;gt; -
\left| 1 \right&amp;gt; \otimes \left| 0 \right&amp;gt;
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 0 \right&amp;gt; -
\left| 0 1 \right&amp;gt; +
\left| 1 1 \right&amp;gt; -
\left| 1 0 \right&amp;gt;
]
\end{align}
$$&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="math"&gt;\(f(x) = !x \quad \forall x\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) -
\left| 0 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 1 \right&amp;gt;) +
\left| 1 \right&amp;gt; \otimes (\left| 0 \right&amp;gt; \oplus \left| 0 \right&amp;gt;) -
\left| 1 \right&amp;gt; \otimes (\left| 1 \right&amp;gt; \oplus \left| 0 \right&amp;gt;)
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 \right&amp;gt; \otimes \left| 1 \right&amp;gt; -
\left| 0 \right&amp;gt; \otimes \left| 0 \right&amp;gt; +
\left| 1 \right&amp;gt; \otimes \left| 0 \right&amp;gt; -
\left| 1 \right&amp;gt; \otimes \left| 1 \right&amp;gt;
]
\\
&amp;amp;= \frac{1}{2} [
\left| 0 1 \right&amp;gt; -
\left| 0 0 \right&amp;gt; +
\left| 1 0 \right&amp;gt; -
\left| 1 1 \right&amp;gt;
]
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Lets compact this a bit:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
&amp;amp;f(x) = 0          &amp;amp; \Rightarrow \left| \Psi_2 \right&amp;gt;_{f=0} = \frac{1}{2} [\left| 0 0 \right&amp;gt; - \left| 0 1 \right&amp;gt; + \left| 1 0 \right&amp;gt; - \left| 1 1 \right&amp;gt;]
\\
&amp;amp;f(x) = 1          &amp;amp; \Rightarrow \left| \Psi_2 \right&amp;gt;_{f=1} = \frac{1}{2} [\left| 0 1 \right&amp;gt; - \left| 0 0 \right&amp;gt; + \left| 1 1 \right&amp;gt; - \left| 1 0 \right&amp;gt;]
\\
&amp;amp;f(x) = x          &amp;amp; \Rightarrow \left| \Psi_2 \right&amp;gt;_{f=x} = \frac{1}{2} [\left| 0 0 \right&amp;gt; - \left| 0 1 \right&amp;gt; + \left| 1 1 \right&amp;gt; - \left| 1 0 \right&amp;gt;]
\\
&amp;amp;f(x) = !x &amp;amp; \Rightarrow \left| \Psi_2 \right&amp;gt;_{f=!x} = \frac{1}{2} [\left| 0 1 \right&amp;gt; - \left| 0 0 \right&amp;gt; + \left| 1 0 \right&amp;gt; - \left| 1 1 \right&amp;gt;]
\end{align}
$$&lt;/div&gt;
&lt;p&gt;One notice 2 things. First:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left\{
\begin{align}
f(x)=0 \ or \ f(x)=1 \quad \Rightarrow f\ constant.
\\
f(x)=x \ or \ f(x)=!x \quad \Rightarrow f\ balanced.
\end{align}
\right.
$$&lt;/div&gt;
&lt;p&gt;Then:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left\{
\begin{align}
\left| \Psi_2 \right&amp;gt;_{f=0} = -\left| \Psi_2 \right&amp;gt;_{f=1}
\\
\left| \Psi_2 \right&amp;gt;_{f=x} = -\left| \Psi_2 \right&amp;gt;_{f=!x}
\end{align}
\right.
$$&lt;/div&gt;
&lt;p&gt;We end up with&lt;/p&gt;
&lt;div class="math"&gt;$$
\left\{
\begin{align}
\left| \Psi_2 \right&amp;gt; = \pm \frac{1}{2} [\left| 0 0 \right&amp;gt; - \left| 0 1 \right&amp;gt; + \left| 1 0 \right&amp;gt; - \left| 1 1 \right&amp;gt;] \quad \text{if f constant}
\\
\left| \Psi_2 \right&amp;gt; = \pm \frac{1}{2} [\left| 0 0 \right&amp;gt; - \left| 0 1 \right&amp;gt; + \left| 1 1 \right&amp;gt; - \left| 1 0 \right&amp;gt;] \quad \text{if f balanced}
\end{align}
\right.
$$&lt;/div&gt;
&lt;p&gt;Now, remember a propeties of qbits &lt;a href="/quantum-processing-an-introduction-to-qbit.html#the-bloch-sphere"&gt;we have seens previously&lt;/a&gt;. Multiplying a qubit by a phase &lt;span class="math"&gt;\(e^{i\theta}\)&lt;/span&gt; doesn't really matter, whatever &lt;span class="math"&gt;\(\theta\)&lt;/span&gt;. An multiplyin by &lt;span class="math"&gt;\(-1\)&lt;/span&gt; is multiplyin by a phase &lt;span class="math"&gt;\(\Pi\)&lt;/span&gt;. So we can get rid of the &lt;span class="math"&gt;\(\pm\)&lt;/span&gt;, and factorize into:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left\{
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [(\left| 0 \right&amp;gt; + \left| 1 \right&amp;gt;) \otimes (\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;)] \quad \text{if f constant}
\\
&amp;amp;= \frac{\left| 0 \right&amp;gt; + \left| 1 \right&amp;gt;}{\sqrt{2}} \otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}}
\\
\left| \Psi_2 \right&amp;gt;
&amp;amp;= \frac{1}{2} [(\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;) \otimes (\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;)] \quad \text{if f balanced}
\\
&amp;amp;= \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}} \otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}}
\end{align}
\right.
$$&lt;/div&gt;
&lt;p&gt;– Ohhhhh, it smell like Hadamard's gate here !&lt;/p&gt;
&lt;p&gt;Indeed. And we now reach the last step of our algorithm.&lt;/p&gt;
&lt;h2 id="left-psi_3-right"&gt;&lt;span class="math"&gt;\(\left| \Psi_3 \right&amp;gt;\)&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Pfew, we're nearly done. Hardest part is behind us. We just have to apply an Hadamard gate on the first qbit:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left\{
\begin{align}
\left| \Psi_2 \right&amp;gt;
&amp;amp;= H\left(\frac{\left| 0 \right&amp;gt; + \left| 1 \right&amp;gt;}{\sqrt{2}}\right) \otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}} \quad \text{if f constant}
\\
&amp;amp;= \left| 0 \right&amp;gt; \otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}}
\\
\left| \Psi_2 \right&amp;gt;
&amp;amp;= H\left(\frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}} \right)\otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}} \quad \text{if f balanced}
\\
&amp;amp;= \left| 1 \right&amp;gt; \otimes \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}}
\end{align}
\right.
$$&lt;/div&gt;
&lt;p&gt;And we just have to measure the 1st qbit. If &lt;span class="math"&gt;\(f\)&lt;/span&gt; is constant, its value will be &lt;span class="math"&gt;\(0\)&lt;/span&gt; with 100% probability. If &lt;span class="math"&gt;\(f\)&lt;/span&gt; is balanced, it will be &lt;span class="math"&gt;\(1\)&lt;/span&gt;. And we don't care about value of second qbit.&lt;/p&gt;
&lt;p&gt;In conclusion, wa can check if our companies has parity or not by asking a single question to HR.&lt;/p&gt;
&lt;h2 id="takeaways"&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Deutsch algorithm proves that Quantum algorithm can decrease the number of queries required to solve a problem.&lt;/li&gt;
&lt;li&gt;The &lt;span class="math"&gt;\(\oplus\)&lt;/span&gt; operator is use to create Quantum entanglement, when the value of a qbit depend on the value of another qbit.&lt;/li&gt;
&lt;li&gt;By using entanglement, we can use information of other qbits without having to measure them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the next article about &lt;a href="/quantum-processing-creating-quantum-circuit-with-qiskit.html"&gt;Quantum Processing with Qiskit&lt;/a&gt;.&lt;/p&gt;
&lt;script type="text/javascript"&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="misc"/></entry><entry><title>Quantum Processing – The Controled Gates.</title><link href="/quantum-processing-the-controled-gates.html" rel="alternate"/><published>2025-09-04T18:56:00+02:00</published><updated>2025-09-04T18:56:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-09-04:/quantum-processing-the-controled-gates.html</id><summary type="html">&lt;p&gt;We have seen &lt;a href="/quantum-processing-the-quantum-gates-single-qbit.html"&gt;before&lt;/a&gt; some quantum gates acting on a single qbit.
We will now see a family of qgates taking 2 qbits as input and returning 2 qbits: the &lt;strong&gt;Controlled gates&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;– Why does it return 2 qbits ? In classical logic, gates take 2 bits and return only 1 bit …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We have seen &lt;a href="/quantum-processing-the-quantum-gates-single-qbit.html"&gt;before&lt;/a&gt; some quantum gates acting on a single qbit.
We will now see a family of qgates taking 2 qbits as input and returning 2 qbits: the &lt;strong&gt;Controlled gates&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;– Why does it return 2 qbits ? In classical logic, gates take 2 bits and return only 1 bit.&lt;/p&gt;
&lt;p&gt;Ah, yes, that's a very good point. Let me open a parenthesis here.&lt;/p&gt;
&lt;h1 id="conservation-of-quantum-information"&gt;Conservation of quantum information&lt;/h1&gt;
&lt;p&gt;One of the fundamental principles in quantum mechanics is that information cannot disappear. Well, it is &lt;a href="https://en.wikipedia.org/wiki/No-hiding_theorem"&gt;much more complicated&lt;/a&gt;,
but that's the main idea. This implies that, when you use information to compute a result, you should be able to find back which information was used knowing only the result.
More formally, let's define a function &lt;span class="math"&gt;\(f: E -&amp;gt; F\)&lt;/span&gt; representing a quantum process acting on an information &lt;span class="math"&gt;\(x\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="math"&gt;$$
y = f(x)
$$&lt;/div&gt;
&lt;p&gt;To respect quantum mechanics, it means there exists a function &lt;span class="math"&gt;\(g\)&lt;/span&gt; that gives us the initial &lt;span class="math"&gt;\(x\)&lt;/span&gt; knowing the result &lt;span class="math"&gt;\(y\)&lt;/span&gt;:&lt;/p&gt;
&lt;div class="math"&gt;$$
x = g(y)
$$&lt;/div&gt;
&lt;p&gt;This means &lt;span class="math"&gt;\(f\)&lt;/span&gt; is bijective, or invertible, and &lt;span class="math"&gt;\(g = f^{-1}\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;– OK, but what about qgates ?&lt;/p&gt;
&lt;p&gt;As we saw in the previous article, a qgate can be represented by a matrix. That's also true for qgates acting on several qbits. To be invertible, a matrix must, among other things, be square.
So, input dimension = output dimension.&lt;/p&gt;
&lt;h1 id="representing-multiple-qbits"&gt;Representing multiple qbits&lt;/h1&gt;
&lt;p&gt;A single qbit &lt;span class="math"&gt;\(\left| \Psi \right&amp;gt;\)&lt;/span&gt; can be represented in the 2D base &lt;span class="math"&gt;\(\left| 0 \right&amp;gt;\)&lt;/span&gt; and &lt;span class="math"&gt;\(\left| 1 \right&amp;gt;\)&lt;/span&gt; by:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left| \Psi \right&amp;gt; = \alpha \left| 0 \right&amp;gt; + \beta \left| 1 \right&amp;gt; \quad a,b \in \mathbb{C}
$$&lt;/div&gt;
&lt;p&gt;&lt;span class="math"&gt;\(\alpha\)&lt;/span&gt; and &lt;span class="math"&gt;\(\beta\)&lt;/span&gt; are thus coordinates of &lt;span class="math"&gt;\(\Psi\)&lt;/span&gt; inside canonical base &lt;span class="math"&gt;\(\left| 0 \right&amp;gt;\)&lt;/span&gt; and &lt;span class="math"&gt;\(\left| 1 \right&amp;gt;\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The quantum state &lt;span class="math"&gt;\(\left| \Psi \right&amp;gt;\)&lt;/span&gt; corresponding to 2 qbit &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; and &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; can be represented using the tensor product (&lt;span class="math"&gt;\(\otimes\)&lt;/span&gt;):&lt;/p&gt;
&lt;div class="math"&gt;$$
\left| \Psi \right&amp;gt; = \left| \psi_1 \right&amp;gt; \otimes \left| \psi_2 \right&amp;gt; = \left| \psi_1 \psi_2 \right&amp;gt;
$$&lt;/div&gt;
&lt;p&gt;Let's decompose this.&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left| \psi_1 \right&amp;gt; \otimes \left| \psi_2 \right&amp;gt; &amp;amp;= (\alpha_1 \left| 0 \right&amp;gt; + \beta_1 \left| 1 \right&amp;gt;) \otimes (\alpha_2 \left| 0 \right&amp;gt; + \beta_2 \left| 1 \right&amp;gt;) \\
&amp;amp;= \alpha_1 \left| 0 \right&amp;gt; \otimes \alpha_2 \left| 0 \right&amp;gt; + \alpha_1 \left| 0 \right&amp;gt; \otimes \beta_2 \left| 1 \right&amp;gt; + \beta_1 \left| 1 \right&amp;gt; \otimes \alpha_2 \left| 0 \right&amp;gt; + \beta_1 \left| 1 \right&amp;gt; \otimes  \beta_2 \left| 1 \right&amp;gt; \\
&amp;amp;= \alpha_1 \alpha_2 \left| 00 \right&amp;gt; + \alpha_1 \beta_2 \left| 01 \right&amp;gt; + \beta_1 \alpha_2 \left| 10 \right&amp;gt; + \beta_1 \beta_2 \left| 11 \right&amp;gt; \\
\end{align}
$$&lt;/div&gt;
&lt;p&gt;If you don't feel fluent with tensor products, you might take a look at &lt;a href="/TheQuantumComputingCheatSheet.pdf"&gt;The Quantum Computing CheatSheet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We end up with the canonical base &lt;span class="math"&gt;\(\left| 00 \right&amp;gt;, \left| 01 \right&amp;gt;, \left| 10 \right&amp;gt;, \left| 10 \right&amp;gt;\)&lt;/span&gt;, and coordinates of &lt;span class="math"&gt;\(\left| \psi_1 \psi_2 \right&amp;gt;\)&lt;/span&gt; being
&lt;span class="math"&gt;\((\alpha_1 \alpha2, \alpha1 \beta_2, \beta_1 \alpha_2, \beta_1, \beta_2)\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left.
\begin{matrix}
\left| \psi_1 \right&amp;gt; = \alpha_1 \left| 0 \right&amp;gt; + \beta_1 \left| 1 \right&amp;gt; \\
\left| \psi_2 \right&amp;gt; = \alpha_2 \left| 0 \right&amp;gt; + \beta_2 \left| 1 \right&amp;gt;
\end{matrix}
\right\}
\quad
\Rightarrow
\quad
\left| \psi_1 \psi_2 \right&amp;gt; =
\begin{bmatrix}
\alpha_1 \alpha_2 \\
\alpha_1 \beta_2 \\
\beta_1 \alpha_2 \\
\beta_1 \beta_2 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;&lt;span class="math"&gt;\(\left| \Psi \right&amp;gt;\)&lt;/span&gt; is represented by 4 complex coordinates. So, a qgate acting on 2 qbits will be represented by a 4x4 matrix.&lt;/p&gt;
&lt;h1 id="controlled-gates"&gt;Controlled gates&lt;/h1&gt;
&lt;p&gt;Controlled gates are a family of gates acting on 2 qbits. One of the qbits acts as a "control" and is not modified by the gates, and the other one will be modified by the gate.
If the first qbit is &lt;span class="math"&gt;\( \left| 0 \right&amp;gt;\)&lt;/span&gt;, the gate is disabled and the second qubit remains unchanged. If the first qbit is &lt;span class="math"&gt;\( \left| 1 \right&amp;gt;\)&lt;/span&gt;, the gate is enabled and the second qbit is modified.&lt;/p&gt;
&lt;p&gt;Matrices of such gates are 4x4 block matrices that look like this:&lt;/p&gt;
&lt;div class="math"&gt;$$
g=
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; a &amp;amp; b \\
0 &amp;amp; 0 &amp;amp; c &amp;amp; d \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;The top left block is &lt;strong&gt;identity&lt;/strong&gt;, which won't change the control qbit, and the bottom right block is some single qbit gate operation called &lt;span class="math"&gt;\(U\)&lt;/span&gt;, with&lt;/p&gt;
&lt;div class="math"&gt;$$
U =
\begin{bmatrix}
a &amp;amp; b \\
c &amp;amp; d \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;div class="math"&gt;$$
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; a &amp;amp; b \\
0 &amp;amp; 0 &amp;amp; c &amp;amp; d \\
\end{bmatrix}
\begin{pmatrix}
x \\
y \\
z \\
w \\
\end{pmatrix}
=
\begin{pmatrix}
x \\
y \\
a z + b w \\
c z + d w \\
\end{pmatrix}
$$&lt;/div&gt;
&lt;p&gt;Let's prove this matrix implements a controlled gate.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;case &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt; = \left| 0 \right&amp;gt;\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\left| \psi_1 \right&amp;gt; = \left| 0 \right&amp;gt; \rightarrow \alpha_1 = 1, \beta_1 = 0 \rightarrow \left| \Psi \right&amp;gt; = \alpha_2 \left| 0 0 \right&amp;gt; + \beta_2 \left| 0 1 \right&amp;gt; =
\begin{bmatrix}
\alpha_2 \\
\beta_2 \\
0 \\
0 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;div class="math"&gt;$$
\left&amp;lt; G | \Psi \right&amp;gt; =
\begin{pmatrix}
\alpha_2 \\
\beta_2 \\
a * 0 + b * 0 \\
c * 0 + d * 0 \\
\end{pmatrix}
= \left| \Psi \right&amp;gt;
$$&lt;/div&gt;
&lt;p&gt;So &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; and &lt;span class="math"&gt;\(\left| \psi_2 \right&amp;gt;\)&lt;/span&gt; remaine unchanged.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;case &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt; = \left| 1 \right&amp;gt;\)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="math"&gt;$$
\left| \psi_1 \right&amp;gt; = \left| 1 \right&amp;gt; \rightarrow \alpha_1 = 0, \beta_1 = 1 \rightarrow \left| \Psi \right&amp;gt; = \alpha_2 \left| 1 0 \right&amp;gt; + \beta_2 \left| 1 1 \right&amp;gt; =
\begin{bmatrix}
0 \\
0 \\
\alpha_2 \\
\beta_2 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;div class="math"&gt;$$
\begin{align}
\left&amp;lt; G | \Psi \right&amp;gt; &amp;amp;=
\begin{pmatrix}
0 \\
0 \\
a*\alpha_2 + b*\beta*2 \\
c*\alpha*2 + d*\beta_2 \\
\end{pmatrix}
\\
&amp;amp;= (a*\alpha_2 + b * \beta_2) \left| 10 \right&amp;gt; + (c*\alpha_2 + d*\beta_2) \left| 11 \right&amp;gt; \\
&amp;amp;= \left| 1 \right&amp;gt; \otimes [(a*\alpha_2 + b*\beta_2)\left| 0 \right&amp;gt; + (c*\alpha_2 + d*\beta_2)\left| 1 \right&amp;gt;)] \\
&amp;amp;= \left| \psi_1 \right&amp;gt; \otimes \left&amp;lt; U | \psi_2 \right&amp;gt;
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Reminder: a quantum state &lt;span class="math"&gt;\(\left| \Psi \right&amp;gt;\)&lt;/span&gt; composed of &lt;span class="math"&gt;\(n\)&lt;/span&gt; qbits is &lt;span class="math"&gt;\(\left| \psi_0 \right&amp;gt; \otimes \left| \psi_1 \right&amp;gt; \otimes \left| \psi_2 \right&amp;gt; \otimes ... \left| \psi_n \right&amp;gt;\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; is unchanged and gate &lt;span class="math"&gt;\(U\)&lt;/span&gt; is applied to &lt;span class="math"&gt;\(\left| \psi_2 \right&amp;gt;\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;– Do I really need to understand all of this to create a quantum gate ?&lt;/p&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;p&gt;We'll see some classical controlled gates, based on the PauliX/Y/Z gate we have seen before.&lt;/p&gt;
&lt;h2 id="cnot-gate"&gt;CNOT Gate&lt;/h2&gt;
&lt;p&gt;&lt;img alt="CNOT gate icone." src="/images/2025/cnot_icone.png"&gt;&lt;/p&gt;
&lt;p&gt;This gate apply a NOT on the second qbit only when the first qbit is &lt;span class="math"&gt;\(\left| 1 \right&amp;gt;\)&lt;/span&gt;. It is sometime called &lt;strong&gt;CX&lt;/strong&gt; for &lt;strong&gt;Controleld PauliX&lt;/strong&gt;. Indeed, PauliX is &lt;strong&gt;NOT&lt;/strong&gt; gate for qbits.&lt;/p&gt;
&lt;div class="math"&gt;$$
CNOT =
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \\
0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;h2 id="controlled-y-gate"&gt;Controlled Y Gate&lt;/h2&gt;
&lt;p&gt;&lt;img alt="CY gate icone." src="/images/2025/cy_icone.png"&gt;&lt;/p&gt;
&lt;p&gt;This gate apply a NOT and a phase shift on the second qbit only when the first qbit is &lt;span class="math"&gt;\(\left| 1 \right&amp;gt;\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="math"&gt;$$
CY =
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; 0 &amp;amp; -i \\
0 &amp;amp; 0 &amp;amp; i &amp;amp; 0 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;h2 id="controlled-z-gate"&gt;Controlled Z Gate&lt;/h2&gt;
&lt;p&gt;&lt;img alt="CZ gate icone." src="/images/2025/cz_icone.png"&gt;&lt;/p&gt;
&lt;p&gt;or also:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Alternative CZ gate icone." src="/images/2025/cz1_icone.png"&gt;&lt;/p&gt;
&lt;p&gt;No, this gate do not Undo the last action. It apply a phase shift qbit only when the first qbit is &lt;span class="math"&gt;\(\left| 1 \right&amp;gt;\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="math"&gt;$$
CZ =
\begin{bmatrix}
1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0 \\
0 &amp;amp; 0 &amp;amp; 0 &amp;amp; -1 \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;h1 id="takeways"&gt;Takeways&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The quantum state &lt;span class="math"&gt;\(\left| \Psi \right&amp;gt;\)&lt;/span&gt; corresponding to 2 qbit &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; and &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt;\)&lt;/span&gt; is written &lt;span class="math"&gt;\(\left| \psi_1 \right&amp;gt; \otimes \left| \psi_2 \right&amp;gt;\)&lt;/span&gt; or &lt;span class="math"&gt;\(\left| \psi_1 \psi_2 \right&amp;gt;\)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Unlike classical logic gates, quantum gates must have the same number of input and ouput qbits, because operation must be invertible.&lt;/li&gt;
&lt;li&gt;For any single qbit gate, you can build the corresponding controlled gates using a block matrix.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the next article about &lt;a href="/the-deutsch-algorithm.html"&gt;The Deutsch Algorithm&lt;/a&gt;.&lt;/p&gt;
&lt;script type="text/javascript"&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="misc"/></entry><entry><title>Quantum Processing – The Quantum Gates: Single QBit.</title><link href="/quantum-processing-the-quantum-gates-single-qbit.html" rel="alternate"/><published>2025-07-10T18:56:00+02:00</published><updated>2025-07-10T18:56:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-07-10:/quantum-processing-the-quantum-gates-single-qbit.html</id><summary type="html">&lt;p&gt;Like the classical AND, OR, NOT, etc... gates for classical bit, there are
Quantum Gates for QBits. We will see some examples on Quantum gates acting on a single QBit.&lt;/p&gt;
&lt;h2 id="small-reminder-of-classical-gates"&gt;Small reminder of classical gates&lt;/h2&gt;
&lt;p&gt;A boolean gate is a gate taking one or several boolean values as input, and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Like the classical AND, OR, NOT, etc... gates for classical bit, there are
Quantum Gates for QBits. We will see some examples on Quantum gates acting on a single QBit.&lt;/p&gt;
&lt;h2 id="small-reminder-of-classical-gates"&gt;Small reminder of classical gates&lt;/h2&gt;
&lt;p&gt;A boolean gate is a gate taking one or several boolean values as input, and
return a boolean value.
For example, the &lt;strong&gt;NOT&lt;/strong&gt; gate return 0 if input is 1 and return 1 if input is 0.
Its Truth Table is as below:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In&lt;/th&gt;
&lt;th&gt;Out&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;strong&gt;AND&lt;/strong&gt; gate takes 2 input bits and return one value:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;In1&lt;/th&gt;
&lt;th&gt;In2&lt;/th&gt;
&lt;th&gt;Out&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="qbit-vector-representation"&gt;QBit Vector Representation&lt;/h2&gt;
&lt;p&gt;In &lt;a href="/quantum-processing-an-introduction-to-qbit.html"&gt;previous article&lt;/a&gt;, wa have seen that a qbit can be represented using Cartesian coordinates with &lt;span class="math"&gt;\(\left| \Psi \right&amp;gt; = \alpha \left| 0 \right&amp;gt; + \beta \left| 1 \right&amp;gt;\)&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/qbit1279725149916932464.png?w=512"&gt;&lt;/p&gt;
&lt;p&gt;and using the &lt;strong&gt;Bloch Sphere&lt;/strong&gt; and some spherical coordinates with &lt;span class="math"&gt;\( \left| \Psi \right&amp;gt; = cos(\frac{\theta}{2}) \left| 0 \right&amp;gt;+ sin(\frac{\theta}{2}) e^{i\phi} \left| 0 \right&amp;gt;\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Bloch Sphere" src="/images/2025/07/sphere7077807762601323878.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;A qbit can have an infinite number of values, we cannot represent it through a Truth Table. However, they can be represented as a matrix.&lt;/p&gt;
&lt;p&gt;There are an uncountable infinite number of quantum gates, but here are the most interesting one.&lt;/p&gt;
&lt;h3 id="identity"&gt;Identity&lt;/h3&gt;
&lt;div class="math"&gt;$$
\left&amp;lt; I | \Psi \right&amp;gt; = \left| \Psi \right&amp;gt;
$$&lt;/div&gt;
&lt;p&gt;Or, using matrix representation:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{bmatrix}
1 &amp;amp; 0 \\
0 &amp;amp; 1
\end{bmatrix}
\cdot
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
=
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;h3 id="pauli-x"&gt;Pauli X&lt;/h3&gt;
&lt;p&gt;Equivalent of &lt;strong&gt;NOT&lt;/strong&gt; gate, noted &lt;span class="math"&gt;\(\sigma_x\)&lt;/span&gt;:&lt;/p&gt;
&lt;div class="math"&gt;$$
\left&amp;lt; \sigma_x | 0 \right&amp;gt; = \left| 1 \right&amp;gt;
\\
\left&amp;lt; \sigma_x | 1 \right&amp;gt; = \left| 0 \right&amp;gt;
$$&lt;/div&gt;
&lt;p&gt;Using matrix representation:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{bmatrix}
0 &amp;amp; 1 \\
1 &amp;amp; 0
\end{bmatrix}
\cdot
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
=
\begin{bmatrix}
\beta \\
\alpha \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;&lt;img alt="PauliX Applied to Phi QBit using cartesian representation" src="/images/2025/pauliXCartesian.png"&gt;&lt;/p&gt;
&lt;p&gt;In Bloch Sphere:&lt;/p&gt;
&lt;p&gt;&lt;img alt="PauliX Applied to Phi QBit on the Bloch Sphere" src="/images/2025/pauliXBloch.png"&gt;&lt;/p&gt;
&lt;p&gt;It apply a &lt;strong&gt;180º rotation around X axis&lt;/strong&gt;, swap α and β probabilities and keep the same phase ϕ.&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\begin{bmatrix}
0 &amp;amp; 1 \\
1 &amp;amp; 0
\end{bmatrix}
\cdot
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
&amp;amp;=
\begin{bmatrix}
e^{i\phi} sin(\frac{\theta}{2}) \\
cos( \frac{\theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
e^{i\phi} cos(\frac{\theta}{2} + \frac{\pi}{2}) \\
sin(\frac{\theta}{2} + \frac{\pi}{2}) \\
\end{bmatrix}
\\
&amp;amp;\cong
\begin{bmatrix}
cos(\frac{\theta + \pi}{2}) \\
e^{-i\phi}sin( \frac{\theta + \pi}{2}) \\
\end{bmatrix}
\end{align}
$$&lt;/div&gt;
&lt;h3 id="pauli-y"&gt;Pauli Y&lt;/h3&gt;
&lt;p&gt;Noted &lt;span class="math"&gt;\(\sigma_y\)&lt;/span&gt;:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
&amp;amp;\left&amp;lt; \sigma_y | 0 \right&amp;gt; = i\left| 1 \right&amp;gt;
\\
&amp;amp;\left&amp;lt; \sigma_y | 1 \right&amp;gt; = -i\left| 0 \right&amp;gt;
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Using matrix representation:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{bmatrix}
0 &amp;amp; -i \\
i &amp;amp; 0
\end{bmatrix}
\cdot
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
=
\begin{bmatrix}
-i\beta \\
i\alpha \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;&lt;img alt="PauliY Applied to Phi QBit using cartesian representation" src="/images/2025/pauliYCartesian.png"&gt;&lt;/p&gt;
&lt;p&gt;In Bloch Sphere:&lt;/p&gt;
&lt;p&gt;&lt;img alt="PauliY Applied to Phi QBit on the Bloch Sphere" src="/images/2025/pauliYBloch.png"&gt;&lt;/p&gt;
&lt;p&gt;It apply a &lt;strong&gt;180º rotation around Y axis&lt;/strong&gt;, swap α and β probabilities and shift the phase ϕ.&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\begin{bmatrix}
0 &amp;amp; -i \\
i &amp;amp; 0
\end{bmatrix}
\cdot
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
&amp;amp;=
\begin{bmatrix}
-i \cdot e^{i\phi} sin(\frac{\theta}{2}) \\
i \cdot cos( \frac{\theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
e^{i\frac{-\pi}{2}}e^{i\phi} cos(\frac{\pi}{2} - \frac{\theta}{2}) \\
e^{i\frac{\pi}{2}}sin(\frac{\pi}{2} - \frac{\theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
e^{i (\phi - \frac{\pi}{2})}cos(\frac{\pi - \theta}{2}) \\
e^{i\frac{\pi}{2}}sin(\frac{\pi - \theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;\cong
\begin{bmatrix}
cos(\frac{\pi - \theta}{2}) \\
e^{i(\frac{\pi}{2} - (\phi - \frac{\pi}{2}))}sin(\frac{\pi - \theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
cos(\frac{\pi - \theta}{2}) \\
e^{i(\pi - \phi)}sin(\frac{\pi - \theta}{2}) \\
\end{bmatrix}
\end{align}
$$&lt;/div&gt;
&lt;h3 id="pauli-z"&gt;Pauli Z&lt;/h3&gt;
&lt;p&gt;Noted &lt;span class="math"&gt;\(\sigma_z\)&lt;/span&gt;:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
&amp;amp;\left&amp;lt; \sigma_z | 0 \right&amp;gt; = \left| 0 \right&amp;gt;
\\
&amp;amp;\left&amp;lt; \sigma_z | 1 \right&amp;gt; = -\left| 1 \right&amp;gt;
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Using matrix representation:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{bmatrix}
1 &amp;amp; 0 \\
0 &amp;amp; -1
\end{bmatrix}
\cdot
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
=
\begin{bmatrix}
\alpha \\
-\beta \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;&lt;img alt="PauliZ Applied to Phi QBit using cartesian representation" src="/images/2025/pauliZCartesian.png"&gt;&lt;/p&gt;
&lt;p&gt;In Bloch Sphere:&lt;/p&gt;
&lt;p&gt;&lt;img alt="PauliZ Applied to Phi QBit on the Bloch Sphere" src="/images/2025/pauliZBloch.png"&gt;&lt;/p&gt;
&lt;p&gt;It apply a &lt;strong&gt;180º rotation around Z axis&lt;/strong&gt;, keep α and β probabilities and flip the phase ϕ.&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\begin{bmatrix}
1 &amp;amp; 0 \\
0 &amp;amp; -1
\end{bmatrix}
\cdot
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
&amp;amp;=
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
-e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i\pi}e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
\\
&amp;amp;=
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i(\phi + \pi)} sin(\frac{\theta}{2}) \\
\end{bmatrix}
\end{align}
$$&lt;/div&gt;
&lt;h3 id="hadamard"&gt;Hadamard&lt;/h3&gt;
&lt;p&gt;Hadamard gate is used to create a superposition state given a basis state.&lt;/p&gt;
&lt;p&gt;Noted &lt;span class="math"&gt;\( H :\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
&amp;amp;\left&amp;lt; H | 0 \right&amp;gt; = \frac{\left| 0 \right&amp;gt; + \left| 1 \right&amp;gt;}{\sqrt{2}} = \left|+\right&amp;gt;
\\
&amp;amp;\left&amp;lt; H | 1 \right&amp;gt; = \frac{\left| 0 \right&amp;gt; - \left| 1 \right&amp;gt;}{\sqrt{2}} = \left|-\right&amp;gt;
\end{align}
$$&lt;/div&gt;
&lt;p&gt;Using matrix representation:&lt;/p&gt;
&lt;div class="math"&gt;$$
\frac{1}{\sqrt{2}}
\begin{bmatrix}
1 &amp;amp; 1 \\
1 &amp;amp; -1
\end{bmatrix}
\cdot
\begin{bmatrix}
\alpha \\
\beta \\
\end{bmatrix}
=
\frac{1}{\sqrt{2}}
\begin{bmatrix}
\alpha + \beta \\
\alpha - \beta \\
\end{bmatrix}
$$&lt;/div&gt;
&lt;p&gt;Let's note that:&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
&amp;amp;H = XY^{\frac{1}{2}} = R_x(\pi)R_y(\frac{\pi}{2})
\\
&amp;amp;H = Y^{-\frac{1}{2}}X = R_y(-\frac{\pi}{2})R_x(\pi)
\\
&amp;amp;H = Y^{\frac{1}{2}}Z = R_y(\frac{\pi}{2})R_z(\pi)
\\
&amp;amp;H = ZY^{-\frac{1}{2}} = R_z(\pi)R_y(-\frac{\pi}{2})
\\
&amp;amp;H = H^{-1}
\end{align}
$$&lt;/div&gt;
&lt;p&gt;In Bloch Sphere:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hadamard Applied to Phi QBit on the Bloch Sphere" src="/images/2025/HadamardBloch.png"&gt;&lt;/p&gt;
&lt;p&gt;It apply a &lt;strong&gt;90º rotation around the Y-axis, followed by a 180º rotation around the X-axis&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="math"&gt;$$
\begin{align}
\frac{1}{\sqrt{2}}
\begin{bmatrix}
1 &amp;amp; 1 \\
1 &amp;amp; -1
\end{bmatrix}
\cdot
\begin{bmatrix}
cos( \frac{\theta}{2}) \\
e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
&amp;amp;=
\begin{bmatrix}
cos( \frac{\theta}{2}) + e^{i\phi} sin(\frac{\theta}{2}) \\
cos( \frac{\theta}{2}) - e^{i\phi} sin(\frac{\theta}{2}) \\
\end{bmatrix}
\\
\end{align}
$$&lt;/div&gt;
&lt;h2 id="takeaways"&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Single Qbit Quantum gates change the orientation of QBit on the Bloch sphere. They act on &lt;span class="math"&gt;\(\alpha\)&lt;/span&gt; and &lt;span class="math"&gt;\(\beta\)&lt;/span&gt; probability (through acting on &lt;span class="math"&gt;\(\theta\)&lt;/span&gt; angle) and on phase &lt;span class="math"&gt;\(\phi\)&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;When there are only 2 logic gates that can act on a single bit (&lt;strong&gt;Identity&lt;/strong&gt; and &lt;strong&gt;NOT&lt;/strong&gt;), there is an infinite number of Quantum gates that can act on a single qbit.&lt;/li&gt;
&lt;li&gt;PauliX gate is the equivalent of &lt;strong&gt;NOT&lt;/strong&gt; gate.&lt;/li&gt;
&lt;li&gt;Hadamard gate is classically used to create superposition state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the next article about &lt;a href="/quantum-processing-the-controled-gates.html"&gt;Controlled Gates&lt;/a&gt;.&lt;/p&gt;
&lt;script type="text/javascript"&gt;if (!document.getElementById('mathjaxscript_pelican_#%@#$@#')) {
    var align = "center",
        indent = "0em",
        linebreak = "false";

    if (false) {
        align = (screen.width &lt; 768) ? "left" : align;
        indent = (screen.width &lt; 768) ? "0em" : indent;
        linebreak = (screen.width &lt; 768) ? 'true' : linebreak;
    }

    var mathjaxscript = document.createElement('script');
    mathjaxscript.id = 'mathjaxscript_pelican_#%@#$@#';
    mathjaxscript.type = 'text/javascript';
    mathjaxscript.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/latest.js?config=TeX-AMS-MML_HTMLorMML';

    var configscript = document.createElement('script');
    configscript.type = 'text/x-mathjax-config';
    configscript[(window.opera ? "innerHTML" : "text")] =
        "MathJax.Hub.Config({" +
        "    config: ['MMLorHTML.js']," +
        "    TeX: { extensions: ['AMSmath.js','AMSsymbols.js','noErrors.js','noUndefined.js'], equationNumbers: { autoNumber: 'none' } }," +
        "    jax: ['input/TeX','input/MathML','output/HTML-CSS']," +
        "    extensions: ['tex2jax.js','mml2jax.js','MathMenu.js','MathZoom.js']," +
        "    displayAlign: '"+ align +"'," +
        "    displayIndent: '"+ indent +"'," +
        "    showMathMenu: true," +
        "    messageStyle: 'normal'," +
        "    tex2jax: { " +
        "        inlineMath: [ ['\\\\(','\\\\)'] ], " +
        "        displayMath: [ ['$$','$$'] ]," +
        "        processEscapes: true," +
        "        preview: 'TeX'," +
        "    }, " +
        "    'HTML-CSS': { " +
        "        availableFonts: ['STIX', 'TeX']," +
        "        preferredFont: 'STIX'," +
        "        styles: { '.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn': {color: 'inherit ! important'} }," +
        "        linebreaks: { automatic: "+ linebreak +", width: '90% container' }," +
        "    }, " +
        "}); " +
        "if ('default' !== 'default') {" +
            "MathJax.Hub.Register.StartupHook('HTML-CSS Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax['HTML-CSS'].FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
            "MathJax.Hub.Register.StartupHook('SVG Jax Ready',function () {" +
                "var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;" +
                "VARIANT['normal'].fonts.unshift('MathJax_default');" +
                "VARIANT['bold'].fonts.unshift('MathJax_default-bold');" +
                "VARIANT['italic'].fonts.unshift('MathJax_default-italic');" +
                "VARIANT['-tex-mathit'].fonts.unshift('MathJax_default-italic');" +
            "});" +
        "}";

    (document.body || document.getElementsByTagName('head')[0]).appendChild(configscript);
    (document.body || document.getElementsByTagName('head')[0]).appendChild(mathjaxscript);
}
&lt;/script&gt;</content><category term="misc"/></entry><entry><title>An introduction to Quantum Processing - The QBit</title><link href="/quantum-processing-an-introduction-to-qbit.html" rel="alternate"/><published>2025-07-09T21:30:00+02:00</published><updated>2025-07-09T21:30:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-07-09:/quantum-processing-an-introduction-to-qbit.html</id><summary type="html">&lt;p&gt;I don't like deep learning and current AI buzz. Really. That "Hey, let's initialize billions of values and make them converge to whatever good enough solution could solve some problem with good probability, but we don't know how" really annoys me. So I decided to take a look at the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I don't like deep learning and current AI buzz. Really. That "Hey, let's initialize billions of values and make them converge to whatever good enough solution could solve some problem with good probability, but we don't know how" really annoys me. So I decided to take a look at the next breakthrough technology before it becomes a buzzword: Quantum Computing.&lt;/p&gt;
&lt;p&gt;Classical computers use bits. Quantum computers use qbits. That's it, end of the discussion.&lt;/p&gt;
&lt;p&gt;Just kidding...&lt;/p&gt;
&lt;h2 id="quantum-superposition"&gt;Quantum Superposition&lt;/h2&gt;
&lt;p&gt;First, let's talk about some properties of Quantum space:  the Quantum superposition. In classical computing, the value of a bit is either 0 or 1. Light is on or off. Gate is open or closed, etc...&lt;/p&gt;
&lt;p&gt;In quantum computing, the value of a qbit is undefined until we measure it. You can imagine the qbit oscillating very quickly between 0 and 1, but when you take a measure, it stops where it was when it was. Let's assume the qbit flipping from 1 to 0 every millisecond. Then, you measure it by pressing a button. You have a 50% chance of measuring it to 1 and a 50% chance of measuring it to 0.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/measure_qbit-3.gif"&gt;&lt;/p&gt;
&lt;p&gt;Now, imagine a qbit staying 3 ms in 1 state and 1 ms in 0 state. When you measure it, you have a 25% chance of measuring 0 and a 75% chance of measuring 1.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/measure_qbit75.gif?w=256"&gt;&lt;/p&gt;
&lt;p&gt;This “oscillation” is called &lt;strong&gt;quantum superposition&lt;/strong&gt;. You can also imagine the qbit having both values at the same time if you prefer. We call this the &lt;strong&gt;quantum state&lt;/strong&gt; of the qbit.&lt;/p&gt;
&lt;p&gt;— So it has 2 states in once ?&lt;/p&gt;
&lt;p&gt;Not really. Qbit has only one quantum state. But when we measure it, it will be either 0, either 1.&lt;/p&gt;
&lt;p&gt;In classical physics, the state of a system is equivalent to its value. If your car is moving at 100 km/h and a police officer measures its speed, he will get 100km/h.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/bit_measure-2.gif?w=512"&gt;&lt;/p&gt;
&lt;p&gt;In quantum mechanics, the quantum state of a particle is not equivalent to its measure. The particle is in a superposition state, which can be described as "50% 0, 50% 1". But when we measure it, we won't have something like 0.5. We have either 0 or 1. And the crazy thing is the qbit then keeps this value after the measure. Meaning several values in a row will all give the same value.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/qbit_measure.gif?w=512"&gt;&lt;/p&gt;
&lt;p&gt;— But how is this possible? How can measuring something have an impact on this thing? I didn't touch the qbit, I've just watched it !&lt;/p&gt;
&lt;p&gt;Yes, yet another fun thing about quantum mechanics. Seeing something actually change its state. You can imagine that, to see something, you have to light it, and see what effect this object has on light. You have to see its interaction with photons. Generally speaking, measuring something means measuring how this thing impacts its environment. In human scale, this would be similar to throw a rock at someone and see how the rock is deviated. You will for sure change the state of the specimen. But we are getting off topic; let's go back to our qbits.&lt;/p&gt;
&lt;h2 id="vector-representation"&gt;Vector representation&lt;/h2&gt;
&lt;p&gt;To represent the qbit state, we can use Vector representation.&lt;/p&gt;
&lt;p&gt;Let's assume a vector ψ [α, β] of unit length:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/qbit_vect8985388264044544175.png?w=512"&gt;&lt;/p&gt;
&lt;p&gt;We know that α² + β² = 1. In the case above, α=β=1/√2.&lt;/p&gt;
&lt;p&gt;We can represent a qbit ψ the same way, using a slightly different notation convention called &lt;a href="https://en.wikipedia.org/wiki/Bra%E2%80%93ket_notation"&gt;Bra-Ket notation&lt;/a&gt; :&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/qbit1279725149916932464.png?w=512"&gt;&lt;/p&gt;
&lt;p&gt;One pronounces |0⟩ "Ket zeros", |1⟩ "Ket one", |ψ⟩ "Ket Phi", etc...&lt;/p&gt;
&lt;p&gt;Using Cartesian coordinates, these vectors respectively have coordinates&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;|0⟩: [1, 0]&lt;/li&gt;
&lt;li&gt;|1⟩: [0, 1]&lt;/li&gt;
&lt;li&gt;|ψ⟩: [α, β]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;α and β represent the probability of measuring a qbit in the value 0 or 1. More precisely, probabilities are respectively p(0)=α² and p(1)=β², so that p(0)+p(1)=1.&lt;/p&gt;
&lt;p&gt;We end up with p(0)=1/(√2)²=1/2. So, there is a 50% chance of having 0 when measuring a qbit. Same for 1.&lt;/p&gt;
&lt;p&gt;Any qbit |ψ⟩ can be expressed as a superposition of values |0⟩ and |1⟩ using the formula:&lt;/p&gt;
&lt;p&gt;|ψ⟩ = α|0⟩ + β|1⟩&lt;/p&gt;
&lt;h2 id="the-bloch-sphere"&gt;The Bloch sphere&lt;/h2&gt;
&lt;p&gt;The subtlety is that α and β are actually complex numbers. So |ψ⟩ is actually described using 4 real numbers a, b, c, and d:&lt;/p&gt;
&lt;p&gt;|ψ⟩ = α|0⟩ + β|1⟩ α, β ∈ ℂ ⇔ |ψ⟩ = (a+b*i) |0⟩ + (c+d*i)β|1⟩ a, b, c, d ∈ ℝ&lt;/p&gt;
&lt;p&gt;Complex numbers can also be written as &lt;em&gt;r&lt;/em&gt; e&lt;sup&gt;i&lt;em&gt;θ&lt;/em&gt;&lt;/sup&gt;, so:&lt;/p&gt;
&lt;p&gt;|ψ⟩ = &lt;em&gt;r&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt; e&lt;sup&gt;i&lt;em&gt;θ&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt;&lt;/sup&gt;|0⟩ + &lt;em&gt;r&lt;sub&gt;&lt;sup&gt;&lt;/em&gt;&lt;sub&gt;β&lt;/sub&gt;&lt;em&gt;&lt;/sup&gt;&lt;/sub&gt;&lt;/em&gt; e&lt;sup&gt;i&lt;em&gt;θ&lt;sub&gt;β&lt;/sub&gt;&lt;/em&gt;&lt;/sup&gt;|1⟩&lt;/p&gt;
&lt;p&gt;However, in quantum mechanics, only the relative phase between α and β has any physical meaning. Only &lt;sup&gt;&lt;em&gt;θ&lt;sub&gt;β&lt;/sub&gt; - θ&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt;&lt;/sup&gt; is important. We can offset the phase so that &lt;em&gt;θ&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt; = 0 and have&lt;/p&gt;
&lt;p&gt;|ψ⟩ = &lt;em&gt;r&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt; |0⟩ + &lt;em&gt;r&lt;sub&gt;&lt;sup&gt;&lt;/em&gt;&lt;sub&gt;β&lt;/sub&gt;&lt;em&gt;&lt;/sup&gt;&lt;/sub&gt;&lt;/em&gt; e&lt;sup&gt;i&lt;em&gt;θ&lt;sub&gt;β&lt;/sub&gt;&lt;/em&gt;&lt;/sup&gt;|1⟩ = α|0⟩ + β|1⟩ with α ∈ ℝ, α &amp;gt; 0, and β ∈ ℂ.&lt;/p&gt;
&lt;p&gt;|ψ⟩ can now be perfectly described with 3 real values. We also know that |ψ⟩ has unit length. This gives us another constrains:&lt;/p&gt;
&lt;p&gt;∥|ψ⟩∥² = ∥&lt;em&gt;r&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt; |0⟩ + &lt;em&gt;r&lt;sub&gt;&lt;sup&gt;&lt;/em&gt;&lt;sub&gt;β&lt;/sub&gt;&lt;em&gt;&lt;/sup&gt;&lt;/sub&gt;&lt;/em&gt; e&lt;sup&gt;i&lt;em&gt;θ&lt;sub&gt;β&lt;/sub&gt;&lt;/em&gt;&lt;/sup&gt;|1⟩∥²&lt;/p&gt;
&lt;p&gt;&lt;em&gt;r&lt;sub&gt;α&lt;/sub&gt;²&lt;/em&gt; + &lt;em&gt;r&lt;sub&gt;β&lt;/sub&gt;²&lt;/em&gt; = 1&lt;/p&gt;
&lt;p&gt;Among all the trigonometric equations you have learned at school, there is a one saying:&lt;/p&gt;
&lt;p&gt;cos(θ)&lt;em&gt;²&lt;/em&gt; + sin(θ)&lt;em&gt;²&lt;/em&gt; = 1&lt;/p&gt;
&lt;p&gt;Let's define θ so that &lt;em&gt;r&lt;sub&gt;α&lt;/sub&gt;&lt;/em&gt; = cos(θ/2) and &lt;em&gt;r&lt;sub&gt;β&lt;/sub&gt;&lt;/em&gt; = sin(θ/2) which satisfies this constrains.&lt;/p&gt;
&lt;p&gt;— Wait, why not cos(θ) ?&lt;/p&gt;
&lt;p&gt;Because Math hates you.&lt;/p&gt;
&lt;p&gt;So, we finally reach the final forms of the equation:&lt;/p&gt;
&lt;p&gt;|ψ⟩ = &lt;em&gt;cos(θ/2)&lt;/em&gt; |0⟩ + &lt;em&gt;sin(θ/2)&lt;/em&gt; e&lt;sup&gt;iϕ&lt;/sup&gt; |1⟩&lt;/p&gt;
&lt;p&gt;And ended up with only 2 real parameters, θ and ψ, where 0 ≤ θ ≤ π and 0 ≤ ϕ \&amp;lt; 2π. But contrary to the first Cartesian representation, the quantum state of |ψ⟩ is now perfectly described.&lt;/p&gt;
&lt;p&gt;To visualize this new representation, we can interpret ϕ and θ as azimuth and elevation angles:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2025/07/sphere7077807762601323878.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;This sphere is called the &lt;strong&gt;Bloch sphere&lt;/strong&gt;. And one can notice that when &lt;em&gt;θ=0, |ψ⟩=|0⟩, and&lt;/em&gt; when &lt;em&gt;θ&lt;/em&gt;=π, |ψ⟩=|0⟩, which also correspond to cartesian representation from previous section, modulo a 1/2 factor on &lt;em&gt;θ&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;— So, couldn't we call it the Bloch Hemisphere and get rid of the /2 factor ?&lt;/p&gt;
&lt;p&gt;No, we can't. 😠&lt;/p&gt;
&lt;h2 id="takeaways"&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;In classical computing, a bit &lt;em&gt;ψ&lt;/em&gt; has value 0 or 1, which correspond to its current state.&lt;/li&gt;
&lt;li&gt;In quantum computing, a qbit &lt;em&gt;|ψ⟩&lt;/em&gt; has an infinite of possible state which are combination of |0⟩ and |1⟩. But when measuring it, its value will be either |0⟩ or |1⟩.&lt;/li&gt;
&lt;li&gt;The probability to have |0⟩ or |1⟩ when measuring &lt;em&gt;|ψ⟩&lt;/em&gt; is respectively equal to α² and β².&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See the next article about &lt;a href="/quantum-processing-the-quantum-gates-single-qbit.html"&gt;Quantum Gates&lt;/a&gt;.&lt;/p&gt;</content><category term="misc"/><category term="physics"/><category term="quantum-mechanics"/><category term="science"/></entry><entry><title>Forced Perspective in Video Game</title><link href="/forced-perspective-in-video-game.html" rel="alternate"/><published>2025-01-31T14:30:00+01:00</published><updated>2025-01-31T14:30:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2025-01-31:/forced-perspective-in-video-game.html</id><summary type="html">&lt;p&gt;Last year, I have developed a small video game for my company to raise awareness about renewable energy. I named it &lt;strong&gt;Synergia&lt;/strong&gt;. Unfortunatly, because of process issues, I cannot publish it and it is only avaible on the company's intranet. Anyway. This game takes the form of a small city …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Last year, I have developed a small video game for my company to raise awareness about renewable energy. I named it &lt;strong&gt;Synergia&lt;/strong&gt;. Unfortunatly, because of process issues, I cannot publish it and it is only avaible on the company's intranet. Anyway. This game takes the form of a small city builder. User starts with a board of 4*4 tiles and must power plants to generate enough energy for the city:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image.png?w=988"&gt;&lt;/p&gt;
&lt;p&gt;The gameplay loop is not very interesting. However, I had to deal with some unexpected challenge regarding the camera and its field of view.&lt;/p&gt;
&lt;h2 id="where-to-put-the-camera"&gt;Where to put the Camera ?&lt;/h2&gt;
&lt;p&gt;I wanted the game to have its own toonish style, but I also wanted to create a small universe, with its own personality. I was inspired by &lt;strong&gt;Hearthstone&lt;/strong&gt;, where the board contains small scenes at each corners, that give a lot of personnality to the game:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-1.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;I also wanted to have large perspective and an horizon. I wanted the vanishing point to be visible. Something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-2.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;But, with this configuration, the playing area occupy barely 30% of the screen, and it become confusing as soon as player start building things:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-3.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;So I tried to changed Camera view angle to make the game more playable:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-4.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;But doing so, I completly lose the horizon effect I want to produce.&lt;/p&gt;
&lt;p&gt;So, how to have both ?&lt;/p&gt;
&lt;h2 id="forced-perspective"&gt;Forced perspective&lt;/h2&gt;
&lt;p&gt;That's where I though about &lt;a href="https://nintendoeverything.com/nintendo-shows-its-trick-for-zelda-a-link-between-worlds-top-down-view/"&gt;an article&lt;/a&gt; about &lt;strong&gt;Zelda A Link Between World&lt;/strong&gt;, and how Nintendo tricked the Top Down view. As Hiromasa Shikata said during an &lt;a href="https://iwataasks.nintendo.com/interviews/3ds/a-link-between-worlds/0/3/"&gt;Iwata Ask&lt;/a&gt; interview:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you looked straight down from the top, all you could see was Link's hat. So it looked like some mysterious green object moving around!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And so, to have better result, they "bend" all the object to the back, as in picture below:  &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-5.png?w=560"&gt;&lt;/p&gt;
&lt;p&gt;Yes. Perpective don't have to be realistic to be aesthetic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Animal Crossing&lt;/strong&gt; also use a Forced Perspective effect, as the whole world seems on the surface of a cylinder, which makes an impresion of depth.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-7.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;In the Comics "&lt;strong&gt;&lt;em&gt;La 2,333&lt;sup&gt;e&lt;/sup&gt; Dimension&lt;/em&gt;&lt;/strong&gt;" from Marc-Antoine Mathieu, the univers has lost a vanishing point, creating uncanny perspective:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-6.png?w=942"&gt;&lt;/p&gt;
&lt;h2 id="synergias-forced-perspective"&gt;Synergia's Forced Perspective&lt;/h2&gt;
&lt;p&gt;Here is how the scene initially looked like in Blender:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-10.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-16.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-17.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Let's try to use the Animal Crossing's cylindrical world effect :  &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-11.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-14.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-15.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;And the result in-game:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-8.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Cool, I have my Horizon back. But I find it still lack of depth. Let's improve it by "squishing" object on the back:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-12.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-13.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-18.png?w=826"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-19.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Much better. Lets add the final touch to the bridge:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-20.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image.png?w=988"&gt;&lt;/p&gt;
&lt;p&gt;As a reminder, here is the scene with true perspective:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/09/image-4.png?w=1024"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Forced Perspective has been use since centuries, especially in &lt;a href="https://en.wikipedia.org/wiki/Forced_perspective"&gt;architecture&lt;/a&gt;. When used correctly, it can alter the perception of a scene and make objects appear larger or further away than they actually are.&lt;/p&gt;</content><category term="misc"/></entry><entry><title>Evolutive Design: A new approach to conceive complex system.</title><link href="/evolutive-design-a-new-approach-to-conceive-complex-system.html" rel="alternate"/><published>2024-02-08T11:27:00+01:00</published><updated>2024-02-08T11:27:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2024-02-08:/evolutive-design-a-new-approach-to-conceive-complex-system.html</id><summary type="html">&lt;p&gt;For a long time, I have considered that to build a complex system, you had to take a lot of care in the design phase, and this design phase should happen at the beginning of the project. You should carefully define your architecture and anticipate future needs in order to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;For a long time, I have considered that to build a complex system, you had to take a lot of care in the design phase, and this design phase should happen at the beginning of the project. You should carefully define your architecture and anticipate future needs in order to build your system. Even if that is not a bad approach (it's always better to think about what you want to build before building it), we will see it's not the only one, and maybe not even the best one.&lt;/p&gt;
&lt;h2 id="darwin-and-the-theory-of-evolution"&gt;Darwin and the theory of evolution&lt;/h2&gt;
&lt;p&gt;Before talking about engineering, let's talk about biology. I assume you know &lt;a href="https://en.wikipedia.org/wiki/Charles_Darwin"&gt;Charles Darwin&lt;/a&gt; and his theory of evolution.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-1.png?w=745"&gt;&lt;/p&gt;
&lt;p&gt;Evolution and Natural selection is easy to understand for simple traits. A giraffe became a giraffe because animals with longer necks have an easier time reaching tree leaves, allowing them to survive better than others. But, how does it work for complex organs ? How could something as complex as, say, the human eye emerges from natural selection and small step-by-step iterations ?&lt;/p&gt;
&lt;p&gt;You can find a detailed explanation &lt;a href="https://en.wikipedia.org/wiki/Evolution_of_the_eye"&gt;here&lt;/a&gt;, but let summarize the main idea.&lt;/p&gt;
&lt;p&gt;Long, long time ago, our life was much simpler than nowadays, and we use to peacefully swim in the oceans of this planet. At that time, our biggest enemy was the Sun. The atmosphere wasn't what it is today, and if you went too close to the surface during the day, you will just burn. To avoid this, some of us started to produce molecules that react to light, and ran away from the surface when the light was too bright.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-2.png?w=863"&gt;&lt;/p&gt;
&lt;p&gt;Those molecules then start to regroup at the front of the organisms and form a small dot, to have a better estimation of where the light came from. This dot has widened and finally created a small bag with a small hole: a &lt;a href="https://en.wikipedia.org/wiki/Camera_obscura"&gt;Camera Obscura&lt;/a&gt;. Five hundred millions year later, it became what we know today.&lt;/p&gt;
&lt;p&gt;The initial need was to runaways from the sun. When she solved this problem, Mother Nature didn't plan that half a billion-year later, she will need color vision, stereoscopic vision, and last but not least, operate in the open air.&lt;/p&gt;
&lt;p&gt;Species evolve by mutating their genetic code, like a software evolve by mutating its source code. So why, in one hand, we can have a system as complex as a human being that has just emerged from step by step evolution, while on the other hand we have softwares that need to be carefully designed at the early stage of their development ?&lt;/p&gt;
&lt;h2 id="predators-are-drivers-of-evolution"&gt;Predators are drivers of evolution&lt;/h2&gt;
&lt;p&gt;To evolve, a system requires constrains. Why would you change anything if you don't have to ? Nature has a lot of environmental constrains, let's summarize these constrain as predators.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, predators are here to force you to evolve. No predators, no evolutions.&lt;/li&gt;
&lt;li&gt;Then, predators are here to constrain your evolution. If you evolve in the wrong way, you will be eaten.&lt;/li&gt;
&lt;li&gt;Finally, predators are here to prevent you from regressing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-3.png?w=874"&gt;&lt;/p&gt;
&lt;h2 id="what-does-all-this-have-to-do-with-software-engineering"&gt;What does all this have to do with software engineering ?&lt;/h2&gt;
&lt;p&gt;If we consider a software as a living entity, what would be its predators ? What prevent a mutation to be accepted ? What prevent a code modification to be deployed in production ? Could it be our tests, more specifically, our test pipeline ?&lt;/p&gt;
&lt;p&gt;Modern software strongly relies on their integration pipeline to accept or refuse a Pull Request. Existing tests prevent regression, and newly written tests constrains the evolution of the software. In a sense, they act like software predators.&lt;/p&gt;
&lt;h2 id="tests-are-software-predators"&gt;Tests are software predators&lt;/h2&gt;
&lt;p&gt;When talking about tests, I talk about automated tests, as it should represent the broad majority of your tests. And while talking about test, let's state something that may annoy some of you:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-7.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Remember the number of time you fixed a bug, a unit test start to fail, and you realized the test was actually validating the buggy behavior. Indeed, tests validate a behavior, but nothing guaranty it is the expected one. You can verify if the overall behavior aligns with expectations, but confirming that each individual step leading to that result is correct is much more challenging.&lt;/p&gt;
&lt;p&gt;That bring us to another statements:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-8.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Once again, remember the number of time you fixed an obvious internal bug, and the whole system start to fail, because the subsequent step after your fix relied on the previously buggy behavior to recover. When a test fail, the only things we are sure is that something changed.&lt;/p&gt;
&lt;p&gt;Ultimately, tests are constraints, not validators. When they fail, they are not saying: “You broke something.”. They say: “It's not the way it used to be. Are you sure of what you are doing ?”.&lt;/p&gt;
&lt;p&gt;And last but not least:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-9.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Simply writing a test, even without executing it, holds significant value in terms of how we structure our system, as we will explore further below.&lt;/p&gt;
&lt;h2 id="test-driven-development-design"&gt;Test Driven ~~Development~~ Design&lt;/h2&gt;
&lt;p&gt;TDD, or “Test Driven Development”, refer to a development strategy where you write tests before writing code. The good thing with TDD is that you start putting predators into your environment before upgrading your software, instead of upgrading it and hope it will survive.&lt;/p&gt;
&lt;p&gt;While TDD is often appreciated for the positive impact it has regarding software compliance with specifications, it is underrated regarding the positive impact it also has on software architecture. That's why I personally prefer referring to TDD as “Test Driven Design”.&lt;/p&gt;
&lt;p&gt;Indeed, one of the characteristics of a well design software is its testability. Good design are easy to test. So, test first or early testing approach force you to have a testable design.&lt;/p&gt;
&lt;p&gt;TDD also make you ask “How will I expose this new functionality ?”. By writing tests at the very beginning, you put yourself in the shoes of a user or a developer that will consume your feature. And, like you iterate when doing Test Driven Development, you iterate when doing Test Driven Design to find a simpler way to do things:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-5.png?w=938"&gt;&lt;/p&gt;
&lt;p&gt;This also highlight that design should be pulled by requirements, and will evolve with them. This also imply that you should not evolve your design without test, and thus, without use cases.&lt;/p&gt;
&lt;p&gt;Test Driven Design is also simpler than canonical Test Driven Development. By doing Test Driven Design, you focus on the nominal case. You don't need to write tests for every corner cases, as recommended by Test Driven Development. You focus on the overall architecture and main entry point. Not limit or buggy cases.&lt;/p&gt;
&lt;h2 id="tests-prevent-design-regressions"&gt;Tests prevent Design regressions&lt;/h2&gt;
&lt;p&gt;Like test prevent behavior regression, they also prevent design regression. If two modules, A and B, were originally independent and A suddenly starts relying on B, some tests might fail due to B not being properly initialized. The tests will complain about why B needs to be initialized while it was functioning perfectly until now.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/02/image.png?w=812"&gt;&lt;/p&gt;
&lt;p&gt;You might question the necessity of this new dependency and could find a way to avoid it.&lt;/p&gt;
&lt;h2 id="refactoring-is-not-a-crime"&gt;Refactoring is not a Crime&lt;/h2&gt;
&lt;p&gt;With planned design, refactoring is often seen as a failure. You failed in your design phase, and you have to fix your design issues.&lt;/p&gt;
&lt;p&gt;With evolutive design, refactoring is part of the development process. It's not a sign of failure, it's a sign of maturity. Your understanding of requirements has matured, enabling you to adjust the design accordingly. Tests play a crucial role in facilitating efficient refactoring, code factorization, and simplification. Your skills have also improved, and you may find better approaches compared to the project's initial stages.&lt;/p&gt;
&lt;p&gt;However, refactoring is a double-edged sword. Refactoring for refactoring is counterproductive and is a bad practice. A refactoring should have a measurable outcome. I previously talked about this in a &lt;a href="https://kissyagni.wordpress.com/2022/03/07/how-to-justify-refactoring-to-your-product-owner/"&gt;prior article&lt;/a&gt;, but the main outcomes of refactoring should be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remove a significant amount of code (Factorization).&lt;/li&gt;
&lt;li&gt;Remove an internal or external dependency (Decoupling).&lt;/li&gt;
&lt;li&gt;Replace a custom solution with a well established, existing one (Don't reinvent the wheel).&lt;/li&gt;
&lt;li&gt;Any measurable improvement: Performances, memory, scalability, …&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your sole argument is “The system will be cleaner”, then you are just saying “I don't like the way it is done, I want to do it my way”.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Planned design frequently leads to over-design, as you try to anticipate all the use cases.&lt;br&gt;
The majority of these scenarios will likely never occur, and the rest will unfold differently than initially imagined. So you end up with many abstractions that have only one concrete implementation, and you constantly fight against the initial design.&lt;/p&gt;
&lt;p&gt;Evolutive design focus on implementing the simplest solution to address the current requirement, assuming that simpler architectures are easier to evolve than complex ones. You create an abstraction only when you have several similar use cases. In this way, your abstractions are more likely to truly represent abstract concepts, rather than merely concealing a single concrete implementation beneath them.&lt;/p&gt;
&lt;p&gt;Nature has produced highly complex systems, relying solely on evolution rather than planning. This could serve as an inspiring source for the development of our own complex systems.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/02/image-1.png?w=1024"&gt;&lt;/p&gt;</content><category term="misc"/><category term="clean code"/><category term="refactoring"/></entry><entry><title>How to Profile Unity WebGL Based Application on Your Browser ?</title><link href="/how-to-profile-unity-webgl-based-application-on-your-browser.html" rel="alternate"/><published>2024-01-30T16:09:00+01:00</published><updated>2024-01-30T16:09:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2024-01-30:/how-to-profile-unity-webgl-based-application-on-your-browser.html</id><summary type="html">&lt;p&gt;Let's set the scene. You have a Unity application. It goes smoothly in Unity Editor, but when built in WebGL, embedded into your web page, and feed up with real data, it starts to slow down. How to profile that ?&lt;/p&gt;
&lt;h2 id="using-chrome-profiler"&gt;Using Chrome profiler&lt;/h2&gt;
&lt;p&gt;Long story short, run your app in …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Let's set the scene. You have a Unity application. It goes smoothly in Unity Editor, but when built in WebGL, embedded into your web page, and feed up with real data, it starts to slow down. How to profile that ?&lt;/p&gt;
&lt;h2 id="using-chrome-profiler"&gt;Using Chrome profiler&lt;/h2&gt;
&lt;p&gt;Long story short, run your app in Chrome, click F12-&amp;gt;Performances-&amp;gt;Record button. Play a few second with your app and stop recording. You end up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-12.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Let's zoom a bit on a single frame:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-14.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;We have a few insights of what happen, but we end up with useless "&lt;strong&gt;wasm-function&lt;/strong&gt;".&lt;/p&gt;
&lt;p&gt;How to have access to Unity's code function names ?&lt;/p&gt;
&lt;h2 id="enable-symbols-generation"&gt;Enable Symbols Generation&lt;/h2&gt;
&lt;p&gt;Going back to Unity, File-&amp;gt;Build Settings, and check &lt;strong&gt;Development Built&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-11.png?w=806"&gt;&lt;/p&gt;
&lt;p&gt;Build, run your app. If you are like me, you'll end up with this errors:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Assertion failed: undefined
ERROR Error: Uncaught (in promise): TypeError: stackSave is not a function
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-15.png?w=850"&gt;&lt;/p&gt;
&lt;h2 id="enable-symbols-generation_1"&gt;Enable Symbols Generation !!!&lt;/h2&gt;
&lt;p&gt;It seems there is a bug, either in Unity 2023.1, either in emscripten, I'm not sure. After some research, it seems related to &lt;a href="https://github.com/emscripten-core/emscripten/issues/18578"&gt;this issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's try to work around this. Uncheck &lt;strong&gt;Development Built&lt;/strong&gt;, as it doesn't work. Create a script "&lt;strong&gt;BuildScript.cs&lt;/strong&gt;" in your Asset/Editor folder, and copy/past this (adapt &lt;strong&gt;scenes&lt;/strong&gt; and &lt;strong&gt;locationPathName&lt;/strong&gt; to your case):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;using UnityEditor;

public class BuildScript
{
&lt;span class="gh"&gt;#&lt;/span&gt;if UNITY_EDITOR
    [UnityEditor.MenuItem(&amp;quot;Tools/BuildWebGL with Debug info&amp;quot;)]
    public static void BuildWebGLWithDebugInfo()
    {
        UnityEditor.PlayerSettings.WebGL.emscriptenArgs = &amp;quot;-s DEMANGLE_SUPPORT=1&amp;quot;;
        UnityEditor.PlayerSettings.WebGL.debugSymbolMode = WebGLDebugSymbolMode.Embedded;

        BuildPlayerOptions buildOptions = new BuildPlayerOptions();
        buildOptions.scenes = new[] { &amp;quot;Assets/Scenes/SampleScene.unity&amp;quot; };
        buildOptions.locationPathName = &amp;quot;build&amp;quot;;
        buildOptions.target = BuildTarget.WebGL;

        BuildPipeline.BuildPlayer(buildOptions);
    }
&lt;span class="gh"&gt;#&lt;/span&gt;endif
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, in Unity Editor, build your app using Tools-&amp;gt;BuildWebGL with Debug info.&lt;/p&gt;
&lt;h2 id="profiling-app"&gt;Profiling App&lt;/h2&gt;
&lt;p&gt;Go back to Chrome, F12-&amp;gt;Performances-&amp;gt;Record, zoom on a frame and...&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image-17.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Now, name of Unity's function are visible. You can profile your code and understand what's going on 😉&lt;/p&gt;</content><category term="misc"/><category term="3D"/><category term="Unity"/></entry><entry><title>How to have your own ChatGPT on your machine (and make him discussed with himself)</title><link href="/how-to-have-your-own-chatgpt-on-your-machine-and-make-him-discussed-with-himself.html" rel="alternate"/><published>2024-01-24T11:40:00+01:00</published><updated>2024-01-24T11:40:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2024-01-24:/how-to-have-your-own-chatgpt-on-your-machine-and-make-him-discussed-with-himself.html</id><summary type="html">&lt;p&gt;I've just followed an excellent training from &lt;a href="https://cnrsformation.cnrs.fr/"&gt;CRNS&lt;/a&gt; about Trusted AI, especially applied to &lt;a href="https://en.wikipedia.org/wiki/Natural_language_processing"&gt;NLP&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;LLM&lt;/a&gt; (well, ChatGPT in the end). And I wanted to play a bit with the different models.&lt;/p&gt;
&lt;p&gt;I'm very protective with my data. I'm using ChatGPT daily, but I often spend time finding a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've just followed an excellent training from &lt;a href="https://cnrsformation.cnrs.fr/"&gt;CRNS&lt;/a&gt; about Trusted AI, especially applied to &lt;a href="https://en.wikipedia.org/wiki/Natural_language_processing"&gt;NLP&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Large_language_model"&gt;LLM&lt;/a&gt; (well, ChatGPT in the end). And I wanted to play a bit with the different models.&lt;/p&gt;
&lt;p&gt;I'm very protective with my data. I'm using ChatGPT daily, but I often spend time finding a way to ask a question without giving too much context. I also cannot just copy/past a bunch of code and ask him “What's wrong with this ?!!!”, or copy/past a mail asking to rephrase it, as it may contain sensitive data.&lt;/p&gt;
&lt;p&gt;I recently discovered &lt;a href="https://gpt4all.io/index.html"&gt;gpt4all&lt;/a&gt;, which is basically an On Premise ChatGPT. Let's see how to use it. No external provider, No internet. Everything runs, and stay, on your machine.&lt;/p&gt;
&lt;h2 id="installing-gpt4all-on-your-machine"&gt;Installing GPT4ALL on your machine&lt;/h2&gt;
&lt;p&gt;It's incredibly simple. Just download the installer and install it. You will then be asked to download a &lt;strong&gt;Model&lt;/strong&gt;. If you don't know what you are doing, you can just download the &lt;strong&gt;Mistral Instruct&lt;/strong&gt; model, which works quite well without using that many resources.&lt;/p&gt;
&lt;p&gt;Ensure &lt;strong&gt;Mistral Instruct&lt;/strong&gt; is properly selected in gpt4all:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2024/01/image.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;And start discussing with your personal AI assistant.&lt;/p&gt;
&lt;h2 id="what-is-a-model"&gt;What is a Model ?&lt;/h2&gt;
&lt;p&gt;We are talking about Model, but what is a Model anyway ? To understand what is a model, let's see how AI assistant works.&lt;/p&gt;
&lt;p&gt;An AI assistant is a neural network. It's a “brain” that have some size and shapes. At first, this brain knows nothing, so it has to be trained. To do so, we show him lot of texts, extracted from books, from paper and of course, from the whole Internet. Training this kind of neural network takes time. Typically, &lt;strong&gt;several months&lt;/strong&gt; on supercomputer. Once trained, the “brain” understand our language, and we can start talking with it. This “brain” is a Model.&lt;/p&gt;
&lt;p&gt;Depending on its size, its structure and the way it has been trained, the Model is more or less “stupid”. GPT2, GPT3.5, GPT4, etc… are the models created by OpenAI company. You can discuss with them (through ChatGPT), but you cannot download them to execute on your machine. Business is business…&lt;/p&gt;
&lt;p&gt;However, some models are publicly available. It's the case for &lt;a href="https://mistral.ai/"&gt;Mistral&lt;/a&gt;, a fast, and efficient French model which seems to outperform GPT4 on some &lt;a href="https://jshelbyj.medium.com/tested-mixtral-8x7b-vs-gpt-4-for-boolean-classification-062530b05d49"&gt;tasks&lt;/a&gt;. And it is under Apache 2.0 license 😊.&lt;/p&gt;
&lt;h2 id="going-back-to-gpt4all"&gt;Going back to GPT4All&lt;/h2&gt;
&lt;p&gt;Running AI assistant on your machine has some limitation. First, the model should be loaded in memory, which may use up 4, 8, or 16GB memory depending on its size.&lt;/p&gt;
&lt;p&gt;Then, your computer is probably not as powerful as ChatGPT servers. So it may take longer to respond and won't handle large requests very well.&lt;/p&gt;
&lt;p&gt;Finally, ChatGPT has been “tweaked”, or is continuously trained with what users type to works well as an AI assistant. Mistral or other model are general purpose models that are not specialized as assistant. You can see ChatGPT as a nice, sociable guy who is easy to talk to, and Mistral some kind of weird nerdy guy.&lt;/p&gt;
&lt;p&gt;Now, let's go further with GPT4All. GPT4All also provide a &lt;a href="https://docs.gpt4all.io/gpt4all_python.html"&gt;python API&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="using-gpt4all-in-python"&gt;Using GPT4All in Python&lt;/h2&gt;
&lt;p&gt;Let's start by installing pip package:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip install gpt4all&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And execute the GPT4All “Hello World”:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;gpt4all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GPT4All&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GPT4All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;path/to/mistral-7b-instruct-v0.1.Q4_0.gguf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;The capital of France is &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;p&gt;The first thing I thought when I saw that was, "What would happen if 2 models talk to each other ?”. Ok, here is the code:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;gpt4all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GPT4All&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Loading models&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GPT4All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;path/to/mistral-7b-instruct-v0.1.Q4_0.gguf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GPT4All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;path/to/mistral-7b-instruct-v0.1.Q4_0.gguf&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Models loaded&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You are Alice. You will be introduced to Bob, a nice guy. You will have a conversation with him. Wait for bob to talk to you before answering.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;---------------------&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You are Bob. You will be introduced to Alice, a nice girl. You will have a conversation with her. Wait for Alice to talk to you before answering.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;---------------------&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bob_response&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Hi, I&amp;#39;m Bob. How are your ?&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bob: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bob_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;alice_response&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Alice: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;alice_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bob_response&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alice_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bob: &amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bob_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;p&gt;And the result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Hi&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m Bob. How are your ?&lt;/span&gt;
&lt;span class="s1"&gt;Alice: Hi Bob! Nice to meet you.&lt;/span&gt;

&lt;span class="s1"&gt;Bob: Hey Alice, it&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;great&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;too&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;been&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ve been good, thanks for asking. Just keeping busy with work and such. And yourself?&lt;/span&gt;

&lt;span class="s1"&gt;Bob: Same here. Work can be pretty demanding sometimes, but it&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;worth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Absolutely&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;So&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Well&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enjoy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;playing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sports&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reading&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;spending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;friends&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;What&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;about&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;That&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sounds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;love&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;walks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;recipes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;kitchen&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Wow&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;that&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;diverse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;favorite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subjects&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hobbies&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Yes&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;really&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;enjoy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;art&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;photography&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Worked quite well 😂. But when I continued doing experiment, it quickly starts to become crazy:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Hi&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m Bob. How are your ?&lt;/span&gt;

&lt;span class="s1"&gt;Alice: Hi there! I&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;well&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thanks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;asking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;And&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;(-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Suppose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Calculate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remainder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divided&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)/(-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)*(-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;)/(-&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;


&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;What&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;remainder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;127039856&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divided&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;What&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;highest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divisor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5496&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;


&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;

&lt;span class="n"&gt;Bob&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;What&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;derivative&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1047896&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5239655&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;

&lt;span class="n"&gt;Alice&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2095792&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don't ask Bob for flirting advice…&lt;/p&gt;
&lt;p&gt;I'm not yet very familiar with GPT4All and LLM. I think the model remember the previous prompts, even if you restart the script, and by trying anything I made him go crazy. I don't find a way to flush history yet.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;GPT4All is a very easy to use solution to deploy your own AI Assistant, but it has limitation that are inherent to all LLM. It takes resources, and would require some &lt;a href="https://en.wikipedia.org/wiki/Fine-tuning_(deep_learning)"&gt;fine-tuning&lt;/a&gt; depending on what you want to do with it. This out of the scope of this article. However, if you're handling sensitive data, it might be useful as is.&lt;/p&gt;</content><category term="misc"/><category term="AI"/><category term="ChatGPT"/><category term="LLM"/><category term="NLP"/></entry><entry><title>How to do Graphical Tests in Unity ?</title><link href="/how-to-do-graphical-tests-in-unity.html" rel="alternate"/><published>2023-11-15T16:12:00+01:00</published><updated>2023-11-15T16:12:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2023-11-15:/how-to-do-graphical-tests-in-unity.html</id><summary type="html">&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Certain tests cannot be conducted solely by comparing the return value of a function, particularly when custom shaders are in use. In such scenarios, it becomes necessary to perform comparisons based on screenshots. Fortunately, Unity offers some tools to do so, using the Unity's Graphics Tests Framework.&lt;/p&gt;
&lt;h2 id="graphics-tests-framework"&gt;Graphics Tests …&lt;/h2&gt;</summary><content type="html">&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Certain tests cannot be conducted solely by comparing the return value of a function, particularly when custom shaders are in use. In such scenarios, it becomes necessary to perform comparisons based on screenshots. Fortunately, Unity offers some tools to do so, using the Unity's Graphics Tests Framework.&lt;/p&gt;
&lt;h2 id="graphics-tests-framework"&gt;Graphics Tests Framework&lt;/h2&gt;
&lt;p&gt;I supposed you are already familiar with &lt;a href="https://docs.unity3d.com/Packages/com.unity.test-framework@1.3/manual/index.html"&gt;Unity Test Framework&lt;/a&gt; and Unit Tests in general.&lt;/p&gt;
&lt;p&gt;Windows -&amp;gt; Package Manager -&amp;gt; Add package by name...&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image.png?w=242"&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;strong&gt;com.unity.testframework.graphics&lt;/strong&gt; package.&lt;/p&gt;
&lt;p&gt;Then, add &lt;strong&gt;UnityEngine.TestTools.Graphics&lt;/strong&gt; to your test Assembly Definition Asset:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image-2.png?w=512"&gt;&lt;/p&gt;
&lt;p&gt;And add a new script file in your Tests folder. Let's call it &lt;strong&gt;GraphicTests.cs&lt;/strong&gt; and past this code (inspired from &lt;a href="https://github.com/Unity-Technologies/Graphics-Test-Framework-Examples/blob/master/Assets/Tests/GraphicTest.cs"&gt;https://github.com/Unity-Technologies/Graphics-Test-Framework-Examples/blob/master/Assets/Tests/GraphicTest.cs&lt;/a&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;UnityEngine.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;NUnit.Framework&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;UnityEngine.TestTools&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;UnityEngine.TestTools.Graphics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;GraphicTests&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;[PrebuildSetup(&amp;quot;SetupGraphicsTestCases&amp;quot;)]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// This will call the &amp;quot;Setup&amp;quot; function in SetupGraphicsTestCases.cs&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;[UseGraphicsTestCases]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Tells TestRunner that the following function is a test. (it inherits from UnityTest)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IEnumerator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GraphicTest1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GraphicsTestCase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ScenePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Arbitrary wait for 5 frames for the scene to load, and other stuff to happen (like Realtime GI to appear ...)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Load the test settings.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindObjectOfType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GraphicsTestSettings&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Missing test settings for graphic tests.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Get the test camera&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindObjectOfType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Camera&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Do the image comparison test&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;ImageAssert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AreEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReferenceImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ImageComparisonSettings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="na"&gt;[TearDown]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;DumpImagesInEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Save the result images in the project.&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;UnityEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Graphics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResultsUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtractImagesFromTestProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TestContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Graphical test will collect Scene present in your build, load it, take a snapshot and compare it with a reference image. Let's see how to add new graphical test case in the following section.&lt;/p&gt;
&lt;h2 id="adding-a-new-graphical-test"&gt;Adding a new Graphical Test&lt;/h2&gt;
&lt;p&gt;Create a new scene with object to test. Make it as simple as possible and ensure camera is properly located at scene startup.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add an empty &lt;strong&gt;GameObject&lt;/strong&gt;, call it &lt;strong&gt;GraphicsTestSettings&lt;/strong&gt; and add it a &lt;strong&gt;GraphicsTestSettings&lt;/strong&gt; component. This component contains various settings: Image size, Image comparison threshold, etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image-3.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;It's also a good practice to remove the Skybox : Windows -&amp;gt; Rendering -&amp;gt; Lighting -&amp;gt; Environment -&amp;gt; Skybox Material -&amp;gt; None&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image-5.png?w=670"&gt;&lt;/p&gt;
&lt;p&gt;and have a black background: Camera -&amp;gt; Environment -&amp;gt; Background Type -&amp;gt; Solid Color -&amp;gt; Black:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image-6.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;To really focus on object to test and avoid false positive caused by environment variations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add test scene to build: File -&amp;gt; Build Settings -&amp;gt; Add Open Scene.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/11/image-7.png?w=638"&gt;&lt;/p&gt;
&lt;p&gt;Execute Tests. This will create a folder &lt;strong&gt;Assets/ActualImages&lt;/strong&gt;. Rename it to &lt;strong&gt;ReferencesImages.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Execute Tests again. This time, tests should be green.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Graphical tests are highly susceptible to false positives and flakiness. Differences in GPU, system configurations, and driver versions from the environment where the reference images were generated can lead to test failures, even if there are no visible differences to the naked eye. Here are some suggestions to minimize the occurrence of false positives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don't use Graphical test for complex scene. Prefer doing small, isolated test for each asset and each use case.&lt;/li&gt;
&lt;li&gt;Remove anything that is not directly related to your test: Other objects, UI, Skybox, Shadows, Anti-Aliasing, etc... are source of flakiness.&lt;/li&gt;
&lt;li&gt;Run tests always on the same machine. And generate references images on this machine.&lt;/li&gt;
&lt;li&gt;Adjust thresholds in &lt;strong&gt;GraphicsTestSettings&lt;/strong&gt; component.&lt;/li&gt;
&lt;li&gt;Generate small images: 256x256 or 512x512 are enough for most cases.&lt;/li&gt;
&lt;/ul&gt;</content><category term="misc"/><category term="3D"/><category term="Unity"/></entry><entry><title>How to Handle Double Precision Coordinates in Unity ?</title><link href="/how-to-handle-double-precision-coordinates-in-unity.html" rel="alternate"/><published>2023-09-08T11:24:00+02:00</published><updated>2023-09-08T11:24:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2023-09-08:/how-to-handle-double-precision-coordinates-in-unity.html</id><summary type="html">&lt;p&gt;Like most of 3D/Game engines, Unity works with single float precision coordinates. As it is not an issue for most use cases, this may be a problem when you deal with geographical coordinates or very large world. Let's see how to handle this problem using the Unity's High Precision …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Like most of 3D/Game engines, Unity works with single float precision coordinates. As it is not an issue for most use cases, this may be a problem when you deal with geographical coordinates or very large world. Let's see how to handle this problem using the Unity's High Precision Framework.&lt;/p&gt;
&lt;h2 id="the-unity-high-precision-framework"&gt;The Unity High Precision Framework&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/Unity-Technologies/com.unity.gis.high-precision-framework"&gt;The Unity High Precision Framework&lt;/a&gt; is a package that add double precision support to Unity. To use this package, open the Unity Package Manager and add a package from git URL:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image.png?w=1020"&gt;&lt;/p&gt;
&lt;p&gt;Then past the git url from Github repos:&lt;br&gt;
https://github.com/Unity-Technologies/com.unity.gis.high-precision-framework.git&lt;/p&gt;
&lt;p&gt;This package comes with a very good sample. It contains a huge plane of 100.000 km over 100.000 km and 3 small scenes located at random places.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/animation-1.gif?w=640"&gt;&lt;/p&gt;
&lt;h2 id="using-the-unity-high-precision-framework"&gt;Using The Unity High Precision Framework&lt;/h2&gt;
&lt;p&gt;High Precision Framework define two new components:&lt;/p&gt;
&lt;h3 id="the-hproot-component"&gt;The HPRoot component&lt;/h3&gt;
&lt;p&gt;Create an &lt;strong&gt;HPRoot&lt;/strong&gt; &lt;strong&gt;GameObject&lt;/strong&gt; and add an &lt;strong&gt;HPRoot&lt;/strong&gt; component. Every objects should be under this &lt;strong&gt;HPRoot&lt;/strong&gt;. Even the camera:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-8.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HPRoot&lt;/strong&gt; can also contains a &lt;strong&gt;Local Coordinate System&lt;/strong&gt; script to automatically update &lt;strong&gt;RootUniversePosition&lt;/strong&gt; property depending on some logic. See &lt;a href="#Strategies-to-Update-HPRoot"&gt;Strategies to Update HPRoot&lt;/a&gt; to get some ideas.&lt;/p&gt;
&lt;h3 id="the-hptransform-component"&gt;The HPTransform component&lt;/h3&gt;
&lt;p&gt;Add this component for &lt;strong&gt;GameObjects&lt;/strong&gt; that require double precision position. If possible, try to make "container" objects with &lt;strong&gt;HPTransforms&lt;/strong&gt;, and children &lt;strong&gt;GameObject&lt;/strong&gt; with position relative to parent. If you build a map of a country, put an &lt;strong&gt;HPTransform&lt;/strong&gt; for each city and put building under corresponding city, but avoid using an &lt;strong&gt;HPTransform&lt;/strong&gt; for each objects.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-9.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Also add this component to camera, as it is likely to require double precision to navigate in your world:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-10.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;The most important thing is to update &lt;strong&gt;HPRoot.RootUniversePosition&lt;/strong&gt; to a position near your current work area. In the sample, the position is update when camera go to another position. See LocalCoordinateSystem.cs:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;private void LateUpdate()
{
    if (m_Origin != null &amp;amp;&amp;amp; !m_LastPosition.Equals(m_Origin.UniversePosition))
    {
        m_LastPosition = m_Origin.UniversePosition;
        m_Root.RootUniversePosition = m_LastPosition;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;h2 id="understanding-the-problem-of-float-precision"&gt;Understanding the Problem of Float Precision&lt;/h2&gt;
&lt;p&gt;I wrote a &lt;a href="https://kissyagni.wordpress.com/2022/03/21/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-1/"&gt;series&lt;/a&gt; &lt;a href="https://kissyagni.wordpress.com/2022/03/28/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2/"&gt;of&lt;/a&gt; &lt;a href="https://kissyagni.wordpress.com/2022/04/04/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-3/"&gt;articles&lt;/a&gt; that details problem of float precision in 3D. Let summarize this and see how the HP framework handle it:&lt;/p&gt;
&lt;p&gt;Floating point values have a limited number of digit. To simplify, it can store only 6 digits in decimal representation. This means that possible position for objects are aligned on a grid of representable values. If your game consists in walking around a garden near a house, your position will never be higher than a few dozen of meters, giving you a sub-millimeter precision. The grid has a spacing of less than a millimeter, you don't see you character jumping from millimeter to millimeter.&lt;/p&gt;
&lt;p&gt;However, imagine you develop an open world game with planet size map and origin in bottom left. Your grid will look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-2.png?w=992"&gt;&lt;/p&gt;
&lt;p&gt;A few meters aways from the origin, you will have a sub millimeter precision. But if you go 100 km away, you barely have 10 cm precision. And if you go even further, let say 1.000 km aways, you don't even have 1 meter precision.&lt;/p&gt;
&lt;p&gt;This means that, if you try to put a car on a road, it will "jump" from place to place, because its position can only be on the grid of representable floating point values.&lt;/p&gt;
&lt;p&gt;Using double precision don't completely fix the problem, it just push it farther away. With double, you would have ~15 digits precision. Meaning you will keep a millimeter precision even at the other end of the solar system. If you want to cross the galaxy... You will have to find another solution 😊. That's the role of &lt;strong&gt;HPTransform&lt;/strong&gt;: To define object's position in double precision.&lt;/p&gt;
&lt;p&gt;Using double precision to gives objects position in worlds space is just one part of the problem. GPU works in float precision. You &lt;strong&gt;CAN NOT&lt;/strong&gt; have end to end double precision. You &lt;strong&gt;MUST&lt;/strong&gt; go back to float precision at some point.&lt;/p&gt;
&lt;p&gt;The good news is that floating precision issues are visible only for... visible objects, so only for object close to the camera. And good news is that, in camera space, you can go back to float precision because object close to camera are... close to camera space origin 😊, so float precision is enough:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-5.png?w=703"&gt;&lt;/p&gt;
&lt;p&gt;Now, the bad news 😭... Doing this "back to float precision" in camera space would require doing it at every frame (or at least every time camera moves). Which would kill performances. It can work for simple cases, but framerate will drop down as soon as you will have many objects in your scene.&lt;/p&gt;
&lt;p&gt;BUT, what we could do is to define a space which is "not far away from camera", and update it only once from time to time. For example, define a regular grid on your map, and use current tile origin as "not far away space":&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/09/image-7.png?w=702"&gt;&lt;/p&gt;
&lt;p&gt;That's the role of the &lt;strong&gt;HPRoot&lt;/strong&gt; component. Define a position near current position, and expresse all &lt;strong&gt;GameObjects&lt;/strong&gt; position relative to this position, using float precision.&lt;/p&gt;
&lt;h2 id="strategies-to-update-hproot"&gt;Strategies to Update HPRoot&lt;/h2&gt;
&lt;p&gt;The root of the problem is to properly update &lt;strong&gt;HPRoot.RootUniversePosition&lt;/strong&gt;. There are several strategies to do so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Attach it to camera position. It works, but kill performances.&lt;/li&gt;
&lt;li&gt;Define regular grid, and update it when player go to another tile.&lt;/li&gt;
&lt;li&gt;Define a maximum distance, and update it to current player position when distance is higher than a threshold.&lt;/li&gt;
&lt;li&gt;Update it regularly through a timer. By the way, this strategy was actually used in the old &lt;a href="https://aviationweek.com/vistanav-16-includes-3-d-guidance"&gt;VistaNav GPS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Update depending on "teleportation" logic, like in sample.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="limitations"&gt;Limitations&lt;/h2&gt;
&lt;p&gt;Unity's HP Framework is not magic and currently have limitations (taken from &lt;a href="https://github.com/Unity-Technologies/com.unity.gis.high-precision-framework/tree/main/Documentation~"&gt;documentation&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Platform Support&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Currently, only 64 bit windows is fully tested. However, the framework is reported to work on other platforms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Physics&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Physics can only work in a static rebasing context due to the performance cost of moving colliders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Navigation Mesh&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Authored navigation meshes can only be used in a static rebasing context.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Particle Systems&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;World-space particle simulations may or may not behave as expected depending on the rebasing strategy that is used by the high precision rendering scheme. If dynamic rebasing updates the &lt;code&gt;HPRoot&lt;/code&gt;, particles simulated in world space will appear to jump around as a function of the rebasing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scripts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Any script that reads world-space positions will likely behave strangely when using the High Precision Framework. These scripts would need to be written such that only relative values are used or so that they use the &lt;code&gt;HPTransform&lt;/code&gt; component rather than the &lt;code&gt;Transform&lt;/code&gt; component.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shaders&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Shaders that rely on world space coordinates, such as tri-planar shaders will behave oddly when used with the High Precision Framework as the world space is constantly being adjusted with dynamic rebasing schemes.&lt;/p&gt;
&lt;p&gt;For the Shader part, I've used this package with complex shader based on &lt;a href="https://en.wikipedia.org/wiki/Ray_casting"&gt;ray-casting&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Signed_distance_function"&gt;signed distance field&lt;/a&gt; and didn't have any trouble.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It may be hard to adapt an existing Unity game to High Precision framework because of limitations described above. Script dealing with world coordinates might also require rework to use the &lt;strong&gt;HPTransform UniversePosition&lt;/strong&gt; instead of &lt;strong&gt;GameObject transform position&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;However, this package it is very well adapter to render static objects in very large scene like in GIS applications or flying simulation game.&lt;/p&gt;</content><category term="misc"/><category term="3D"/><category term="IEEE754"/><category term="Unity"/></entry><entry><title>How to Design a Good API ?</title><link href="/how-to-design-a-good-api.html" rel="alternate"/><published>2023-07-28T16:26:00+02:00</published><updated>2023-07-28T16:26:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2023-07-28:/how-to-design-a-good-api.html</id><summary type="html">&lt;p&gt;The term "API," which stands for Application Programming Interface, has been a fundamental concept in computer science from its inception. Whenever you develop a function, create a class, or establish an entry point, you are essentially defining an API. However, the crucial question is: Who will be using your APIs …&lt;/p&gt;</summary><content type="html">&lt;p&gt;The term "API," which stands for Application Programming Interface, has been a fundamental concept in computer science from its inception. Whenever you develop a function, create a class, or establish an entry point, you are essentially defining an API. However, the crucial question is: Who will be using your APIs?&lt;/p&gt;
&lt;h2 id="who-consume-apis"&gt;Who consume APIs ?&lt;/h2&gt;
&lt;p&gt;Developers consume APIs. But there are two kinds of developers. Those who work on the project, and those who will consume your project. If the only developers that will consume your API are the one of your team, there is nothing much to say. This is generally the case when you develop pure UI based application. Try to keep your code clean, respect the &lt;a href="https://en.wikipedia.org/wiki/SOLID"&gt;SOLID&lt;/a&gt; principles and good development practices. However, in scenarios like developing REST-based web services, C++ libraries, or Python packages, the target audience includes external developers who are not part of the project. In such cases, it becomes essential to differentiate between Internal APIs, designed for team usage, and Exposed APIs, which are meant for external consumption.&lt;/p&gt;
&lt;h2 id="internal-api-vs-exposed-api"&gt;Internal API vs Exposed API&lt;/h2&gt;
&lt;p&gt;When developing a new component, you'll come across methods that handle internal behavior, while others will act as entry points for the component's users to call.&lt;/p&gt;
&lt;p&gt;In most Object-Oriented languages like C++, C#, or Java, there's a clear distinction between Private, Public, and sometimes Protected members, defined explicitly using keywords. In Python, this distinction is more of a convention where members starting with an "_" are considered private. The best practice is to make public methods serve as entry points, allowing external users to interact with the component, while keeping implementation details hidden and designated as private.&lt;/p&gt;
&lt;p&gt;In real world, many public members are public because another class need it, and are not aimed to be called by external users. That's the distinction between Internal and Exposed API. Internal API can be a little tricky, but there will always be a developer in your team to explain you how to use such and such method.&lt;/p&gt;
&lt;p&gt;However, Exposed API should be as user friendly as possible. It's really the Frontend of your product. And no matter how exceptional your product may be, if users find it challenging to utilize, it's just garbage.&lt;/p&gt;
&lt;h2 id="how-to-design-an-api"&gt;How to Design an API ?&lt;/h2&gt;
&lt;p&gt;The key to designing a user-friendly API is to prioritize writing simple examples. Instead of diving straight into the implementation of a feature and then considering how to expose it, begin by crafting an example—a concise code snippet that demonstrates how the feature will be utilized. This approach may remind you of Test-Driven Development (TDD).&lt;/p&gt;
&lt;p&gt;TDD serves not only as a means to test your software but also as an effective way to define your API and illustrate its usage. I discussed this concept in my article titled &lt;a href="https://kissyagni.wordpress.com/2022/04/25/tests-are-good-but-what-are-good-tests/"&gt;"Tests Are Good. But What Are Good Tests?"&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By practicing TDD, you ensure low coupling between modules, which promotes modularity and maintainability. Moreover, it guarantees that your API will be easy to use. After all, who would want to write dozens of initialization lines before even getting to the actual testing? TDD allows you to focus on the essential aspects of your API, making it more intuitive and developer-friendly.&lt;/p&gt;
&lt;p&gt;To create a user-friendly API, it's crucial to have it used by people who didn't work on its development. Your own bias, as the creator, can hinder accurate judgment of its usability. External feedback is invaluable for making necessary improvements and ensuring a more effective design. To do so, you can do API Review.&lt;/p&gt;
&lt;h2 id="how-to-organize-an-api-review"&gt;How to Organize an API Review ?&lt;/h2&gt;
&lt;p&gt;The best way to do API review is to write a code snippet that use your API, to present it to some developers and see if they understand what the code do.&lt;/p&gt;
&lt;p&gt;It's essential not to reveal the methods' implementation during this review, as the focus is on the API design, not its implementation. It's better to do a first API review before writing the implementation anyway. Keep in mind this will be an iterative process. The API you imagine may not be implementable. So you'll have to iterate and do other API reviews as long as your API will converge.&lt;/p&gt;
&lt;h2 id="good-and-bad-practices"&gt;Good and Bad practices&lt;/h2&gt;
&lt;p&gt;If you practice C++, Qt has a very good &lt;a href="https://wiki.qt.io/API_Design_Principles"&gt;API Design guidelines&lt;/a&gt;. And below are some examples I've encountered in my career that can be applied to any language or framework:&lt;/p&gt;
&lt;h3 id="an-object-should-always-be-in-a-consistent-state-and-thus-from-its-creation"&gt;An object should always be in a consistent state, and thus from its creation.&lt;/h3&gt;
&lt;p&gt;Do not define&lt;code&gt;init()&lt;/code&gt;, &lt;code&gt;create()&lt;/code&gt;, &lt;code&gt;build()&lt;/code&gt;, etc... methods that must be called just after object creation:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ServiceClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myservice.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Prefer instead:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ServiceClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myservice.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or using a factory, so you can return &lt;code&gt;null&lt;/code&gt; , or a &lt;a href="https://en.wikipedia.org/wiki/Null_object_pattern"&gt;Null Object Pattern&lt;/a&gt; if creation fail for any reasons:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serviceClient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ServiceClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myservice.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="you-api-should-be-stateless"&gt;You API should be stateless.&lt;/h3&gt;
&lt;p&gt;Not only for REST API, but for any kind of API. Creating an object, or calling a method, should not depend on current state of application. In particular, it should not be needed to call unrelated method before using a function or creating an object:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;LogManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;ConfigManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;registerConfigManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ConfigManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;don&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;t know what the line above do but if I don&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;them&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;below&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;crash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;icone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Icone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If your object do need some other object to be initialized, request these objects as argument:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;configManager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConfigManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;icone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Icone&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configManager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As a corollary, avoid using global variable or &lt;a href="https://en.wikipedia.org/wiki/Singleton_pattern"&gt;Singleton pattern&lt;/a&gt;, which makes your API stateful.&lt;/p&gt;
&lt;p&gt;Another example are what I call the "Stateful getters", where you need to call some initialization method before you can call a getter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;object.computeSize();
object.getSize();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Solution is to use a lazy evaluation approach:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;getSize&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;if(m_size.empty())&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;m_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;computeSize()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;m_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="if-a-method-is-present-it-should-be-callable"&gt;If a method is present, it should be callable&lt;/h3&gt;
&lt;p&gt;Avoid throwing "Not Implemented" or "Not Supported" exception. It's very frustrating to find the exact function we look for using autocompletion just to figure out at runtime that we cannot use it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Image readOnlyImage = Image.open(ïmage.png&amp;quot;, &amp;quot;r&amp;quot;);
readOnlyImage.write(someData); // throw NotSupported
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If possible, prefer splitting in Interfaces:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ReadImage readOnlyImage = Image.openRead(&amp;quot;image.png&amp;quot;);
readOnlyImage.write(someData); // write is no part of ReadImage interface
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="do-not-ask-for-parameters-that-can-be-deducted-from-others"&gt;Do not ask for parameters that can be deducted from others.&lt;/h3&gt;
&lt;p&gt;You just look like an idiot if you request for something you can deduct by yourself. It also avoids the need to handle inconsistent parameters:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myserver.com/folder/image.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;folder/image.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;fileExtension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And good luck to handle the following case 😊:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myserver.com/folder/image.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ftp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;folder/sound.mp3&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;fileExtension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.jpg&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Avoiding redundancy avoid you a lot of trouble:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;http://myserver.com/folder/image.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="makes-the-nominal-use-case-trivial-to-do"&gt;Makes the nominal use case trivial to do&lt;/h3&gt;
&lt;p&gt;90% of your user will do the same things. Makes this 90% doable in a single line of code. Don't provide a super generic API only to makes life easier for the remaining 10%.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imgDims&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getDimensions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;widthDim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;imgDims&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WIDTH_AXIS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;widthDim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even if an image can be a 3D multispectral time series video, 99% of peoples handle 2D images:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id="expose-only-what-is-strictly-necessary"&gt;Expose only what is strictly necessary.&lt;/h3&gt;
&lt;p&gt;Anything you expose can, and will, be used by user. And user will complain about anything that don't work. So don't expose that nice stuff you did during lunch or that internal function that you use to debug some specific cases. Exposing a feature is the PO's responsibility, not the developer one.&lt;/p&gt;
&lt;h3 id="avoid-doing-thing-if-the-user-hasnt-explicitly-asked-you"&gt;Avoid doing thing if the user hasn't explicitly asked you.&lt;/h3&gt;
&lt;p&gt;Some language enables you to call function at startup, when the library is loaded for example. Python has &lt;code&gt;__init__.py&lt;/code&gt;, C# has&lt;code&gt;[RuntimeInitializeOnLoadMethod()]&lt;/code&gt; tag, etc... Be very careful when using it. There is nothing more frustrating than experiencing crashes or error logs from a third-party when you haven't explicitly invoked any of its functions.&lt;/p&gt;
&lt;p&gt;Also, keep this in mind:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not because you did something complicated means you did something smart&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="misc"/><category term="clean code"/></entry><entry><title>Improve Your Unity Asset Usability With Samples</title><link href="/improve-your-unity-asset-usability-with-samples.html" rel="alternate"/><published>2023-06-01T17:10:00+02:00</published><updated>2023-06-01T17:10:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2023-06-01:/improve-your-unity-asset-usability-with-samples.html</id><summary type="html">&lt;p&gt;No one read the documentation.&lt;/p&gt;
&lt;p&gt;It is the sad truth. You have developed the most awesome Unity asset, using the most advanced state of the art ray-casted-signed-distance-field-backed-layer-based-mipmap-inspired-linear-fading technic, but no-one understands how to use it. So you wrote a documentation. But people won't read it. Because no one read the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;No one read the documentation.&lt;/p&gt;
&lt;p&gt;It is the sad truth. You have developed the most awesome Unity asset, using the most advanced state of the art ray-casted-signed-distance-field-backed-layer-based-mipmap-inspired-linear-fading technic, but no-one understands how to use it. So you wrote a documentation. But people won't read it. Because no one read the documentation anymore.&lt;/p&gt;
&lt;p&gt;If you want people to use your work, you have to make it easy to use.&lt;/p&gt;
&lt;h2 id="unity-package-layout"&gt;Unity Package Layout&lt;/h2&gt;
&lt;p&gt;Unity recommends a &lt;a href="https://docs.unity3d.com/Manual/cus-layout.html"&gt;specific folder layout&lt;/a&gt; for your package. It looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/06/image.png?w=598"&gt;&lt;/p&gt;
&lt;p&gt;If you respect this layout, you can import your package in Unity using Unity's package manager &lt;strong&gt;Add package from disk&lt;/strong&gt; or &lt;strong&gt;Add package from git URL&lt;/strong&gt; if you store your sources on a git repository.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/06/image-2.png?w=802"&gt;&lt;/p&gt;
&lt;p&gt;Try to import the Unity's &lt;a href="https://github.com/Unity-Technologies/com.unity.gis.high-precision-framework"&gt;High Precision Framework&lt;/a&gt; package:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click on Add package from git URL...&lt;/li&gt;
&lt;li&gt;past the git url: https://github.com/Unity-Technologies/com.unity.gis.high-precision-framework.git&lt;br&gt;
  (for some reasons, you may have to add git+ if your git is stored on custom server:&lt;br&gt;
  git+https://my-company@dev.azure.com/MyProject/_git/my-unity-package)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The package is importing. This may take a few minutes. You will notice the " View documentation" that no one ever click.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/06/image-3.png?w=347"&gt;&lt;/p&gt;
&lt;p&gt;But a much more interesting part is the "Samples". This list samples provided in the package.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/06/image-4.png?w=424"&gt;&lt;/p&gt;
&lt;p&gt;If you click on "Import" button, Samples will be downloaded and added to your Project Browser.&lt;/p&gt;
&lt;h2 id="how-to-create-samples-for-your-custom-package"&gt;How to create samples for your custom package&lt;/h2&gt;
&lt;p&gt;Samples are stored in &lt;strong&gt;&lt;em&gt;Samples~&lt;/em&gt;&lt;/strong&gt; folder of &lt;a href="https://docs.unity3d.com/Manual/cus-layout.html"&gt;Unity Package Layout&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2023/06/image.png?w=598"&gt;&lt;/p&gt;
&lt;p&gt;But to be present as Samples in Package Manager, you have to reference them in package.json:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s2"&gt;&amp;quot;samples&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;[
&lt;span class="w"&gt;        &lt;/span&gt;{
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;displayName&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;High Precision Sample&amp;quot;&lt;/span&gt;,
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Contains sample scene for the high precision framework&amp;quot;&lt;/span&gt;,
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Samples~/SampleScene&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;}
&lt;span class="w"&gt;    &lt;/span&gt;],
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="how-to-create-good-sample"&gt;How to create good sample&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sample should contains a scene and should work out of the box when user load the scene.&lt;/li&gt;
&lt;li&gt;Sample should be minimal, and focus on a single feature&lt;/li&gt;
&lt;li&gt;Sample should be small. Ideally, a single scene with a single node and a single script.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;People prefer copy/past something they don't understand than understanding something to make it work. That's why they won't read the doc. So instead of spending time on documentation, prefer spending time on writing simple, self-contained examples.&lt;/p&gt;
&lt;p&gt;Also, keep this in mind:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not because you did something complicated means you did something smart&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="misc"/><category term="3D"/><category term="Unity"/></entry><entry><title>How to locate DICOM in space</title><link href="/how-to-locate-dicom-in-space.html" rel="alternate"/><published>2022-12-20T10:04:00+01:00</published><updated>2022-12-20T10:04:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-12-20:/how-to-locate-dicom-in-space.html</id><summary type="html">&lt;p&gt;I've worked in medical domain from time to time since 2010, especially to display DICOM images, and if I had a dollar every time I heard “This picture is upside down”, I think I could have bought a sandwich. Yes, that's not so frequent but when it happens, it quickly …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I've worked in medical domain from time to time since 2010, especially to display DICOM images, and if I had a dollar every time I heard “This picture is upside down”, I think I could have bought a sandwich. Yes, that's not so frequent but when it happens, it quickly becomes a nightmare. So let's try to demystify DICOM image position.&lt;/p&gt;
&lt;h2 id="some-convention-in-3d"&gt;Some Convention in 3D&lt;/h2&gt;
&lt;p&gt;I noticed that some convention that was obvious to me was not obvious to everyone, so let's remind them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The vast majority of 3D software always use the same colors to draw axes:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-19.png?w=342"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When an axis is normal to the image, a circle with a dot indicates this axis goes toward you:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-20.png?w=429"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;And a circle with a cross indicate this axis is moving away from you:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-21.png?w=441"&gt;&lt;/p&gt;
&lt;h2 id="coordinate-system"&gt;Coordinate system&lt;/h2&gt;
&lt;p&gt;A very important thing to understand is that coordinates of a point always refer to a reference system. In the example below, the coordinates of point P are in both case (2, 1), but depending on which coordinate system we use, its final position won't be the same:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;When talking about &lt;a href="https://dicom.innolitics.com/ciods/rt-dose/image-plane/00200032"&gt;Image Position (Patient) Attribute - (0020,0032)&lt;/a&gt; for example, one should understand in which space are expressed these coordinates. Same for &lt;a href="https://dicom.innolitics.com/ciods/rt-dose/image-plane/00200037"&gt;Image Orientation (Patient) Attribute - (0020,0037)&lt;/a&gt;. So, how to know in which space these coordinates are expressed ?&lt;/p&gt;
&lt;h2 id="rcs-reference-coordinates-system"&gt;RCS - Reference Coordinates System&lt;/h2&gt;
&lt;p&gt;DICOM define two reference coordinates system depending on if the patient is a biped or a quadruped. It corresponds to the natural way of putting specimen in device (scanner, MRI, ...) so that patient space correspond to device space. This information can be retrieved with the &lt;a href="https://dicom.innolitics.com/ciods/mr-image/general-series/00102210"&gt;Anatomical Orientation Type Attribute - (0010,2210)&lt;/a&gt;. As states in the doc: “If this Attribute is not present, the default human standard anatomical position is used”, that is to say Biped.&lt;/p&gt;
&lt;p&gt;BIPED&lt;/p&gt;
&lt;p&gt;X: from right to left&lt;br&gt;
Y: from front to back&lt;br&gt;
Z: from foot to head&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-3.png?w=428"&gt;&lt;/p&gt;
&lt;p&gt;QUADRUPED&lt;/p&gt;
&lt;p&gt;X: from left to right&lt;br&gt;
Y: from dorsal to ventral&lt;br&gt;
Z: from tail to head&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-2.png?w=501"&gt;&lt;/p&gt;
&lt;h2 id="image-space"&gt;Image space&lt;/h2&gt;
&lt;p&gt;DICOM also define an image space with origin in &lt;strong&gt;center&lt;/strong&gt; of first pixel. Note that most render engine consider origin in corner of texture, which cause a lot of “half pixel shift” issues in medical applications.&lt;/p&gt;
&lt;p&gt;X: along rows, unit of 1mm&lt;br&gt;
Y: along column, unit of 1mm&lt;br&gt;
Z: cross product of X and Y to form a unit direct coordinate system.&lt;br&gt;
Origin: Center of first pixel of image&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-4.png?w=450"&gt;&lt;/p&gt;
&lt;p&gt;When talking about 1st pixel of image, I'm not referring to top left one or bottom or whatever. I'm referring about the &lt;strong&gt;first value in pixel buffer&lt;/strong&gt;. For example, with a 256*256 image:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-6.png?w=607"&gt;&lt;/p&gt;
&lt;p&gt;If you do a simple DICOM image viewer, you can just locate 1st pixel in top left and that's it. But if you do a 3D viewer and have to deal with patient orientation, oblique slices and so on, thing will becomes much more complicated, and you should better not focussing on displaying 1st pixel in top left.&lt;/p&gt;
&lt;h2 id="locating-image-in-patient-space"&gt;Locating image in patient space&lt;/h2&gt;
&lt;p&gt;Now serious things begin. Let's remind the 3 tags involved here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dicom.innolitics.com/ciods/mr-image/image-plane/00200032"&gt;Image Position (Patient) Attribute - (0020,0032)&lt;/a&gt; gives Image space origin in patient space.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dicom.innolitics.com/ciods/mr-image/image-plane/00200037"&gt;Image Orientation (Patient) Attribute - (0020, 0037)&lt;/a&gt; gives Image space x and y axis direction in patient space. z can be retrieved with cross product between x and y.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dicom.innolitics.com/ciods/mr-image/image-plane/00280030"&gt;Pixel Spacing Attribute - (0028, 0030)&lt;/a&gt; gives length of Image space x and y axes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can then build a transformation matrix from image space to patient space:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-7.png?w=645"&gt;&lt;/p&gt;
&lt;p&gt;Applying this transformation matrix to image properly locate it relative to patient:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-8.png?w=639"&gt;&lt;/p&gt;
&lt;p&gt;Before taking care of image orientation on screen, you first have to ensure the image is properly located into patient space. Else, you will just do shotgun debugging by blindly flipping and rotating the image until that particular one is well oriented. And you will have a bug for the next one.&lt;/p&gt;
&lt;h2 id="a-few-words-about-anatomical-planes"&gt;A few words about Anatomical planes&lt;/h2&gt;
&lt;p&gt;Before talking about image orientation on screen, we should introduce Anatomical Planes. Medical domains defines 3 cutting planes, relative to each of 3 patient main axes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sagittal: Normal to X axis&lt;/li&gt;
&lt;li&gt;Coronal: Normal to Y axis&lt;/li&gt;
&lt;li&gt;Axial (Transverse): Normal to Z axis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-9.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Defining if an image is along Sagittal, Coronal or Axial plane is easy in case of axis aligned images, but in case of oblique slicing, this may be more difficult. To do so, we have to find which of the Sagittal, Coronal or Axial plane is the closer to slice plane.&lt;/p&gt;
&lt;p&gt;Let's first compute image normal, expressed in patient space. It is the cross product of image's X and Y axes, returned by &lt;a href="https://dicom.innolitics.com/ciods/mr-image/image-plane/00200037"&gt;Image Orientation (Patient) Attribute - (0020, 0037)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-11.png?w=293"&gt;&lt;/p&gt;
&lt;p&gt;Now, let's find which of the Sagittal, Coronal or Axial axis is closest to slice's axis. This can be done by computing dot product between slice normal and X, Y, Z patient space axes. But as we have slice normal directly expressed in patient space, dot product between X, Y, Z patient axes are directly the coordinates of slice's normal:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-12.png?w=362"&gt;&lt;/p&gt;
&lt;p&gt;If the highest value is Zimg.x, it means the slice is closest to Sagittal plane, and thus can be considered as a sagittal slice.&lt;/p&gt;
&lt;h2 id="displaying-a-slice-on-screen"&gt;Displaying a slice on screen&lt;/h2&gt;
&lt;p&gt;Until now, I didn't talk about slice orientation on screen. I never talked about Up or Down. This is because these concept is a matter of Camera, not position in space.&lt;/p&gt;
&lt;p&gt;Let's assume you have a Coronal slice of the patient's head. How would you want to see it on screen ? Like on the left or like on the right ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-14.png?w=763"&gt;&lt;/p&gt;
&lt;p&gt;Note that both orientations are valid. In both cases, Z axis goes from foot to head and X axis goes from patient's left to right.&lt;/p&gt;
&lt;p&gt;To decide which is the better, a convention defines how Sagittal, Coronal and Axial images should be displayed on screen. I didn't find any literature affirming this convention, but it seems the most widely used among medical software.&lt;/p&gt;
&lt;p&gt;Note that the convention is not the same for &lt;strong&gt;BIPED&lt;/strong&gt; and for &lt;strong&gt;QUADRUPED&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sagittal Biped&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patient Z axis along UP screen vector&lt;/li&gt;
&lt;li&gt;Patient Y axis along RIGHT screen vector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-15.png?w=807"&gt;&lt;/p&gt;
&lt;p&gt;The patient is standing up and look to the left of the screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-25.png?w=516"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sagittal Quadruped&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patient -Y axis along UP screen vector&lt;/li&gt;
&lt;li&gt;Patient -Z axis along RIGHT screen vector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-18.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;The patient is lying down is standing up and look to the left of the screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-26.png?w=519"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coronal (Biped and Quadruped)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patient Z axis along UP screen vector&lt;/li&gt;
&lt;li&gt;Patient X axis along RIGHT screen vector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-16.png?w=645"&gt;&lt;/p&gt;
&lt;p&gt;The patient is standing up and face you. Its left side is on the right of the screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-27.png?w=516"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Axial (Biped and Quadruped)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Patient -Y axis along UP screen vector&lt;/li&gt;
&lt;li&gt;Patient X axis along RIGHT screen vector&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-17.png?w=807"&gt;&lt;/p&gt;
&lt;p&gt;Patient is lying down and look to the top of the screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-28.png?w=507"&gt;&lt;/p&gt;
&lt;h2 id="lets-write-some-code"&gt;Let's write some code&lt;/h2&gt;
&lt;p&gt;Let's wrap this into some pseudo-code:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;(0020,0037)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cross&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;z&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sagittal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;z&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Transverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;biped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quadruped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sagittal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Transverse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lookAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;p&gt;This will really depend on your application, which lib you use to read DICOM, which render engine you use for your display, but the main idea is here. From Image Orientation, you can compute an UP and a RIGHT vector, and then ask your camera to look at some point using the given UP and RIGHT orientation. Most render engines have this kind of feature.&lt;/p&gt;
&lt;h2 id="not-axis-aligned-image"&gt;Not axis-aligned image&lt;/h2&gt;
&lt;p&gt;The code above ensure having patient space always aligned with screen axes. But what if you have an image which is not aligned with patient axes, like the case below ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/12/image-24.png?w=533"&gt;&lt;/p&gt;
&lt;p&gt;We have a perfectly Sagittal acquisition. The slice normal is along X axis, but image rows are not aligned with patient Y axis. In this case, what do you want ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Left: Patient aligned with screen. Image not aligned with screen.&lt;/li&gt;
&lt;li&gt;Right: Image aligned with screen. Patient not aligned with screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well... it depends on what you want, but you have to choose. You cannot have both image and patient aligned on screen.&lt;/p&gt;
&lt;p&gt;The code presented previously will give you the Left result. Patient axes aligned on screen. If you want the Right one, you should add an extra step to ensure left and up vector are aligned with image X and Y vectors:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;readtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;(0020,0037)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cross&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;y&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;z&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sagittal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxCoord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SliceNormalInPatientSpace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;z&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Transverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;biped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Coronal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quadruped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sagittal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Transverse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;yPatientInWorldSpace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Extra step to handle Image screen aligned {&lt;/span&gt;
&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findClosestVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findClosestVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;xImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yImageInPatientSpace&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="nb"&gt;camera&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lookAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;up&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;p&gt;With findClosestVector:&lt;/p&gt;
&lt;div style="background: #272822;overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em"&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// Find among vectors, the vector which is the closest to refVector.&lt;/span&gt;
&lt;span class="c1"&gt;// All vectors must be normalized.&lt;/span&gt;
&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;findClosest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;refVector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;closestDot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;closestVector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vec3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;refVector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;closestDot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;closestVector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;closestVector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;refVector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;closestVector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;closestVector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;/div&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I think That video perfectly summarize the kind of argument you may have when your user require “having images always aligned on screen and patient looking to the left”.&lt;/p&gt;
&lt;div class="wp-block-embed__wrapper"&gt;
https://www.youtube.com/watch?v=BKorP55Aqvg
&lt;/div&gt;</content><category term="misc"/><category term="3D"/><category term="DICOM"/><category term="LifeScience"/><category term="Medical imaging"/></entry><entry><title>The Retrobinet</title><link href="/the-retrobinet.html" rel="alternate"/><published>2022-11-16T16:24:00+01:00</published><updated>2022-11-16T16:24:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-11-16:/the-retrobinet.html</id><summary type="html">&lt;p&gt;Do you have difficulties choosing between creating new features and fixing bugs ? Maybe you should give a try to the &lt;strong&gt;Retrobinet&lt;/strong&gt;. A sprint retrospective format to trigger discussion about priorities between maintenance and feature.&lt;/p&gt;
&lt;h2 id="the-concept"&gt;The concept&lt;/h2&gt;
&lt;p&gt;Retrobinet comes from "Robinet", the French word for Faucet. The idea is to have …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Do you have difficulties choosing between creating new features and fixing bugs ? Maybe you should give a try to the &lt;strong&gt;Retrobinet&lt;/strong&gt;. A sprint retrospective format to trigger discussion about priorities between maintenance and feature.&lt;/p&gt;
&lt;h2 id="the-concept"&gt;The concept&lt;/h2&gt;
&lt;p&gt;Retrobinet comes from "Robinet", the French word for Faucet. The idea is to have two faucets: one for the bugs and one for the features, that fill up a bucket representing your team velocity. You have a 10 litter bucket. You cannot fill up more than 10 litters.&lt;/p&gt;
&lt;p&gt;Question: How do you adjust the faucets ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/10/retrobinet-1.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;To trigger discussion and ideas, you can imagine what do you do if you have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;5L&lt;/strong&gt; feature, &lt;strong&gt;5L&lt;/strong&gt; bug ? (this one is easy 😉)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10L&lt;/strong&gt; feature, &lt;strong&gt;5L&lt;/strong&gt; bug ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;5L&lt;/strong&gt; feature, &lt;strong&gt;10L&lt;/strong&gt; bug ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;15L&lt;/strong&gt; feature, &lt;strong&gt;15L&lt;/strong&gt; bug ?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You cannot put 15L in a bucket of 10L. So a strategy should be defined. Bug first ? Feature first ? 50/50 ? 80/20 ?&lt;/p&gt;
&lt;p&gt;Let your team think about this during 10 minutes. The first thing they may argue is:&lt;/p&gt;
&lt;p&gt;— Things are not that simple in real life !&lt;/p&gt;
&lt;p&gt;Yes, so what information is missing ? Is this information present in the ticket tracker ? Does having such information will really help you ? If things were that simple, what would you do ?&lt;/p&gt;
&lt;p&gt;Things are not that simple in real life, but this exercise highlight that prioritizing imply sacrifices. If you don't want to sacrifice anything, you can just let the bucket overflow, and you'll get what you get.&lt;/p&gt;</content><category term="misc"/><category term="retrospective"/><category term="scrum"/></entry><entry><title>An introduction to Machine Learning applied to Real Estate Estimation</title><link href="/an-introduction-to-machine-learning-applied-to-real-estate-estimation.html" rel="alternate"/><published>2022-09-19T11:33:00+02:00</published><updated>2022-09-19T11:33:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-09-19:/an-introduction-to-machine-learning-applied-to-real-estate-estimation.html</id><summary type="html">&lt;p&gt;I'm currently looking for a house in Montpellier, and I'm still wondering if the price displayed could be negotiated or not. So instead of thinking for myself (I'm very bad at business…), I prefer to let the computer do it for me.&lt;/p&gt;
&lt;p&gt;To have a rough estimation of a property …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I'm currently looking for a house in Montpellier, and I'm still wondering if the price displayed could be negotiated or not. So instead of thinking for myself (I'm very bad at business…), I prefer to let the computer do it for me.&lt;/p&gt;
&lt;p&gt;To have a rough estimation of a property, you can get the average price per square meter and multiply by the property surface. But you know that lots of criteria can influence the final price. For example, the land area in case of houses. Let's see how machine learning can help us to refine our estimation by taking in account more than only living area.&lt;/p&gt;
&lt;h2 id="building-our-model"&gt;Building our Model&lt;/h2&gt;
&lt;p&gt;We will suppose, for this very simple model, that real estate prices mainly depend on living area and land area. Our goal is to have a program that takes those 2 values as input and give us the price of the house:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;house_price = compute_price([living_area, land_area])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By convention, inputs of the model are called the “Xs", and output are called the "Ys". The model is a function that compute a Y from a given X.&lt;/p&gt;
&lt;p&gt;Unfortunately, there is no such thing as “The Model to rule them all”. There are dozens and dozens of models, more or less complicated, more or less easy to use, more or less adapted for certain category of problems. For example, assuming a “Price per square meter” is already a model in itself. You assume price grows linearly with living area. It may not be the case, it may grow exponentially, or stagnate at some point, or do some crazy things like “A house less than 100m² cost €300.000 and a house more than 100m² cost €500.000, and that's it”. But you assume using a linear variation is a good approximation of what happen.&lt;/p&gt;
&lt;p&gt;We can assume final cost will also vary linearly with land area. The bigger the land, the more expensive the house. So let's create a simple model that assume house price is a linear function of living_area and land_area.&lt;/p&gt;
&lt;p&gt;In Python, we will use the &lt;em&gt;linear_model&lt;/em&gt; module of &lt;em&gt;sklearn&lt;/em&gt; package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sklearn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linear_model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="training-our-model"&gt;Training our Model&lt;/h2&gt;
&lt;p&gt;To train this model, we need data. There are several ways to get real estate transaction data. You can get them for example from &lt;a href="https://www.immo-data.fr/" rel="noreferrer noopener" target="_blank"&gt;https://www.immo-data.fr/&lt;/a&gt;. I won't detail how to get data here, but let's assume you manage to have a few dozens of real estate transaction over the last year on a given town. You know, for each house, its living_area, its land_area, and its price. For each couple [living_area, land_area], you have a corresponding price. This gives us 2 lists:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The list of [living_area, land_area], which are inputs of the model, the “Xs”.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The list of price, which are output of the model, the “Ys”.&lt;/p&gt;
&lt;p&gt;# [living_area, land_area]
X = [[137, 800], 
     [120, 400],
     [125, 425],
     [130, 1500],
     [250, 1825],
     [351, 1612],
     [203, 4135],
     [173, 1690],
     [115, 622],
     [91, 388],
     [160, 2854],
     [106, 913],
     [86, 471],
     [80, 767],
     [135, 1497],
     [217, 2000],
     [167, 1796],
     [98, 3544],
     [120, 1007],
     [101, 3286],
     [134, 1108],
     [180, 1854],
     [137, 1784],
     [117, 1570],
     [176, 1743],
]&lt;/p&gt;
&lt;h1 id="house-price"&gt;House price&lt;/h1&gt;
&lt;p&gt;Y = [629000, 
     599000, 
     594000, 
     650000, 
     840000,
     1074648,
     590000,
     625000,
     700540,
     465170,
     1000000,
     430000,
     503900,
     370000,
     632000,
     1200000,
     700000,
     655750,
     564000,
     600000,
     568400,
     815000,
     650000,
     485800,
     724700,
]&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We train our model using those data. It will &lt;em&gt;learn&lt;/em&gt; how price vary in function of living/land area in this particular town.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt; model = linear_model.LinearRegression().fit(X, Y)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="using-our-model"&gt;Using our Model&lt;/h2&gt;
&lt;p&gt;When a new house for sale appears in that city, you can run your model to see if the price displayed is consistent with the local market.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt; living_area = 110
land_area = 880
house_price = model.predict([[living_area, land_area]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, the model gives a price of €589.010. If this house is for sale for €590.000, that seems fair. If it's for sale for €650.000, you probably have room for negotiation.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Machine learning is a huge topic that has existed long before the trend of deep learning, and it exists model that are much simpler and require much smaller training set than deep neural network.&lt;/p&gt;
&lt;p&gt;House pricing depend on various things like condition of the house, its location, the year of construction, its energy balance, etc… It could be a good exercise to build a more complex model taking in account those criteria. 😉&lt;/p&gt;
&lt;p&gt;I let you the full python code. To run it, copy/past into a &lt;em&gt;run.py&lt;/em&gt; file and type:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python run.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may have to install sklearn with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip install sklearn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sklearn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linear_model&lt;/span&gt;

&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;125&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;425&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;130&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1825&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;351&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1612&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;203&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4135&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1690&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;622&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;388&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2854&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;106&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;913&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;86&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;471&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;767&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;135&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1497&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;217&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1796&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3544&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1007&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3286&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;134&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1108&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1854&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1784&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1570&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;176&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1743&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;629000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;599000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;594000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;650000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;840000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1074648&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;590000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;625000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;700540&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;465170&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;430000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;503900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;370000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;632000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;1200000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;700000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;655750&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;564000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;600000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;568400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;815000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;650000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;485800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mi"&gt;724700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linear_model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LinearRegression&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;living_area&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;110&lt;/span&gt;
&lt;span class="n"&gt;land_area&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;880&lt;/span&gt;
&lt;span class="n"&gt;house_price&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="n"&gt;living_area&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;land_area&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Estimated Price: &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;house_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ps: I would like to thank the &lt;a href="https://www.mscsoftware.com/product/odyssee" rel="noreferrer noopener" target="_blank"&gt;Odysee&lt;/a&gt; team that introduced me to machine learning domain. "It was short but intense" 😉&lt;/p&gt;</content><category term="misc"/><category term="AI"/><category term="machine learning"/><category term="ML"/><category term="python"/></entry><entry><title>Scrum Retrospective: Archetype</title><link href="/scrum-retrospective-archetype.html" rel="alternate"/><published>2022-09-08T10:42:00+02:00</published><updated>2022-09-08T10:42:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-09-08:/scrum-retrospective-archetype.html</id><summary type="html">&lt;p&gt;A few years ago, a hiring slot was opened in my team and our manager asked us which profile will be the most useful. We were a dream team, the best of the best. We lacked no skills ! And we didn't really know how to orient the job description. Should …&lt;/p&gt;</summary><content type="html">&lt;p&gt;A few years ago, a hiring slot was opened in my team and our manager asked us which profile will be the most useful. We were a dream team, the best of the best. We lacked no skills ! And we didn't really know how to orient the job description. Should we hire a specialist ? A swiss knife ? A facilitator ? Hard to tell. So I've created a retrospective focused on team and individual profile which I had called:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;"The Archetype retrospective"&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="description"&gt;Description&lt;/h2&gt;
&lt;p&gt;This retrospective is based on Role play and character creation. You have to chose between various archetype: The soldier, the Mage, the Paladin, etc... each with their strengths and weaknesses. So I defined a list of archetypes and asked to each team member to assign an archetype to each of its colleague, including himself. I end up with the following personas:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-11_164658.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-38.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-39.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-40.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-41.png?w=1024"&gt;&lt;/p&gt;
&lt;h2 id="benefits"&gt;Benefits&lt;/h2&gt;
&lt;p&gt;This retrospective has 2 benefits:&lt;/p&gt;
&lt;p&gt;First, this allows everyone to realize the image they give off. Sometime, there is a consensus on a person. Sometime, a person is seen differently by different members. It helps people to better know themselves.&lt;/p&gt;
&lt;p&gt;Second, once you agreed on each member's archetype, you can plot the global team profile by accumulating each archetype profile. Goal is not to have a perfectly balanced team, this is an indicator to help you analyzing your team and should be interpreted. In my case, I end up with a profile like this one:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-42.png?w=518"&gt;&lt;/p&gt;
&lt;p&gt;At first, one could think our team were lacking of team spirit and organization and would greatly benefit of hiring a "Paladin" profile. But our team worked well. There was a very good atmosphere and our release were always on time. But we noticed that we were lacking of polyvalence. And that was true. We were skilled, motivated and efficient developers, but no one was really "transverse". We came to the conclusion that, instead of adding another specialist, a DevOps polyvalent profile would be much more valuable for us.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This retrospective requires people to open themselves and accept judgement, which can be difficult for some. That's why before doing it, you should be sure you know your team, and it will accept this exercise.&lt;/p&gt;
&lt;p&gt;Also, presenting the accumulated graph to management can be dangerous. They may be tempted to always have a balanced team which is not the goal.&lt;/p&gt;
&lt;p&gt;I leave you the PowerPoint below. Let me know if you have tried this retrospective in your team and how it went 🙂&lt;/p&gt;
&lt;div class="wp-block-file"&gt;

&lt;a href="https://kissyagni.wordpress.com/wp-content/uploads/2022/03/archetype.pptx" id="wp-block-file--media-bd9ee8d1-dc84-4df2-9813-9be176cce739"&gt;Archetype_retrospective.pptx&lt;/a&gt;&lt;a href="https://kissyagni.wordpress.com/wp-content/uploads/2022/03/archetype.pptx" class="wp-block-file__button wp-element-button" download="" aria-describedby="wp-block-file--media-bd9ee8d1-dc84-4df2-9813-9be176cce739"&gt;Télécharger&lt;/a&gt;

&lt;/div&gt;</content><category term="misc"/><category term="retrospective"/><category term="scrum"/></entry><entry><title>An Introduction to Electron Microscopy</title><link href="/an-introduction-to-electron-microscopy.html" rel="alternate"/><published>2022-06-27T09:30:00+02:00</published><updated>2022-06-27T09:30:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-06-27:/an-introduction-to-electron-microscopy.html</id><summary type="html">&lt;p&gt;In this article, I'm going to talk about something that has nothing to do with software development, but something I enjoyed working on and would like to put down on paper before I forgot everything.&lt;/p&gt;
&lt;p&gt;Indeed, I will talk about Electron Microscopy, a topic I worked on when I was …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In this article, I'm going to talk about something that has nothing to do with software development, but something I enjoyed working on and would like to put down on paper before I forgot everything.&lt;/p&gt;
&lt;p&gt;Indeed, I will talk about Electron Microscopy, a topic I worked on when I was at Thermo Fisher company. All the information here are taken from the excellent playlist of Professor Grant Jensen: &lt;a href="https://www.youtube.com/watch?v=gDgFbAqdM_c&amp;amp;list=PL8_xPU5epJdctoHdQjpfHmd_z9WvGxK8-" rel="noreferrer noopener" target="_blank"&gt;Getting Started in Cryo-EM with Professor Grant Jensen&lt;/a&gt; that I strongly encourage you to watch if you work in electron microscopy field, or if you have a strong appetite for knowledge that is useless in everyday life.&lt;/p&gt;
&lt;h2 id="what-is-an-electron-microscope"&gt;What is an Electron Microscope ?&lt;/h2&gt;
&lt;p&gt;This is an electron microscope:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/titan.jpg?w=555"&gt;&lt;/p&gt;
&lt;p&gt;It is a big box that measure about 3.5 meter high, connected to an army of computing cluster, a big power plug, some water and air tubes and sometimes a liquid Nitrogen tank. And it can do SCIENCE ! You can literally count the atom composing a transistor or see a COVID-19 virus entering a cell with this machine. For example, below is a spike of coronavirus reconstructed from CryoEM acquisition. This is basically what is inside the vaccine and that teach your cells how to recognize the virus:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-18.png?w=430"&gt;&lt;/p&gt;
&lt;h2 id="so-is-it-just-a-microscope-with-electronic-parts"&gt;So, is it just a microscope with electronic parts ?&lt;/h2&gt;
&lt;p&gt;Yes, there are electronics in Electron microscope. But it is called &lt;em&gt;Electron Microscope&lt;/em&gt; because, instead of using Photon like classical microscope you use in biology course, it uses Electrons. To understand why Electron are better than Photons, let's have a look at how a classical microscope works:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-41.png?w=481"&gt;&lt;/p&gt;
&lt;p&gt;Looking to an object is measuring how photons interact with this object. You light up the object from below and use a lens to scale up the resulting image. This works as long as photons are smaller than this object, because the size of a pixel of the resulting image cannot be smaller than the size of the photo that create this pixel.&lt;/p&gt;
&lt;p&gt;The problem with photons is that they are much bigger than atoms. An Atom is ~1 Å, which is about 0.1 nm. A photon is ~4000 Å, so 4000 time bigger. On the other hand, an electron is ~0.01 Å, a hundred time smaller. And if you think about it, an atom is just a nucleus with electrons spinning around. So yes, an electron IS much smaller than an atom.&lt;/p&gt;
&lt;p&gt;In the end we just have to build an electron flashlight to illuminate our object, an electron magnifying glass to magnify the image and an electron camera to take a picture, and we have an electron microscope 😎&lt;/p&gt;
&lt;h2 id="parts-of-an-electron-microscope"&gt;Parts of an Electron Microscope&lt;/h2&gt;
&lt;p&gt;If we open our electron microscope, we have the Column, which is the heart of the system:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-19.png?w=454"&gt;&lt;/p&gt;
&lt;p&gt;This column look like an optical microscope, except that it is upside down. The light is at the top, then you have a few lenses to diverge/converge the light, then the sample, another bunch of lenses and finally the sensor at the bottom.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-22.png?w=563"&gt;&lt;/p&gt;
&lt;h2 id="electron-gun"&gt;Electron Gun&lt;/h2&gt;
&lt;p&gt;2 parts compose the Electron gun :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The cathode, which generates the electron.&lt;/li&gt;
&lt;li&gt;The accelerator, which accelerate the electron to the good direction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cathode is a very simple object. It is basically a tungsten wire bent into a V shape:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-23.png?w=395"&gt;&lt;/p&gt;
&lt;p&gt;We then apply a very high tension to this wire, and the spiky shape will naturally emit electrons thanks to the &lt;a href="https://en.wikipedia.org/wiki/Thermionic_emission"&gt;Thermionic effect&lt;/a&gt; and the "&lt;a href="https://fr.wikipedia.org/wiki/Effet_de_pointe"&gt;Effet de pointe&lt;/a&gt;" (sorry, didn't find English references).&lt;/p&gt;
&lt;p&gt;So we apply a negative tension, typically -300 kV. As an electron has a negative charge, it will be pushed back. On the other end, the ground of the Electron Microscope is kept at 0V potential, so electron will be attracted by the bottom of the microscope. Furthermore, to properly accelerate electron, they go through an accelerator which maintain a gradient of potential that smoothly go from -300kV to 0V:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-25.png?w=598"&gt;&lt;/p&gt;
&lt;p&gt;By the way, an electron emitted with a 300Kv tension has an energy of 300 kilo electron volts, or 300keV. And current microscopes are able to generate electron one by one.&lt;/p&gt;
&lt;h2 id="lens"&gt;Lens&lt;/h2&gt;
&lt;p&gt;An optical lens converges and diverge light rays. It is the same for electron: it converges and diverge electrons "rays" except that electron lens are not made in glasses or transparent material. They are made with magnetic field generate by electromagnet:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-27.png?w=386"&gt;&lt;/p&gt;
&lt;p&gt;These magnets heat when in use. And heating a copper wire change its resistivity, which change its magnetic field, which is not a good thing for us because it's like changing the focus while taking a picture with a camera. So to avoid this, we have to cool down all these elements with water. Remember there is a 300,000 Volt electrical device operating a few inches away…&lt;/p&gt;
&lt;p&gt;But how does an electron lens work ? If we compare to optical lens, you probably have seen in college that rays emitted from a point converge on a single point to form an image, with some stories of focal point, focal distance, etc… :&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-28.png?w=606"&gt;&lt;/p&gt;
&lt;p&gt;Actually, there is a reason why rays converge in this particular points. To understand why, we have to remember that light is a wave, so the diagram above should look like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-29.png?w=650"&gt;&lt;/p&gt;
&lt;p&gt;The interesting thing about waves is that they can add themselves if they have the same phase:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-30.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;or subtract themselves if their phases are opposite:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-32.png?w=844"&gt;&lt;/p&gt;
&lt;p&gt;It is the same for lights. Traversing a transparent material change the light frequency, and traversing different thickness change the light wave phase when it comes out of the lens. Also, when a wave comes out of a surface, it is emitted into every direction. So we can consider that every single point of the universe potentially have an image of the initial object, but for most of these points, waves arrive with the wrong phase, and they destroyed each others.&lt;/p&gt;
&lt;p&gt;But there is a single point where all the light rays arrive with the same phase, and all contribute together to form the image:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-33.png?w=687"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-34.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;It is the same for electron. Electrons are also waves, and when they pass through a magnetic field, we can change their phase like a lens do for light.&lt;/p&gt;
&lt;h2 id="sample-holder"&gt;Sample Holder&lt;/h2&gt;
&lt;p&gt;One thing to know about Electron microscope column is that they are maintained in a nearly perfect vacuum. Any "air" molecule can interact with the electron beam and decrease acquisition quality. In that case, how do you place the sample inside the acquisition chamber ? With an airlock of course 😉&lt;/p&gt;
&lt;p&gt;On the side of the microscope, there is a tube with a valve where we can insert the sample holder:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-36.png?w=635"&gt;&lt;/p&gt;
&lt;p&gt;The sample holder also contains a liquid nitrogen tank to keep the sample frozen during the whole acquisition.&lt;/p&gt;
&lt;h2 id="energy-filter"&gt;Energy filter&lt;/h2&gt;
&lt;p&gt;EM Acquisition energy is measure in kilo-electron volt (keV). A typical CryoEM acquisition is done at 300keV. For various reason, it is very important that electrons that reach the detector really are at 300keV. We don't really care if electron traversing the sample are not at the good energy, but electrons reaching the detector must be at 300keV.&lt;/p&gt;
&lt;p&gt;To enforce this, there is a system placed before the detector called Energy filter, which goal is to filter electrons that are not perfectly at 300keV.&lt;/p&gt;
&lt;p&gt;To do so, the energy filter will generate (yet another) magnetic field to bend the electron beam up to a diaphragm. Electrons with an energy of 300keV will pass through a hole in this diaphragm, whereas other electron will not follow the same trajectory and will crash into the shield:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-37.png?w=369"&gt;&lt;/p&gt;
&lt;h2 id="detector"&gt;Detector&lt;/h2&gt;
&lt;p&gt;Today's detectors are able to detect electron one by one, and a raw electron microscope acquisition is far far away from beautiful colored images you can see on scientific papers. Indeed, a raw image looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-38.png?w=284"&gt;&lt;/p&gt;
&lt;p&gt;Each white dot is an electron impact. But by accumulating lots and lots of images, we can obtain this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-39.png?w=386"&gt;&lt;/p&gt;
&lt;p&gt;And finally, with lots of mathematics and processing, we can obtain this kind of images that, in addition to being beautiful, really helps scientist and biologist to understand the deep behavior of nature:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-40.png?w=515"&gt;&lt;/p&gt;</content><category term="misc"/><category term="CroyEM"/></entry><entry><title>How to Work Efficiently With Git ?</title><link href="/how-to-work-efficiently-with-git.html" rel="alternate"/><published>2022-06-07T09:31:00+02:00</published><updated>2022-06-07T09:31:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-06-07:/how-to-work-efficiently-with-git.html</id><summary type="html">&lt;p&gt;Git is a tool, and like any tool, there is a big difference between using it and using it properly. I will describe in this article the workflow I'm using in my day-to-day developer's job.&lt;/p&gt;
&lt;h2 id="starting-to-work-on-a-ticket"&gt;Starting to Work on a Ticket&lt;/h2&gt;
&lt;p&gt;When I start working on a Bug, on a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Git is a tool, and like any tool, there is a big difference between using it and using it properly. I will describe in this article the workflow I'm using in my day-to-day developer's job.&lt;/p&gt;
&lt;h2 id="starting-to-work-on-a-ticket"&gt;Starting to Work on a Ticket&lt;/h2&gt;
&lt;p&gt;When I start working on a Bug, on a User Story, on a Task or on whatever, I always start by checkout a branch containing my name, a short description of the issue and ticket number. It looks like :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git checkout -b tan/fix-event-crash-MIC-1831 origin/master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="saving-my-work"&gt;Saving my work&lt;/h2&gt;
&lt;p&gt;After a few minutes or a few hours, depending on the complexity of the task, I end up to commit my modifications. I rarely use command line for commit, but use git gui instead:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git gui
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And I systematically push my branch, also with git gui push button. This has 2 advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If I screw up my repos, I can still reset on the last time I pushed by branch.&lt;/li&gt;
&lt;li&gt;If my computer crash for any reason, I have a backup of my work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also use gitk a lot to see current status of my branch:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gitk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-2.png?w=720"&gt;&lt;/p&gt;
&lt;p&gt;Here I can see that I'm based on master, thanks to the &lt;code&gt;remote/origin/master&lt;/code&gt; label. I have 3 commits in my branch and my branch is currently pushed, thanks to the &lt;code&gt;remotes/origin/tan/feat2&lt;/code&gt; label being the same as local &lt;code&gt;tan/feat2&lt;/code&gt;. So my work is saved.&lt;/p&gt;
&lt;p&gt;I really commit/push A LOT. I push several times a day, and sometime up to several times per minutes for very short modifications.&lt;/p&gt;
&lt;h2 id="retrieving-others-work"&gt;Retrieving Others' Work&lt;/h2&gt;
&lt;p&gt;I regularly rebase my branch on current master to retrieve other's work and address conflicts as soon as possible.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git fetch
git rebase origin/master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that I rebase, and not merge master into my branch. I want my history to be linear, and the only merge points that appear in history are merged of feature branches into the master branch.&lt;/p&gt;
&lt;h2 id="always-push-at-the-end-of-the-day"&gt;Always Push at the End of the Day&lt;/h2&gt;
&lt;p&gt;Whatever the status of my code, I always commit my work at the end of the day and push it. I never know what can happen. If I'm in a draft state, I just put everything in a commit and prefix commit message with “WIP”:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-17.png?w=747"&gt;&lt;/p&gt;
&lt;h2 id="modifying-the-yesterdays-wip-commit"&gt;Modifying the Yesterday's WIP Commit&lt;/h2&gt;
&lt;p&gt;After a good night, I wake up and wonder what the hell I was doing yesterday. I clean up my mess and want to do a clean commit. But I commit an ugly “WIP” commit yesterday. Here comes the awesome “Amend Last Commit” git gui checkbox:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image.png?w=888"&gt;&lt;/p&gt;
&lt;p&gt;This checkbox let you modify the last commit, rewrite commit message, stage/unstage files etc… So I really have no reasons to not commit a WIP work.&lt;/p&gt;
&lt;h2 id="interactive-rebase"&gt;Interactive Rebase&lt;/h2&gt;
&lt;p&gt;I often do intermediates WIP commit, to explore a path until it leads to something concrete. I also frequently do small dumb fixes or typo correction that should go on older commit. To avoid having a lot of intermediate commits that goes back and forth, I practice interactive rebase. Interactive rebase is a wide topic. You can have a look &lt;a href="https://www.sitepoint.com/git-interactive-rebase-guide/"&gt;here&lt;/a&gt; to have more details.&lt;/p&gt;
&lt;p&gt;In the example below, while fixing a crash, I fix a typo in documentation I previously wrote. To indicate it, I prefix the commit message with an &lt;code&gt;f&lt;/code&gt; for &lt;code&gt;fixup&lt;/code&gt;. I would like this commit to be squashed with the 2nd &lt;code&gt;add doc&lt;/code&gt; commit, and then I would like to squash the &lt;code&gt;WIP&lt;/code&gt;commits with the &lt;code&gt;fix feat 1&lt;/code&gt; commit.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-5.png?w=719"&gt;&lt;/p&gt;
&lt;p&gt;To do so, I do an interactive rebase:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git rebase -i origin/master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And go from this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-7.png?w=496"&gt;&lt;/p&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-9.png?w=484"&gt;&lt;/p&gt;
&lt;p&gt;Now my branch is clean, I can publish the merge request and ask for review.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-11.png?w=717"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This workflow is well adapted to Trunk based development, but can also be used for any &lt;a href="https://kissyagni.wordpress.com/2022/03/14/an-overview-of-some-git-branching-models/"&gt;git branching models&lt;/a&gt;. The most important points are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rebase branch on master instead of merging master in branch.&lt;/li&gt;
&lt;li&gt;Always push branches, even draft and work in progress branches.&lt;/li&gt;
&lt;li&gt;Learn interactive rebase.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="bonus-for-git-masters-retrieving-temporary-work-of-others"&gt;(Bonus for Git masters) Retrieving Temporary Work of Others&lt;/h3&gt;
&lt;p&gt;Ideally, development branches should not live more than a few days, or even a few hours, so you should never have to use the work of other developers before it has been integrated in master. But in complex monolithic legacy projects, integration may take days or weeks… In such a case, your work may depend on someone else work that is still not integrated. There are many ways to do this: Rebasing branch on each other, cherry-picking commits, merging branches, … I will describe the method I use.&lt;/p&gt;
&lt;p&gt;Assuming I am in this situation. I already have some commit, starting from master:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-12.png?w=719"&gt;&lt;/p&gt;
&lt;p&gt;But I some &lt;code&gt;bob/fix-db&lt;/code&gt; branch to continue my work. This branch is in the integration pipeline, but won't be available before next week. In this case, what I do is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ensure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;everything&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;date&lt;/span&gt;
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fetch&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;save&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;work&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;If&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;screw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;up&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;still&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;just&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pushed&lt;/span&gt;
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;HEAD&lt;/span&gt;:&lt;span class="nv"&gt;tan&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;feat2&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;overview&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;work&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;keep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;side&lt;/span&gt;
&lt;span class="nv"&gt;gitk&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;serous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;things&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;begins&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;common&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;trunk&lt;/span&gt;
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;hard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;master&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;merging&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;need&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;ff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;explicite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;merge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commit&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;flatten&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;history&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;fast&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;forward&lt;/span&gt;.
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;merge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;bob&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fix&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;db&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;ff&lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Maybe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;need&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;several&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;branches&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;work&lt;/span&gt;.&lt;span class="w"&gt; &lt;/span&gt;
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;each&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;branches&lt;/span&gt;.
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;merge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;ben&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;fix&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;ff&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;now&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;retrieve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;commits&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;gitk&lt;/span&gt;
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cherry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cherry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cherry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cherry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;sha1&lt;/span&gt;...&lt;span class="nv"&gt;sha2&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;And&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;finally&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;looks&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;good&lt;/span&gt;
&lt;span class="nv"&gt;gitk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;History should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-15.png?w=716"&gt;&lt;/p&gt;
&lt;p&gt;I can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My branch &lt;code&gt;tan/feat2&lt;/code&gt; start from master&lt;/li&gt;
&lt;li&gt;It first merges the &lt;code&gt;bob/fix-db&lt;/code&gt;. I see this thanks to commit &lt;code&gt;Merge branch 'bob/fix-db' into tan/feat2&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The label &lt;code&gt;remote/origin/bob/fix-db&lt;/code&gt; is just before merge point, so I'm up-to-date with Bob's work.&lt;/li&gt;
&lt;li&gt;I've added 4 commits on top of Bob's work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main advantage of merging dependencies and cherry-picking your own commits, is that you and your colleagues can clearly see in history what is your own work and which branches your work depend on.&lt;/p&gt;
&lt;p&gt;There is also another big advantage. Imagine the branch &lt;code&gt;bob/fix-db&lt;/code&gt; broke something during integration and Bob had to fix its branch. By cherry-pick its commits or by basing your branch on its branch, you cannot see this. With the merge technique, you can directly see it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;git fetch
gitk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="" src="/images/2022/06/image-16.png?w=717"&gt;&lt;/p&gt;
&lt;p&gt;You notice that the &lt;code&gt;remote/origin/bob/fix-db&lt;/code&gt; has disappeared, indicating bob did something to its branch. In this case, just repeat the procedure described previously.&lt;/p&gt;
&lt;p&gt;This procedure can also handle case when &lt;code&gt;pbr/fix-db&lt;/code&gt; has finally been integrated in master. In this case, the &lt;code&gt;git merge origin/pbr/fix-db&lt;/code&gt; will tell you this branch is already merge and there are nothing to merge.&lt;/p&gt;
&lt;p&gt;Ideally, you should repeat this procedure until all dependent branches has been merged, and send your merge request only when you have only your modifications in your branch.&lt;/p&gt;
&lt;p&gt;As said at the beginning, this technique is really a workaround to handle very long integration pipeline. If your work depend on other's one, it is always better to wait their work to be integrated than doing high-flying gitology.&lt;/p&gt;</content><category term="misc"/><category term="branching model"/><category term="Git"/><category term="productivity"/></entry><entry><title>How to Organize a Backlog ?</title><link href="/how-to-organize-a-backlog.html" rel="alternate"/><published>2022-05-20T09:39:00+02:00</published><updated>2022-05-20T09:39:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-05-20:/how-to-organize-a-backlog.html</id><summary type="html">&lt;p&gt;Product backlog is really the barebones of agile scrum teams. It help Product Owner to communicates vision to stakeholders, it help dev team to anticipate future needs and adjust design accordingly and it help Scrum master analyzing how team can be more efficient in its work.&lt;/p&gt;
&lt;p&gt;Unfortunately, backlog is often …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Product backlog is really the barebones of agile scrum teams. It help Product Owner to communicates vision to stakeholders, it help dev team to anticipate future needs and adjust design accordingly and it help Scrum master analyzing how team can be more efficient in its work.&lt;/p&gt;
&lt;p&gt;Unfortunately, backlog is often a mess filled with "could be useful" ticket , "will never be fixed" bugs and other "I got this idea the other day when taking a shower" stories. We will see in this article some tips to help maintaining your backlog clean and focusing on what really matter.&lt;/p&gt;
&lt;h2 id="addressing-stories"&gt;Addressing stories&lt;/h2&gt;
&lt;p&gt;I won't detail the different level of Program/Initiative/Epic/Story here. I've always been closer to production team than marketing team, so I have not so much experience regarding Epics or Program ticket level. Lets just assume a story represent something needed by a user that can be implemented in less than a few weeks of effort by dev team. As we are in an agile environment, user require this feature now and will certainly change its mind in a few month. So this story should be addressed quickly to be valuable for our user, and as a consequence, for us. This lead us to the first statement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A story is not a long term vision.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Story should be addressed in the next few months, in current or next quarter. A story planed to be addressed in a year has lot of chances to be obsolete and no more adapted to user need, and just pollute backlog during months with useless information. That's why Product Backlog should only contains the detailed stories for the next 2 quarters at worst.&lt;/p&gt;
&lt;p&gt;— Yeah, but I have lot of important ideas !&lt;/p&gt;
&lt;p&gt;That's cool ! But, either your ideas are priority for next release, so they are in backlog, either it's just some good ideas but not required for next releases, in this case they should not appear in backlog to avoid drowning important stories.&lt;/p&gt;
&lt;p&gt;— Yeah, but I want to keep trace of it !&lt;/p&gt;
&lt;p&gt;Yes, I know it's very critical to keep trace of those 2 minutes cogitation you had during your breakfast... You then have 2 solutions:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution 1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;you really want your team to spend time on it. You want to spend money refining this idea, having a rough estimation of its efforts and its ROI but you are still not ready to plan it in a release. You can store it in something called a "Funnel". It can be a completely separate backlog like &lt;a href="https://www.productboard.com/"&gt;Productboard&lt;/a&gt;, &lt;a href="https://www.aha.io/roadmapping/guide/release-management/what-is-a-product-backlog"&gt;Aha&lt;/a&gt;, a dedicated &lt;a href="https://www.atlassian.com/software/jira"&gt;Jira&lt;/a&gt; board or even lighter tools like &lt;a href="https://miro.com/"&gt;Miro&lt;/a&gt; or &lt;a href="https://trello.com/"&gt;Trello&lt;/a&gt;. It can also be a filter in main backlog to hide these story by default. Once you find this story valuable enough, you can move this ticket to product backlog and really refine it in order to implement it in short term.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-43.png?w=789"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Your idea is just an idea. You can talk about it during coffee time, takes inputs, etc... but keep it in your own PO's TODO list until you consider it important enough to be placed in Funnel.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-44.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Remember, the more stories are in backlog, the harder it is to focus on what matter.&lt;/p&gt;
&lt;p&gt;— And what about stories that were top priority at some time but were canceled because of reasons ?&lt;/p&gt;
&lt;p&gt;As you said. They were canceled. So stop lying to yourself. Either you will do it, either you won't. Either you implement it for next release, either you remove it from backlog to focus on what matter. You can put it into Funnel or completely cancel it. Cancelling a story in Jira or any other board does not delete the ticket, it is still somewhere and can still be reopened in the future. (Spoil: this will never ever happen...).&lt;/p&gt;
&lt;h2 id="addressing-bugs"&gt;Addressing bugs&lt;/h2&gt;
&lt;p&gt;Stories are ticket that should be planed in short/middle term depending on their ROI. Bugs should be handle differently, more like a continuous flow. You can stop the flow of story. You decide to open or close the faucet. You can close the faucet and stop any activity if you want. Unfortunately, you cannot do this for bugs. Bug flow is controlled by user. And if you are falling behind to fix bugs, they will pile up and overwhelm you.&lt;/p&gt;
&lt;p&gt;As a rule of thumb, put bugs in top of backlog so that they will be addressed in next sprint. Do not be tempted to accumulate bugs to do a "stabilization sprint" just before release. By "address", I don't mean "Fix". To address means giving a solution to user. You can fix it, you can find an acceptable workaround, or you can purely cancel it considering bug is too costly to address. You would be surprised by the amount of user who can accept a bug if you explain them gently why it cannot be fixed. And you would be even more surprised by amount of user that would find a workaround as valuable as the actual fix. Finally, handling bugs in backlog can be summarize by:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;- Bugs are top priority.&lt;br&gt;
- Either you fix it, either you close it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's theory. In practice, I encountered a case where it was a better idea to accumulate bugs and fixing them by bunch. It was an old C++/COM legacy software. Deploying a dev environment required a day or two, copying file here and there, setting environment variable, downgrading to an old Visual Studio, etc... There was no activity on this product anymore but we still receive some bugs from time to time. In this case, we agreed to spent a "bug fix sprint" once or twice a year to fix all bugs at once and release a new patch.&lt;/p&gt;
&lt;h2 id="what-about-long-term-vision"&gt;What about long term vision ?&lt;/h2&gt;
&lt;p&gt;We just saw that product backlog should gives a few months, maybe a years of visibility, no more. But How do you share your long term vision ?&lt;/p&gt;
&lt;p&gt;You don't share a vision with tickets. You share a vision with discussions and with coherence on what you do day after day. If you put in backlog stories that don't have any link to each other, no one will understand where you want to go. If you put stories that &lt;em&gt;Tell a story&lt;/em&gt;, a common thread will emerge and people will understand your vision.&lt;/p&gt;
&lt;h2 id="what-about-the-past"&gt;What about the past ?&lt;/h2&gt;
&lt;p&gt;Backlog is NOT an overview of all the thing that was asked one day by some customer. It is NOT an overview of all the missing and broken stuff in your product. It is an overview of what you are going to do in the next months. So stop archiving every single request in the backlog.&lt;/p&gt;
&lt;h2 id="in-the-end-what-does-a-clean-backlog-look-like"&gt;In the end, what does a clean backlog look like ?&lt;/h2&gt;
&lt;p&gt;A good theoretical backlog look like this :&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/backlog-4.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Backlog is alive. Priorities can be changed and stories can be cancelled at any time. But the idea is to keep good visibility in short terms by having well defined stories on top and have a rough idea of what is going middle term with stories to be refined at the bottom.&lt;/p&gt;
&lt;p&gt;Remember: The Backlog is not a tool to show everyone all the great idea you have for your product. It is not an archive of everything your users have ever asked for. It is a tool to focus on what is important. The hardest part of a PO's job is not overfilling backlog. It is on the contrary to keeping it short and valuable.&lt;/p&gt;</content><category term="misc"/><category term="backlog"/><category term="product backlog"/><category term="product owner"/><category term="scrum"/><category term="sprint backlog"/></entry><entry><title>How to Write a User Story ?</title><link href="/how-to-write-a-user-story.html" rel="alternate"/><published>2022-05-05T11:24:00+02:00</published><updated>2022-05-05T11:24:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-05-05:/how-to-write-a-user-story.html</id><summary type="html">&lt;p&gt;Ah, stories... Dev team complains they are not enough specified, Product Owner complains he doesn't have time to write them and Scrum Master complains they are a meaningless mess. But writing a story should not takes than much time and it doesn't have to be detailed to be clear. Let's …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Ah, stories... Dev team complains they are not enough specified, Product Owner complains he doesn't have time to write them and Scrum Master complains they are a meaningless mess. But writing a story should not takes than much time and it doesn't have to be detailed to be clear. Let's see how to be efficient in writing stories and see some good and bad examples.&lt;/p&gt;
&lt;h2 id="a-story-tells-a-story"&gt;A story tells a story&lt;/h2&gt;
&lt;p&gt;First, goal of a stories is to synthesize a user's need. It should create empathy so that developers understand how they can help user. So a story should &lt;em&gt;tells a story.&lt;/em&gt; It should contains a protagonist who aspires to a goal. And to reach this goal, he needs something from you, he require your help. You are the support. You are the Sam Gamgie that will help Frodo throwing that damn ring into Mount Doom. So a good story should contains a protagonist, a need and a goal. And a very good way to always have these 3 points is using the famous:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a [protagonist], I need [something] in order to [achieve a goal].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really hated this phrase at the beginning of my career because I didn't understood the important part was not its structure "As a ... I need ... in order to ...", but the 3 points we just discussed before. Lets analyze them more in details:&lt;/p&gt;
&lt;h3 id="the-protagonist"&gt;The protagonist&lt;/h3&gt;
&lt;p&gt;A lot of stories start with "As a user". That's the worst way of starting a story because it gives no information. Anyone using your code is a user, including yourself. Imagine starting a tales by "Once upon a time, in a place, lived a character."... That's the case for any single story told since the beginning of mankind, so try to be more specific.&lt;/p&gt;
&lt;p&gt;In our stories, protagonist can be:&lt;/p&gt;
&lt;p&gt;An identified customer:&lt;br&gt;
- As Renault Truck, ...&lt;br&gt;
- As Walmart, ...&lt;br&gt;
- As GE Aviation, ...&lt;/p&gt;
&lt;p&gt;A persona:&lt;br&gt;
- As portal administrator, ...&lt;br&gt;
- As front-end developer, ...&lt;br&gt;
- As game artist, ...&lt;/p&gt;
&lt;p&gt;Or even an identified team if you are developing internal tools:&lt;br&gt;
- As Kernel team, ...&lt;br&gt;
- As Marketing team, ...&lt;br&gt;
- As ML team, ...&lt;/p&gt;
&lt;h3 id="the-need"&gt;The need&lt;/h3&gt;
&lt;p&gt;The need should be expressed from protagonist point of view, and not from developper's point of view. Don't write "update library version" but "be compatible with new hardware". Don't write "Integrate elasticsearch" but "have search bar in main page". The technical solution will be decided by developers once they will have understood the need.&lt;/p&gt;
&lt;h3 id="the-goal"&gt;The goal&lt;/h3&gt;
&lt;p&gt;The goal gives context to dev team and let them understand the scope and criticize the need. Maybe you won't be able to achieve your goal with just what you're asking for ? Maybe you don't need that at all to achieve your goal and there is a much simpler solution ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/05/image-1.png?w=485"&gt;&lt;/p&gt;
&lt;p&gt;Yes, I know, Gandalf could not asked this to the Eagles because of reasons, bla bla bla, but that's not the subject. The subject here is that, if dev team know why they implement such and such feature, they won't lose energy over-designing, they will be more inclined to propose a suitable solution, and maybe they will tell you "you can already do that".&lt;/p&gt;
&lt;h2 id="a-story-should-be-demonstrable"&gt;A story should be demonstrable&lt;/h2&gt;
&lt;p&gt;Last but not least, a Story should be demonstrable. As a developer, how can you prove you implement something ? As a QA, how do you validate new behavior is the expected one ? As a PO, how do you prove you add a new feature in your product ? As a team, how do you show the new feature during sprint review and get feedback from stakeholders ?&lt;/p&gt;
&lt;p&gt;There are several ways to define acceptance criteria. You can write detailed specification that no one will read anyway, or you can use simpler format like "Given ... When ... Then ..." or my favorite one: &lt;strong&gt;How to Demo&lt;/strong&gt;. let's see a small example.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;As&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;administrator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;currently&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;who&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;impacted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;maintenance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Demo&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;few&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fake&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Click&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;Current Users&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fakes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;should&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This small scenario gives us a LOT of information and questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You need to populate database with fake data, or at least a dataset. Do you have one ? Are you able to create those fake data ?&lt;/li&gt;
&lt;li&gt;Go to Admin page. Does it already exist ?&lt;/li&gt;
&lt;li&gt;Click on "Current user" button. Do we have mockup for this button ?&lt;/li&gt;
&lt;li&gt;List of fakes users should be displayed. Do we have mockup for this list ?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So you can iterate on the story until it is ready, and avoid dev team working on it to discover in the middle of the sprint they lack half of the information.&lt;/p&gt;
&lt;p&gt;This &lt;strong&gt;How to demo&lt;/strong&gt; also tells to developers when to stop. If you don't explain how to demo, dev team may be tempted to extrapolate and work on the maintenance part. Here, development ends when we have the list of connected users, we don't care about maintenance operation, this is another topic.&lt;/p&gt;
&lt;p&gt;Having an &lt;strong&gt;How to demo&lt;/strong&gt; also tells to QA how it can validate the story. And finally, It gives the scenario to present to sprint review.&lt;/p&gt;
&lt;h2 id="example"&gt;Example&lt;/h2&gt;
&lt;p&gt;To conclude, here are some bad and good examples.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Implement GPU picking

Acceptance criteria:
Picking should be done on GPU
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;As&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Airbus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CAD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;team&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;picking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;responsive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;improve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;experience&lt;/span&gt;

&lt;span class="nv"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Demo&lt;/span&gt;:
&lt;span class="nv"&gt;Given&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;attached&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;displayed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;viewer&lt;/span&gt;
&lt;span class="nv"&gt;When&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;objects&lt;/span&gt;
&lt;span class="k"&gt;Then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Selecting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;should&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;takes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="nv"&gt;ms&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="example_1"&gt;Example&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;As&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;need&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CUDA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;.&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;support&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Ampere&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;GPU&lt;/span&gt;.

&lt;span class="nv"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Demo&lt;/span&gt;:
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;about&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;dialog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;show&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CUDA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;should&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;.&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;As IT department, I need application to support new Ampere GPU in order to move to new infrastructure.

Note: Ampere GPU require CUDA &amp;gt;=11.4

How to Demo:
- Deploy application on new infrastructure
- Load some data
=&amp;gt; Application should works correctly

- Execute test suite on new infrastructure
=&amp;gt; Test should be green
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="example_2"&gt;Example&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;As a User, I want elasticsearch in order to have a search bar

How to demo:
- Load main page
=&amp;gt; There should be a search bar (see attached mockup) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;As&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;buyer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;persona&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;order&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;

&lt;span class="nv"&gt;How&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;demo&lt;/span&gt;:
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;search&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;bar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;see&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;attached&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;mockup&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;corresponding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;products&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;should&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;display&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="misc"/><category term="backlog"/><category term="product owner"/><category term="story"/></entry><entry><title>Tests Are Good. But What Are Good Tests ?</title><link href="/tests-are-good-but-what-are-good-tests.html" rel="alternate"/><published>2022-04-25T09:02:00+02:00</published><updated>2022-04-25T09:02:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-04-25:/tests-are-good-but-what-are-good-tests.html</id><summary type="html">&lt;p&gt;Tests are an essential part of development. Well tested application have more line of code in tests than in actual code. But not all tests are equals and, unfortunately, some tests are written only for the sake of reaching a code coverage target or making QA happy to see test …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Tests are an essential part of development. Well tested application have more line of code in tests than in actual code. But not all tests are equals and, unfortunately, some tests are written only for the sake of reaching a code coverage target or making QA happy to see test base increasing.&lt;/p&gt;
&lt;h2 id="what-is-a-test-anyway"&gt;What is a test anyway ?&lt;/h2&gt;
&lt;p&gt;Let's kill a myth. Autotests had never ensured your application works correctly. It ensures your application works like before. It is up to developer, QA, Product Owner and finally User to decide if the application behaves correctly. Once you have the correct behavior, you set it in stone by writing a test.&lt;/p&gt;
&lt;p&gt;But what about &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt;, which advocate writing tests before writing code ? If we look at the big picture, TDD's real added value is not really to respect written requirements, but to ensure the design you are conceiving is testable. TDD Katas and scholar exercises are often toys with clearly defined specifications and simple use case. In the real world, you often iterate on your TDD because you realize the unit test you wrote last week contradicts the integration test you are writing today. Because API has changed, because result was not the good one after all, because user change its mind and prefer logging an error than throwing an exception, etc... And it's not an issue. As you wrote test first, you ensure your design is testable now, but also in the future. Even if requirement change, you can easily update your test assertions to match the new expected result.&lt;/p&gt;
&lt;p&gt;In some cases, you don't even know what result you would expect until you have implemented your algorithm. This often happen when dealing with scientific computation. Let's imagine this not-so-fictive conversation between a biologist and a developer:&lt;/p&gt;
&lt;p&gt;— Hi, I want to compute size of a Coronavirus from CryoEM acquisition.&lt;br&gt;
— Ok, do you have a dataset ?&lt;br&gt;
— Sure, here it is.&lt;br&gt;
— Cool, and what is the expected size of virus in this dataset ?&lt;br&gt;
— Are you kidding me ? That's what I'm asking for !&lt;/p&gt;
&lt;p&gt;So you go home with inputs data but no outcomes. You start writing a test, because you know TDD is a good practice, but you don't know what to write as an expected result. Never mind, you leave it blank and start implementing the algorithm. Once you have a result, you give a pre-version to your user which will decide if the result is coherent or not (it often happens in scientific domain that you don't know what result to expect but can validate a result a posteriori). If the result is OK, you put it as expected result in a test to forbid regression in the future.&lt;/p&gt;
&lt;p&gt;What is also important to understand is that failing test does not always indicate something is broken. It indicates something has changed. If you make an improvement in your algorithm, the test will fail, indicating the result is different from before. Scientist will tell you if result is better or worst, but if result is better, you have to update test baseline to freeze this new behavior.&lt;/p&gt;
&lt;p&gt;In the previous example, you may argue that only the final result is really validated. You cannot guaranty there are no bugs in intermediates results. You just hope that, as the final result is good, intermediate result should be good, no ? Unfortunately, no. And that's lead me to a statement I discover with pain in my career:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any working software contains an even number of internal bugs which correct each other.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And worse than that, some unit tests are here to ensure these buggy behavior stay in place to avoid collapsing the whole system.&lt;/p&gt;
&lt;h2 id="gross-value-a-net-value"&gt;Gross value a net value&lt;/h2&gt;
&lt;p&gt;Now we have seen what is a test, let's talk about its value.&lt;/p&gt;
&lt;p&gt;Like for your salary, gross value doesn't matter that much. What matter in the end is net value. And like your salary, tests have a gross value and a net value. Gross value is the test ability to detect regression. Net value is much more subtle.&lt;/p&gt;
&lt;p&gt;A test failing half of the time for no reason, taking several minutes to execute and a day to be deployed on the developer environment has a negative net value. You waste more time maintaining it than you actually gain by catching the regression early. On the other hand, a test executed on a few seconds, both on test and developer environment, which detect only true positive is much more valuable.&lt;/p&gt;
&lt;p&gt;To have a high net value, a test should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a high probability of detecting regressions&lt;/li&gt;
&lt;li&gt;Have a low probability of creating a false positive&lt;/li&gt;
&lt;li&gt;Be fast and easy to execute, both on Test and Dev environment&lt;/li&gt;
&lt;li&gt;Have a low maintenance cost&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="filter-your-test"&gt;Filter your test&lt;/h2&gt;
&lt;p&gt;Choosing if a test is valuable or not really depend on your domain. Critical DO-178A aeronautics system should be fully tested, whatever the cost. Temporary mobile applications don't need such a robustness. It is up to you to place the cursor. Then, you (I mean, not you personally, but your organization) have to be honest with yourself and drop the tests you judge not profitable enough. The time you will save by not maintaining useless tests can be invested in writing new highly valuable tests. In a nutshell:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-31.png?w=792"&gt;&lt;/p&gt;</content><category term="misc"/><category term="autotest"/><category term="clean code"/><category term="refactoring"/></entry><entry><title>Chevron Anti-pattern</title><link href="/chevron-anti-pattern.html" rel="alternate"/><published>2022-04-20T08:21:00+02:00</published><updated>2022-04-20T08:21:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-04-20:/chevron-anti-pattern.html</id><summary type="html">&lt;p&gt;I will talk about an antipattern I've encountered a few time, but I didn't find it in literature, so I called it the "Chevron antipattern". Let-me know if you recognize it and if it has a true name 😉&lt;/p&gt;
&lt;h2 id="class-diagram"&gt;Class Diagram&lt;/h2&gt;
&lt;p&gt;Let's start by an example. Assume you develop an application …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I will talk about an antipattern I've encountered a few time, but I didn't find it in literature, so I called it the "Chevron antipattern". Let-me know if you recognize it and if it has a true name 😉&lt;/p&gt;
&lt;h2 id="class-diagram"&gt;Class Diagram&lt;/h2&gt;
&lt;p&gt;Let's start by an example. Assume you develop an application that should support 2 render engines. One, let says, based on Unity and the other based on Unreal, for example. Your render area is embedded in a Window. You define a Widget abstraction layer to handle event, and a Render abstraction layer to handle rendering. You end up with this class diagram:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/05/image-3.png?w=618"&gt;&lt;/p&gt;
&lt;p&gt;You have your Windows that has a &lt;strong&gt;WidgetInterface&lt;/strong&gt; which can be either a Unity based widget or an Unreal based widget. Nice, isn't it ?&lt;/p&gt;
&lt;p&gt;I called it "Chevron" pattern because one can see 2 chevrons pointing to the top.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/05/chevron.png?w=618"&gt;&lt;/p&gt;
&lt;p&gt;And this can continue on several layers.&lt;/p&gt;
&lt;h2 id="why-is-it-an-anti-pattern"&gt;Why is it an Anti-Pattern ?&lt;/h2&gt;
&lt;p&gt;The antipattern part comes from the &lt;strong&gt;RendererInterface&lt;/strong&gt;. An interface defines a set of services that should be implemented by concrete implementation, so that client of this interface don't care about the underlying implementation.&lt;/p&gt;
&lt;p&gt;In this case, &lt;strong&gt;RendererInterface&lt;/strong&gt; is not used by any client.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/05/renderinterfaceowner-edited.png"&gt;&lt;/p&gt;
&lt;p&gt;Even if it is not owned by anyone, it may still be used as a function parameter, but when I encountered this pattern, those usages could easily be removed with small refactoring.&lt;/p&gt;
&lt;p&gt;You end up having very strong constraints on how concrete Unity and Unreal Renderers have to be implemented, without real reasons. Maybe &lt;strong&gt;UnityWidget&lt;/strong&gt; is just a pass-through &lt;strong&gt;UnitRenderer&lt;/strong&gt;, but this design forced you to have such a layer.&lt;/p&gt;
&lt;h2 id="how-to-fix-this"&gt;How to Fix This ?&lt;/h2&gt;
&lt;p&gt;This antipattern is very easy to fix if discovered soon enough. If &lt;strong&gt;RendererInterface&lt;/strong&gt; is useless, just remove it:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/05/image-4.png?w=493"&gt;&lt;/p&gt;
&lt;p&gt;Now it decouple &lt;strong&gt;UnityRender&lt;/strong&gt; and &lt;strong&gt;UnrealRender&lt;/strong&gt; implementations. You can implement those classes as you want, even merge them into the Widget layer if it makes sense. Keep in mind that the important part here is the &lt;strong&gt;WidgetInterface&lt;/strong&gt;. It is this interface that let you change render engine without impacting Windows layer. &lt;strong&gt;RendereInterface&lt;/strong&gt; was initially added, probably to keep a symmetry in the design and having a beautiful class diagram. But this is not a good reason to define an interface.&lt;/p&gt;</content><category term="misc"/><category term="c++"/><category term="clean code"/><category term="refactoring"/></entry><entry><title>Scrum retrospective: Cool Runnings</title><link href="/scrum-retrospective-cool-runnings.html" rel="alternate"/><published>2022-04-19T09:12:00+02:00</published><updated>2022-04-19T09:12:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-04-19:/scrum-retrospective-cool-runnings.html</id><summary type="html">&lt;p&gt;If you are in your mid-thirties, you probably remember &lt;strong&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Cool_Runnings"&gt;Cool Runnings&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; (or &lt;a href="https://fr.wikipedia.org/wiki/Rasta_Rockett"&gt;&lt;strong&gt;&lt;em&gt;Rasta Rocket&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; for French people). I watched this movie a dozen times when I was a child. But did you know this movie was about a young Scrum team doing its Agile transformation ? Let's have a look at …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you are in your mid-thirties, you probably remember &lt;strong&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Cool_Runnings"&gt;Cool Runnings&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; (or &lt;a href="https://fr.wikipedia.org/wiki/Rasta_Rockett"&gt;&lt;strong&gt;&lt;em&gt;Rasta Rocket&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; for French people). I watched this movie a dozen times when I was a child. But did you know this movie was about a young Scrum team doing its Agile transformation ? Let's have a look at this.&lt;/p&gt;
&lt;h2 id="the-team"&gt;The team&lt;/h2&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_160616.png?w=766"&gt;&lt;/p&gt;
&lt;p&gt;So we have a group of Jamaican trained for olympic bobsled event leaded by their captain Derice Bannock. They are technically ready but struggle to find their place in the competition.&lt;/p&gt;
&lt;h2 id="the-winners-secret"&gt;The winner's secret&lt;/h2&gt;
&lt;p&gt;Derice, the captain, go to a training of the Swiss team, favorite for the event, to see what is their secret for being such a powerful team.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_161543.png?w=782"&gt;&lt;/p&gt;
&lt;p&gt;The Swiss team happens to butt each other's heads before the event to reinforce their team spirit and count "Eins Zwei Drei" when pushing the bobsled. So, Derice decide to hit its teammates head before the qualification race and count "Eins Zwei Drei".&lt;/p&gt;
&lt;p&gt;Yeah, you got it: &lt;a href="https://en.wikipedia.org/wiki/Cargo_cult"&gt;Cargo cult&lt;/a&gt;...&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_162248.png?w=781"&gt;&lt;/p&gt;
&lt;p&gt;But things didn't went as planned and they did a catastrophic departure...&lt;/p&gt;
&lt;h2 id="the-retrospective"&gt;The retrospective&lt;/h2&gt;
&lt;p&gt;Going back to their room, the team analyze what has failed. Derice don't understand what they did wrong as they did exactly like the Swiss team. Sanka gets angry and explain they are not Swiss, they are Jamaican. There is no point doing a Swiss bobsled, they must do a Jamaican bobsled.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_163028.png?w=777"&gt;&lt;/p&gt;
&lt;h2 id="the-next-sprint"&gt;The next sprint&lt;/h2&gt;
&lt;p&gt;Team finally find its own way of doing with their famous "Cool Running" battle cry.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_164319.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;They qualify for the finals, do an excellent race and won the golden medal.... No, just kidding, they crash just before the finish line.&lt;/p&gt;
&lt;h2 id="so-what"&gt;So What ?&lt;/h2&gt;
&lt;p&gt;We have a team that were told to do Scrum. So they do Sprint planning, they have a Jira backlog with lots of ticket, they do "Stand up" meeting, but as they were still too long they even tried "Push up" meeting, they do Sprint reviews, Sprint retrospectives, smash their head and count "Eins Zwei Drei" at the beginning of each sprint, but it still doesn't works. Why ? Because a Team has to find its own way of working. All the scrum ceremonies are not the cause of becoming Agile. They are the consequences.&lt;/p&gt;
&lt;h2 id="the-cool-runnings-retrospective"&gt;The Cool Runnings retrospective&lt;/h2&gt;
&lt;p&gt;I designed a few years ago a sprint retrospective based on this movies. I spent a couple of minutes explaining the plot like what I did in this article, and then asked the team to put all the Scrum stuff we were doing into 2 categories:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/02/image_2022-02-22_172732.png?w=954"&gt;&lt;/p&gt;
&lt;p&gt;And something really interesting happened. I had a bunch of grumpy people at this time that put everything in the "Eins Zwei Drei" column. Retro, stand up, planif, etc... When I asked them why they put ticket here, they quickly run out of arguments. In the end, they decided to put the stand up at 10am by themselves, they decided to do continuous backlog refinement along the sprint and have a quick planif on monday morning, they chose their DoR and DoD, they chose their workflow in Jira, etc... So my grumpy team that continuously complained about the process just realized that They put this process in place for reasons, and if it doesn't fit their needs anymore, They have to change it.&lt;/p&gt;</content><category term="misc"/><category term="agile"/><category term="retrospective"/><category term="scrum"/></entry><entry><title>How to Evaluate a Refactoring Project ?</title><link href="/how-to-evaluate-a-refactoring-project.html" rel="alternate"/><published>2022-04-11T08:53:00+02:00</published><updated>2022-04-11T08:53:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-04-11:/how-to-evaluate-a-refactoring-project.html</id><summary type="html">&lt;p&gt;I won't surprise anyone if I say evaluations are most of the time underestimated. &lt;a href="https://en.wikipedia.org/wiki/Parkinson%27s_law"&gt;Parkinson's law&lt;/a&gt; ensure estimations will never be overestimated anyway, but how can we better anticipate all the impediments that will delay our project ?&lt;/p&gt;
&lt;p&gt;This article is taken from the "&lt;a href="https://youtu.be/bNp9Xv18wi8?t=1988"&gt;How (not) to refactor a kernel&lt;/a&gt;" conference …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I won't surprise anyone if I say evaluations are most of the time underestimated. &lt;a href="https://en.wikipedia.org/wiki/Parkinson%27s_law"&gt;Parkinson's law&lt;/a&gt; ensure estimations will never be overestimated anyway, but how can we better anticipate all the impediments that will delay our project ?&lt;/p&gt;
&lt;p&gt;This article is taken from the "&lt;a href="https://youtu.be/bNp9Xv18wi8?t=1988"&gt;How (not) to refactor a kernel&lt;/a&gt;" conference I did during the Agile Tour 2021 in Bordeaux.&lt;/p&gt;
&lt;h2 id="problems-occurs-at-the-end"&gt;Problems occurs at the end&lt;/h2&gt;
&lt;p&gt;The devil is in the details, and details happen at the end. For a lot of project, startup goes well. You put in place architecture, you handle generic case, post-pone all the small features that bother you and are confident you will meet the deadline. But approaching 80% of project scope, you start to slow down, corner cases don't fit in your design, more and more cases were not anticipate and in the end, you end up with another 80% of work to address and your burn up curve look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-1.png?w=777"&gt;&lt;/p&gt;
&lt;h2 id="modeling-the-curve"&gt;Modeling the curve&lt;/h2&gt;
&lt;p&gt;"The more there is to do, the easier it is to pick stuff to do"&lt;br&gt;
"When nothing works, small changes have big impact"&lt;br&gt;
"The last use cases are the hardest to address"&lt;/p&gt;
&lt;p&gt;I think I'm not the only one to already have heard this regarding project advancement. Lets use these statements as starting point for our model. Note that I cannot prove they are true. I suppose they are true and I will extrapolate what they imply. You are free to disagree with them and thus, disagree with the the conclusion I'm going to draw.&lt;/p&gt;
&lt;p&gt;Assume we have a finite and constant quantity of work to address in order to fulfill our project. This can be a number of use case, a number of bugs, a performance level to reach, etc... As we stated before, the greater is this remaining quantity, the more effective the team will be at addressing it. This can be formalized by this formula:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-08_141057.png?w=939"&gt;&lt;/p&gt;
&lt;p&gt;For a small period of time (let say, a Sprint), the work done by the team depends on the remaining work, using a constant coefficient "effort" which characterizes the team. We assume the team is constant and stay focus on its project, so the effort coefficient is constant. Now, lets do some math and write this equation slightly differently with infinitesimal time:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-08_141324.png?w=488"&gt;&lt;/p&gt;
&lt;p&gt;You may recognize a 1st order differential equation which is solved this way:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-08_141423.png?w=405"&gt;&lt;/p&gt;
&lt;p&gt;With k and τ constant. Their values is not meaningful for our demonstration. If we plot this equation, we end up with this curve:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-08_141714.png?w=757"&gt;&lt;/p&gt;
&lt;p&gt;This curve really look like the project burn up curve we had at the beginning, so our model may not be that silly after all.&lt;/p&gt;
&lt;h2 id="graphical-interpretation"&gt;Graphical interpretation&lt;/h2&gt;
&lt;p&gt;1st order equation have some particular characteristics easily visible graphically. First of all, they never reach their limit. This is annoying to estimate the end of our project... In practice, we consider this kind of system reach its limit when it reach 95% of its target. And we know that these systems take the same time to go from 0 to 80% than to go from 80% to 95%. This means that, once you had implemented 80% of feature, you are just in the middle of your project:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-2.png?w=887"&gt;&lt;/p&gt;
&lt;p&gt;Despite being a very good way to kill the mood of your team, this information is not very useful to build a roadmap because you have to wait the middle of your project to know when it will be finished. But this curve has another much more interesting particularity: Its initial slope tells us when it will reach the target which is actually 3 times latter than you think:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-4.png?w=854"&gt;&lt;/p&gt;
&lt;p&gt;As any human being, as soon as you start having a curve you hasten to draw a straight line to extrapolate its evolution. This extrapolation gives you an estimated end date that you happily communicate to your direction and stakeholders. But in this case, you know your end date will be 3 time this estimation. This can be summarized by:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It will take tree time your initial velocity to complete the project&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="is-3-a-magic-number"&gt;Is 3 a magic number ?&lt;/h2&gt;
&lt;p&gt;I've heard some project manager stating that estimation should always be multiplied by 3, or even Pi, using more or less serious justifications like "&lt;a href="https://www.projectteamblog.com/index.php/improve-task-estimates-multiply-by-pi/"&gt;Three-point estimating technique&lt;/a&gt;" or the infamous "&lt;a href="https://tefter.io/bookmarks/757014/readable"&gt;Circular Estimation Conjecture&lt;/a&gt;". But my favorite argument for Pi is that, as an estimation is always irrational, multiply it by Pi will ensure making it irrational anyway.&lt;/p&gt;</content><category term="misc"/><category term="estimation"/><category term="product owner"/><category term="refactoring"/></entry><entry><title>The Problem of Floating Point Precision in Opengl, Vulkan and 3D in General - Part 3</title><link href="/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-3.html" rel="alternate"/><published>2022-04-04T10:38:00+02:00</published><updated>2022-04-04T10:38:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-04-04:/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-3.html</id><summary type="html">&lt;p&gt;We have seen in the &lt;a href="https://kissyagni.wordpress.com/2022/03/28/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2/"&gt;previous article&lt;/a&gt; how to handle position of object and camera in very large scene. But this still won't solve the shaky problem caused by matrix accumulation. We will here see that only a few place needs to use double precision, and not all your rendering …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We have seen in the &lt;a href="https://kissyagni.wordpress.com/2022/03/28/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2/"&gt;previous article&lt;/a&gt; how to handle position of object and camera in very large scene. But this still won't solve the shaky problem caused by matrix accumulation. We will here see that only a few place needs to use double precision, and not all your rendering pipeline.&lt;/p&gt;
&lt;h2 id="reminder-about-space-changes"&gt;Reminder about space changes&lt;/h2&gt;
&lt;p&gt;We have a point P expressed in Model space, and we want to express it in View space knowing Model matrix and View matrix:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-18.png?w=732"&gt;&lt;/p&gt;
&lt;p&gt;Model is a shortcut for ModelToWorld matrix. With this matrix, you can express P coordinates in World space knowing P coordinates in Model space. On the other hand, View matrix is a shortcut for WorldToView matrix with which we can express P coordinate in View space knowing P coordinate in World space. In the end:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P_view = WorldToView * P_world = WorldToView * ModelToWorld * P_model&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The (WoldToView * ModelToWorld) is also known as the ModelView matrix. Legacy OpenGL only used the ModelView matrix for performance reason and didn't split it into 2 Model and View matrix, but separate World and View are much more convenient, especially for beginners. And in todays computer, multiplying 2 matrices together is really not a bottleneck anymore.&lt;/p&gt;
&lt;h2 id="what-is-p-precision-in-view-space"&gt;What is P precision in view space ?&lt;/h2&gt;
&lt;p&gt;As we saw, precision issues occurs when point of interest is faw aways from its reference space. Both Camera and P are far away from World origin. We saw in previous article how to handle that. But when Camera and P are really close to each other, why P would be shaky ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-19.png?w=898"&gt;&lt;/p&gt;
&lt;h2 id="and-once-again-precision-comes-into-play"&gt;And once again, precision comes into play...&lt;/h2&gt;
&lt;p&gt;Problems are located in 3 place: the &lt;strong&gt;WorldToView&lt;/strong&gt; matrix, the &lt;strong&gt;ModelToWorld&lt;/strong&gt; and the &lt;strong&gt;WorldToView * &lt;/strong&gt;ModelToWorld**** computation. Imagine P and Camera located in Saturn with an Heliocentric world space. You will do a +1 billion km to express P in World space and -1 billion to go back to View space. Now you slightly move your camera of 1 meter to the left and your P of 1 meter to the right. Using a proper model space and tripod position &lt;a href="https://kissyagni.wordpress.com/2022/03/28/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2/"&gt;as described before&lt;/a&gt;, you can do it. You do 1 000 000 000 001 - 999 999 999 999. Cast these values to Float to generate corresponding matrices and your meter has been lost on both side. So should we accumulate everything in double precision ?&lt;/p&gt;
&lt;p&gt;Well, not exactly. Only a few thing should be done in double precision. Most of other space transformations can remains in single precision.&lt;/p&gt;
&lt;h2 id="managing-model-matrix"&gt;Managing model matrix&lt;/h2&gt;
&lt;p&gt;Render engines often have a stack of several transformation before reaching the final object. To render a tire on car on a track, you have the main car position, then translation from car origin to tire origin, then rotation of tire around its axis. For complex models, you may have a dozen of transformation like this before reaching the actual point. But not all transformation should be done in Double. Car may be far far away from its origin, like &lt;a href="https://en.wikipedia.org/wiki/Elon_Musk%27s_Tesla_Roadster"&gt;Elon Musk's Tesla Roadster&lt;/a&gt;, but once on the car, object are relatively close to each other. So only the first big translation should be accumulate in double:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-20.png?w=1006"&gt;&lt;/p&gt;
&lt;p&gt;If we represent this scene with a scene graph, we would have 3 Translation node T1, T2 and T3. T2 and T3 can use float precision and matrix accumulation can be done in float. Lets call T'=T2*T3.&lt;br&gt;
However, even though T1 translation value can be stored in float, the computation T"=T1 * T' should be done and stored in double precision and final Model matrix result stored in double precision. In the end, this scene graph should look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-21.png?w=235"&gt;&lt;/p&gt;
&lt;p&gt;A root node, immediately followed by a "Double translation" which generate a Double precision Model matrix, followed by classical scene graph: translations working in single Float precision and final object with single precision coordinated.&lt;/p&gt;
&lt;h2 id="managing-view-matrix"&gt;Managing View matrix&lt;/h2&gt;
&lt;p&gt;Same story for the view matrix. You should first locate the camera "Tripod" using a double precision translation and then locate your camera as usual:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-22.png?w=229"&gt;&lt;/p&gt;
&lt;p&gt;So finale scene graph look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-23.png?w=233"&gt;&lt;/p&gt;
&lt;h2 id="and-what-about-modelview"&gt;And what about ModelView ?&lt;/h2&gt;
&lt;p&gt;In the end, we end up with a double precision Model matrix and a double precision View matrix. With them, we can have the final double precision ModelView matrix. And you will tell me "Yeah, but GPU don't work with double precision, they need single precision ModelView matrix to compute all the vertices, lighting and so on".&lt;/p&gt;
&lt;p&gt;Yes, you are right. We cannot send double precision ModelView matrix directly to GPU. But suddenly, magic comes into play...&lt;/p&gt;
&lt;p&gt;Remember, ModelView express coordinates of point relative to Camera. In our case, both point and Camera are somewhere around Saturn, they are both close to each other and thus, we don't need a lot of precision to locate a point relative to camera. We don't care anymore about World space. Remember this diagram:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-19.png?w=898"&gt;&lt;/p&gt;
&lt;p&gt;This means, once we have computed ModelView = View * Model in double precision, we can cast back ModelView matrix to single precision and send it to GPU. ModelView matrix no more have large magnitude coefficient and precision won't be an issue anymore.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-24.png?w=595"&gt;&lt;/p&gt;
&lt;p&gt;Difficulty is how to define the initial double precision translation. Unfortunately, it depend on your use case. This big translation can be seen as a local origin for your scene, so for wide open world, this can be the tile position where you currently are. For fly simulator, you can update this translation with current plane position every hundred of km for examples. I had a use case where user wanted to render different factories in a Google earth like background. Off course, each factories were very detailed and you can literally see the pipes and ladders when zooming it. In this case, local origin was the position of currently selected factory.&lt;/p&gt;</content><category term="misc"/><category term="3D"/><category term="c++"/><category term="IEEE754"/><category term="opengl"/><category term="vulkan"/></entry><entry><title>The Problem of Floating Point Precision in Opengl, Vulkan and 3D in General - Part 2</title><link href="/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2.html" rel="alternate"/><published>2022-03-28T07:56:00+02:00</published><updated>2022-03-28T07:56:00+02:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-03-28:/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2.html</id><summary type="html">&lt;p&gt;We have seen in a &lt;a href="https://kissyagni.wordpress.com/2022/03/21/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-1/"&gt;previous article&lt;/a&gt; why floating point representation may shake our objects in scene. We will now see how to use space change tricks to mitigate this problem.&lt;/p&gt;
&lt;h2 id="a-brief-reminder-about-world-model-and-view-space"&gt;A brief reminder about World, Model and View space&lt;/h2&gt;
&lt;p&gt;When dealing with 3D coordinates, we generally use 3 coordinate …&lt;/p&gt;</summary><content type="html">&lt;p&gt;We have seen in a &lt;a href="https://kissyagni.wordpress.com/2022/03/21/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-1/"&gt;previous article&lt;/a&gt; why floating point representation may shake our objects in scene. We will now see how to use space change tricks to mitigate this problem.&lt;/p&gt;
&lt;h2 id="a-brief-reminder-about-world-model-and-view-space"&gt;A brief reminder about World, Model and View space&lt;/h2&gt;
&lt;p&gt;When dealing with 3D coordinates, we generally use 3 coordinate systems: World space, Model space and View space. World space is stuck on the ground. Model space is stuck on the object. So there are lots of model spaces in you scene, one for each object. View space is stuck to the camera. I won't talk about Projection space, which define camera lens, in this article.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-13.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;Coordinates of P are always relative to a space. So here, coordinates of P relative to Model space are (1, 0, 1). But we can Also define coordinates of P relative to other spaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;P_model = (1, 0, 1)&lt;/li&gt;
&lt;li&gt;P_view = (-1, 0, 3)&lt;/li&gt;
&lt;li&gt;P_world = (4, 0, 5)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-about-precision-of-those-coordinates"&gt;What about precision of those coordinates ?&lt;/h2&gt;
&lt;p&gt;One can see that P_world have a higher magnitude than P_model, because P is far away from World space origin. Well, not so much in this exemple, but imagine Model spaces millions miles away from World Space. What happen when taking in account floating precision error ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-14.png?w=769"&gt;&lt;/p&gt;
&lt;p&gt;P will actually jump to a floating representable position. But what happen if we locate P using P_model instead ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-15.png?w=861"&gt;&lt;/p&gt;
&lt;p&gt;P would jump to a much closer position. So close that you would barely see P jumping when moving it relative to model space. However, you may have noticed that model space has to be aligned into world space representable values. In this case, moving model space will make it jump from one position to another. So to use this trick, you have to define a fixed space close to your point of interest, and move you points relative to this reference space.&lt;/p&gt;
&lt;h2 id="what-about-view-space"&gt;What about View space ?&lt;/h2&gt;
&lt;p&gt;The View space moves a LOT when doing 3D rendering. It is probably the most dynamic space. It can be linked to a car for racing game, player for FPS, mouse for CAD application, etc... So we really have to ensure this space move smoothly if we don't want to give our users a headache. To do so, we can use the same trick than before. Instead of locating camera relative to world space, we can define a "Tripod" space, and locate your camera relative to this tripod:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-17.png?w=894"&gt;&lt;/p&gt;
&lt;h2 id="isnt-it-double-precision-with-extra-steps"&gt;Isn't it Double precision with extra steps ?&lt;/h2&gt;
&lt;p&gt;In the end, what we did was encoding a position with 2 floats, giving us 64bit floating precision. But this trick can be implemented using your current render engine architecture. It doesn't require using double precision values in computations, and any render engine already has a "Translation" object that can be used to do this. Last but not least, it doesn't change your current floating precision API.&lt;/p&gt;
&lt;p&gt;Unfortunately, for various reasons, Render engines require expressing all the coordinates in View space at some point. Accumulating transformations like we did won't solve the precision error we will have when expressing coordinates in View space. We will see in the &lt;a href="https://kissyagni.wordpress.com/2022/04/04/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-3/"&gt;next article&lt;/a&gt; how to handle this with very local modifications to our matrix accumulation code.&lt;/p&gt;</content><category term="misc"/><category term="3D"/><category term="c++"/><category term="IEEE754"/><category term="opengl"/><category term="vulkan"/></entry><entry><title>The Problem of Floating Point Precision in Opengl, Vulkan and 3D in General - Part 1</title><link href="/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-1.html" rel="alternate"/><published>2022-03-21T09:06:00+01:00</published><updated>2022-03-21T09:06:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-03-21:/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-1.html</id><summary type="html">&lt;p&gt;When zooming a lot on 3D objects or when having small object lost in a very large scene, it can happen that your objects "jiggle" from one position to another, making rendering really shaky. We will see in this series of article where does it comes from and how to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;When zooming a lot on 3D objects or when having small object lost in a very large scene, it can happen that your objects "jiggle" from one position to another, making rendering really shaky. We will see in this series of article where does it comes from and how to workaround it without using double precision everywhere.&lt;/p&gt;
&lt;h2 id="what-we-would-like"&gt;What we would like&lt;/h2&gt;
&lt;p&gt;Lets think in 2D. We have an X/Y coordinate system. When we specify the (x, y) coordinate of some point, we would like this point to be located at (x, y):&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-5.png?w=440"&gt;&lt;/p&gt;
&lt;h2 id="what-we-have-using-integer-coordinate"&gt;What we have using integer coordinate&lt;/h2&gt;
&lt;p&gt;What would happen if we were using integer coordinate system ? When locating a point in (1.5, 1.3), its position would be rounded to (1, 1). And if we move this point, it will jump from position to position:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-6.png?w=450"&gt;&lt;/p&gt;
&lt;h2 id="what-we-have-using-float-coordinates"&gt;What we have using float coordinates&lt;/h2&gt;
&lt;p&gt;Floating points suffer from the same issue than integer values. Only a set of position are accessible, the difference is that, near to 0, a lot of position are possible. But the further away from zeros, the further the possible positions are. Instead of having regular grid of position like for integers, we have a logarithmic grid:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-7.png?w=468"&gt;&lt;/p&gt;
&lt;p&gt;What does it means ? It means that for small scene you won't see your point jumping from one position to another. There are enough precision, enough possible position so that your point correspond to what you expect. But for large scene, object far from the origin will not have a lot of possible position and will jump from one point to another.&lt;/p&gt;
&lt;h2 id="what-does-large-scene-means"&gt;What does "large scene" means ?&lt;/h2&gt;
&lt;p&gt;I'm talking about "large scene", but what does it means practically ? As a first approximation, you can consider your scene as large if you need more that 6 digit precision to locate your objects. I will detail why 6 digit later.&lt;/p&gt;
&lt;p&gt;So a large scene does not depend on the absolute size of your scene but the ratio between your smallest object and the whole scene. A solar system can be consider as a small scene: Distance from Earth to the Sun is around 150 millions km, or 150.10e6 km. Meaning with 6 digit precision, assuming heliocentric coordinates, you can locate the earth position +/- 100km in space. If your goal is just to have an overview of the main planets in space, then this precision is enough. No one will notice earth is actually 100km to the left when looking at the whole system.&lt;/p&gt;
&lt;p&gt;However, if you want to localize the International Space Station which orbit at ~400km altitude, and zooming on it, then 100km precision is not enough. You cannot just use heliocentric coordinates with single floating point precision. When animating your station, it will jump from one position to another.&lt;/p&gt;
&lt;h2 id="where-does-these-6-digits-comes-from"&gt;Where does these "6 digits" comes from ?&lt;/h2&gt;
&lt;p&gt;Computers does not have infinite amount of memory, and thus cannot store infinite amount of digits. Furthermore, they work only with power of 2, but lets thinks with decimal system for now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Base 10 precision&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To represent a floating value using finite precision, you can store a certain amount of digit times a power of 10. For example, to store the value "1.5", you will store the value "000015 * 10^-01". In this case, 000015 is called "the fraction" and ^-1 is called "the exponent".&lt;/p&gt;
&lt;p&gt;Here is a few other example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;150 =&amp;gt; 000015 * 10^01&lt;/li&gt;
&lt;li&gt;150 000 000 000 =&amp;gt; 000015 * 10^10&lt;/li&gt;
&lt;li&gt;0.15 =&amp;gt; 000015 * 10^-02&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think you get the point. Values are stored as M * 10^n, with M having a fixed size of 6 digits and n an exponent of size 2.&lt;/p&gt;
&lt;p&gt;But what happen when using more than 6 digit precision ?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;123 456 789 =&amp;gt; 123456 * 10^3 =&amp;gt; 123 456 000&lt;/li&gt;
&lt;li&gt;0.123 456 789 =&amp;gt; 123456 * 10^-9 =&amp;gt; 0.123 456 000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will just "drop" them, as it cannot store them in our representation. Note that exponent is also clamped. As we cannot store more than 2 digits for the exponent, we cannot store value higher than 999999 * 10^99.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Base 2 precision&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now, lets go back to power of 2. As you know, computer use base 2 representation, not base 10. Number of base 2 digit they can store is defined by the &lt;a href="https://en.wikipedia.org/wiki/IEEE_754"&gt;IEEE 754 standard&lt;/a&gt;, which gives for 32bit floating point type:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-9.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;1 bit for sign (&amp;gt;0 or \&amp;lt;0), 8 bits for exponent (so up to ^255) and 23 digit. But where does the "6 digit in base 10" comes from ? To understand it, you have to ask "how many base 2 digits is required to represent a base 10 digit" ? The answer is:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-10.png?w=455"&gt;&lt;/p&gt;
&lt;p&gt;So, 23 base 2 digits can represent ~6.9 base 10 digits:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-11.png?w=712"&gt;&lt;/p&gt;
&lt;p&gt;It is not easy to understand what is "6.9" digits after all. A method I use is that, as a very unprecise approximation, you need 3 bits to count up to 10 (111 = 7 ~=10). 3 binary digits represent 1 decimal digit. So 23 binary digit represent 23/3=7.6 decimal digit. As we know this is a very rough approximation, lets get safe and take only 6 decimal digit precision.&lt;/p&gt;
&lt;h2 id="using-double-precision"&gt;Using Double precision&lt;/h2&gt;
&lt;p&gt;Double precision are like single Float precision, except they use 11 bits for exponent and 52 bits for fraction, which can represent ~15 decimal digits precision instead of 6.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-12.png?w=1024"&gt;&lt;/p&gt;
&lt;p&gt;But using double precision has a cost regarding memory consumption, performances and legacy code refactoring effort.&lt;/p&gt;
&lt;p&gt;I hope you better understand where does this problem comes from. I will develop in next articles the problem of floating precision when accumulating transformation matrices.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://kissyagni.wordpress.com/2022/03/28/the-problem-of-floating-point-precision-in-opengl-vulkan-and-3d-in-general-part-2/"&gt;The problem of floating point precision in OpenGL, Vulkan and 3D in general - part 2&lt;/a&gt;&lt;/p&gt;</content><category term="misc"/><category term="3D"/><category term="c++"/><category term="IEEE754"/><category term="opengl"/><category term="vulkan"/></entry><entry><title>An Overview of Some Git Branching Models</title><link href="/an-overview-of-some-git-branching-models.html" rel="alternate"/><published>2022-03-14T09:27:00+01:00</published><updated>2022-03-14T09:27:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-03-14:/an-overview-of-some-git-branching-models.html</id><summary type="html">&lt;p&gt;Git is a wonderful tool. But like all tools, it require methods to be used correctly. We will cover in this article some git branching model I have encountered during my career.&lt;/p&gt;
&lt;h2 id="trunk-only-development"&gt;Trunk Only Development&lt;/h2&gt;
&lt;p&gt;Used either by student who don't know what they are doing or by skilled and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Git is a wonderful tool. But like all tools, it require methods to be used correctly. We will cover in this article some git branching model I have encountered during my career.&lt;/p&gt;
&lt;h2 id="trunk-only-development"&gt;Trunk Only Development&lt;/h2&gt;
&lt;p&gt;Used either by student who don't know what they are doing or by skilled and mature team as an extreme interpretation of "Trunk Based Development".&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image_2022-03-14_093107.png?w=646"&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;br&gt;
- Real time integration.&lt;br&gt;
- Makes developers aware of their responsibilities: If you break something, everyone is impacted.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- When a commit break something, everyone is impacted...&lt;br&gt;
- Don't forget to pull before pushing.&lt;br&gt;
- Quickly becomes a real mess if your team is not mature enough. Even if history stay linear, your product will be broken several times a day and developers will spend lot of time fixing conflict.&lt;/p&gt;
&lt;h2 id="one-branch-per-developer"&gt;One branch per developer&lt;/h2&gt;
&lt;p&gt;If you don't know what to do, take this one. Simple to explain, very well adapted to Github's Pull Request or Gitlab's Merge Request paradigm, and ensure some stability even with beginners team.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-26.png?w=748"&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;br&gt;
- Master branch always works.&lt;br&gt;
- No integration dependency. Each developer is responsible of its own branch.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- Isolate developer on its own task.&lt;br&gt;
- No validation of branches together.&lt;br&gt;
- Require well dimensioned test infrastructure. May not be possible for embedded development or heavy legacy software.&lt;/p&gt;
&lt;h2 id="one-branch-per-feature"&gt;One branch per feature&lt;/h2&gt;
&lt;p&gt;Similar to the one before, but enforce collaboration between developers. For me, the best trade off between having real time integration and having a stable Master branch.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-27.png?w=721"&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;br&gt;
- Master branch always work.&lt;br&gt;
- No integration dependency.&lt;br&gt;
- Several developers can work on the same feature.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- No validation of branches together.&lt;br&gt;
- Require good collaboration between developers.&lt;br&gt;
- Require well dimensioned test infrastructure. May not be possible for embedded development or heavy legacy software.&lt;/p&gt;
&lt;h2 id="trunk-based-development"&gt;Trunk Based Development&lt;/h2&gt;
&lt;p&gt;This one seems to be the most fashionable model today. Warning, "Trunk Based Development" is not "Trunk Only Development". Developers can work both on master branch for small fixes or on feature branches for more complex development, as long as feature branches have a short lifetime. You can take a look to &lt;a href="http://qszhuan.github.io/agile/2018/10/09/the-things-you-need-to-know-about-trunk-based-development"&gt;this article&lt;/a&gt; to have more details about this model.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-33.png?w=689"&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;br&gt;
- Benefit of real time integration and longer term development&lt;br&gt;
- Empower collaboration and accountability.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- Master can be broken&lt;br&gt;
- High and variable pressure on test system =&amp;gt; Require a dynamic scalable infrastructure.&lt;br&gt;
- Risk of drifting to Trunk Only Development by laziness.&lt;/p&gt;
&lt;h2 id="nightly-integration-test"&gt;Nightly integration test&lt;/h2&gt;
&lt;p&gt;Developer merge their branch in a "Nightly test branch". Test are executed nightly and result are available in the morning. If you don't have a very exotic test system with strong constrains that prevent you doing real continuous integration, please don't do this.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-28.png?w=773"&gt;&lt;/p&gt;
&lt;p&gt;Pros:&lt;br&gt;
- Branch are validated together.&lt;br&gt;
- Load is constant on test infrastructure.&lt;br&gt;
- Can handle complex test system or very long tests.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- Have to wait the next day to have results.&lt;br&gt;
- If test infrastructure crash during the night, have to wait another day.&lt;br&gt;
- When test fail, have to investigate which branch is responsible.&lt;/p&gt;
&lt;h2 id="gitflow"&gt;Gitflow&lt;/h2&gt;
&lt;p&gt;Gitflow has a little success back in the 2015's, especially with the git-flow CLI tool. It is today more and more criticized for its complexity and the latency it introduced in integration. What I personally think about Gitflow can be summarized by:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just because you are doing something complicated doesn't mean you are doing something smart.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-29.png?w=742"&gt;&lt;/p&gt;
&lt;p&gt;Pro:&lt;br&gt;
- Explicitly handle all the case than can occurs during product life time: Feature development, stabilization, code freeze, last minute hotfixes.&lt;br&gt;
- Each branches are tested before integration and common result is tested before release.&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- Complicated to explain for people who are not familiar with Git.&lt;br&gt;
- Lot of branches, lot of complexity, lot of mistakes.&lt;br&gt;
- Going from feature to master takes times, slowing down continuous integration.&lt;/p&gt;
&lt;h2 id="guitar-hero-world-tour"&gt;Guitar hero world tour&lt;/h2&gt;
&lt;p&gt;&lt;img alt="" src="/images/2022/03/image-30.png?w=679"&gt;&lt;/p&gt;
&lt;p&gt;Pro:&lt;br&gt;
- Very good with friends&lt;/p&gt;
&lt;p&gt;Cons:&lt;br&gt;
- Is not a branching model&lt;/p&gt;</content><category term="misc"/><category term="branching model"/><category term="Git"/><category term="gitflow"/><category term="trunk based development"/></entry><entry><title>How to Justify Refactoring to Your Product Owner ?</title><link href="/how-to-justify-refactoring-to-your-product-owner.html" rel="alternate"/><published>2022-03-07T13:57:00+01:00</published><updated>2022-03-07T13:57:00+01:00</updated><author><name>andrieuconsulting</name></author><id>tag:None,2022-03-07:/how-to-justify-refactoring-to-your-product-owner.html</id><summary type="html">&lt;p&gt;Refactoring is an intrinsic part of software development. However, it seems often difficult to justify a refactoring to the Product Owner. We will see in this article how to properly justify refactoring, when it is useful but also when refactoring is a lost of time.&lt;/p&gt;
&lt;h2 id="why-refactoring-is-a-good-thing"&gt;Why refactoring is a good …&lt;/h2&gt;</summary><content type="html">&lt;p&gt;Refactoring is an intrinsic part of software development. However, it seems often difficult to justify a refactoring to the Product Owner. We will see in this article how to properly justify refactoring, when it is useful but also when refactoring is a lost of time.&lt;/p&gt;
&lt;h2 id="why-refactoring-is-a-good-thing"&gt;Why refactoring is a good thing ?&lt;/h2&gt;
&lt;p&gt;Some developer see refactoring as a failure, especially when they have to refactor their own code. A failure of having conceived a good evolutive design. A failure for having chosen the wrong architecture. But it is not the case. You have conceived a software with the vision, needs and skills your had at that time. Now you have a better vision of how things should works. Now you have new needs that you couldn't anticipate. Now you are a better developer. Now you know what is good and what is wrong with current design, and you are ready to improve your code. So let's state a point:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A good design is not a design that won't need refactoring in the future. A good design is a design that will facilitate refactoring in the future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So refactoring is mandatory to make your code follow your business, to make your code evolve in the direction you chose. Refactoring is that good friend that drive its drunk buddy until its home and avoid it being lost in the middle of the highway.&lt;/p&gt;
&lt;h2 id="why-refactoring-is-seen-as-a-lost-of-time"&gt;Why refactoring is seen as a lost of time ?&lt;/h2&gt;
&lt;p&gt;Let me be the devil's advocate to see why some Product Owners may be reluctant to do refactoring. From a product point of view, refactoring don't add any value. You begin with a set of feature and you end up with the same set of feature with the risk of breaking something.&lt;/p&gt;
&lt;p&gt;— Yeah, but the code is cleaner !&lt;br&gt;
— Customer don't care about code.&lt;br&gt;
— Yeah, but it is less buggy !&lt;br&gt;
— By how much ? Do your refactoring will fix bugs we have in our database ? Which one ? We don't care about 5 years old bugs, we care about important bugs that has been opened recently. How many bug will it fix compared to bug it will create ?&lt;br&gt;
— Yeah, but future feature will be faster to implement !&lt;br&gt;
— By how much ? You want to plan a 1 month refactoring. Could you ensure that future feature will take half the time to be done so that it can be profitable in 2 months ?&lt;/p&gt;
&lt;p&gt;I think you got it. Refactoring for refactoring is pointless and risky. "The code will be cleaner" is not an argument. How can you prove that YOUR code is actually better than existing code ? And what does it mean to have a "clean code" ?&lt;/p&gt;
&lt;h2 id="how-to-justify-refactoring"&gt;How to justify refactoring ?&lt;/h2&gt;
&lt;p&gt;Refactoring is a good practice but it should be done intelligently. You must have a reason to touch existing code and you should do it to achieve a goal. I will present below some good reasons to refactor a code:&lt;/p&gt;
&lt;h2 id="refactor-to-implement-a-story"&gt;&lt;strong&gt;Refactor to implement a story&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Never say to your PO: "We can do a quick and dirty implementation for 2 points but this would require 5 points to do it correctly". Your PO will understand "We can do it for 2 points or for 5 points". Just tell him this story is 5 points, and use this time to do it properly. Remember The Boy Scout Rule: "Always leave the campground cleaner than you found it." But keep in mind the main goal is the story, not the refactoring.&lt;/p&gt;
&lt;h2 id="refactor-to-enable-more-features"&gt;&lt;strong&gt;Refactor to enable more features&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Sometime you really need a 10 point refactoring effort to implement a 1 point story. In this case, you should ask yourself: does this effort will enable other 1 point stories ?&lt;/p&gt;
&lt;p&gt;If the answer is no, then is the effort worth it ? Maybe this development touch an old forgotten code that probably won't be modified in the next 10 years. In this case, maybe it is better to do a small hack and let this code rest in peace.&lt;/p&gt;
&lt;p&gt;But if the answer is yes, you should show to your PO what features this refactoring will make possible and not focus on the beauty and readability of the new code. PO don't care about code.&lt;/p&gt;
&lt;h2 id="refactor-to-improve-metrics"&gt;&lt;strong&gt;Refactor to improve metrics&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The 2 previous parts were focused on story oriented refactoring. A user story trigger addressing technical dept. But sometime, you want to rewrite a part of code just because it is really hard to maintain and you've had enough working in dirty code. In this case, you must show, with facts, that new code is actually better than previous one. Here is a non-exhaustive list of arguments that demonstrate a refactoring was actually useful :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You have significantly decreased line of code.&lt;/li&gt;
&lt;li&gt;You have replaced custom code by well established 3rd part library or tool.&lt;/li&gt;
&lt;li&gt;You have removed a dependency with an annoying/unsupported 3rd part library or tool.&lt;/li&gt;
&lt;li&gt;You have improved code coverage (or any code quality metric).&lt;/li&gt;
&lt;li&gt;You have decreased build/test/packaging time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the only argument you have is "The code is cleaner and more readable", then you didn't refactor your code. You have only written different code. Not better, not worse than before. Just different. And you now are the only one who know how it works, congratulation.&lt;/p&gt;</content><category term="misc"/><category term="product owner"/><category term="refactoring"/></entry></feed>