<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>jwwwb</title>
    <description>jwwwb. Home to my projects and ruminations on natural language processing, machine learning, acoustics, programming and life. May be updated more frequently in the future.
</description>
    <link>http://blog.jwwwb.com/</link>
    <atom:link href="http://blog.jwwwb.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 23 Dec 2017 15:37:38 +0100</pubDate>
    <lastBuildDate>Sat, 23 Dec 2017 15:37:38 +0100</lastBuildDate>
    <generator>Jekyll v3.6.2</generator>
    
      <item>
        <title>Variational Auto-Encoders and the Reparameterization Trick</title>
        <description>&lt;p&gt;Having spent the last half a year or so working on variational inference for
my thesis, I don’t consider myself an expert at it, but I’m a whole lot more
knowledgable than I was two years ago when I got the idea into my head that
the only way machine learning could result in something that is actually
capable of reasoning in a “smart” way was by using a Bayesian approach. It made
perfect sense to me, but I was lacking the mathematical and theoretical
foundations to utilize this idea. So now that I’ve spent so many hours dealing
with the subject, I wanted to write some kind of a tutorial that would make my
former self understand the beauty of the Variational Auto-Encoder — and maybe
it would also be useful for somebody else in the same position.&lt;/p&gt;

&lt;h2 id=&quot;deterministic-auto-encoders&quot;&gt;Deterministic Auto-Encoders&lt;/h2&gt;

&lt;p&gt;I won’t go into any detail on neural nets and their variants, as much has been
written by folks smarter than me - I recommend Karpathy’s blog as a start point.
The multi-layer perceptron and the auto-encoder were pretty much my very first
exposure to machine learning, some six years ago, and I was fascinated by them
right off the bat. What was not immediately clear to me, however, was the fact
that different-dimensional real spaces do not necessarily represent a “smaller”
or “bigger” place than each other. Anything infinite is always confusing to me
(and most humans probably) and it took a step back from intuitive reasoning to
looking at just the math in order for me to get to grip with the fact that you
can (within reason — it gets complicated when you’re talking about countable
and uncountable infinities) find a bijective mapping from just about any
inifinite set to another. So what is an auto-encoder really doing? Well, if you
use weight regularization and tricks like that, you can certainly ensure some
compression in the bottleneck layer, but it’s rather hit or miss getting it to
work.&lt;/p&gt;

&lt;h2 id=&quot;variational-bayes&quot;&gt;Variational Bayes&lt;/h2&gt;

&lt;p&gt;A few years ago a clever model called the Variational Auto-Encoder (or VAE) was
invented. As is so often the case, the theoretical breakthrough was made by
several teams in parallel, more or less at the same time. Although the VAE
shares two thirds of its name as well as most of its structure superficially
with the auto-encoder, the underlying idea is rather different and more
grounded in mathematical theory. Taking a probabilistic approach, one assumes
that the data being examined are samples from a random variable called the
observation &lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt;. This random variable is not fully independent, but rather
depends on some unobservable latent factors &lt;strong&gt;&lt;em&gt;z&lt;/em&gt;&lt;/strong&gt;. It would be lovely if it
were simply possible to determine the latent factors &lt;strong&gt;&lt;em&gt;z&lt;/em&gt;&lt;/strong&gt; from looking at
observations, but this is in all but the most trivial cases intractable. Instead
one assumes that the distributions in question are parametrizable and attempts
to learn them using neural networks.&lt;/p&gt;

&lt;p&gt;In the simplest case all distributions in question are Gaussians, which can be
described by their sufficient statistics mean and (co)variance. This assumption
makes many things easier, so I shall stick with it throughout the rest of this
post, but in principle there is nothing stopping one from using any distribution
that can be parameterized and is differentiable — also there is no reason why
&lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;z&lt;/em&gt;&lt;/strong&gt; must be of the same class of distribution.&lt;/p&gt;

&lt;p&gt;The first thing to learn is the generative or forward model, which is to say the
conditional dependencies of the real underlying process that generate samples of
&lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt; based on a given latent &lt;strong&gt;&lt;em&gt;z&lt;/em&gt;&lt;/strong&gt; — or at least a good approximation to
it. Given known pairs of latents and observations, it’s easy to train a neural
network using back-propagation to predict p(&lt;strong&gt;&lt;em&gt;x&lt;/em&gt;&lt;/strong&gt;|&lt;strong&gt;&lt;em&gt;z&lt;/em&gt;&lt;/strong&gt;). Expressed as a
probabilistic graphical model (PGM) the generative network looks something like
this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/vae/vae_forward.png&quot; alt=&quot;Generative Model of a VAE.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

</description>
        <pubDate>Sat, 23 Dec 2017 14:20:20 +0100</pubDate>
        <link>http://blog.jwwwb.com/ai/2017/12/23/variational.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/ai/2017/12/23/variational.html</guid>
        
        
        <category>AI</category>
        
      </item>
    
      <item>
        <title>Sandbar - a C++ Music Player for *nix.</title>
        <description>&lt;p&gt;Somehow I started writing this post about my music player but never finished it, 
so here it goes, with some delay.&lt;/p&gt;

