<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Zhéyuán Chén</title>
    <description>Zhéyuán Chén&apos;s homepage</description>
    <link>https://czheo.github.io/</link>
    <atom:link href="https://czheo.github.io/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Model Training Memory Simulator</title>
        <description>&lt;style&gt;
  /* Widen only this page so the simulator can stay in desktop layout. */
  .wrapper {
    max-width: 1280px;
  }
  .oom-sim-frame {
    width: 100%;
    height: min(88vh, 980px);
    min-height: 680px;
    border: 1px solid #ddd;
  }
  @media (max-width: 900px) {
    .oom-sim-frame {
      height: 78vh;
      min-height: 560px;
    }
  }
&lt;/style&gt;

&lt;iframe class=&quot;oom-sim-frame&quot; src=&quot;/viz/oom-sim.html&quot; loading=&quot;lazy&quot;&gt;
&lt;/iframe&gt;

&lt;h2 id=&quot;what-this-visualizes&quot;&gt;What This Visualizes&lt;/h2&gt;

&lt;p&gt;This simulator models a simplified training input pipeline as three stages:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Data loading into a CPU-side prefetch queue (often pinned host memory).&lt;/li&gt;
  &lt;li&gt;Host-to-device transfer into a GPU-side VRAM backlog queue.&lt;/li&gt;
  &lt;li&gt;GPU compute consuming queued batches.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each stage has a throughput and each queue has a capacity. The key idea is that memory pressure is created by &lt;strong&gt;mismatch between rates&lt;/strong&gt;, not just by one parameter in isolation.&lt;/p&gt;

&lt;h2 id=&quot;tradeoffs-it-tries-to-show&quot;&gt;Tradeoffs It Tries To Show&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Larger prefetch can improve utilization, but it increases pinned RAM usage.&lt;/li&gt;
  &lt;li&gt;Faster loading helps only if transfer and compute can keep up.&lt;/li&gt;
  &lt;li&gt;Faster transfer helps only if data is available and compute can drain VRAM.&lt;/li&gt;
  &lt;li&gt;Larger VRAM backlog capacity can smooth bursts, but it can also increase VRAM residency.&lt;/li&gt;
  &lt;li&gt;Bigger batch size raises memory footprint everywhere at once (CPU queue, transfer payload, GPU queue).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;practical-reading-guide&quot;&gt;Practical Reading Guide&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;If prefetch queue fills and pinned memory saturates, reduce prefetch depth, loader rate, or batch size.&lt;/li&gt;
  &lt;li&gt;If the VRAM backlog queue fills and VRAM saturates, reduce backlog depth or batch size, or speed up compute.&lt;/li&gt;
  &lt;li&gt;If transfer is starved, the loader is too slow for the downstream pipeline.&lt;/li&gt;
  &lt;li&gt;Stable throughput comes from balancing all stages, not maximizing any single slider.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a first-order mental model for input-pipeline pressure during training. In real systems, total VRAM also includes relatively stable components (weights, gradients, optimizer state) plus activation/workspace effects.&lt;/p&gt;
</description>
        <pubDate>Sun, 08 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2026/02/08/model-training-memory-simulator/</link>
        <guid isPermaLink="true">https://czheo.github.io/2026/02/08/model-training-memory-simulator/</guid>
      </item>
    
      <item>
        <title>Park construction observation journal</title>
        <description>&lt;p&gt;Recently, construction started at a park near my home. It has presented me with a unique opportunity to observe the intricacies of a construction site up close. Having majored in urban planning, I find it especially enlightening to witness these procedures firsthand.&lt;/p&gt;

&lt;p&gt;Just today, I noticed a new addition to the site – straw wattles. They were installed along the edges. A shallow trench was dug specifically for placing these wattles. They weren’t simply laid down; the wattles were anchored securely with long wooden stakes. Moreover, the ends of the wattles overlapped, ensuring their stability.&lt;/p&gt;

&lt;p&gt;I did some research for the purpose of these installations and found that they might be mainly for sediment control.&lt;/p&gt;

&lt;p&gt;Before construction, the park’s terrain was covered by a dense spread of wild plants, holding the soil together. However, as construction advanced, the natural vegetation was removed, and the once compact dirt would be loosened.
This transformation poses a risk, especially during storms. Rainwater could wash away the loose dirt and other construction debris, spilling it onto the nearby roads. This not only disrupts traffic but can also block the street drainages. These wattles act as barriers, effectively preventing sediment and debris from leaving the construction site.&lt;/p&gt;

