<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us">
    <generator uri="https://gohugo.io/" version="0.152.2">Hugo</generator><title type="html"><![CDATA[Scipy on Blog]]></title>
    
    
    
            <link href="https://blog.scientific-python.org/tags/scipy/" rel="alternate" type="text/html" title="html" />
            <link href="https://blog.scientific-python.org/tags/scipy/atom.xml" rel="self" type="application/atom" title="atom" />
    <updated>2026-04-04T04:32:36+00:00</updated>
    
    
    
    
        <id>https://blog.scientific-python.org/tags/scipy/</id>
    
        
        <entry>
            <title type="html"><![CDATA[Your Code Could Go To Space]]></title>
            <link href="https://blog.scientific-python.org/community-stories/will_tirone/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
                <link href="https://blog.scientific-python.org/scipy/internships/smit/?utm_source=atom_feed" rel="related" type="text/html" title="SciPy Internship: 2021-2022" />
                <link href="https://blog.scientific-python.org/scipy/qmc-basics/?utm_source=atom_feed" rel="related" type="text/html" title="A quick tour of QMC with SciPy" />
            
                <id>https://blog.scientific-python.org/community-stories/will_tirone/</id>
            
            
            <published>2023-07-19T00:00:00+00:00</published>
            <updated>2023-07-19T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>How I learned to code and contributed to a library used on the Mars 2020 mission.</blockquote><p>In mid-2018 I started learning Python by reading textbooks and watching online tutorials. I had absolutely zero background in computer science, but it seemed interesting so I continued to try. At some point, I decided I wanted to do a master’s degree in statistics, so I began to work on more statistics-based programming. That’s when I found SciPy. I became (and still am) fascinated by the idea of open-source software that is completely free to use and supported by a community of diligent programmers.</p>
<p>With plenty of extra time on my hands during the pandemic, I made it my goal to contribute to a Python library. My first contribution was actually to a project called <a href="https://github.com/firstcontributions/first-contributions">first contributions</a> which walks you through a very basic commit and push to GitHub. That built up my confidence a bit, so I decided to tackle a SciPy issue.
It was not easy. I watched several videos and guides on how to contribute to an open-source library but got stuck many times along the way! I have to admit I felt incompetent trying to make changes to this huge library, but the maintainers and community could not have been nicer or more supportive. That’s really the magic of open source. I was confused and lost, but the (largely volunteer) community was amazing.</p>
<p>Eventually, I managed to get a very small commit merged into the main branch of SciPy (which you can see <a href="https://github.com/scipy/scipy/pull/12962">here</a>). Despite being, at most, a few lines of code, this was a huge landmark for me as a programmer. To my surprise though, in early 2021, a little badge pop up on my GitHub profile that said “Mars 2020 Helicopter Contributor”. I was confused. I didn’t recall working on helicopters, much less helicopters that flew on Mars. I still remember getting chills when I read that I contributed to a library that was used on NASA’s Mars 2020 mission, which involved the robotic helicopter Ingenuity. GitHub posted an <a href="https://github.blog/2021-04-19-open-source-goes-to-mars/">article</a> explaining how about 12,000 people received a badge indicating that they had contributed to an open-source library that was used on the mission! Keep in mind that I made an absolutely tiny contribution, but I was extremely proud to be recognized in that way.</p>
<p>In an even stranger twist, this summer, I’m interning at NASA’s Jet Propulsion Laboratory (JPL) which built and still flies the Ingenuity helicopter along with the other robotic space exploration missions. It’s truly surreal to have come full circle like this, from learning Python in my living room during the pandemic to using SciPy in my daily work at JPL. Here, my work involves writing statistical simulations to estimate the probability of system failures during a mission.
If you’re reading this and interested in contributing, please know that your contributions to an open-source library, no matter how small, can have an impact larger than you could ever imagine. Collaboration like this is essential to pushing forward the boundaries of science. If you want to contribute, please feel free to reach out to me (@WillTirone) or anyone else in the SciPy community, and we can get you started on the right path. Last, I want to thank the maintainers of SciPy for their endless support and assistance while I was learning the basics of contribution to the library.</p>]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="open-source" label="Open-source" />
                             
                                <category scheme="taxonomy:Tags" term="testimonial" label="testimonial" />
                             
                                <category scheme="taxonomy:Tags" term="nasa" label="NASA" />
                             
                                <category scheme="taxonomy:Tags" term="jpl" label="JPL" />
                             
                                <category scheme="taxonomy:Tags" term="scipy" label="scipy" />
                             
                                <category scheme="taxonomy:Tags" term="internship" label="internship" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[SciPy Internship: 2021-2022]]></title>
            <link href="https://blog.scientific-python.org/scipy/internships/smit/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
            
                <id>https://blog.scientific-python.org/scipy/internships/smit/</id>
            
            
            <published>2022-06-04T00:00:00+00:00</published>
            <updated>2022-06-04T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Internship Experience</blockquote><p>I was <a href="https://mail.python.org/archives/list/scipy-dev@python.org/message/4S43BYHDQIPQENNJ6EMQY5QZDZK3ZT5I/">selected as an intern</a> to work on SciPy build system. In this blog post, I will be describing my journey of this 10-months long internship at SciPy. I worked on a variety of topics starting from migrating the SciPy build system to <a href="https://mesonbuild.com/index.html">Meson</a>, cleaning up the public API namespaces and adding <a href="https://uarray.org/en/latest/">Uarray</a> support to SciPy submodules.</p>