&lt;p&gt;I mostly switched from Windows to Unix-like operating systems about a decade  ago,
but I’ve always been discontent with the music players available. The obvious choice
on MacOS would of course be iTunes, but alongside a whole host of other issues,
its inability to playback FLAC files disqualifies it right from the bat. On Ubuntu
I remember trying Amarok back in the mid 00s, and also running Winamp or Foobar2k
in WINE, but a lot of things like hotkeys and window sizing didn’t work properly
through WINE. I realize music players for linux have come a long way, with
apps like Clementine being immensely powerful and customizable, but I’ve gotten
used to certain idosynchracies that I wouldn’t want to miss. Besides, who doesn’t
love a challenge, and I thought making my own player gives me the highest level
of customization.&lt;/p&gt;

&lt;p&gt;Thus emerged what I am tentatively calling sandbar, after a word heard in a song
lyric that reminds me of nicer climates. C was one of the first programming
languages I learned, back in 2007, but I never really came close to mastering it.
C++ had been something I only ever dealt with in passing, but given their
importance I figured this would be a perfect project to get to know the languages
much better, as well as figure out their differences (beyond just Objects vs. no
Objects). Having used PyQt4 for a work project some time back, I was at least
vaguely familiar with the Qt framework, so I decided to go with the Qt5 library
to make GUI and threading a lot easier for me. Although I’m not targetting the
application for Windows, the cross-platform nature of Qt already takes a load off
my shoulders in terms of making it run on MacOS and Linux.&lt;/p&gt;

&lt;p&gt;Some of my requirements for the project are tabbed playlists (in my opinion a
comparable innovation to tabs in browser windows, and one that I really don’t
want to be without), a playback queue separate from the actual playlists (which
I first encountered on Winamp2, but services like Spotify also include these days),
and good network support (both control and playback).*&lt;/p&gt;

</description>
        <pubDate>Tue, 15 Aug 2017 20:07:44 +0200</pubDate>
        <link>http://blog.jwwwb.com/general/2017/08/15/sandbar.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2017/08/15/sandbar.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Installing Ubuntu with CuDNN and Tensorflow from Scratch</title>
        <description>&lt;p&gt;Since I’ve found myself installing tensorflow with GPU support a few times recently, and looking at 7 different stackexchange posts in the process,
I figured I would write up all the necessary steps in one place, since I could only find instructions for individual components.
Although I initially just wrote this for myself, a colleague suggested I publish it since surely others can profit from the information.&lt;/p&gt;

&lt;h2 id=&quot;software-to-install&quot;&gt;Software to Install&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Ubuntu 16.04 (clean installation)&lt;/li&gt;
  &lt;li&gt;nVidia drivers&lt;/li&gt;
  &lt;li&gt;CUDA 8.0&lt;/li&gt;
  &lt;li&gt;cuDNN 6.0&lt;/li&gt;
  &lt;li&gt;Python 3.5&lt;/li&gt;
  &lt;li&gt;Tensorflow 1.2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;ubuntu&quot;&gt;Ubuntu&lt;/h2&gt;

&lt;p&gt;To make an Ubuntu boot disk on a mac, download the 16.04 LTS ubuntu .iso from the web. While this is downloading, open the Disk Manager application, select the usb drive you want to install to (not the partition on it) and click Erase. Select Fat32 and MBR, and format the drive.
Next, install uNetbootin, and from there simply open your .iso, select the right disk (compare with the ID in Disk Manager) and go.
Eject the USB stick and insert it into your Tensorflow machine, and boot from the drive and install.
Make sure to disable secure boot in your BIOS menu, otherwise this will cause problems with the nvidia driver installation.
Once it’s up and running, always good practice to:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;nvidia-drivers&quot;&gt;nVidia Drivers&lt;/h2&gt;

&lt;p&gt;Make sure there are no previous nvidia drivers installed, add the repository, and update:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get purge nvidia*
sudo add-apt-repository ppa:graphics-drivers
sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl+alt+f2&lt;/code&gt; to close X / get into shell&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo service lightdm stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Create a file at &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/modprobe.d/blacklist-nouveau.conf&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;blacklist nouveau
options nouveau modeset=0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Type the following commands to apply changes, install and reboot:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo update-initramfs -u
sudo apt-get install nvidia-375
sudo reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;cuda&quot;&gt;CUDA&lt;/h2&gt;

&lt;p&gt;Installation from apt-get would get you version 7.5, instead we want 8.0. So go to https://developer.nvidia.com/cuda-downloads and select Linux -&amp;gt; x86_64 -&amp;gt; Ubuntu -&amp;gt; 16.04 -&amp;gt; runfile (local), and then download the base installer. Type the following command to install:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo sh cuda_8.0.61_375.26_linux.run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and If your filename isn’t completing after the shell command, type:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;complete -A file sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and then it should work.
When asked if you should “Install NVIDIA Accelerated Graphics Driver for Linux-x86_64”, answer no, because you did this already. For all other prompts choose yes or the default location.
If you get an error saying the
https://devtalk.nvidia.com/default/topic/978812/installing-cuda-7-5-fails-on-ubuntu-14-0-4-5-with-error-driver-installation-is-unable-to-locate-the-kernel-source/
You’ve done something wrong. Because the instructions I have arrived at now no longer give this error.
And if you get the “Warning: Incomplete installation!” notification, just follow the instructions and do:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo sh cuda_8.0.61_375.26_linux.run -silent -driver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once this is done, type&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nvcc --version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;to verify that it worked. If it says currently not installed, you have to add it to your path first by adding these lines to your ~/.bashrc file:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export PATH=/usr/local/cuda-8.0/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and start a new shell session for the changes to take effect.&lt;/p&gt;