&lt;p&gt;Another possible purpose is to act as cushions, protecting the adjacent concrete sidewalks from being accidentally damaged by construction machineries.&lt;/p&gt;

&lt;p align=&quot;center&quot;&gt;
  &lt;img width=&quot;460&quot; height=&quot;300&quot; src=&quot;/static/img/straw_wattle.jpg&quot; /&gt;
&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;Straw wattles secured by wooden stakes&lt;/p&gt;
</description>
        <pubDate>Thu, 05 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2023/10/05/park-construction-observation-journal/</link>
        <guid isPermaLink="true">https://czheo.github.io/2023/10/05/park-construction-observation-journal/</guid>
      </item>
    
      <item>
        <title>Humbled by Fork</title>
        <description>&lt;p&gt;Luckily, I have never had to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt; in my everyday work.
Otherwise, I guess I would produce 10x more bugs.
Here is an example why I think so.&lt;/p&gt;

&lt;p&gt;In a nutshell, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt; creates a child process who copies the parent’s current status, including the instruction pointer, data/stack/heap space and etc.&lt;/p&gt;

&lt;p&gt;Here’s a short example.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// test.c&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;child pid = %d, forked by %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getppid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x in child = %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;parent pid: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x in parent = %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output of the above problem will be something like this.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; ./test
parent pid: 47557
x in parent = 42
child pid = 47558, forked by 47557
x in child = 42
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; is copied from the parent’s to the child’s memory space after fork.&lt;/p&gt;

&lt;p&gt;Here is a brain teaser.
Can you predict how many lines the following program outputs?&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// test.c&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;iteration %d: child pid = %d, forked by %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getppid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;iteration %d: parent pid: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you run it in terminal, you will find something like below.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ./test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iteration 0: parent pid: 48102
iteration 1: parent pid: 48102
iteration 0: child pid = 48103, forked by 48102
iteration 1: child pid = 48104, forked by 48102
iteration 1: parent pid: 48103
iteration 1: child pid = 48105, forked by 48103
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is what happened.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt; is called in iteration 0, parent process 48102 (line 1) will create a child 48103 (line 3).&lt;/li&gt;
  &lt;li&gt;Since the full process status is copied, 48102 and 48103 will each increment &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; and continue the loop. So you will see
    &lt;ol&gt;
      &lt;li&gt;48102 creates a child 48104 in iteration 1, where the parent 48102 outputs line 2 and the child 48104 outputs line 4.&lt;/li&gt;
      &lt;li&gt;Similarly, the child 48103 created during iteration 0 will create its own child 48105 in iteration 1, which then print line 5 and line 6 correspondingly.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is an illustration of the parent-child relations of all processes.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;48102: root process
    &lt;ul&gt;
      &lt;li&gt;48103: created in iteration 0
        &lt;ul&gt;
          &lt;li&gt;48105: created in iteration 1&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;48104: created in iteration 1&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now is the most interesting part.
Can you predict the output of below?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; ./test | wc -l
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may think &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wc -l&lt;/code&gt; will just print the count of lines which should be 6, but surprisingly the output is 8. What the hell is happening now?&lt;/p&gt;

&lt;p&gt;Here is a clearer picture.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ./test &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; test.output
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;test.output
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;iteration 0: parent pid: 48230
iteration 1: child pid = 48232, forked by 48230
iteration 0: child pid = 48231, forked by 48230
iteration 1: child pid = 48233, forked by 48231
iteration 0: child pid = 48231, forked by 48230
iteration 1: parent pid: 48231
iteration 0: parent pid: 48230
iteration 1: parent pid: 48230
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output file will also contain 8 lines, if you redirect the program output.
Remember that the child will copy the parent’s memory space.
What has caused this behavior is that the child has copied the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; buffer of the parent, just like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; variable we saw before, but somehow more implicitly.&lt;/p&gt;

&lt;p&gt;What is buffer?
You may think of it as just a limited size in-memory array that holds the characters before writing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt;.
To reduce the syscalls and IO operations, instead of writing to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt; every time a new character arrives, the buffer will hold the characters up for a while until it really needs flushed out to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are 2 buffering modes: line buffering and full buffering.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Line buffering will flush every time when there is a newline character. Terminal uses this mode, which is what we observed when running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./test&lt;/code&gt; directly.&lt;/li&gt;
  &lt;li&gt;Full buffering will flush when the buffer reaches its size limit, which is what we observed when piping to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wc -l&lt;/code&gt; or redirecting to a file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the later case, when the parent process calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf(...)&lt;/code&gt; in iteration 0, the characters will be held in the buffer without flushing.