<h1 id="experience">Experience<a class="headerlink" href="#experience" title="Link to this heading">#</a></h1>
<h2 id="meson-build-system">Meson Build System<a class="headerlink" href="#meson-build-system" title="Link to this heading">#</a></h2>
<p>The main reasons for switching to Meson include (in addition to <code>distutils</code> being deprecated):</p>
<ol>
<li><em>Much faster builds</em></li>
<li><em>Reliability</em></li>
<li><em>Support for cross-compiling</em></li>
<li><em>Better build logs</em></li>
<li><em>Easier to debug build issues</em></li>
</ol>
<p><em>For more details on the initial proposal to switch to Meson, see <a href="https://github.com/scipy/scipy/issues/13615">scipy-13615</a></em></p>
<p>I was initially selected to work on the migrating the SciPy build system to <a href="https://mesonbuild.com/index.html">meson</a>. I started by adding Meson build support
for <a href="https://github.com/rgommers/scipy/pull/35">scipy.misc</a> and <a href="https://github.com/rgommers/scipy/pull/37">scipy.signal</a>. While working on this, we came across many <a href="https://github.com/rgommers/scipy/issues/42">build warnings</a> which we wanted to fix, since they unnecessarily increased the build log and might point to some hidden bugs. I fixed these warnings, the majority of which came from <a href="https://github.com/rgommers/scipy/issues/30">deprecated NumPy C API calls</a>.</p>
<ul>
<li>I also started <a href="https://github.com/rgommers/scipy/issues/58">benchmarking</a> the Meson build with various optimization levels, during which I ended up finding some <a href="https://github.com/scipy/scipy/issues/14667">failing benchmark tests</a> and tried to fix them.</li>
<li>I implemented the <a href="https://github.com/rgommers/scipy/pull/94">dev.py</a> interface that works in a similar way to <code>runtests.py</code>, but using Meson for building SciPy.</li>
<li>I extended my work on the Meson build by writing Python scripts for checking the installation of all <a href="https://github.com/rgommers/scipy/issues/69">test files</a> and <a href="https://github.com/scipy/scipy/pull/16010">.pyi files</a>.</li>
<li>I documented how to use <a href="https://github.com/rgommers/scipy/pull/96">dev.py</a>, and use <a href="https://github.com/scipy/scipy/pull/15953">parallel builds and optimization levels</a> with Meson.</li>
<li>I added <a href="https://github.com/rgommers/scipy/pull/130">meson option</a> to switch between BLAS/LAPACK libraries.</li>
</ul>
<p>Meson build support including all the above work was merged into SciPy&rsquo;s <code>main</code> branch around Christmas 2021. Meson will now become the default build in the upcoming 1.9.0 release.</p>
<h2 id="making-cleaner-public-namespaces">Making cleaner public namespaces<a class="headerlink" href="#making-cleaner-public-namespaces" title="Link to this heading">#</a></h2>
<h4 id="whats-the-issue">What&rsquo;s the issue?<a class="headerlink" href="#whats-the-issue" title="Link to this heading">#</a></h4>
<p><em>&ldquo;A basic API design principle is: a public object should only be available from one namespace. Having any function in two or more places is just extra technical debt, and with things like dispatching on an API or another library implementing a mirror API, the cost goes up.&rdquo;</em></p>

<div class="highlight">
  <pre>&gt;&gt;&gt; from scipy import ndimage
&gt;&gt;&gt; ndimage.filters.gaussian_filter is ndimage.gaussian_filter  # :(
True</pre>
</div>