&lt;h2 id=&quot;cudnn&quot;&gt;CuDNN&lt;/h2&gt;

&lt;p&gt;First go to
https://developer.nvidia.com/rdp/cudnn-download
And sign up at the developer portal in order to be able to download CuDNN. Once your account has been accepted, you can click “Download cuDNN v6.0 (April 27, 2017), for CUDA 8.0” and then select “cuDNN v6.0 Library for Linux”
Extract your downloaded file using&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tar -xzf cudnn-8.0-linux-x64-v6.0.tgz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Change directory into the extracted folder:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd cuda
sudo cp -P include/cudnn.h /usr/local/cuda/include/
sudo cp -P lib64/libcudnn* /usr/local/cuda/lib64/
sudo chmod a+r /usr/local/cuda/lib64/libcudnn*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;python-3&quot;&gt;Python 3&lt;/h2&gt;

&lt;p&gt;Python 3.5 comes pre-installed on Ubuntu. Although I initially included instructions on how to install Python 3.6 and make
it the default python, I found that that caused more trouble than it was worth, so I’m just sticking to 3.5 for now.&lt;/p&gt;

&lt;h2 id=&quot;tensorflow&quot;&gt;Tensorflow&lt;/h2&gt;

&lt;p&gt;First install and upgrade pip, then install numpy and tensorflow:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install python3-pip
sudo pip3 install --upgrade pip
sudo pip3 install numpy
sudo pip3 install tensorflow-gpu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To test if it works, simply open the python interactive interpreter and try to import tensorflow:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import tensorflow as tf
a = tf.constant([1.0, 2.0], name=’a’)
b = tf.constant([1.0, 2.0], name=’b’)
c = tf.multiply(a, b, name=’c’)
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print(sess.run(c))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;if you get an error saying that libcudnn.so.5 is not found, this is because the tensorflow library is still looking for cudnn 5, even though you have cudnn 6. Simply symlinking the new file should resolve this:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo ln -s /usr/local/cuda-8.0/lib64/libcudnn.so.6 /usr/local/cuda-8.0/lib64/libcudnn.so.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;p&gt;In no real order, the information I have is taken from at least the following pages, maybe more that I can no longer find.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.linuxandubuntu.com/home/how-to-install-latest-nvidia-drivers-in-linux&quot;&gt;http://www.linuxandubuntu.com/home/how-to-install-latest-nvidia-drivers-in-linux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://askubuntu.com/questions/799184/how-can-i-install-cuda-on-ubuntu-16-04&quot;&gt;https://askubuntu.com/questions/799184/how-can-i-install-cuda-on-ubuntu-16-04&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://askubuntu.com/questions/767269/how-can-i-install-cudnn-on-ubuntu-16-04&quot;&gt;https://askubuntu.com/questions/767269/how-can-i-install-cudnn-on-ubuntu-16-04&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 14 Aug 2017 20:27:44 +0200</pubDate>
        <link>http://blog.jwwwb.com/general/2017/08/14/cudnn.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2017/08/14/cudnn.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Large Scale Graph Mining: Pregel</title>
        <description>&lt;p&gt;One of the things that has been keeping me busy lately was a paper I had to write
for one of my classes about large-scale graph mining. It’s been a lot of work,
but it’s been quite enlightening - I’ve learnt quite a bit. I will probably
upload the paper to my site as well, once I’ve finished this seminar, but in the
meantime I want to write a bit about Pregel, since I found it a really
interesting concept.&lt;/p&gt;

&lt;p&gt;Pregel is Google’s architecture for distributed computation of a variety of
values pertaining to graphs and to a certain extent represents their successor
to the widely popular MapReduce framework. In contrast to MapReduce it’s designed
for a more specific task and also differs quite a bit with regard to its
implementation. The parallelization occurs on a far lower level and unlike the
reduce stage of MapReduce, data and results typically stay local for the duration
of the execution.&lt;/p&gt;

&lt;p&gt;It essentially operates on the same principle as multi-agent systems, with each
node of the graph representing its own autonomous agent with local data and
behavior rules. These node agents are distributed across a typically large number
of computers and use message passing to communicate between each other when
necessary. To avoid race conditions and deadlocks, communication is not performed
at arbitrary times, but rather in globally synchronized fixed intervals called
supersteps. Between communication phases, the individual nodes execute their
computations completely asynchronously without access to external data (neither
reads nor writes). During the computation phase, nodes may enqueue any number of
messages to be sent to other nodes, however due to the iterative nature of the
execution, these messages will only be available to their target nodes at the
next superstep.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/pregel_network.png&quot; alt=&quot;Schematic of a very small Pregel network. Multiple workers can run on the same
machine for better load balancing.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Schematic of a small Pregel Network. Multiple workers can run on the same
machine for better load balancing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pregel is written in C++ and contains all the necessary code to distribute data
across different workers, monitor worker health and roll back to backups when
necessary, facilitate communication, and provide analytics to the user. To
implement an algorithm for Pregel, all the user must do is inherit from the
&lt;code class=&quot;highlighter-rouge&quot;&gt;Vertex&lt;/code&gt; class and override its &lt;code class=&quot;highlighter-rouge&quot;&gt;compute&lt;/code&gt; function. How to write this function
is however not so straightforward. Many existing graph algorithms rely on access
to global data throughout the execution, and writing a Pregel implementation
that sends data from every node to every other node in each step would thoroughly
saturate the I/O bottleneck and defeat the purpose of the decentralized
computing. Instead, typical applications have vertices sending messages only to
their neighbors, which for most sparse graphs derived from real world data is a
small number.&lt;/p&gt;