When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt; is called during iteration 1, the buffer array is copied to the child as it is.
So when the child prints, the line will be appended to the buffer and eventually get flushed containing the output previously printed by the parent.&lt;/p&gt;

&lt;p&gt;Here is the detailed sequence of events producing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.output&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;After the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt;, the parent process 48230 will print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteration 0: parent pid: 48230\n&lt;/code&gt; and hold it in its buffer.
The child process 48231 will print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteration 0: child pid = 48231, forked by 48230\n&lt;/code&gt; and hold it in its own buffer.&lt;/li&gt;
  &lt;li&gt;After the second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fork()&lt;/code&gt;, child 48232 will be created by 48230, which copies 48230’s buffer first and prints &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteration 1: child pid = 48232, forked by 48230\n&lt;/code&gt;. At this point, 48232’s buffer contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iteration 0: parent pid: 48230\niteration 1: child pid = 48232, forked by 48230\n&lt;/code&gt;. At the end of this process, the buffer is flushed and produces line 1 and line 2 as we see in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.output&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Similarly, line 3 and line 4 are produced by process 48233, where line 3 has been copied from its parent process 48231.&lt;/li&gt;
  &lt;li&gt;Line 5 and 6 get flushed at the end of process 48231, while line 7 and 8 are flushed at the end of process 48230.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As another experiment, if you add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fflush(stdout);&lt;/code&gt; after each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printf(...);&lt;/code&gt;, the output file will have 6 lines just like printing directly in the terminal.&lt;/p&gt;

&lt;p&gt;Imagining what other data that we can accidently copy during fork that we are fully unaware of and the side effects they can possibly cause, I’m so humbled now.&lt;/p&gt;
</description>
        <pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2023/02/11/humbled-by-fork/</link>
        <guid isPermaLink="true">https://czheo.github.io/2023/02/11/humbled-by-fork/</guid>
      </item>
    
      <item>
        <title>Combinatorics is Fun</title>
        <description>&lt;p&gt;I did some fun combinatorial exercises to reach an optimal O(n) solution for &lt;a href=&quot;https://leetcode.com/problems/sum-of-all-odd-length-subarrays/&quot;&gt;an “easy” level leetcode problem (LeetCode 1588)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Look at the problem and think for 5 minutes. It is relatively easy to reach this approach: For each element \(a_i\), if you can find the count of odd-length sub-arrays containing it, denoted as \(n_i\), the sum of all odd-length sub-arrays will be equal to \(\sum a_i n_i\). The interesting part is how we can find out \(n_i\).&lt;/p&gt;

&lt;h2 id=&quot;step-1-visualize-all-sub-arrays&quot;&gt;Step 1: visualize all sub-arrays&lt;/h2&gt;