<p>The <a href="http://scipy.github.io/devdocs/reference/index.html#api-definition">API reference docs</a> of SciPy define the public API. However, SciPy still had some submodules that were <em>accidentally</em> somewhat public by missing an underscore at the start of their name.
I worked on <a href="https://github.com/scipy/scipy/issues/14360">cleaning the pubic namespaces</a> for about a couple of months by carefully adding underscores to the <code>.py</code> files that were not meant to be public and added depecrated warnings if anyone tries to access them.</p>
<h4 id="the-solution">The solution:<a class="headerlink" href="#the-solution" title="Link to this heading">#</a></h4>

<div class="highlight">
  <pre>&gt;&gt;&gt; from scipy import ndimage
&gt;&gt;&gt; ndimage.filters.gaussian_filter is ndimage.gaussian_filter
&lt;stdin&gt;:1: DeprecationWarning: Please use `gaussian_filter` from the `scipy.ndimage` namespace, the `scipy.ndimage.filters` namespace is deprecated.
True</pre>
</div>

<h2 id="adding-uarray-support">Adding Uarray support<a class="headerlink" href="#adding-uarray-support" title="Link to this heading">#</a></h2>
<p><em>&ldquo;SciPy adopted uarray to support a multi-dispatch mechanism with the goal being: allow writing backends for public APIs that execute in parallel, distributed or on GPU.&rdquo;</em></p>
<p>For about the last four months, I worked on adding <a href="https://github.com/scipy/scipy/issues/14353">Uarray support</a> to SciPy submobules. I do recommend reading <a href="https://labs.quansight.org/blog/2021/10/array-libraries-interoperability/">this blog post</a> by Anirudh Dagar covering the motivation and actual usage of <code>uarray</code>. I picked up the following submodules for adding <code>uarray</code> compatibility:</p>
<ul>
<li><a href="https://github.com/rgommers/scipy/pull/101">signal</a></li>
<li><a href="https://github.com/scipy/scipy/pull/15610">linalg</a></li>
<li><a href="https://github.com/scipy/scipy/pull/15665">special</a></li>
</ul>
<p>At the same time, in order to show a working prototype, I also added <code>uarray</code> backends in CuPy to the following submodules:</p>
<ul>
<li><code>cupyx.scipy.ndimage</code> (<a href="https://github.com/cupy/cupy/pull/6403">PR #6403</a>)</li>
<li><code>cupyx.scipy.linalg</code> (<a href="https://github.com/cupy/cupy/pull/6460">PR #6460</a>)</li>
<li><code>cupyx.scipy.special</code> (<a href="https://github.com/cupy/cupy/pull/6564">PR #6564</a>)</li>
</ul>
<p>The pull requests contain links to Colab notebooks which show these features in action.</p>
<h4 id="what-does-usage-of-such-a-backend-look-like">What does usage of such a backend look like?<a class="headerlink" href="#what-does-usage-of-such-a-backend-look-like" title="Link to this heading">#</a></h4>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">scipy</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">cupy</span> <span class="k">as</span> <span class="nn">cp</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">scipy.linalg</span> <span class="kn">import</span> <span class="n">inv</span><span class="p">,</span> <span class="n">set_backend</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">cupyx.scipy.linalg</span> <span class="k">as</span> <span class="nn">_cupy_backend</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">x_cu</span><span class="p">,</span> <span class="n">x_nu</span> <span class="o">=</span> <span class="n">cp</span><span class="o">.</span><span class="n">array</span><span class="p">([[</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">3.0</span><span class="p">,</span> <span class="mf">4.0</span><span class="p">]]),</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([[</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">],</span> <span class="p">[</span><span class="mf">3.0</span><span class="p">,</span> <span class="mf">4.0</span><span class="p">]])</span>
</span></span><span class="line"><span class="cl"><span class="n">y_scipy</span> <span class="o">=</span> <span class="n">inv</span><span class="p">(</span><span class="n">x_nu</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">with</span> <span class="n">set_backend</span><span class="p">(</span><span class="n">_cupy_backend</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">y_cupy</span> <span class="o">=</span> <span class="n">inv</span><span class="p">(</span><span class="n">x_cu</span><span class="p">)</span></span></span></code></pre>
</div>
<h2 id="miscelleanous-work">Miscelleanous Work<a class="headerlink" href="#miscelleanous-work" title="Link to this heading">#</a></h2>
<ul>
<li><a href="https://github.com/scipy/scipy/pull/15440">Fix path issues in runtests.py</a></li>
<li><a href="https://github.com/scipy/scipy/pull/15250">Array inputs for stats.kappa4</a></li>
<li><a href="https://github.com/rgommers/scipy/pull/115">Fixes mac CI conda env cache</a></li>
</ul>
<h2 id="future-work">Future Work<a class="headerlink" href="#future-work" title="Link to this heading">#</a></h2>
<ul>
<li>The &ldquo;switch to Meson&rdquo; project is nearing its completion. One of the final issues was to allow <a href="https://github.com/scipy/scipy/pull/15476">building wheels</a> with the <code>meson-python</code> backend.</li>
<li>The PRs opened for adding <code>uarray</code> support are still under heavy discussion, and the main aim will be get them merged as soon as possible once we have reached a concrete decision.</li>
</ul>
<h2 id="things-to-remember">Things to remember<a class="headerlink" href="#things-to-remember" title="Link to this heading">#</a></h2>
<ol>
<li><em>Patience</em>: Setting up new project always takes some time. We might need to update/fix the system libraries and try to resolve the errors gradually.</li>
<li><em>Learning</em>: Learning new things was one of the main key during the internship. I was completely new to build systems and GPU libraries.</li>
</ol>
<h2 id="thank-you">Thank You!!<a class="headerlink" href="#thank-you" title="Link to this heading">#</a></h2>
<p>I am very grateful to <a href="https://github.com/rgommers">Ralf Gommers</a> for providing me with this opportunity and believing in me. His guidance, support and patience played a major role during the entire course of internship.
I am also thankful to whole SciPy community for helping me with the PR reviews and providing essential feedback. Also, huge thanks to <a href="https://github.com/czgdp1807">Gagandeep Singh</a> for always being a part of this wonderful journey.</p>
<p><em>In a nutshell, I will remember this experience as: <a href="https://github.com/rgommers">Ralf Gommers</a> has boosted my career by millions!</em></p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="scipy" label="SciPy" />
                             
                                <category scheme="taxonomy:Tags" term="internship" label="internship" />
                             
                                <category scheme="taxonomy:Tags" term="meson-build" label="meson-build" />
                             
                                <category scheme="taxonomy:Tags" term="uarray" label="uarray" />
                            
                        
                    
                
            
        </entry>
    
        
        <entry>
            <title type="html"><![CDATA[A quick tour of QMC with SciPy]]></title>
            <link href="https://blog.scientific-python.org/scipy/qmc-basics/?utm_source=atom_feed" rel="alternate" type="text/html" />
            
            
                <id>https://blog.scientific-python.org/scipy/qmc-basics/</id>
            
            
            <published>2022-04-04T00:00:00+00:00</published>
            <updated>2022-04-04T00:00:00+00:00</updated>
            
            
            <content type="html"><![CDATA[<blockquote>Do you need to use random numbers? Use Quasi-Monte Carlo (QMC) methods instead. QMC, what is it? Why you should care? And how to use it?</blockquote><p>At the end of this article, my goal is to convince you that: if you need to
use random numbers, you <em>should</em> consider using
<a href="https://scipy.github.io/devdocs/reference/stats.qmc.html"><code>scipy.stats.qmc</code></a>
instead of
<a href="https://numpy.org/doc/stable/reference/random/index.html"><code>np.random</code></a>.</p>
<p>In the following, we assume that <em>SciPy</em>, <em>NumPy</em> and <em>Matplotlib</em> are
installed and imported:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">qmc</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span></span></span></code></pre>
</div>
<blockquote>
<p>Note that no seeding is used in these examples. This will be the topic
of another article: seeding should <strong>only</strong> be used for testing purposes.</p>
</blockquote>
<p><strong>So what are Monte Carlo (MC) and Quasi-Monte Carlo (QMC)?</strong></p>
<h2 id="monte-carlo-mc">Monte Carlo (MC)<a class="headerlink" href="#monte-carlo-mc" title="Link to this heading">#</a></h2>
<blockquote>
<p>MC methods are a broad class of computational algorithms that rely on
repeated random sampling to obtain numerical results.
The underlying concept is to use randomness to solve problems that might be
deterministic in principle. They are often used in physical and mathematical
problems and are most useful when it is difficult or impossible to use other
approaches. MC methods are mainly used in three classes of problem:
optimization, numerical integration, and generating draws from a probability
distribution.</p>
</blockquote>
<p>Put simply, this is how you would usually generate a <em>sample</em> of points using
MC:</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">default_rng</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">sample</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">random</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="p">(</span><span class="mi">256</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span></span></span></code></pre>
</div>
<p>In this case, <code>sample</code> is a 2-dimensional array with 256 points which can be
visualized using a 2D scatter plot.</p>
<p><img src="/scipy/qmc-basics/mc.png" alt="MC sample using a 2D scatter plot."></p>
<p>In the plot above, points are generated randomly without any
knowledge about previously drawn points. It is clear that some regions of the
space are left unexplored while other regions have clusters. In an optimization
problem, it could mean that you would need to generate more sample to find the
optimum. Or in a regression problem, you could also overfit a model due to
some cluster of points.</p>
<p>Generating random numbers is a more complex problem than it sounds. Simple MC
methods are designed to sample points to be independent and identically
distributed (IID).</p>
<p>One could think that the solution is just to use a grid! But look what
happens if we have a distance of 0.1 between points in the unit-hypercube (
with all bounds ranging from 0 to 1).</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">disc</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="cl"><span class="n">x1</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">disc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">x2</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">disc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">x3</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">disc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">x1</span><span class="p">,</span> <span class="n">x2</span><span class="p">,</span> <span class="n">x3</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">meshgrid</span><span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">x2</span><span class="p">,</span> <span class="n">x3</span><span class="p">)</span></span></span></code></pre>
</div>
<p>The number of points required to fill the unit interval would be 10.
In a 2-dimensional hypercube the same spacing would require 100, and in 3
dimensions 1,000 points. As the number of dimensions grows, the number of
samples which is required to fill the space rises exponentially as the
dimensionality of the space increases. This exponential growth is called
the <em>curse of dimensionality</em>.</p>
<p><img src="/scipy/qmc-basics/curse.png" alt="Curse of dimensionality. 3 figures: 1D, 2D and 3D scatter plots of samples."></p>
<h2 id="quasi-monte-carlo-qmc">Quasi-Monte Carlo (QMC)<a class="headerlink" href="#quasi-monte-carlo-qmc" title="Link to this heading">#</a></h2>
<p>To mitigate the <em>curse of dimensionality</em>, you could decide to randomly
remove points from the sample or randomly sample in n-dimension. In both
cases, this <strong>will</strong> need to empty regions and clusters of points elsewhere.</p>
<p>Quasi-Monte Carlo (QMC) methods have been created specifically to answer this
problem. As opposed to MC methods, QMC methods are deterministic. Which means
that the points are not IID, but each new point knows about previous points.
The result is that we can construct samples with good coverage of the space.</p>
<blockquote>
<p>Deterministic does <strong>not</strong> mean that samples are always the same.
the sequences can be scrambled.</p>
</blockquote>
<p>Starting with version 1.7, SciPy provides QMC methods in
<a href="https://scipy.github.io/devdocs/reference/stats.qmc.html"><code>scipy.stats.qmc</code></a>.</p>
<p>Let&rsquo;s generate 2 samples with MC and a QMC method named <em>Sobol&rsquo;</em>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">n</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="mi">256</span><span class="p">,</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">default_rng</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_mc</span> <span class="o">=</span> <span class="n">rng</span><span class="o">.</span><span class="n">random</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">d</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">qrng</span> <span class="o">=</span> <span class="n">qmc</span><span class="o">.</span><span class="n">Sobol</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="n">d</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_qmc</span> <span class="o">=</span> <span class="n">qrng</span><span class="o">.</span><span class="n">random</span><span class="p">(</span><span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="p">)</span></span></span></code></pre>
</div>
<p>A very similar interface, but as seen below, with radically different results.</p>
<p><img src="/scipy/qmc-basics/mc_sobol.png" alt="Comparison between MC and QMC samples using a 2D scatter plot."></p>
<p>The 2D space clearly exhibit less empty areas and less clusters with the QMC
sample.</p>
<h2 id="quality">Quality?<a class="headerlink" href="#quality" title="Link to this heading">#</a></h2>
<p>Beyond the visual improvement of <em>quality</em>, there are metrics to assess the
quality of a sample. Geometrical criteria are commonly used, one can
compute the distance (L1, L2, etc.) between all pairs of points. But there
are also statistical criteria such as: the
<a href="https://scipy.github.io/devdocs/reference/generated/scipy.stats.qmc.discrepancy.html">discrepancy</a>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">qmc</span><span class="o">.</span><span class="n">discrepancy</span><span class="p">(</span><span class="n">sample_mc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 0.0009</span>
</span></span><span class="line"><span class="cl"><span class="n">qmc</span><span class="o">.</span><span class="n">discrepancy</span><span class="p">(</span><span class="n">sample_qmc</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 1.1e-05</span></span></span></code></pre>
</div>
<p>The lower the value, the better the quality.</p>
<h2 id="convergence">Convergence<a class="headerlink" href="#convergence" title="Link to this heading">#</a></h2>
<p>If this still does not convince you, let&rsquo;s look at a concrete example:
integrating a function. Let&rsquo;s look at the mean of the squared sum in
5 dimensions:</p>
<p>$$f(\mathbf{x}) = \left( \sum_{j=1}^{5}x_j \right)^2,$$</p>
<p>with $x_j \sim \mathcal{U}(0,1)$. It has a known mean value,
$\mu = 5/3+5(5-1)/4$. By sampling points, we can compute that mean numerically.</p>
<blockquote>
<p>The samplings are done 99 times and averaged. The variance is not reported
for simplicity, just know that it&rsquo;s guaranteed to be lower with QMC than with
MC.</p>
</blockquote>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="n">dim</span> <span class="o">=</span> <span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="n">ref</span> <span class="o">=</span> <span class="mi">5</span> <span class="o">/</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">5</span> <span class="o">*</span> <span class="p">(</span><span class="mi">5</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="mi">4</span>
</span></span><span class="line"><span class="cl"><span class="n">n_conv</span> <span class="o">=</span> <span class="mi">99</span>
</span></span><span class="line"><span class="cl"><span class="n">ns_gen</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">**</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">13</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">sample</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># dim 5, true value 5/3 + 5*(5 - 1)/4</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">sample</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="o">**</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">conv_method</span><span class="p">(</span><span class="n">sampler</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">n_samples</span><span class="p">,</span> <span class="n">n_conv</span><span class="p">,</span> <span class="n">ref</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">samples</span> <span class="o">=</span> <span class="p">[</span><span class="n">sampler</span><span class="p">(</span><span class="n">n_samples</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n_conv</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">    <span class="n">samples</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">samples</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">evals</span> <span class="o">=</span> <span class="p">[</span><span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">func</span><span class="p">(</span><span class="n">sample</span><span class="p">))</span> <span class="o">/</span> <span class="n">n_samples</span> <span class="k">for</span> <span class="n">sample</span> <span class="ow">in</span> <span class="n">samples</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="n">squared_errors</span> <span class="o">=</span> <span class="p">(</span><span class="n">ref</span> <span class="o">-</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">evals</span><span class="p">))</span> <span class="o">**</span> <span class="mi">2</span>
</span></span><span class="line"><span class="cl">    <span class="n">rmse</span> <span class="o">=</span> <span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">squared_errors</span><span class="p">)</span> <span class="o">/</span> <span class="n">n_conv</span><span class="p">)</span> <span class="o">**</span> <span class="mf">0.5</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">rmse</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Analysis</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_mc_rmse</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_sobol_rmse</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">default_rng</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">ns</span> <span class="ow">in</span> <span class="n">ns_gen</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Monte Carlo</span>
</span></span><span class="line"><span class="cl">    <span class="n">sampler_mc</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">rng</span><span class="o">.</span><span class="n">random</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">dim</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="n">conv_res</span> <span class="o">=</span> <span class="n">conv_method</span><span class="p">(</span><span class="n">sampler_mc</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">ns</span><span class="p">,</span> <span class="n">n_conv</span><span class="p">,</span> <span class="n">ref</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">sample_mc_rmse</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conv_res</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1"># Sobol&#39;</span>
</span></span><span class="line"><span class="cl">    <span class="n">engine</span> <span class="o">=</span> <span class="n">qmc</span><span class="o">.</span><span class="n">Sobol</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="n">dim</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">conv_res</span> <span class="o">=</span> <span class="n">conv_method</span><span class="p">(</span><span class="n">engine</span><span class="o">.</span><span class="n">random</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">ns</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ref</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">sample_sobol_rmse</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conv_res</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">sample_mc_rmse</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">sample_mc_rmse</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_sobol_rmse</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">sample_sobol_rmse</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Plot</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_aspect</span><span class="p">(</span><span class="s2">&#34;equal&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># MC</span>
</span></span><span class="line"><span class="cl"><span class="n">ratio</span> <span class="o">=</span> <span class="n">sample_mc_rmse</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">ns_gen</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">**</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">ns_gen</span><span class="p">,</span> <span class="n">ns_gen</span> <span class="o">**</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="n">ratio</span><span class="p">,</span> <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s2">&#34;k&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">ns_gen</span><span class="p">,</span> <span class="n">sample_mc_rmse</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s2">&#34;MC: np.random&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Sobol&#39;</span>
</span></span><span class="line"><span class="cl"><span class="n">ratio</span> <span class="o">=</span> <span class="n">sample_sobol_rmse</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="n">ns_gen</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">**</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">ns_gen</span><span class="p">,</span> <span class="n">ns_gen</span> <span class="o">**</span> <span class="p">(</span><span class="o">-</span><span class="mi">2</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span> <span class="o">*</span> <span class="n">ratio</span><span class="p">,</span> <span class="n">ls</span><span class="o">=</span><span class="s2">&#34;-&#34;</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="s2">&#34;k&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">ns_gen</span><span class="p">,</span> <span class="n">sample_sobol_rmse</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s2">&#34;QMC: qmc.Sobol&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xlabel</span><span class="p">(</span><span class="sa">r</span><span class="s2">&#34;$N_s$&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xscale</span><span class="p">(</span><span class="s2">&#34;log&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xticks</span><span class="p">(</span><span class="n">ns_gen</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_xticklabels</span><span class="p">([</span><span class="sa">rf</span><span class="s2">&#34;$2^</span><span class="se">{{</span><span class="si">{</span><span class="n">ns</span><span class="si">}</span><span class="se">}}</span><span class="s2">$&#34;</span> <span class="k">for</span> <span class="n">ns</span> <span class="ow">in</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">13</span><span class="p">)])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_ylabel</span><span class="p">(</span><span class="sa">r</span><span class="s2">&#34;$\log (\epsilon)$&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">set_yscale</span><span class="p">(</span><span class="s2">&#34;log&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">ax</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s2">&#34;upper right&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">tight_layout</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/scipy/qmc-basics/conv_mc_sobol.png" alt="Convergence of the integration error with MC and QMC."></p>
<p>With MC the approximation error follows a theoretical rate of $O(n^{-1/2})$.
But, QMC methods have better rates of convergence and achieve $O(n^{-1})$
for this function–and even better rates on very smooth functions.</p>
<p>This means that using $2^8=256$ points from <em>Sobol&rsquo;</em> leads to a lower
error than using $2^{12}=4096$ points from MC! When the function evaluation
is costly, it can bring huge computational savings.</p>
<h2 id="sampling-from-any-distribution-advanced">Sampling from any distribution (advanced)<a class="headerlink" href="#sampling-from-any-distribution-advanced" title="Link to this heading">#</a></h2>
<p>But there is more! Another great use of QMC is to sample arbitrary
distributions. In SciPy 1.8, there are new classes of
<a href="https://scipy.github.io/devdocs/reference/stats.sampling.html">samplers</a>
that allow you to sample from any custom distribution. And some of
these methods can use QMC with a <code>qrvs</code> method:</p>
<ul>
<li><a href="https://scipy.github.io/devdocs/reference/generated/scipy.stats.sampling.NumericalInversePolynomial.html">NumericalInversePolynomial</a></li>
<li><a href="https://scipy.github.io/devdocs/reference/generated/scipy.stats.sampling.NumericalInverseHermite.html">NumericalInverseHermite</a></li>
</ul>
<p>Here is an example with a distribution from SciPy: <em>fisk</em>. We generate
a MC sample from the distribution (either directly from the distribution with
<code>fisk.rvs</code> or using <code>NumericalInverseHermite.rvs</code>) and another sample with
QMC using <code>NumericalInverseHermite.qrvs</code>.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">scipy.stats</span> <span class="k">as</span> <span class="nn">stats</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">scipy.stats</span> <span class="kn">import</span> <span class="n">sampling</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Any distribution</span>
</span></span><span class="line"><span class="cl"><span class="n">c</span> <span class="o">=</span> <span class="mf">3.9</span>
</span></span><span class="line"><span class="cl"><span class="n">dist</span> <span class="o">=</span> <span class="n">stats</span><span class="o">.</span><span class="n">fisk</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># MC</span>
</span></span><span class="line"><span class="cl"><span class="n">rng</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">default_rng</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_mc</span> <span class="o">=</span> <span class="n">dist</span><span class="o">.</span><span class="n">rvs</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="n">rng</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># QMC</span>
</span></span><span class="line"><span class="cl"><span class="n">rng_dist</span> <span class="o">=</span> <span class="n">sampling</span><span class="o">.</span><span class="n">NumericalInverseHermite</span><span class="p">(</span><span class="n">dist</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># sample_mc = rng_dist.rvs(128, random_state=rng)  # MC alternative same as above</span>
</span></span><span class="line"><span class="cl"><span class="n">qrng</span> <span class="o">=</span> <span class="n">qmc</span><span class="o">.</span><span class="n">Sobol</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">sample_qmc</span> <span class="o">=</span> <span class="n">rng_dist</span><span class="o">.</span><span class="n">qrvs</span><span class="p">(</span><span class="mi">128</span><span class="p">,</span> <span class="n">qmc_engine</span><span class="o">=</span><span class="n">qrng</span><span class="p">)</span></span></span></code></pre>
</div>
<p>Let&rsquo;s visualize the difference between MC and QMC by calculating the empirical
Probability Density Function (PDF). The QMC results are clearly superior
to MC.</p>


<div class="highlight">
  <pre class="chroma"><code><span class="line"><span class="cl"><span class="c1"># Visualization</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="p">,</span> <span class="n">axs</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">subplots</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">sharey</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">sharex</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="n">dist</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mf">0.01</span><span class="p">),</span> <span class="n">dist</span><span class="o">.</span><span class="n">ppf</span><span class="p">(</span><span class="mf">0.99</span><span class="p">),</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">pdf</span> <span class="o">=</span> <span class="n">dist</span><span class="o">.</span><span class="n">pdf</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">delta</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">max</span><span class="p">(</span><span class="n">pdf</span><span class="p">)</span> <span class="o">*</span> <span class="mf">5e-2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">samples</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;MC: np.random&#34;</span><span class="p">:</span> <span class="n">sample_mc</span><span class="p">,</span> <span class="s2">&#34;QMC: qmc.Sobol&#34;</span><span class="p">:</span> <span class="n">sample_qmc</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">for</span> <span class="n">ax</span><span class="p">,</span> <span class="n">sample</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">axs</span><span class="p">,</span> <span class="n">samples</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_title</span><span class="p">(</span><span class="n">sample</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">pdf</span><span class="p">,</span> <span class="s2">&#34;-&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s2">&#34;fisk PDF&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">samples</span><span class="p">[</span><span class="n">sample</span><span class="p">],</span> <span class="o">-</span><span class="n">delta</span> <span class="o">-</span> <span class="n">delta</span> <span class="o">*</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">(</span><span class="mi">128</span><span class="p">),</span> <span class="s2">&#34;+k&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">kde</span> <span class="o">=</span> <span class="n">stats</span><span class="o">.</span><span class="n">gaussian_kde</span><span class="p">(</span><span class="n">samples</span><span class="p">[</span><span class="n">sample</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">kde</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="s2">&#34;-.&#34;</span><span class="p">,</span> <span class="n">lw</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="s2">&#34;empirical PDF&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># or use a histogram</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># ax.hist(sample, density=True, histtype=&#39;stepfilled&#39;, alpha=0.2)</span>
</span></span><span class="line"><span class="cl">    <span class="n">ax</span><span class="o">.</span><span class="n">set_xlim</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">axs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">legend</span><span class="p">(</span><span class="n">loc</span><span class="o">=</span><span class="s2">&#34;best&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">supylabel</span><span class="p">(</span><span class="s2">&#34;Density&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">supxlabel</span><span class="p">(</span><span class="s2">&#34;Sample value&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">fig</span><span class="o">.</span><span class="n">tight_layout</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span></span></span></code></pre>
</div>
<p><img src="/scipy/qmc-basics/fisk_mc_sobol.png" alt="Probability density function of the fisk distribution.
Comparison with empirical distributions built with MC and QMC."></p>
<p>Careful readers will note that there is no seeding. This is intentional as
noted at the beginning of this article. You might run this code
again and have better results with MC. <strong>But</strong> only sometimes. And that&rsquo;s
exactly my point. On average, you are guaranteed to have more consistent
results with a better quality using QMC. I invite you to try it and see for
yourself!</p>
<h2 id="conclusion">Conclusion<a class="headerlink" href="#conclusion" title="Link to this heading">#</a></h2>
<p>I hope that I convinced you to use QMC the next time you need random numbers.
QMC is superior to MC, period.</p>
<p>There is an extensive body of literature and rigorous proofs. One reason MC is
still more popular is that QMC is harder to implement and, depending on the
method, there are rules to follow.</p>
<p>Take the <em>Sobol&rsquo;</em> method we used: you must use exactly $2^n$ sample. If you
don&rsquo;t do it, you will break some properties and end up having the same
performance than MC. This is why some people argue that QMC is not better:
they simply don&rsquo;t use the methods properly, hence fail to see any benefits and
conclude that MC is &ldquo;enough&rdquo;.</p>
<p>In
<a href="https://scipy.github.io/devdocs/reference/stats.qmc.html"><code>scipy.stats.qmc</code></a>,
we went to great lengths to explain how to use the methods, and we added some
explicit warnings to make the methods accessible and useful to
everyone.</p>
]]></content>
            
                 
                    
                 
                    
                         
                        
                            
                             
                                <category scheme="taxonomy:Tags" term="scipy" label="scipy" />
                             
                                <category scheme="taxonomy:Tags" term="tutorial" label="tutorial" />
                             
                                <category scheme="taxonomy:Tags" term="random-numbers" label="random-numbers" />
                            
                        
                    
                
            
        </entry>
    
</feed>