&lt;p&gt;So far this is quite theoretical, and the reader may be wondering how
limited-scope agents can be used to achieve the desired global behavior. For
this we first have to look at what exactly a node is capable of doing. In fact,
a node is capable of doing very little, possessing only a few methods and
properties. In pseudo-code, a vertex looks more or less like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;class Vertex:
    function compute(received_messages)
    function vote_to_halt()
    function send_message_to(destination, message)
    var value;
    var out_edges;
    bool active;
    const var superstep;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As mentioned previously, the &lt;code class=&quot;highlighter-rouge&quot;&gt;compute&lt;/code&gt; method is what the user must override for
their specific application and it is passed an iterable containing the incoming
messages at each step, and may call the other methods and modify the instance
variables. The &lt;code class=&quot;highlighter-rouge&quot;&gt;vote_to_halt&lt;/code&gt; method is already implemented by the parent class,
and simply changes the instance’s active attribute to False, which means that in
subsequent supersteps the node will do nothing unless reactivated by incoming
messages. Also already implemented is &lt;code class=&quot;highlighter-rouge&quot;&gt;send_message_to&lt;/code&gt;, although users can
specify arbitrary data types for the &lt;code class=&quot;highlighter-rouge&quot;&gt;message&lt;/code&gt; itself. Similar to messages, the
attribute &lt;code class=&quot;highlighter-rouge&quot;&gt;value&lt;/code&gt; can also be user defined depending on the application, and
represents some form of local storage. The &lt;code class=&quot;highlighter-rouge&quot;&gt;out_edges&lt;/code&gt; property is set
externally at initialization and contains a list of edges connected to the node
(in the shape of target ID and weight pairs) and can be changed during runtime.
The &lt;code class=&quot;highlighter-rouge&quot;&gt;active&lt;/code&gt; property indicates whether the node has voted to halt and is
accessible globally: when all nodes have voted to halt, execution terminates.
Finally &lt;code class=&quot;highlighter-rouge&quot;&gt;superstep&lt;/code&gt; is provided externally and basically represents a global
clock signal.&lt;/p&gt;

&lt;p&gt;So, given that one can really only customize the method compute, and the data
types for method and value, the programming paradigm must change significantly
from traditional algorithms. To illustrate this shift, here is an example of
how to implement single source shortest path (SSSP):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;value&lt;/code&gt;: integer, initalized to INF for all nodes except the source, which starts with 0&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;message&lt;/code&gt;: integer&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;compute&lt;/code&gt;: the following (rather Python-like) pseudocode:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;compute(received_messages):
    minimum_distance = min(received_messages)
    if minimum_distance &amp;lt; value:
        value = minimum_distance
        for destination, weight in out_edges:
            send_message_to(destination, value + weight)
    vote_to_halt()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When every vertex has voted to halt, their values will be either the shortest
path to the source, or INF for unreachable nodes. Total number of supersteps is
the diameter of the graph, and at each step a vertex sends at most
&lt;code class=&quot;highlighter-rouge&quot;&gt;len(out_edges)&lt;/code&gt; messages, though often none at all if its value hasn’t been
updated since the last send. To my knowledge this is typical of the amount of
messages that need to be sent in a Pregel run, and indicates that computing a
global result can be achieved without very large exchanges of information.&lt;/p&gt;

&lt;p&gt;Nonetheless, it is common knowledge that I/O operations are orders of magnitude
slower than computations and especially so when performed over the network
(when you consider that even writes/reads from SSDs are typically bottlenecks)
so there are a certain number of optimizations implemented in Pregel to reduce
the cost of communication. For starters, although each node can send messages to
any other node, which may all be on disparate machines, each worker processes
the messages enqueued during a superstep by its contained nodes and groups them
by target location to send in a single bulk message.&lt;/p&gt;

&lt;p&gt;Another bandwidth saving measure is the option to combine messages before
sending them, according to a user-specified combiner function. This combiner
function must be manually enabled and implemented depending on the algorithm, as
Pregel cannot automatically determine a suitable combiner. In the case of SSSP,
a combiner would look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;combine(destination, messages_for_same_destination):
    return destination, min(messages_for_same_destination)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;According to Google, use of combiners reduces bandwidth use by a factor of four
in practice. One key question that I have not addressed at all so far is: how
does a worker know which machine to send messages intended for a certain vertex
to? How are the vertices distributed across the machines in the first place?
The answer to this is disappointingly primitive: each node has a unique ID, and a
hash function of this ID is modulo’ed with the number of workers to obtain the
index of which machine to place the node on. This same hash and modulo determine
where to send messages during execution. This means that graph structure is not
considered at all in the distribution of vertices and a clique of strongly
connected nodes may wind up on different computers (or even different continents
on the scale that Google operates on) and communication between them must be
performed over network.&lt;/p&gt;