&lt;p&gt;Let’s use a tuple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(i,j)&lt;/code&gt; to denote a sub-array where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt; are the start and end index.
Then we can plot all sub-arrays of an array with length &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt; in the table below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(0,  0)
(0,  1)  (1,  1)
(0,  2)  (1,  2)  (2,  2)
(0,  3)  (1,  3)  (2,  3)  (3,  3)
(0,  4)  (1,  4)  (2,  4)  (3,  4)  (4,  4)
...      ...      ...      ...      ...     ... 
(0,L-1)  (1,L-1)  (2,L-1)  (3,L-1)  (4,L-1) ... (L-1,L-1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-2-visualize-all-sub-arrays-containing-a-specific-element&quot;&gt;Step 2: visualize all sub-arrays containing a specific element&lt;/h2&gt;

&lt;p&gt;For an element \(a_i\), let’s mark all sub-arrays containing it in the table below.
For example, those surrounded in the box below are the sub-arrays who contain \(a_1\).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; (0,  0)          sub-arrays containing a1
+----------------+
|(0,  1)  (1,  1)|
|(0,  2)  (1,  2)| (2,  2)
|(0,  3)  (1,  3)| (2,  3)  (3,  3)
|(0,  4)  (1,  4)| (2,  4)  (3,  4)  (4,  4)
|...      ...    | ...      ...      ...     ... 
|(0,L-1)  (1,L-1)| (2,L-1)  (3,L-1)  (4,L-1) ... (L-1,L-1)
+----------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As another example, below are the sub-arrays who contain \(a_3\).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; (0,  0)
 (0,  1)  (1,  1)
 (0,  2)  (1,  2)  (2,  2)           sub-arrays containing a3
+----------------------------------+
|(0,  3)  (1,  3)  (2,  3)  (3,  3)|
|(0,  4)  (1,  4)  (2,  4)  (3,  4)| (4,  4)
|...      ...      ...      ...    | ...     ... 
|(0,L-1)  (1,L-1)  (2,L-1)  (3,L-1)| (4,L-1) ... (L-1,L-1)
+----------------------------------+ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For generalization, given any \(a_i\), there exists a rectangular “table”, where each “cell” represents a sub-array containing \(a_i\), illustrated as below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-------------------------------------+
|(0,  i)  (1,  i)  (2,  3) ... (i,  i)|
|(0,i+1)  (1,i+1)  (2,i+1) ... (i,i+1)|
|...      ...      ...     ... ...    |
|(0,L-1)  (1,L-1)  (2,L-1) ... (i,L-1)|
+-------------------------------------+ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see the width of the table is \((i+1)\) and the height is \((L-i)\) so there are \((i+1) \times (L-i)\) sub-arrays in total.&lt;/p&gt;

&lt;p&gt;A non-visual proof: For a sub-array starting at \(m\) and ending at \(n\), we have \(m \leq i \leq n\) if \(a_i\) is in it. Thus, there are \(i + 1\) choices to pick m in the range of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0...i&lt;/code&gt; and \(L - i\) choices of n in the range of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i...L-1&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;step-3-find-out-how-many-sub-arrays-in-the-table-have-odd-lengths&quot;&gt;Step 3: find out how many sub-arrays in the table have odd lengths&lt;/h2&gt;

&lt;p&gt;Observation 1: the top-right corner cell &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(i, i)&lt;/code&gt; is a sub-array with length = 1 which is odd.&lt;/p&gt;

&lt;p&gt;Observation 2: given any cell, its 4 neighbors (top, down, left, right) must have a length with different parity. i.e.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If a cell is even length, all 4 neighbors must be odd.&lt;/li&gt;
  &lt;li&gt;If a cell is odd length, all 4 neighbors must be even.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s mark odd-length cells with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; and even-length with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;.
We obtain a chessboard-like shape and just need to find out &lt;strong&gt;how many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; are there in the table&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+----------+
|.. x o x o|&amp;lt;--- the top-right cell must be o
|.. o x o x|
|.. x o x o|
|..........|
|..........|
+----------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observation 3: there are half of the cells are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; (in most cases).
See examples below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---+
|x o|
|o x|
+---+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-----+
|o x o|
|x o x|
+-----+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---+
|x o|
|o x|
|x o|
+---+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Observation 4: there is an exception: if the total number of cells is an odd number, there will be one more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+-----+
|o x o|
|x o x|
|o x o|
+-----+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given all the observations above, we can tell the total number of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o&lt;/code&gt; cells are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(N + 1) // 2&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; is the total number of cells in the table, which we already know in step 2 is \((i+1)\times(L-i)\).&lt;/p&gt;

&lt;h2 id=&quot;final-solution-in-python&quot;&gt;Final solution in Python&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sumOddLengthSubarrays&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;appendix&quot;&gt;Appendix&lt;/h2&gt;

&lt;p&gt;Some refresh of tricks about division:
In Python &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x // y&lt;/code&gt; is a round-down division.
For round-up division, one way is to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import math&lt;/code&gt; and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;math.ceil&lt;/code&gt;.
Another way of rounding up is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(x + y - 1) // y&lt;/code&gt;.
In the exercise above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(N + 1) // 2&lt;/code&gt; is a special case of this formula.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;     &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 10 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2022/12/10/combinatorics-is-fun/</link>
        <guid isPermaLink="true">https://czheo.github.io/2022/12/10/combinatorics-is-fun/</guid>
      </item>
    
      <item>
        <title>Java Duck Typing without Reflection</title>
        <description>&lt;p&gt;Can we implement duck typing in Java without using reflection?&lt;/p&gt;

&lt;p&gt;Consider there are 2 classes defined by an external library that is out of our control.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Whale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{...}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We cannot do below.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Whale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Compilation error since obj is of type `Object` which has no swim() method&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ideally, we want to define a common interface with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swim()&lt;/code&gt; method, and let &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Duck&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Whale&lt;/code&gt; both implement it. But since this is an external library, we cannot modify the definitions. Instead, we can use a pattern like below to achieve duck typing.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanSwim&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanSwim&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;coerce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CanSwim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;duck&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanSwim&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;coerce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Whale&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CanSwim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;whale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CanSwim&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;CanSwim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;coerce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Duck&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()),&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CanSwim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;coerce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Whale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;swim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// obj is a CanSwim now, which has the swim() method&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2022/03/06/java-duck-typing-without-reflection/</link>
        <guid isPermaLink="true">https://czheo.github.io/2022/03/06/java-duck-typing-without-reflection/</guid>
      </item>
    
      <item>
        <title>Streaming birds using Raspberry Pi</title>
        <description>&lt;p&gt;最近几天，我家阳台经常出现了一只哀鸽(mourning dove)。
这是北美常见的一种鸟，它一大早就来，停在那里像是观察什么。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/dove1.jpg&quot; alt=&quot;dove1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;前天，忽然出现了两只鸽子，一只趴在壁灯上，另一只衔来树枝给它，想必是要筑巢。
然而一天下来再去观察，由于壁灯上空间太小，树枝一根不剩全掉落在地上。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/dove2.jpg&quot; alt=&quot;dove2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;于是昨天一大早，我用包装鸡蛋的纸盒，给它们搭了一个宽敞些的台子。
它们看起来甚是喜欢，雄鸟不断衔来新的树枝，雌鸟负责做窝，一整天下来鸟巢有了不少起色。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/dove_nest.jpg&quot; alt=&quot;dove nest&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可是好景不长，傍晚时分我再去看时，地上树枝散落一地，还有一个碎掉的鸟蛋。
鸟巢还没造好，就失去一个未出世的孩子，想必非常可怜。
晚上，雌鸟在那里一动不动地趴了一夜。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/broken_egg.jpg&quot; alt=&quot;broken egg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;今天一大早，我早早起床，看那雌鸟还在那里趴着。
不久，雄鸟飞来把它接走，我开始担心它们不会回来了。
不过趁它们不在，我又稍微加固了平台。
把原先三面围合的平台，做成了四面围合，希望这样鸟蛋不要再掉下来了。&lt;/p&gt;

&lt;p&gt;几天下来，我和家人都非常牵挂这两只小鸟，希望它们能在阳台住下，抚育后代。
于是，我腾出手头的一台Raspberry Pi，搭设了一个观鸟的直播流，来更好地近距离观察它们的动静。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/static/img/rpi.jpg&quot; alt=&quot;raspberry&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不一会后，它们终于回来了。
于是我美滋滋地看起了直播。&lt;/p&gt;

&lt;p&gt;附录. 直播耗材：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Raspberry Pi 3B+ with Camera Module。用ffmpeg推送摄像头信号给Nginx。&lt;/li&gt;
  &lt;li&gt;特地买了个6刀的DigitalOcean服务器，装上Nginx + rtmp-module，用来接收Raspberry Pi的视频信号，并作为直播服务器推送给最终客户端。&lt;/li&gt;
  &lt;li&gt;在Github Page上添加了一个&lt;a href=&quot;http://czheo.github.io/bird&quot;&gt;新页面&lt;/a&gt;，用hls.js做客户端直播。&lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Thu, 10 Jun 2021 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2021/06/10/streaming-birds-using-raspberry-pi/</link>
        <guid isPermaLink="true">https://czheo.github.io/2021/06/10/streaming-birds-using-raspberry-pi/</guid>
      </item>
    
      <item>
        <title>Name of my son</title>
        <description>&lt;p&gt;Our newborn son just arrived in the early morning on July 26, Sunday.
My wife and I decided to name him “Luke”.&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://en.wikipedia.org/wiki/Luke_(name)&quot;&gt;Wikipedia&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;The name Luke is the English form of the Latin name Lucas.
It is derived from the Latin name Lucius, and it either means “the great Lucius”, or it is a shortened form of the Latin name.
Lucius means “the bright one” or “the one born at dawn”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meanwhile, Luke is not just his English name, but also the alphabet spelling of his Chinese name “麓(lù)珂(kē)”.&lt;/p&gt;