&lt;p&gt;That really made me wonder how this naive solution can be the best option they
came up with and how it can be that it doesn’t cause severe bottlenecking by the
communication phases. To investigate this for myself empirically, I set out to
recreate Pregel by myself (I know that there are open source versions such as
Giraph freely available for anybody to download, but I didn’t do this for two
reasons: 1. I wanted to get a better understanding of the inner workings and 2.
I don’t actually have a server cluster).&lt;/p&gt;

&lt;p&gt;So, being a simulation and not designed for high performance, I made it in
Python (ergo: sequentially) since it’s easy to use; and since I wanted
introspection, I made a graphical representation of the system state in Qt5
(simply because that’s what I know and I didn’t want to worry about learning
something new). The project ended up getting surprisingly big, so I decided I
might as well put it on github. The code should probably still get cleaned up a
bit, and since nobody downloads software anymore these days, I want to look into
making it a web-app (yay, web 2.0 :/) as well. I’ll go into more detail about
this simulation and the insights gleaned from it in a future post.
`&lt;/p&gt;
</description>
        <pubDate>Thu, 15 Dec 2016 10:00:00 +0100</pubDate>
        <link>http://blog.jwwwb.com/ai/2016/12/15/pregel.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/ai/2016/12/15/pregel.html</guid>
        
        
        <category>AI</category>
        
      </item>
    
      <item>
        <title>Pointers in Python.</title>
        <description>&lt;p&gt;So it’s been a while since I’ve posted something here, and the reason for that is mostly because I’ve
been quite busy with projects that prevented me from working on my “fun” projects, like the chess bot.
Though I realized that that’s really not an excuse at all, I’ve made so many useful discoveries and
learnt so many new things, I’d really benefit from writing them down and structuring my thoughts a bit.&lt;/p&gt;

&lt;p&gt;As a self-taught programmer with a non-CS background, there are a lot of things I figure out on the fly,
usually only when my lack of knowledge comes around to bite me in the butt. A good example of one such
case is the distiction between call by value and call by reference. It’s actually something I’ve known
about, but without a lot of practical experience it was hard for me to really remember how it affects me
in practice. And these down and dirty details of programming really aren’t something you worry about at
all when working with Python. For the most part you just write code how you think it, and the interpreter
makes it work somehow. And especially with duck typing, you really don’t think about how a variable is 
stored or where it’s located, you just care about what’s inside it. And unlike C++, the last thing you
think about is pointers.&lt;/p&gt;

&lt;p&gt;During my investigations of &lt;a href=&quot;https://blog.acolyer.org/2015/05/26/pregel-a-system-for-large-scale-graph-processing/&quot;&gt;Google’s Pregel&lt;/a&gt; distributed graph mining system, I set out to build a small
scale single machine replica of it, to get a better idea of what is going on behind the scenes, and
how global results emerge from small scale multi-agent type behavior. You write what you know, so
naturally I did it in Python, with a bit of Qt5 for the visualization. Since the real version uses
message passing for communication between workers, and my replica wasn’t going to be using any real 
networking, I just used empty lists as buffers to represent the network buffer. Little did I know, this was
to be the beginning of an hour-long debugging session.&lt;/p&gt;

&lt;p&gt;To cut to the chase, the problem was that all of my buffer lists were the same list. So every entry I
tried to add to one, I actually added to all of them. Why this initially worked anyway, but then started causing errors, 
I don’t know - those are the worst kind of errors: the ones that only arise sometimes and usually not at the point 
in time where you actually introduced the mistake into the code. By sheer luck I had recently been reading 
this excellent &lt;a href=&quot;http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/&quot;&gt;blog post by Rob Heaton about references in Python&lt;/a&gt; which even made me think
of the fact that this could be an issue at all.&lt;/p&gt;

&lt;p&gt;One of the things I love about Python is the overloading of operators and functions that lets you 
write code in a way that makes intuitive sense to a human. Do you want to know if two strings are
the same? Don’t mess around with &lt;code class=&quot;highlighter-rouge&quot;&gt;strcmp()&lt;/code&gt;, just type:&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;s&quot;&gt;'word'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'word'&lt;/span&gt;
&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Want to concatenate strings together? Easy:&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;s&quot;&gt;'word'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'play'&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;'wordplay'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How about concatenate a bunch of copies of a string? Just do:&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;s&quot;&gt;'bla'&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;s&quot;&gt;'blablablablabla'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The human brain has a really good (although perhaps not rigidly defined) idea of what “times” and “equal” 
mean, namely &lt;code class=&quot;highlighter-rouge&quot;&gt;thing1&lt;/code&gt; equals &lt;code class=&quot;highlighter-rouge&quot;&gt;thing2&lt;/code&gt; if they are the same, and &lt;code class=&quot;highlighter-rouge&quot;&gt;thing1 times 3&lt;/code&gt; is &lt;code class=&quot;highlighter-rouge&quot;&gt;thing1 + thing1 + thing1&lt;/code&gt;. 
The beauty of Python is that everything is an object, and every object can (and probably should) define comparison
or arithmetic methods. The same goes for collections: the ability to &lt;code class=&quot;highlighter-rouge&quot;&gt;for item in collection&lt;/code&gt; over just
about any non-atomic data-type is wonderful and makes for really readable code. I’ve totally forgotten how
to even write &lt;code class=&quot;highlighter-rouge&quot;&gt;for ( int i = 0; i &amp;lt; 10; i++ )&lt;/code&gt; style loops anymore.&lt;/p&gt;

&lt;p&gt;One of the things I do often in Python when I need several distinct, but identically behaved, items (though 
I’m sure more experienced Python programmers than me could explain to me in what way this is non-pythonic) is create 
a list of items using multiplication:&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;n&quot;&gt;counters&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counters&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;0&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;0&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;0&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;0&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;0&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;Now whenever some event happens at location i, I can simply increment &lt;code class=&quot;highlighter-rouge&quot;&gt;counters[i]&lt;/code&gt; to count that occurrence.&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;n&quot;&gt;counters&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;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counters&lt;/span&gt;&lt;span class=&quot;p&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;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;counters&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;0&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&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;0&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;0&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;Wonderful. No reason why these have to be integers, I can just as easily use strings:&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;n&quot;&gt;morse_decoders&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;s&quot;&gt;''&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;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;morse_decoders&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;morse_decoders&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;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SOS'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;morse_decoders&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SOS'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&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;Encouraged by this success, you might also try to do the same thing with lists:&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;n&quot;&gt;incoming_messages&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;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hi James.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Hi James.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&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;s&quot;&gt;'Hi James.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&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;s&quot;&gt;'Hi James.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&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;Hmmmmmm…. turns out when you initialize your lists in this way, it just replicates the pointer to
the list three times. So all three lists are the same object, changing one changes them all. The quick
fix for this is to use list comprehension instead of multiplication:&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;n&quot;&gt;incoming_messages&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hi James.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incoming_messages&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;s&quot;&gt;'Hi James.'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;It's mom.&quot;&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;So what happened here? Well, it’s not that lists in Python are pointers and ints are not. In fact, really
everything is a pointer, from the ints to the lists. Using the &lt;code class=&quot;highlighter-rouge&quot;&gt;id()&lt;/code&gt; function to reveal the memory address
of variables can be quite enlightening:&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;n&quot;&gt;list_of_ints&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&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;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&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;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&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;140373411256208&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256184&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256160&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256136&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256112&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;Five different values, five different locations in memory. So far so good. How about this one:&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;n&quot;&gt;list_of_ints&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;5&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;
&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&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;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&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;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&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;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&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;Wait, what? All of these fives, which were initialized separately from each other, are all at the same location 
in memory? So what happens if we modify one of them?&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;n&quot;&gt;list_of_ints&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;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&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;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_ints&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;140373411256016&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;140373411256088&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;Not only did the value of the first entry change, it’s location in memory changed also! This is because ints
are (for some reason that I’m not aware of) immutable in Python. So any time you modify an integer in place,
for example using &lt;code class=&quot;highlighter-rouge&quot;&gt;+=&lt;/code&gt;, you’re actually computing the result, storing it in a different memory location, and
reassigning your pointer. The same applies to all other immutable data types, which in Python includes
strings, integers, floats, and tuples.&lt;/p&gt;

&lt;p&gt;Lists however are a mutable datatype in python. That means that modifications to them can (and will) be 
performed in place. This is actually quite useful - copy operations are expensive, and for a
potentially very long and recursive list, this is not something you want to have to do every time you
call &lt;code class=&quot;highlighter-rouge&quot;&gt;.append()&lt;/code&gt;.&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;n&quot;&gt;list_of_lists&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;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sublist&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;n&quot;&gt;sublist&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_lists&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;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_lists&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sublist&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;n&quot;&gt;sublist&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list_of_lists&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;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4411428592&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;So, the main thing to be aware of, is that any assignments in python simply copy the pointer of the value being
assigned. If you then want to be able to manipulate the two variables separately, make sure that they are a 
mutable data type (&lt;a href=&quot;https://en.wikipedia.org/wiki/Python_(programming_language)#Typing&quot;&gt;there’s a nice overview on wikipedia&lt;/a&gt;)&lt;sup id=&quot;fnref:footnote&quot;&gt;&lt;a href=&quot;#fn:footnote&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. For everything else, &lt;code class=&quot;highlighter-rouge&quot;&gt;copy()&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;deepcopy()&lt;/code&gt; are your friends. Or you may want to take advantage of the fact that objects are passed by reference,
to allow shared reading of the same item.&lt;/p&gt;

&lt;p&gt;What’s even crazier about this is the fact that Python has a short list of integer values (between -5 and 256) 
that are pre-initialized and loaded into memory at runtime and used for any occurrence of this number. So this 
means that any time during the execution of a python program a variable is assigned the number 150 for example, 
this will point to the same place in memory. In contrast, for large numbers that haven’t been pre-initialized, 
each assignment will point to a new location in memory:&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;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;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;300&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;150&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&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;mi&quot;&gt;140368092865608&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;140368092894856&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;140368092865608&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;mi&quot;&gt;140368092895144&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Isn’t that something?&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:footnote&quot;&gt;
      &lt;p&gt;Another interesting thing I learned when reading this is that there is no precision limit for integers in Python: you can store arbitrarily large values in an int without overflow. Just try it out: &lt;code class=&quot;highlighter-rouge&quot;&gt;num = 2**600; print(num)&lt;/code&gt;&amp;nbsp;&lt;a href=&quot;#fnref:footnote&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 11 Dec 2016 19:07:44 +0100</pubDate>
        <link>http://blog.jwwwb.com/python/2016/12/11/references.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/python/2016/12/11/references.html</guid>
        
        
        <category>python</category>
        
      </item>
    
      <item>
        <title>Error Checking the Chess Bot.</title>
        <description>&lt;p&gt;Once I got my &lt;a href=&quot;/general/2016/07/14/chessbot.html&quot;&gt;chess engine up and running rudimentarily&lt;/a&gt; it was time to error check. For that purpose I used &lt;a href=&quot;https://chessprogramming.wikispaces.com/Perft+Results&quot;&gt;perft&lt;/a&gt;, basically the number of possible moves from a given position on the chessboard, for a given number of half-moves or plies (ie, perft from the start for 2 plies is 20 moves for white * 20 possible responses for black = 400). There are correct numbers for a variety of depths to be found on the internet, so you can simply compare the possibilities from your engine and if they differ, you have an error somewhere. I found a lot of useful information on &lt;a href=&quot;http://www.albert.nu/programs/sharper/perft/&quot;&gt;Albert Bertilsson’s site&lt;/a&gt;, who implemented a chess engine himself, and had the following advice to offer:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt;
If you like programming and solving mind games and puzzles &lt;strong&gt;do not&lt;/strong&gt; start writing your own chess engine. I was tricked into chess programming in late 2002 and has never found any other programming to be as challenging and funny. Chess programming is like a discease without a cure, I’ve tried other programming projects but none of them has given me the same intellectual satisfaction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, too late for that now, I fear. But apart from that word of warning, he also had some useful perft values for comparison. And his chess engine, Sharper, has the wonderful feature of a split perft test, which rather than simply compute all the possible move combinations to some depth n, instead computes the perft value for every legal move from the current position to depth n-1, which should then sum back up to the original perft value. By implementing this in my engine (and hoping that Sharper’s values are correct) I was able to easily debug in which move branches led to the errors in my perft numbers. Unsurprisingly it was special moves like en-passant and castling where I found a few errors.&lt;/p&gt;

&lt;p&gt;With this being fixed, it’s now time to attack the search and evaluation. Though I have already read a bit about how to best tackle this, I think the best idea for me is to continue as I had originally planned with some basic pointwise evaluation of piece losses and captures and an exhaustive search. Primitive as this might be, it should at least generate a somewhat legitimate player, which will be nice to see in action, before I move onto more complex algorithms there.&lt;/p&gt;

</description>
        <pubDate>Sun, 17 Jul 2016 23:44:44 +0200</pubDate>
        <link>http://blog.jwwwb.com/general/2016/07/17/perftesting.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2016/07/17/perftesting.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Programming a Chess Bot.</title>
        <description>&lt;p&gt;Sometimes it feels like every project idea I have has already been done. I have a cool idea for a program, and then when I google it, not only has it already been made, there’s already a web app for it. In my internship with with web development stuff, I learned that web development has come a long way from 90s era static html, or even simple php generated code like you might find on a website like this. You need to know half a dozen languages and ten frameworks to work on these modern apps with full native functionality that just happen to be contained in a browser tab. Well, that is something I should try to learn better, but that’s an issue for a different day.&lt;/p&gt;

&lt;p&gt;However just because something has already been done, isn’t a good reason not to try implementing it myself anyway. &lt;code class=&quot;highlighter-rouge&quot;&gt;Hello world&lt;/code&gt; has been implemented in thousands of languages, and yet millions of beginner programmers across the world implement it again over and over. It’s a good learning exercise, and maybe I’ll get lucky and come up with an improvement that nobody has thought of. So I’ve decided to try my own spin on a project that has not only been implemented before, it’s been implemented over and over again and is perhaps one of the most famous types of software in the world - a chess engine.&lt;/p&gt;

&lt;p&gt;I recently overheard some people discussing playing chess, and that reminded me of how bad I am at chess. One approach would be to try to get better at chess, but that’s a lot of work for limited payoff - I’m likely never going to be a chess grandmaster, and it’s always frustrating to practice something you’re terrible at (don’t get me wrong - I’m well aware of the mental benefits of things like chess or playing instruments, and I probably should be doing more for my brain, considering how much I train my body).&lt;/p&gt;

&lt;p&gt;But I had the thought that in less time than it would take me to significantly improve my chess ability, I could sipmly program a chess bot that is better than me. Not a very high standard to aim for, with systems like &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_Blue_(chess_computer)&quot;&gt;Deep Blue (allegedly) beating grandmasters as far back as 20 years ago&lt;/a&gt; already, but Rome wasn’t built in a day. I figured that with that low of a standard and with modern hardware performance on my side, I wouldn’t have to worry about state of the art efficient algorithms, supercomputing, complicated expert-knowledge-based heuristics, or anything like that. The plan was just to exhaustively tree search the move space for maybe 3 turns ahead, score each move according to the traditional piece values (1, 3, 3, 5, and 9 for pawn, knight, bishop, rook, and queen respectively - as well as some high score penalty for danger to the king), and then let it rip. The ability of a computer program to see every potential piece loss should already be enough to beat me, seeing as I lose so many pieces and games to across the board attacks that I don’t even see coming.&lt;/p&gt;

&lt;p&gt;So I hacked together a quick move generator in python, using an 8x8 array to store the board and a whole lot of for-loops and if-checks. As much as I love python, I know that it’s not the most performant language unless you’re using external computational libraries like numpy, but I didn’t think that would become an issue here. Boy was I wrong. Exploring a tree is of course exponential complexity with regard to the depth, which wouldn’t be too bad in a binary tree. But the very first half-move of a chess game already has 20 legal moves, and the average branching factor of a game is somewhere around 30 - this means that my indended three moves (six half-moves) even in the start case explode to around 20^6 or about 10^8 nodes! For my python hack, this wound up being a runtime of around 22 hours - not really acceptable runtime for the decision process in each turn. And that’s at the beginning of the game with most of the powerful pieces still trapped - runtime should be around 10 times that mid-game assuming the average branching factor.&lt;/p&gt;

&lt;p&gt;Since I’m taking a high performance computing class currently, I realized that most of these computations are completely independent of each other, so they should lend themselves to parallelization. As my laptop has intel graphics and my old desktop computer has an AMD video card, CUDA was right out the window, and I decided I should look into learning OpenCL. Caught in my ways (as a lazy duck-typing Python user) as I am, I googled if there was any way to integrate that into Python, and found the wonderful &lt;a href=&quot;https://documen.tician.de/pyopencl/&quot;&gt;OpenCL package&lt;/a&gt; by Andreas Klöckner. As it turns out, OpenCL is pretty easy to learn, since it shares its syntax with C, the first language I learned that I can still remember. Well, remember in theory, in practice I forget so many semicolons, it’s frustrating. After re-writing it in OpenCL, even just running on my CPU, the same three move deep exhaustive search takes about 30 seconds instead of 22 hours - that’s a good start. I had always heard Python was a slow language, but I never knew how slow. It’s not quite as simple as that, but I think this is enough writing for one post. I’ll expand on it more in the future - I’m pretty sure this chess engine will be a many part series.&lt;/p&gt;

</description>
        <pubDate>Thu, 14 Jul 2016 23:40:07 +0200</pubDate>
        <link>http://blog.jwwwb.com/general/2016/07/14/chessbot.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2016/07/14/chessbot.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Writing.</title>
        <description>&lt;p&gt;I do so many things in my life and I always forget about them. I’ve thought several times I should write things down, because you have to think the ideas in your head through and you find out if they actually make sense, or if you’re missing out on something. Over the years I’ve accumulated numerous &lt;code class=&quot;highlighter-rouge&quot;&gt;documentation.txt&lt;/code&gt; files with half completed instructions in them, strewn over numerous hard drives. Perhaps not everything I write is suitable for publication, but at least trying to write it down will help me weed out the good ideas which I can then upload to the site.&lt;/p&gt;

&lt;p&gt;Since switching into a software-related field, I have noticed that there seems to be a trend like in the creative industries, where potential employers want to see your “portfolio,” only that here your portfolio is your github page. Now, I’m not convinced that that should be the only reason to publish your work, but it’s certainly an added benefit. More importantly I hope that by putting my code out there for the world to see, I will hold myself accountable and try to program cleanly - it’s like your mother always telling you to wear clean underwear, because you might be in a car accident and the EMTs will have to cut you out of your pants.&lt;/p&gt;

&lt;p&gt;And of course it’s rather nice to have my ideas somewhere safe in the internet so I can access them anywhere and anytime, rather than them getting buried in a pile of old hard drives in the cellar. Let’s see.&lt;/p&gt;
</description>
        <pubDate>Sun, 24 Jan 2016 18:30:07 +0100</pubDate>
        <link>http://blog.jwwwb.com/general/2016/01/24/writing.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2016/01/24/writing.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Website.</title>
        <description>&lt;p&gt;I have decided to start a website, not necessarily because I expect anybody to read it, but simply because I have found that putting my thoughts on paper helps me think them through.&lt;/p&gt;

&lt;p&gt;I guess I will mainly be writing about computer science related topics here, but I could imagine there will be some ventures into statistics, linguistics, acoustics, and music to come. Maybe something else if I come across something interesting.&lt;/p&gt;

&lt;p&gt;Lately I’ve pretty much only been programming in Python, it’s just so… logical? I do hope I can avoid Matlab in the future, not least because that will free up 10GB on my laptop.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; def hello_world(signature):
...     print 'Hi World! -{}'.format(signature)
... 
&amp;gt;&amp;gt;&amp;gt; hello_world('James')
Hi World! -James
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I will attempt to clean up some of my old code to put on &lt;a href=&quot;https://github.com/jwwwb/&quot;&gt;my GitHub page&lt;/a&gt;, or at the very least put new projects I start there.&lt;/p&gt;

</description>
        <pubDate>Sat, 23 Jan 2016 23:30:07 +0100</pubDate>
        <link>http://blog.jwwwb.com/general/2016/01/23/website.html</link>
        <guid isPermaLink="true">http://blog.jwwwb.com/general/2016/01/23/website.html</guid>
        
        
        <category>general</category>
        
      </item>
    
  </channel>
</rss>