&lt;p&gt;“麓” means “foothill”, for he was born in Mountain View, the city located at the foothill of the Santa Cruz Mountains.
This character also has the same pronunciation as “Six”(陆) of the Chinese capital number character, for he was born on June 6 (06/06) of Chinese Lunar Calendar.
(Six is also considered to be the lucky number in China, similar to 7 in the western culture.)&lt;/p&gt;

&lt;p&gt;“珂” means “pure white jade-like stone”, with our wish of being a bright person of him, similar to the meaning of the Latin origin of his English name.&lt;/p&gt;
</description>
        <pubDate>Thu, 30 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/2020/07/30/name-of-my-son/</link>
        <guid isPermaLink="true">https://czheo.github.io/2020/07/30/name-of-my-son/</guid>
      </item>
    
      <item>
        <title>The first argument of Stream::reduce does not need to be an identity in Java</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-T-java.util.function.BinaryOperator-&quot;&gt;The official documentation of Java&lt;/a&gt; claims that the first argument of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T Stream::reduce(T identity, BinaryOperator&amp;lt;T&amp;gt; accumulator)&lt;/code&gt; must be an identity.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The identity value must be an identity for the accumulator function. This means that for all t, accumulator.apply(identity, t) is equal to t. The accumulator function must be an associative function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream::reduce&lt;/code&gt; works almost identically to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt; in Haskell.
In Haskell, you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt; as below.&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As we see, it is not required that the initial value (the second argument) of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt; be an identity in Haskell (For the addition operation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; is the identity but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt; is not).
Actually, you can even do the same in Java.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, according to the Java doc, the second use case is violating the contract although the result is the same as that of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So why is identity required by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; in Java?
In fact, the Java doc also writes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value … but is not constrained to execute sequentially.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It implies that the requirement of the identity and associativity must be related to parallelism.&lt;/p&gt;

&lt;p&gt;The actual problem occurs when you want to use “parallel stream”. For example, the following code gives 36 as result on my machine instead of 16.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parallel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, I found a similar question on StackOverflow, and
&lt;a href=&quot;https://stackoverflow.com/a/51290673/1061751&quot;&gt;one of the answers&lt;/a&gt; gives a plausible explanation.
The main reason of this behavior seems because Java will assign the initial value to each parallelized reduce job.
Given my previous example with input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2, 3]&lt;/code&gt;, 3 threads were started, each of which was assigned with 10 as the initial value, performing the following computation in parallel.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(10, 1) -&amp;gt; 10 + 1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(10, 2) -&amp;gt; 10 + 2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(10, 3) -&amp;gt; 10 + 3&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After all jobs finished, the final result was summed up to be the wrong answer 36, unfortunately.&lt;/p&gt;

&lt;p&gt;Here is the point I want to make: is it really necessary that the initial value must be an identity to allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; to be executed in parallel?
I strongly believe not, and the associativity of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BinaryOperator&lt;/code&gt; alone should be enough to enable parallelism.&lt;/p&gt;

&lt;p&gt;Given an expression &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A op B op C op D&lt;/code&gt; where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;op&lt;/code&gt; is the binary operator, associativity guarantees that its evaluation is equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A op B) op (C op D)&lt;/code&gt;, such that we would be able to evaluate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A op B&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C op D&lt;/code&gt; in parallel and combine their results afterward.
The only reason I can think of why Java requires identity here is that the language developers wanted to simplify the implementation and keep all sub jobs symmetric.
Otherwise, they may have had to differentiate parallelized jobs with/without initial values.&lt;/p&gt;

&lt;p&gt;My gut feeling tells me that there must exist a simple implementation that does not require the initial value to be an identity.
So I tried to write a “parallel reduce” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pareduce&lt;/code&gt; function in Haskell as a proof of concept (with my limited Haskell proficiency).&lt;/p&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Control.Parallel&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;partitionSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pareduce&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pareduce&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pareduce1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;pareduce1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;pareduce1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headRes&lt;/span&gt;
                              &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headRes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;par&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;headRes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tailRes&lt;/span&gt;
                  &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;take&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partitionSize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partitionSize&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;headRes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foldl1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;tailRes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pareduce1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-haskell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pareduce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pareduce&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;5060&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foldl&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;5060&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Some premature benchmarks show &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pareduce&lt;/code&gt; runs around 5 times faster than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foldl&lt;/code&gt; on my machine to sum up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1..100000000]&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 24 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/code/2019/10/24/the-first-argument-of-stream-reduce-does-not-need-to-be-identity-in-java/</link>
        <guid isPermaLink="true">https://czheo.github.io/code/2019/10/24/the-first-argument-of-stream-reduce-does-not-need-to-be-identity-in-java/</guid>
      </item>
    
      <item>
        <title>Yet Another e Explained</title>
        <description>&lt;h2 id=&quot;不尽人意的例子&quot;&gt;不尽人意的例子&lt;/h2&gt;
&lt;p&gt;虽然有不少关于自然常数e的解释，浏览下来不少都从复利计算的例子展开。
其中的逻辑是，如果年利率是100%，如果按每年计算利息，一年后获得的财富将是200%；
如果按每半年，一年后获得\((1 + \frac{100\%}{2})^2 = 225\%\)；
如果按每月，一年后获得\((1 + \frac{100\%}{12})^{12} = 261.3\%\)；
如果按无限小的时间单位计算，一年后获得\(\underbrace{(1 + \frac{1}{N})^N}_{N \rightarrow \infty}\)，而这个数就是e。&lt;/p&gt;

&lt;p&gt;在历史上，虽然e是在对复利的研究中被发现的，但我觉得这可能并不是一个足够直观的例子。其中的悖论是，既然我们规定了年利率是100%，将每半年的利率当作50%的算法显得很随意粗暴，这么一来，我们一年后实际获得的财富也就超过了100%的既定利率了呀？而且，既然e被称作“自然”常数，这种看似人为随意规定的规则到底和自然有什么关系呢？&lt;/p&gt;

&lt;h2 id=&quot;核心概念&quot;&gt;核心概念&lt;/h2&gt;
&lt;p&gt;e背后的核心概念，是用来描述和“自身大小”相关的“增长率”。
比如，滚一大一小两个雪球，因为大的雪球表面积更大能吸附更多的雪，相同单位时间内，大的雪球比小的雪球变大得更多，换句话说，雪球大小的增长率和它自身的大小正相关。
再比如，比较两个培养皿中的细菌，假设其他条件相同，单位时间内大的群落比小的群落能繁殖更多细菌，也就是说，细菌群落的繁殖速率和群落本身的大小有关。
可以想像现实中存在很多类似的例子，我们不妨暂且将这类变化称作“自然增长”。（其实，也可能是减少。）&lt;/p&gt;

&lt;p&gt;接下来，我们来看“自然增长”与e之间的关系。
我们将“自身大小”的量记作y，把时间记作x，当大小的增长率和自身大小成正比，我们就有了以下式子：&lt;/p&gt;

\[\frac{d y}{d x} = k y\]

&lt;p&gt;其中k是一个代表权重的常量，所以我们不妨先研究\(k=1\)时候的情景。
即：&lt;/p&gt;

\[\frac{d y}{d x} = y\]

&lt;p&gt;稍有微积分基础的人都能看出，\(y = e^x\)这个函数满足上面的式子，也就是说，\(e^x\)的导数是其本身。&lt;/p&gt;

\[\frac{d e^x}{d x} = e^x\]

&lt;p&gt;换句话说，如果大小y和时间x满足\(y = e^x\)，那它符合我们描述的“自然增长”的特征。&lt;/p&gt;

&lt;h2 id=&quot;唯一性&quot;&gt;唯一性&lt;/h2&gt;

&lt;p&gt;其实，\(e^x\)并不是唯一满足“导数是其本身”这一性质的函数：任何\(y = c e^x\)（c为常数）的导数也都是其本身，即&lt;/p&gt;

\[\frac{d (c e^x)}{d x} = c e^x\]

&lt;p&gt;除此以外，还有其他函数的导数是其本身吗？
答案是没有。
我们可以通过反证法证明。&lt;/p&gt;

&lt;p&gt;假设存在一个函数\(f(x)\)不满足\(c e^x\)的形式，但有\(\frac{d f(x)}{d x} = f(x)\)的性质。
那么，我们可以得出\(e^{-x} f(x)\)的导数为0的结论：&lt;/p&gt;

\[\begin{aligned}
(e^{-x} f(x))&apos;
&amp;amp; = e^{-x} f&apos;(x) + (e^{-x})&apos; f(x) \\
&amp;amp; = e^{-x} f(x) - e^{-x} f(x) \\
&amp;amp; = 0
\end{aligned}\]

&lt;p&gt;也就是说，\(e^{-x} f(x) = a\)，\(a\)是一个常数。
可推出，\(f(x) = a e^x\)，与假设矛盾。Q.E.D&lt;/p&gt;

&lt;h2 id=&quot;一般化&quot;&gt;一般化&lt;/h2&gt;

&lt;p&gt;那么对任意的权重k，\(\frac{d y}{d x} = k y\)的原函数是什么呢？
答案是\(y = c e^{k x}\)。
我们可以轻松验算得出：&lt;/p&gt;

\[(c e^{k x})&apos; = c (k x)&apos; e^{k x} = k (c e^{k x})\]

&lt;p&gt;至此，我们可以说\(y = c e^{k x}\)是“自然增长”函数的一般形式。
其中，c是自身“绝对大小”的权重，k是“增速”和“大小”之比的权重。&lt;/p&gt;

&lt;h2 id=&quot;再看复利&quot;&gt;再看复利&lt;/h2&gt;

&lt;p&gt;回头看复利，复利也满足“自然增长”的特征，它就和“滚雪球”类似，单位时间内获得额外利息的多少和本金多少成正比。&lt;/p&gt;

&lt;p&gt;所以，\((1 + \frac{1}{N})^N = e\)究竟在描述什么现象？
假设我们将1年分成\(\Delta x\)时长的N等分，即\(\Delta x = \frac{1 (year)}{N}\)，那这个式子也就变成了\((1 + 100\% \Delta x) ^ N\)。
翻译成自然语言就是：对于任意小的一段时间\(\Delta x\)，我们始终保持100%的增长速率，那么经过N个\(\Delta x\)（1年）以后，我们的财富将变成e倍。&lt;/p&gt;

&lt;p&gt;也就是说，如果你在“任意瞬间”都是100%的年利率增长（\(\frac{d y}{d x} = k y\), where \(k = 100\%\)），那1年后你的财富将变成\(e\)倍，2年后你的财富将变成\(e^2\)倍···（\(y = e^x\)）。
当然，现实中银行多是按月或者按年计算复利，我可不知道哪家银行会按e的指数函数连续计算复利，这也是我觉得用复利作为例子的不够直观的另外一个原因。&lt;/p&gt;

&lt;h2 id=&quot;自然衰减的例子&quot;&gt;自然衰减的例子&lt;/h2&gt;

&lt;p&gt;之前我们稍微提及了，e不但可以描述增加，也可以描述减少。
这里我们举一个热水降温的例子：
我们可以直观地想象出，热水降温的速度，和自身温度与室温的温差有关。
温差越大，热交换越快，降温也就越快。&lt;/p&gt;

&lt;p&gt;为了方便讨论，我们假设室温为0摄氏度，假设热水温度是y摄氏度，时间是x，那么我们有如下关于水温随时间变化率的式子：&lt;/p&gt;

\[\frac{d y}{d x} = - k (y - 0) = - k y\]

&lt;p&gt;其中(y - 0)代表温差，k是一个线性常数，前面的负号代表温度下降。&lt;/p&gt;

&lt;p&gt;这个式子除了符号相反，不是正好满足了之前讨论“自然增长”时的公式形式吗？
我们可以很容易得出，水温y和时间x之间满足\(y = c e^{-k x}\)的关系。&lt;/p&gt;
</description>
        <pubDate>Mon, 02 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/math/2019/09/02/yet-another-e-explained/</link>
        <guid isPermaLink="true">https://czheo.github.io/math/2019/09/02/yet-another-e-explained/</guid>
      </item>
    
      <item>
        <title>One-liner curry decorator in Python</title>
        <description>&lt;p&gt;I discovered the following trick.&lt;/p&gt;

&lt;div class=&quot;language-py highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;functools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class=&quot;language-py highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# output = 9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A more obfuscated way will be:&lt;/p&gt;

&lt;div class=&quot;language-py highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;functools&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__code__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;co_argcount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usage&lt;/p&gt;

&lt;div class=&quot;language-py highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;curry&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# output = 9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 01 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://czheo.github.io/code/2019/03/01/one-liner-curry-decorator-in-python/</link>
        <guid isPermaLink="true">https://czheo.github.io/code/2019/03/01/one-liner-curry-decorator-in-python/</guid>
      </item>
    
  </channel>
</rss>
