diff --git a/config/_default/menus.en.toml b/config/_default/menus.en.toml index 051ab2b..e4e4c84 100644 --- a/config/_default/menus.en.toml +++ b/config/_default/menus.en.toml @@ -38,4 +38,4 @@ # [[footer]] # name = "Tags" # pageRef = "tags" -# weight = 10 +# weight = 20 diff --git a/content/_index.md b/content/_index.md index 57a21f3..073b43f 100644 --- a/content/_index.md +++ b/content/_index.md @@ -15,16 +15,10 @@ Hi there! 👋 I am currently a Quantum Research Data Scientist at [Center for Computational Life Sciences, Lerner Research Institute, Cleveland Clinic](https://my.clevelandclinic.org/research/computational-life-sciences). I am a physicist by training, with a Ph.D. from [Case Western Reserve University](https://case.edu/). I work on interesting quantum computing problems in physics and life sciences. -Beyond my [research](/research/), I am passionate about other emerging science and tech fields. -Sometimes I write stuff on my [blog](/blog/). +Beyond what I do in my [research](/research/), I am also broadly interested in emerging AI technologies. + -
- -{{< alert "email">}} -I am always open to collaborations and discussions. Please feel free to reach out to me via the links above. -{{< /alert >}} -
{{< button href="/about/" target="_self" >}} diff --git a/content/research/index.md b/content/research/_index.md similarity index 97% rename from content/research/index.md rename to content/research/_index.md index e11bb90..ee92eb4 100644 --- a/content/research/index.md +++ b/content/research/_index.md @@ -12,7 +12,6 @@ showComments: false --> - ## Overview My current research interests are focused on leveraging near-term quantum computers to solve problems in various domains, which include but are not limited to: @@ -24,6 +23,11 @@ Things I have worked on in the past: - **Topological materials**: investigating novel spin/charge transport phenomena in topological semimetals, such as Weyl and Dirac semimetals - **Dark matter models**: studying the phenomenology of dark matter models in theories with a gauged baryon symmetry +
+ +{{< alert "email">}} +I am always open to collaborations and discussions. Please feel free to reach out to me via the links in my [homepage](../_index.md). +{{< /alert >}} {{ end }} {{ end }} diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..0786ff7 --- /dev/null +++ b/public/404.html @@ -0,0 +1,412 @@ + + + + + + + + + + + + 404 Page not found · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +

Page Not Found 😕

+

+ Error 404 +

+
+

It seems that the page you've requested does not exist.

+
+ + +
+ + +
+ + diff --git a/public/about/disco_diffusion.png b/public/about/disco_diffusion.png new file mode 100644 index 0000000..d64c938 Binary files /dev/null and b/public/about/disco_diffusion.png differ diff --git a/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1024x0_resize_box_3.png b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1024x0_resize_box_3.png new file mode 100644 index 0000000..127fe03 Binary files /dev/null and b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1024x0_resize_box_3.png differ diff --git a/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1320x0_resize_box_3.png b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1320x0_resize_box_3.png new file mode 100644 index 0000000..52d235f Binary files /dev/null and b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_1320x0_resize_box_3.png differ diff --git a/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_330x0_resize_box_3.png b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_330x0_resize_box_3.png new file mode 100644 index 0000000..939461f Binary files /dev/null and b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_330x0_resize_box_3.png differ diff --git a/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_660x0_resize_box_3.png b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_660x0_resize_box_3.png new file mode 100644 index 0000000..b52e337 Binary files /dev/null and b/public/about/disco_diffusion_hua2be6f31474dc9ba60530d3574436332_1393848_660x0_resize_box_3.png differ diff --git a/public/about/index.html b/public/about/index.html new file mode 100644 index 0000000..871fb86 --- /dev/null +++ b/public/about/index.html @@ -0,0 +1,603 @@ + + + + + + + + + + + + About · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ About +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+
+
+ +
+ +
+ + + + + + + + + + + + +
+ + AI generated artwork + +
AI generated art by Disco Diffusion.
+
+ + + +
+ + +

A Brief Bio #

+ +

Welcome! My name is Ruihao Li (李瑞浩). +I grew up in Guangdong, China. +I received my Bachelor’s degree with First Class Honours in physics from The University of Sydney (Australia) in 2016. +After that, I began to pursue my Ph.D. in physics at Case Western Reserve University (CWRU) in 2017. +I spent the first two years working with Dr. Pavel Fileviez Perez on theories of leptophobic dark matter models. +From 2019, I started working with Dr. Shulei Zhang on charge and spin transport in topological quantum materials, especially topological semimetals. +I graduated in 2023 and am currently working as a Quantum Research Data Scientist at Center for Computational Life Sciences, Lerner Research Institute, Cleveland Clinic, focusing on developing quantum computing applications in life sciences. +I am also actively working on quantum computing projects in physics and am interested in developing open-source tools for research and education. +I make use of both analytical and numerical tools for my research, including Mathematica, Python, Julia, etc. +See my + + research for more details.

+ + + + +

Other Interests #

+ +
    +
  • Huge fan of basketball, the NBA, and LeBron James 👑
  • +
  • Avid cook from time to time 🥘
  • +
  • Animal videos all day 🐱
  • +
  • Mechanical stuff and tech gadgets ⚙️
  • +
+ +
+
+
+ + + + + + + +
+
+ + + + +
+ + +
+ + diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000..518b6ac Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 0000000..d81a442 Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..b163613 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/blog/2d-ising-model/2d_ising.gif b/public/blog/2d-ising-model/2d_ising.gif new file mode 100644 index 0000000..cf0dd02 Binary files /dev/null and b/public/blog/2d-ising-model/2d_ising.gif differ diff --git a/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1024x0_resize_box_1.gif b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1024x0_resize_box_1.gif new file mode 100644 index 0000000..f2b8812 Binary files /dev/null and b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1024x0_resize_box_1.gif differ diff --git a/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1320x0_resize_box_1.gif b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1320x0_resize_box_1.gif new file mode 100644 index 0000000..593245e Binary files /dev/null and b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_1320x0_resize_box_1.gif differ diff --git a/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_330x0_resize_box_1.gif b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_330x0_resize_box_1.gif new file mode 100644 index 0000000..4737007 Binary files /dev/null and b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_330x0_resize_box_1.gif differ diff --git a/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_660x0_resize_box_1.gif b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_660x0_resize_box_1.gif new file mode 100644 index 0000000..1d91fc4 Binary files /dev/null and b/public/blog/2d-ising-model/2d_ising_hu2eafac7367e312449da55aa77b9d7c03_4015190_660x0_resize_box_1.gif differ diff --git a/public/blog/2d-ising-model/index.html b/public/blog/2d-ising-model/index.html new file mode 100644 index 0000000..80e17f2 --- /dev/null +++ b/public/blog/2d-ising-model/index.html @@ -0,0 +1,1140 @@ + + + + + + + + + + + + Supercharging the Pythonic Metropolis Monte Carlo · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Supercharging the Pythonic Metropolis Monte Carlo +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Physics + + Python + + + +
+ + + +
+
+
+ + + +
+ + + +

Okay, I’ll admit that this is neither a super exciting nor a new topic to write about. But I’ve been looking into some ways to simulate/prepare thermal states these days and the Metropolis Monte Carlo algorithm (which is also often referred to as the Metropolis-Hastings algorithm) is probably one of the most well-known methods to do so. Before fully stepping into the quantum realm (see Refs. [1] and [2] for quantum generalizations of this method), I thought I might as well try my hand at the classical version first. I have decided to use this technique to simulate the ferromagnetic phase transition of the famous 2D Ising model in statistical physics. Instead of focusing on the physics or the algorithm itself, the main discussion of this post will revolve around how to use Numba and Cython to “supercharge” the Pythonic implementation.

+

Metropolising the Ising model #

+
+ + + + + + + + + + + + +
+ + 2d ising animation + +
2D Ising model with animated spin flips (figure taken from here).
+
+ + + +
+

Let us first say something about our objective here. Given a two-dimensional Ising model on an $L\times L$ square lattice, that is, $L^2$ spins which can only take values $+1$ (spin-up or red) or $-1$ (spin-down or blue) as displayed in the figure above, we want to simulate the thermal state of the system at finite temperature and extract a few thermal expectation values such as energy and magnetization along the way. Based on the evolution of net magnetization with an increasing temperature, we should observe a phase transition from a ferromagnetic (with finite magnetization) to a non-magnetic state (with zero magnetization) at some critical temperature $T_C$. Note that in 1D such phase transition will not happen due to the Peierls argument that dates back to the 1930s (see an explanation here). In its simplest form, the Ising Hamiltonian of the system is given by +$$ +H = -J\sum_{\braket{i,j}}\sigma_i\sigma_j, +$$ +where $\braket{i, j}$ denotes all pairs of neighboring spins on the lattice and $J$ is the coupling strength between any two spins.

+

To compute any thermal expectation, we need to know the probability distribution of different spin configurations, which, in this case, is the Boltzmann distribution since the system is essentially a canonical ensemble at equilibrium: +$$ +P_S(\beta) = \frac{e^{-\beta E_S}}{Z}, +$$ +where $\beta = 1/k_B T$ is sometimes called the inverse temperature (for simplicity we will set the Boltzmann constant $k_B = 1$ hereafter) and $E_S$ is the energy of the spin configuration $S$, which can be computed from the Hamiltonian. $Z$ is the partition function defined as +$$ +Z = \sum_S e^{-\beta E_S}. +$$ +In particular, for $L^2$ spins, there are totally $2^{L^2}$ possible spin configurations. The partition function can be computed by summing over all these configurations, which is a computationally intractable task, especially for larger systems. However, we can use the Metropolis-Hastings algorithm to sample the distribution $P_S(\beta)$ and estimate the expectation values of interest. The basic idea is to start with a random spin configuration and then propose a new configuration by flipping a single spin. If the new configuration has a lower energy, we simply accept it. Otherwise, we accept it with probability $e^{-\beta(E_\text{new}-E_\text{old})}$, where $E_\text{new}$ and $E_\text{old}$ are the energies of the new and old configurations, respectively. This process is repeated for a large number of times until the sampled configurations are (almost) statistically independent and the distribution converges to the Boltzmann distribution. The expectation values are then computed from the sampled configurations by simply taking +$$ +\braket{O(\beta)} = \sum_S O_S P_S(\beta) +$$ +for any observable $O$. +The Metropolis-Hastings algorithm is a Markov chain Monte Carlo (MCMC) method, which means that the new configuration is only dependent on the old configuration in the previous step and not on the entire history of the chain. This is a very important property of the algorithm, which allows us to parallelize the sampling process and speed up the computation. Here is a nice blog post by Gregory Gundersen justifying why this simple algorithm works if you want to have a deeper understanding of it.

+

Of course, the Metropolis algorithm is not perfect. You can imagine that in each step flipping just one spin could be inefficient. At low temperatures, spin flips are rare because the acceptance probability is low. So we would need to perform more steps to sample the distribution. More severely, as the system approaches the critical temperature, the spin-spin correlation length diverges, so the spins tend to form large aligned domains. This leads to a phenomenon called the critical slowing down, which reflects the difficulty in flipping a spin within a correlated spin cluster. One way to overcome this hurdle is to use a cluster-flipping algorithm which flips multiple spins at once. An example of this is the Wolff algorithm [3] but in this post we will just focus on the Metropolis algorithm.

+

Pythonic implementation #

+

Without further ado, let us implement the Metropolis algorithm for the 2D Ising model in Python. To start with, we can randomly generate the initial spin configuration. We can build a class called Ising with core methods to generate an initial spin configuration, compute the system’s total energy and net magnetization, and of course, update the spin configuration based on the Metropolis algorithm. Since the implementation is pretty straightforward, I will just attach the code below:

+
import numpy as np
+
+class Ising:
+    """
+    Pure Python implementation of Metropolis Monte Carlo Simulation of the 2D 
+    Ising model (square lattice).
+    """
+
+    def __init__(self, J, L, T):
+        """
+        Initialize the Ising model.
+
+        Args:
+            J (float): Coupling constant
+            L (int): Linear size of the lattice
+            T (float): Temperature
+        """
+        self.J = J
+        self.L = L
+        self.T = T
+        self.spin_config = self.generate_spin_config()
+
+    def generate_spin_config(self):
+        """
+        Generate a random spin configuration.
+        """
+        return np.random.choice([-1, 1], size=(self.L, self.L))
+
+    def compute_energy(self):
+        """
+        Compute the energy of the spin configuration.
+        """
+        energy = 0
+        for i in range(self.L):
+            for j in range(self.L):
+                # Periodic boundary conditions
+                energy += (
+                    -self.J * self.spin_config[i, j] * (
+                        self.spin_config[i, (j + 1) % self.L]
+                        + self.spin_config[(i + 1) % self.L, j]
+                        + self.spin_config[i, (j - 1) % self.L]
+                        + self.spin_config[(i - 1) % self.L, j]
+                    )
+                )
+        return energy / 2
+
+    def compute_magnetization(self):
+        """
+        Compute the net absolute magnetization of the spin configuration.
+        """
+        return np.abs(np.sum(self.spin_config))
+
+    def mc_update(self):
+        """
+        Perform L^2 Metropolis steps to update the spin configuration.
+        """
+        for _ in range(self.L**2):
+            # Pick a random site
+            i = np.random.randint(self.L)
+            j = np.random.randint(self.L)
+            # Compute the change in energy
+            delta_E = (
+                2 * self.J * self.spin_config[i, j] * (
+                    self.spin_config[i, (j + 1) % self.L]
+                    + self.spin_config[(i + 1) % self.L, j]
+                    + self.spin_config[i, (j - 1) % self.L]
+                    + self.spin_config[(i - 1) % self.L, j]
+                )
+            )
+            # Flip the spin if the energy decreases or if the Metropolis 
+            # criterion is satisfied
+            if delta_E <= 0:
+                self.spin_config[i, j] *= -1
+            elif np.random.random() < np.exp(-delta_E / self.T):
+                self.spin_config[i, j] *= -1
+

As one can see from mc_update(), one full update corresponds to repeating the Metropolis step $L^2$ times. The next configuration to be used in the Monte Carlo method is obtained after one full update. To set up the simulation, we will need to specify the values of the coupling strength $J$, the length of the square lattice $L$, as well as the temperature range within which to compute the expectation values $(T_\text{low}, T_\text{high})$. Furthermore, as mentioned before, we first need to perform enough Metropolis updates (specified by equil_steps) to sample the equilibrium distribution, after which we again update the system mc_steps times in total to build up the statistics for measuring the expectation values. We also define skip_steps which sets the number of lattice updates between any two consecutive measurements. Therefore, we can define the following function that outputs the energy expectation, magnetization expectation, and the final spin configuration at a range of temperatures:

+
def run_ising(J, L, T_low, T_high, nT, equil_steps, mc_steps, skip_steps):
+    """
+    Run the Monte Carlo simulation for a range of temperatures.
+
+    Args:
+        J (float): Coupling constant
+        L (int): Linear size of the lattice
+        T_low (float): Lower bound of the temperature range
+        T_high (float): Upper bound of the temperature range
+        nT (int): Number of temperatures to simulate
+        equil_steps (int): Number of Monte Carlo steps to perform for equilibration
+        mc_steps (int): Number of Monte Carlo steps to perform during measurement
+        skip_steps (int): Number of Monte Carlo steps to skip between measurements
+
+    Returns:
+        (np.array, np.array, np.array): Arrays of energies (per site), 
+        magnetizations (per site), and spin configurations
+    """
+    T_array = np.linspace(T_low, T_high, nT)
+    # Initialize arrays to store the energies and magnetizations
+    E_array = np.zeros(nT)
+    M_array = np.zeros(nT)
+    # Initialize arrays to store the final spin configurations for each T
+    spin_config_array = np.zeros((nT, L, L))
+    # Loop over temperatures
+    for i in range(nT):
+        Et = Mt = 0
+        # Initialize the Ising model
+        ising = Ising(J, L, T_array[i])
+        # Equilibrate the system
+        for _ in range(equil_steps):
+            ising.mc_update()
+        # Perform Monte Carlo steps after equilibration
+        for j in range(mc_steps):
+            ising.mc_update()
+            # Skip the first few steps
+            if j % skip_steps == 0:
+                Et += ising.compute_energy()
+                Mt += ising.compute_magnetization()
+        # Average the energy and magnetization
+        E_array[i] = Et / (mc_steps // skip_steps) / L ** 2
+        M_array[i] = Mt / (mc_steps // skip_steps) / L ** 2
+        # Store the final spin configuration
+        spin_config_array[i] = ising.spin_config
+    return E_array, M_array, spin_config_array
+

Luckily for us, the 2D Ising model has closed-form solution for the energy and magnetization expectations, as well as the critical temperature $T_c$, which can be used to gauge the accuracy of our simulation. We can also have these exact solutions built in to our Ising class. The full code can be found here.

+

Acceleration with Numba #

+

If you run the above code, you would find it quite slow even with lattice size as small as $L = 10$, which took around 50 seconds on my MacBook Pro. The main bottleneck of the code is the mc_update() function, which involves $L^2$ evaluations of delta_E in the Metropolis step and is called repeatedly in the Monte Carlo simulation. The mc_update() function above is written in pure Python, which is not very efficient. One easy way to accelerate the code is to use the Numba library. Numba is a just-in-time (JIT) compiler that translates Python code into machine code during runtime (rather than pre-runtime like some compiled languages such as C). As we know, Python is an interpreted language, which means that the source code is converted to bytecode and executed line by line. A (good) JIT compiler helps remove the interpreter overhead and also allows for better optimizations since it has access to dynamic runtime information. What’s cool about Numba is that it works at function level and you can simply annotate functions you want to accelerate with the @jit decorators. It works best when a function involves heavy NumPy operations and nested loops. In our case, we should obviously accelerate the mc_update() function, but also compute_energy() and compute_magnetization(). One caveat in this case is that we cannot directly “jit” instance methods of a class. There are multiple ways to get around it. One is to convert the instance methods to static methods. Another is to use @jitclass to decorate the whole class but it is hard to work with more complex classes. Finally, a way that I find most convenient is to define the functions to be “jitted” outside the class and then just call them in the corresponding methods. So we would have something like this:

+
from numba import jit
+
+@jit(nopython=True)
+def compute_energy(spin_config, J):
+    ...
+
+@jit(nopython=True)
+def compute_magnetization(spin_config):
+    ...
+
+@jit(nopython=True)
+def mc_update(spin_config, J, T):
+    ...
+
+class Ising_numba:
+
+    def __init__(self, J, L, T):
+        ...
+
+    def compute_energy(self):
+        return compute_energy(self.spin_config, self.J)
+
+    def compute_magnetization(self):
+        return compute_magnetization(self.spin_config)
+
+    def mc_update(self):
+        mc_update(self.spin_config, self.J, self.T)
+

Note that we have specified nopython=True in the @jit decorator (which is equivalent to using the @njit decorator) to ensure that the function is compiled in “nopython” mode, which means that the decorated function will run without the Python interpreter. The nopython mode gives the best performance but it also requires that the native types of all variables in the function can be inferred. Quoting from Numba’s official documentation: “A failure in type inference can be caused by two reasons. The first reason is user error due to incorrect use of a type. This type of error will also trigger an exception in regular python execution. The second reason is due to the use of an unsupported feature, but the code is otherwise valid in regular python execution.” If nopython=True is not set, the compilation would fall back to the object mode if type inference fails.

+

Overall, Numba is great when it works, leading to huge performance boost (as we will see later), and it has other features which I did not touch upon, such as parallelization and vectorization. However, in its current form, it is still quite limited in its nopython mode as only certain features in Python and NumPy are supported (see a full list here and here). Even when it is possible to make existing Python codes Numba-compatible, one often has to spend time refactoring them in certain ways to make it work.

+

Acceleration with Cython #

+

Another popular way of supercharging Python codes is to use Cython. Cython is a superset of Python that allows you to write (slightly modified) Python code with static type declarations and compile it into C code (hence the name). The C code can then be compiled into a Python extension module that can be imported and used in Python. The main advantage of Cython is that it allows you to write codes that resemble Python but at the same time you can use all the features and functions of C (e.g., pointers, structs, etc.) and also take advantage of the C compiler’s optimizations. One downside is that it is not as straightforward as Numba since you need to write the code in a different syntax and compilation is always needed before using it. The basic usage of Cython is well documented here. Basically, two steps are needed: (1) write the Cython source code in a .pyx file and (2) compile the .pyx file into a Python extension module. The compilation can be done in two ways: (1) using the cython command line tool or (2) using the cythonize() function in the setuptools package. The second method is more convenient when using with an associated setup.py with the following basic structure:

+
from setuptools import setup, Extension
+from Cython.Build import cythonize
+
+setup(
+    ...
+    ext_modules = cythonize(Extension(
+        "ising_cython",
+        sources=["ising_cython.pyx"],
+        include_dirs=[...],
+        extra_compile_args=[...],
+        extra_link_args=[...],
+        ...
+    )),
+    ...
+)
+

Note that the Extension module is used in order to specify compiler options and use extra libraries. You can find the setup.py file used for this project here (inspired by Rajesh Singh’s work), where an additional check for OpenMP support is added. Cython comes with OpenMP support for parallel computing and to enable it, you need to supply '-fopenmp' as the argument in extra_compile_args and extra_link_args above. Within the Cython source code, you can use cython.parallel.prange() in place of range() for parallelizing loops. One thing to keep in mind is that the Global Interpreter Lock (GIL) must be released to use this kind of parallelism. One can release the GIL around a block of code using the with nogil: statement. Alternatively, one can specify nogil in a C function header to declare that it is safe to call without the GIL (but this does not guarantee that the function will be run with the GIL released):

+
cdef void my_nogil_func(...) nogil:
+    ...
+

For our case, one good place to use parallelism is the outer loop of some nested loops. You can see more about parallelism in Cython here.

+

In addition to parallelism, there are other things one can do to make Cython faster. Two of the most frequently used function decorators to speed things up are @cython.boundscheck(False) (assuming no IndexErrors will be raised) and @cython.wraparound(False) (no negative indexing is used). However, you should make sure you know what they do and check your code carefully before using any of these. One pitfall I encountered as a newbie to C was the use of @cython.cdivision(True). I found that it did help speed things up quite a bit, but upon checking the computed energy and thermal expectations against the ones based on pure Python and Python with Numba, it led to some clearly incorrect results. It turns out that this is due to a different behavior of the operator % in Python and C. Unlike in Python where it represents a modulo operation, in C it is actually the reminder operation. For example, -10 % 3 = 2 in Python but doing the same in C leads to -1. To stick to the Pythonic behavior, I defined a separate function to perform the modulo operation in the cdivision mode:

+
@cython.cdivision(True)
+cdef int mod(int a, int b) nogil:
+    if a < 0:
+        return a % b + b
+    else:
+        return a % b
+

The other thing about cdivision is that it does not do floating point division automatically, i.e., int / int = int. So again, one should watch out for unexpected behaviors like this when using Cython. Two blog posts I came across that provide many useful tips for Cython usage are here and here. For a list of complier directives one can toggle please refer to this document.

+

Finally you can find the full source code for my Cython implementation of the 2D Ising model simulation here.

+

A few words about results #

+

So how did the Metropolis algorithm do? I ran the simulation with equil_steps = 5000, mc_steps = 10000, skip_steps = 100 for four different system sizes, $L = [10, 20, 40, 80]$. The following plots show the thermal expectations of energy and magnetization as functions of the temperature (from 0.5 to 4.5 with 50 points in total). The red lines correspond to the exact results and the dashed line denotes the exact critical temperature. In the energy plot, the Monte Carlo results match the exact result pretty well, but the magnetization plot shows some more noticeable discrepancies. In both cases, we can see that generally as the system size increases, the Monte Carlo results match the exact results better due to the fact that the exact solutions are obtained in the limit $L\to\infty$. At the same time, at low temperatures, there are more points that deviate significantly from the exact results as the system size grows. This is due to the fact that the Metropolis algorithm is not very efficient at low temperatures since the acceptance rate is very low.

+
+ +
Thermal expectations of energy and magnetization as functions of temperature, based on the Metropolis Monte Carlo simulation of the 2D Ising model.
+
+

We can also look at how the equilibrium spin configuration evolves with an increasing temperature. Here is an animation showing just that (for $L=80$). The behavior is consistent with the phase diagram of the 2D Ising model (also reflected in the magnetization plot above). At low temperatures, the spins tend to align in the same direction, while at high temperatures, they are randomly oriented, leading to an (almost) vanishing net magnetization.

+

What about the speed? The following plot shows the time it takes (normalized to the time taken by pure Python) to run the full simulation (with the same parameters introduced above) for several different system sizes.

+
+ +
Thermal expectations of energy and magnetization as functions of temperature, based on the Metropolis Monte Carlo simulation of the 2D Ising model.
+
+

Of course, this is by no means a rigorous benchmark for performance. But it does give us a rough idea of how much faster we can make the Metropolis Monte Carlo using Numba or Cython (50 - 250 times faster)! This is pretty important especially for larger systems when the absolute time used can be cut down significantly.

+
+

References #

+
    +
  1. +

    K. Temme, T. J. Osborne, K. G. Vollbrecht, D. Poulin, and F. Verstraete, Quantum Metropolis sampling. Nature 471, 87 (2011).

    +
  2. +
  3. +

    M.-H. Yung and A. Aspuru-Guzik, A quantum–quantum Metropolis algorithm. Proc. Natl. Acad. Sci. U.S.A. 109, 754 (2012).

    +
  4. +
  5. +

    U. Wolff, Collective Monte Carlo Updating for Spin Systems. Phys. Rev. Lett. 62, 361 (1989).

    +
  6. +
+ +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/2d-ising-model/ising_cython.svg b/public/blog/2d-ising-model/ising_cython.svg new file mode 100644 index 0000000..6bc5e15 --- /dev/null +++ b/public/blog/2d-ising-model/ising_cython.svg @@ -0,0 +1,2185 @@ + + + + + + + + 2023-01-12T21:08:13.366287 + image/svg+xml + + + Matplotlib v3.6.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/2d-ising-model/ising_numba.svg b/public/blog/2d-ising-model/ising_numba.svg new file mode 100644 index 0000000..3f2496b --- /dev/null +++ b/public/blog/2d-ising-model/ising_numba.svg @@ -0,0 +1,2185 @@ + + + + + + + + 2023-01-12T21:08:06.098260 + image/svg+xml + + + Matplotlib v3.6.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/2d-ising-model/ising_speedup.svg b/public/blog/2d-ising-model/ising_speedup.svg new file mode 100644 index 0000000..65583fe --- /dev/null +++ b/public/blog/2d-ising-model/ising_speedup.svg @@ -0,0 +1,1006 @@ + + + + + + + + 2023-01-12T22:05:24.656732 + image/svg+xml + + + Matplotlib v3.6.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/2d-ising-model/ising_spins.gif b/public/blog/2d-ising-model/ising_spins.gif new file mode 100644 index 0000000..efdb717 Binary files /dev/null and b/public/blog/2d-ising-model/ising_spins.gif differ diff --git a/public/blog/blog-comments/comment_plugin.png b/public/blog/blog-comments/comment_plugin.png new file mode 100644 index 0000000..35c7ac4 Binary files /dev/null and b/public/blog/blog-comments/comment_plugin.png differ diff --git a/public/blog/blog-comments/index.html b/public/blog/blog-comments/index.html new file mode 100644 index 0000000..e9ab8c4 --- /dev/null +++ b/public/blog/blog-comments/index.html @@ -0,0 +1,737 @@ + + + + + + + + + + + + Adding blog comments · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Adding blog comments +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Software + + + +
+ + + +
+
+
+ +
+
+
+ + Table of Contents + +
+ +
+
+ +
+
+ +
+
+ +
Comments widget by Utterances.
+
+

I am adding a comments widget to my blog. Now you can comment under the blog posts whenever as long as you have a GitHub account. I’ve always wanted one for the sole purpose of encouraging interactions and discussions. Just a place where you (readers) can quickly jot down your thoughts/comments/questions. Hugo, which is the the framework this website is built on, ships with support for Disqus. I guess Disqus is fine for general uses, but I wanted something more lightweight, free of ads, and has Markdown support. Luckily I came across Utterances today. It’s an open-source comments widget that is built on GitHub Issues, developed by Jeremy Danyow (Thank you!). I like its simplistic aesthetics and even better, there are multiple (dark) themes you can choose from. Most importantly, it supports Markdown in the comments. I think it would be even better if there is LaTeX support in the future! The general setup is quite simple and I think the official guide is all you really need.

+

While setting it up on my website (based on the Congo theme for Hugo) by directly following the instructions, I encountered two small problems. One is the positioning of the comments widget, which is centrally aligned by default but was just sitting a bit too far to the right in my current layout. My way of mitigating this is to add a <div> tag with a class attribute which I call comment to the comments.html file (placed under layouts/partials/), which contains the <script> tag for Utterances. Then inside custom.css (under assets/css/) I added the following:

+
.comment {
+  max-width: 60ch;
+  margin-top: 3em;
+  box-shadow: 0 0 5px #ccc;
+  border-radius: 10px;
+}
+

This places the comments widget in a position to my liking.

+

The other problem is related to where the comment widget shows up. By default, having the comments.html file in the layouts/partials/ directory will make the widget appear in any page with an index.md associated with it. This is not the behavior I want because ideally the comments section should be restricted to blog posts only. There is a simple way to add a knob for this in Congo. First, inside config/_default/params.toml, I added showComment = true under the [article] section. This allows us to have a theme parameter article.showComment that can be set to false if we want to hide the comments section in a particular page. Then to link this knob to the Utterances widget, I inserted {{ if .Params.showComment | default (.Site.Params.article.showComment | default true) }} at the beginning of comments.html.

+

This is what my final comments.html looks like:

+
{{ if .Params.showComment | default (.Site.Params.article.showComment | default true) }}
+    <div class="comment">
+        <script src="https://utteranc.es/client.js"
+        repo="ruihao-li/ruihao-li.github.io"
+        issue-term="pathname"
+        label="comment"
+        theme="gruvbox-dark"
+        crossorigin="anonymous"
+        async>
+        </script>
+    </div>
+{{ end }}
+

Update #

+

I just updated Congo to v2.3.0 today (July 6, 2022) and it now comes with the showComments support. See the implementation in layouts/_default/single.html, which automatically solves both of my problems mentioned above. So if you are using Congo v2.3.0 and above, ignore everything I said above. To display the Utterances widget in your blog posts, simply provide the script in layouts/partials/comments.html and set the showComments parameter to true in your config/_default/params.toml file.

+ +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/fish-shell-customization/index.html b/public/blog/fish-shell-customization/index.html new file mode 100644 index 0000000..5295185 --- /dev/null +++ b/public/blog/fish-shell-customization/index.html @@ -0,0 +1,786 @@ + + + + + + + + + + + + Fish shell and customization · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Fish shell and customization +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Software + + + +
+ + + +
+
+
+ +
+
+
+ + Table of Contents + +
+ +
+
+ +
+
+ +
+
+ +
A quick peek at the shell interface.
+
+

This weekend I spent some time tweaking the Terminal on my Mac with iTerm2 and Fish shell. Why did I do it? First of all, I have been quite fed up with the boring black-and-white look of the default Terminal app. In my opinion, the introduction of multiple colors together with glyphs/icons not only makes it look better visually, it also helps one distinguish different contents (e.g. directories, files) more easily. Moreover, I just want more customizations and features like autosuggestions to make working with command lines a little more efficient. So below are the ingredients I used to customize my Terminal and instructions for some key steps.

+

Ingredients #

+
    +
  • iTerm2: A popular terminal emulator for macOS +
      +
    • Colors: I personally use Solarized Dark +
        +
      • Download Solarized
      • +
      • Unzip and double click on the the color scheme Solarized Dark.itermcolors under the directory /iterm2-colors-solarized
      • +
      • Open iTerm2’s Preferences → Profiles → Colors, and select the theme under Color Presets
      • +
      +
    • +
    • Text: We need one of the Nerd Fonts to render the glyphs/icons; I chose two of them +
        +
      • Meslo Nerd Font: Downloaded from the Tide repo; this particular font contains all the glyphs needed
      • +
      • Source Code Pro Nerd Font: Installed on Homebrew via brew tap homebrew/cask-fonts (only need to run this once) and then brew install --cask font-source-code-pro; This is the font I’d like to use in text
      • +
      • Alternatively, all the Powerline Fonts can be installed based on this repo
      • +
      • Go to iTerm2’s Preferences → Profiles → Text, under Font, choose Source Code Pro (for Powerline) or any font you like; select Use a different font for non-ASCII text, then choose MesloLGS NF under Non-ASCII Font
      • +
      +
    • +
    • I also resize the New Windows to be 120 columns and 40 rows under the Window panel
    • +
    +
  • +
  • Fish shell: A great alternative to bash and zsh +
      +
    • Installation: brew install fish
    • +
    • Set fish as the default shell: +
        +
      • Add the shell to /etc/shells with +echo /usr/local/bin/fish | sudo tee -a /etc/shells
      • +
      • Change the default shell with +chsh -s /usr/local/bin/fish
      • +
      +
    • +
    • Oh My Fish: Package manager for customizing the fish shell +
        +
      • Check all the themes contained in Oh My Fish: omf theme
      • +
      • I installed the Agnoster theme: omf install agnoster
      • +
      • Apply the theme: omf theme agnoster
      • +
      +
    • +
    • Fisher: Plugin manager for fish +
        +
      • See all the plugins and prompts here
      • +
      +
    • +
    +
  • +
  • Exa: Replacement for ls +
      +
    • Installation: brew install exa
    • +
    • Customized ll and lla: +
        +
      • Find fish config file (config.fish) in ~/.config/fish
      • +
      • Add the following lines to the config file (I got this trick from the great Takuya Matsuyama): +
        if type -q exa
        +	alias ll "exa -l -g --icons"
        +	alias lla "ll -a"
        +end
        +
      • +
      +
    • +
    +
  • +
+

OK, there you go! Enjoy the fresh new look!

+

Update 1 #

+

While setting up fish on a M1 Mac yesterday, I realized that the fish shell path is not the same as in Intel-based Macs. So if you have a Mac with Apple Silicon, after brew install fish you can run:

+
    +
  • fish_add_path /opt/homebrew/bin
  • +
  • echo "/opt/homebrew/bin/fish" | sudo tee -a /etc/shells
  • +
  • chsh -s /opt/homebrew/bin/fish
  • +
+ +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/fish-shell-customization/shell_demo.png b/public/blog/fish-shell-customization/shell_demo.png new file mode 100644 index 0000000..dab4cfd Binary files /dev/null and b/public/blog/fish-shell-customization/shell_demo.png differ diff --git a/public/blog/ibm-spring-challenge-1/Trot_circuit.svg b/public/blog/ibm-spring-challenge-1/Trot_circuit.svg new file mode 100644 index 0000000..292724a --- /dev/null +++ b/public/blog/ibm-spring-challenge-1/Trot_circuit.svg @@ -0,0 +1,397 @@ + + + + + + + + 2022-06-11T13:17:02.721144 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-1/Trot_error.svg b/public/blog/ibm-spring-challenge-1/Trot_error.svg new file mode 100644 index 0000000..81fe234 --- /dev/null +++ b/public/blog/ibm-spring-challenge-1/Trot_error.svg @@ -0,0 +1,983 @@ + + + + + + + + 2022-06-11T14:08:50.938447 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-1/XX_circuit.svg b/public/blog/ibm-spring-challenge-1/XX_circuit.svg new file mode 100644 index 0000000..2aa1fd1 --- /dev/null +++ b/public/blog/ibm-spring-challenge-1/XX_circuit.svg @@ -0,0 +1,432 @@ + + + + + + + + 2022-06-11T10:41:35.147903 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-1/YY_circuit.svg b/public/blog/ibm-spring-challenge-1/YY_circuit.svg new file mode 100644 index 0000000..4bba148 --- /dev/null +++ b/public/blog/ibm-spring-challenge-1/YY_circuit.svg @@ -0,0 +1,435 @@ + + + + + + + + 2022-06-11T10:56:45.186701 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-1/index.html b/public/blog/ibm-spring-challenge-1/index.html new file mode 100644 index 0000000..292d699 --- /dev/null +++ b/public/blog/ibm-spring-challenge-1/index.html @@ -0,0 +1,1025 @@ + + + + + + + + + + + + Quantum simulation of many-body physics - I · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Quantum simulation of many-body physics - I +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Quantum Computing + + Physics + + + +
+ + + +
+
+
+ +
+
+
+ + Table of Contents + + +
+ +
+
+ +
+

A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. In these problems, we investigated a well-known phenomenon (to the condensed matter physics community, of course) called Anderson localization and one called many-body localization, which I happened to gain some exposure to during the MAGLAB Theory Winter School earlier this year and is still an active topic of research. The majority of this Challenge was about introducing and reproducing some of the results from this nicely written quantum transport paper by Karamlou et al. I will split the full discussion into three parts. This blog post will cover the first part, where we will set up the framework for investigating many-body physics on a quantum computer. This includes building the tight-binding model for a 1-D quantum chain and using Trotterization for simulating dynamics of the quantum states.

+

The other topic of the Quantum Challenge was quantum chemistry calculations with the variational quantum eigensolver (VQE), which I do not intend to discuss this time. Interested readers are encouraged to take a look at the original announcement linked above for more details. Here is the official Github repository if you want to have a go at the challenge problems. Without further ado, let us begin our discussion.

+

Tight-binding model of a quantum chain #

+

The tight-binding model would be the building block for studying the many-body physics that will be discussed throughout this post. In layman’s terms, the tight-binding model describes a solid-state system where most electrons are “tightly bound” to their nuclei, which sit at the fixed lattice sites. Only a few valence electrons are loosely bound and therefore can “hop” to the neighboring sites. This hopping action is what leads to an extended Bloch wavefunction, which is the electron wavefunction in the presence of a period lattice potential. The most common way of writing a (spinless) tight-binding model in condensed matter physics would be in the second-quantization form:

+

+ +\begin{equation} +H_\text{tb}/\hbar = \sum_{i}\epsilon_{i} c_i^\dagger c_i + \sum_{\langle i,j\rangle}J_{ij}\left( c_i^\dagger c_j + \text{h.c.}\right), +\end{equation}

+

where \(c_i^\dagger\) and \(c_i\) are the creation and annihilation operators for the electron at site \(i\), respectively, \(\mu_i\) are the on-site potentials, and \(J_{ij}\) are the elements of a symmetric matrix representing the hopping strengths. Moreover, \(\langle i,j\rangle\) denotes any pair of neighboring sites. To simulate this fermionic system on a gate-based quantum computer which is built on qubits, we need a similar notion for the ladder operators (i.e., creation and annihilation operators) for two-level systems: \(c^\dagger \ket{0} \to \ket{1}\) and \(c\ket{1} \to \ket{0}\). One way of representing them would be to use the Pauli gates:

+

$$ +\begin{split} +& c_i^\dagger = \frac{1}{\sqrt 2}(X_i + iY_i), \\ +& c_i = \frac{1}{\sqrt 2}(X_i - iY_i). +\end{split} +$$

+

Plugging them into Eq. (1) and assuming the hoppings are homogeneous such that they can be described by a single parameter \(J\), we obtain

+

\begin{equation} +H_\text{tb}/\hbar = \sum_i \epsilon_i Z_i + J\sum_{\langle i,j\rangle}(X_i X_j + Y_i Y_j), +\end{equation} +where we have neglected a constant term (proportional to the identity operator) that would not have any impact on the dynamics of the system. Note that we have technically performed the inverse of the Jordan-Wigner transformation.

+

Trotterization #

+

One of the things we care about in quantum simulations is the time-evolution of the quantum system. This is determined by the unitary operator \(e^{-iHt/\hbar}\) in quantum mechanics, where \(H\) is the time-independent Hamiltonian, which is \(H_\text{tb}\) in the case of our 1-D quantum chain. Now, to execute the time evolution unitary on a gate-based quantum computer, one must decompose it into a product of one- and two-qubit gates that can be implemented on the quantum computer. One method to accomplish this is called Trotterization, which essentially performs a discretized approximation to the continuous time evolution. To demonstrate it, let us consider a simple three-site system. The time-evolution unitary of this system is given by +$$ +\begin{split} +U_\text{tb}(t) &= \exp\left[\frac{-it}{\hbar}\left(H_\text{tb}^{(0,1)} + H_\text{tb}^{(1,2)}\right)\right] \\ +&\approx \left[\exp\left(\frac{-it}{n\hbar}H_\text{tb}^{(0,1)}\right) \exp\left(\frac{-it}{n\hbar}H_\text{tb}^{(1,2)}\right) \right]^n, +\end{split} +$$ +where in the second step we have applied Trotterization and \(n\) is the number of Trotter steps, i.e., discrete time steps. Within each two-site subsystem, the Pauli operator pairs \(X_i X_j\) and \(Y_i Y_j\) commute with each other. Therefore, with \(J = 1\) and \(\epsilon_i = 0\), we can write \(U_\text{tb}(t)\) as +$$ +\begin{split} +U_\text{tb}(t) &\approx \left\{\exp\left[\frac{-it}{n} \left(X_0 X_1 + Y_0 Y_1 \right) \right] \exp\left[\frac{-it}{n}\left(X_1 X_2 + Y_1 Y_2 \right) \right] \right\}^n \\ +&= \left[\exp\left(\frac{-it}{n}X_0 X_1\right) \exp\left(\frac{-it}{n}Y_0 Y_1\right) \exp\left(\frac{-it}{n}X_1 X_2\right) \exp\left(\frac{-it}{n}Y_1 Y_2\right) \right]^n \\ +&= \left[R_{X_0X_1}\left(\frac{2t}{n} \right) R_{Y_0Y_1}\left(\frac{2t}{n} \right) R_{X_1X_2}\left(\frac{2t}{n} \right) R_{Y_1Y_2}\left(\frac{2t}{n} \right) \right]^n, +\end{split} +$$ +where \(R_{X_iX_j}\) and \(R_{Y_iY_j}\) are parametric two-qubit \(X\otimes X\) and \(Y\otimes Y\) interaction gates between qubits \(i\) and \(j\). They are sometimes referred to as the Ising gates. Please see RXXGate and RYYGate for more details. In general, for an \(m\)-qubit system, the time-evolution unitary for each individual Trotter step can then be written as +$$ +U_\text{tb}(\Delta t) \approx \prod_{i=0}^{m-2} R_{X_i X_{i+1}}(2\Delta t) R_{Y_i Y_{i+1}}(2\Delta t), +$$ +where \(\Delta t = t/n\) is the discretized time step. The complete evolution over time \(t\) is then \(U_\text{tb}\approx [U_\text{tb}(\Delta t)]^{t/\Delta t}\).

+

We are now just one step shy of implementing \(U_\text{tb}(t)\) on a quantum computer, that is, to further decompose the \(R_{XX}\) and \(R_{YY}\) gates into a set of gates that are native to the quantum hardware, such as the CNOT gate and single-qubit rotation gates. For this, let us introduce another Ising gate, RZZGate \(R_{ZZ}\). It is not hard to verify that this two-qubit gate can be decomposed as a single-qubit rotation gate \(R_Z = \exp(-i\theta Z/2)\) sandwiched between two CNOT gates. Specifically, \(R_{ZZ}(\theta) = \text{CNOT}\, R_Z(\theta)\, \text{CNOT}\). Then by working out the explicit matrix representations, one can show that the \(R_{XX}\) gate has the following decomposition,

+ +

while the \(R_{YY}\) gate is decomposed as

+ +

With the above setup, we are ready to build the Trotterized quantum circuit for a general \(n\)-site quantum chain using Qiskit. First, we need to import some necessary packages.

+
import numpy as np
+import matplotlib.pyplot as plt
+from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
+from qiskit.circuit import Parameter
+import qiskit.quantum_info as qi
+

We then define the Trot_qc function for the Trotterized quantum circuit.

+
def Trot_qc(num_qubits, t=Parameter("t")):
+    """
+    Creates the Trotterized quantum circuit at a given time for the 
+    1D tight-binding model.
+
+    Args:
+        num_qubits (int): The number of qubits in the circuit.
+        t (Parameter): time.
+
+    Returns:
+        qiskit.circuit.QuantumCircuit: The Trotterized quantum circuit.
+    """
+
+    def ZZ_gate(t):
+        ZZ_qr = QuantumRegister(2)
+        ZZ_qc = QuantumCircuit(ZZ_qr, name='ZZ')
+        ZZ_qc.cnot(0,1)
+        ZZ_qc.rz(2 * t, 1)
+        ZZ_qc.cnot(0,1)
+        # Convert custom quantum circuit into a gate
+        ZZ = ZZ_qc.to_instruction()
+        return ZZ
+
+    def XX_gate(t):
+        XX_qr = QuantumRegister(2)
+        XX_qc = QuantumCircuit(XX_qr, name='XX')
+        XX_qc.ry(np.pi/2, [0,1])
+        XX_qc.append(ZZ_gate(t), [0,1])
+        XX_qc.ry(-np.pi/2, [0,1])
+        XX = XX_qc.to_instruction()
+        return XX
+
+    def YY_gate(t):
+        YY_qr = QuantumRegister(2)
+        YY_qc = QuantumCircuit(YY_qr, name='YY')
+        YY_qc.rx(-np.pi/2, [0,1])
+        YY_qc.append(ZZ_gate(t), [0,1])
+        YY_qc.rx(np.pi/2, [0,1])
+        YY = YY_qc.to_instruction()
+        return YY
+    
+    Trot_qr = QuantumRegister(num_qubits)
+    qc = QuantumCircuit(Trot_qr, name='Trot')
+
+    for i in range(num_qubits - 1):
+        qc.append(XX_gate(t), [Trot_qr[i], Trot_qr[i+1]])
+        qc.append(YY_gate(t), [Trot_qr[i], Trot_qr[i+1]])
+        
+    return qc
+

We can inspect the circuit for 3 qubits by calling the QuantumCircuit.draw() method:

+ +

Last but not least, to see if we have implemented Trotterization correctly, we may compute the process fidelity between the Trotterized quantum channel and the exact time-evolution unitary. We define the exact time-evolution unitary as follows:

+
from qiskit.opflow import I, X, Y, Z
+
+def U_tb(t):
+    """
+    Exact time-evolution unitary for 3 qubits.
+    """
+    # Interactions (I is the identity matrix; X and Y are Pauli matricies;
+    # ^ is a tensor product)
+    XXs = (I^X^X) + (X^X^I)
+    YYs = (I^Y^Y) + (Y^Y^I)
+    H_tb = XXs + YYs
+    return (t * H_tb).exp_i()
+

On the other hand, the approximate unitary based on Trotterization is constructed as follows:

+
def U_trot_tb(t_target, trotter_steps, num_qubits):
+    """
+    Creates the Trotterized time-evolution unitary for a 
+    1-D tight-binding model.
+    
+    Args:
+        t_target (float): The total time evolved.
+        trotter_steps (int): The number of Trotter steps.
+        num_qubits (int): The number of qubits in the circuit.
+
+    Returns:
+        qiskit.quantum_info.Operator: The operator corresponding to 
+        the Trotterized time-evolution unitary.
+    """
+
+    t = Parameter("t")
+    qr = QuantumRegister(num_qubits)
+    qc = QuantumCircuit(qr)
+
+    for _ in range(trotter_steps):
+        qc.append(Trot_qc(num_qubits, t), qr)
+    qc = qc.bind_parameters({t: t_target/trotter_steps})
+    return qi.Operator(qc)
+

Finally, we can plot how the Trotter error (= 1 - process fidelity) changes as we increase the number of Trotter steps.

+
t_target = 0.5 # total time evolved
+U_target = U_tb(t_target)
+
+steps=np.arange(1,101,2)
+
+fidelities=[]
+for n in steps:
+    U_trotter = U_trot_tb(t_target, n, 3)
+    fidelity = qi.process_fidelity(U_trotter, target=U_target)
+    fidelities.append(fidelity)
+
+plt.figure(facecolor='white')
+plt.loglog(steps, 1 - np.array(fidelities))
+plt.ylabel('Trotter error')
+plt.xlabel('Trotter steps')
+plt.show()
+

Here is how the plot looks like:

+ +

Yay 🎉! The trotter error decreases as the number of Trotter steps increases, suggesting that we have indeed implemented Trotterization correctly.

+

So here comes the end of the first part. In the next post, we will see how we can use the Trotterized quantum circuit that we just built to study phenomena including the quantum random walk and Anderson localization on a 1-D quantum chain. Stay tuned!

+ +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/ibm-spring-challenge-2/index.html b/public/blog/ibm-spring-challenge-2/index.html new file mode 100644 index 0000000..7360a4a --- /dev/null +++ b/public/blog/ibm-spring-challenge-2/index.html @@ -0,0 +1,1109 @@ + + + + + + + + + + + + Quantum simulation of many-body physics - II · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Quantum simulation of many-body physics - II +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Quantum Computing + + Physics + + + +
+ + + +
+
+
+ +
+ +
+ +
+

As promised in the + + previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. In this post, we want to address the question of how a particle such as an electron, propagates through an intrinsically quantum system, i.e., the 1-D quantum chain that we built previously. Remember everything we discussed so far has not taken into account disorder that is generally present in realistic condensed matter systems. Disorder is something that generically breaks some symmetries of the system Hamiltonian and/or leads to deviations from the lattice periodicity. When disorder is present, all the sites in a lattice are no longer equivalent. So another question naturally arises: how would disorder affect the quantum transport? The exploration of this general question has led to wonderful discoveries of various localization effects in disordered systems. Here we will touch on one of them, Anderson localization, which was first discovered by the great physicist Philip W. Anderson in 1958 [1]. One interesting thing to note is that the dimensionality of a system has a direct impact on Anderson localization. For example, according to the scaling theory of localization [2], in 1- and 2-D, a system will be a perfect insulator in the thermodynamic limit (simply put, when the system size is taken to infinity). Therefore, Anderson localization must happen in one- and two-dimensional disordered systems regardless of the disorder strength! However, in 3-D, Anderson localization is a critical phenomenon where the system undergoes a metal-insulator transition (MIT). This means that localization happens only when the disorder strength exceeds a certain threshold. Even though this is certainly one of the most interesting aspects of Anderson localization, we will not explore it here for the sake of simplicity. We will again stick to the 1-D system as in the previous post.

+

Quantum random walk #

+

Classical random walk is a random process that is prevalent in many phenomena in nature, such as the motion of macroscopic particles in liquids and gases known as Brownian motion and even the price of a fluctuating stock. In the most rudimentary version of a symmetric classical random walk on a lattice, at each time step, the probabilities of the particle jumping to any of the neighboring sites are the same. In 1-D, this means that the particle can move one site to the left or right with equal probability (50%) each time. A well-established result for a symmetric random walk is that in the continuous-time limit, the probability of finding the particle at time \(t\) at position \(r\) (from the origin) follows a Gaussian distribution:

+

+ +$$ +P_\text{classical}(r, t) = \frac{1}{\sqrt{2\pi t}} e^{-r^2/2t}, +$$

+

where we have assumed the distance of each jump to be 1. Therefore, the standard deviation of this probability distribution scales as \(\sigma_\text{classical}\propto \sqrt{t}\). Since \(\langle r \rangle = 0\), this suggests that the mean-square-root displacement of the particle, which quantifies the spatial propagation of the particle relative to the origin, also scales diffusively with time as \(\sqrt{\langle r^2\rangle} \propto \sqrt{t}\).

+

Since we are interested in particle propagation in a quantum system, we will need to deal with quantum random walks instead. In this case, the intrinsic quantum nature including superposition and interferences among different wavefunctions will lead to a qualitative difference from the classical counterpart. Here is a somewhat intuitive way to think about the difference between them. Imagine a “classical walker” who decides whether to step left or right by tossing a coin with two possible outcomes \(+\) and \(-\), with probabilities \(P_+\) and \(P_-\), respectively. After each toss, they would look at the result and decide which way to go. So the classical random walk traces a single path within a decision tree. In contrast, a “quantum walker” flips their coin but never looks at the outcome. Instead, at each step, they step simultaneously to the left and right with some complex amplitudes \(A_+\) and \(A_-\) corresponding to probabilities \(P_+ = \lvert A_+\rvert^2\) and \(P_- = \lvert A_-\rvert^2\). After many iterations the quantum random walk results in an extended wavefunction of the quantum walker that spreads out to all positions in the tree with finite amplitudes. What’s more incredible is that these complex amplitudes at different sites add up for any given path and depending on the phase differences, this creates constructive or destructive interferences when measuring the probabilities at the end. A diagram illustrating the ideas above is shown below (taken from [3]).

+ +

Due to the critical differences highlighted above, it can be shown that a symmetric quantum random walk in the continuous-time limit will lead to a probability distribution that follows a Bessel function of the first kind [4]:

+

$$ +P_\text{quantum}(r, t) = \lvert J_r(2t) \rvert^2. +$$

+

Below is a visualization of the two probability distributions for continuous-time classical and quantum random walks:

+ +

Moreover, a quantum random walk exhibits ballistic propagation with the mean-square-root displacement scaling linearly with time, \(\sqrt{\langle r^2\rangle} \propto t\). The quadratic speed-up of quantum random walks versus classical random walks is analogous to the quadratic speed-up of the Grover search algorithm compared to a classical search!

+

Simulating a quantum random walk #

+

Let us now simulate the quantum random walk on a 1-D tight-binding chain to see if the result matches the theory prediction above. We will first do this on a simulator and then on a real quantum computer. For this simulation, we consider a 5-site tight-binding lattice whose Hamiltonian is given by

+

$$ +H_\text{tb}/\hbar = J\sum_{i=0}^3(X_i X_{i+1} + Y_i Y_{i+1}). +$$

+

Again, we have set the on-site potentials to be zero to simulate a clean system without disorder and will use \(J = 1\) from here onwards [cf. Eq. (2) in + + part I]. Recall that to simulate the dynamics of a quantum system on a gate-based quantum computer, we employ the Trotterization process to discretize the continuous time evolution. Therefore, we use the Trot_qc function established in + + part I to build the Trotterized quantum circuit for this 5-site system at any given time. Next, we want to add a particle in the form of an excitation to site 0, i.e., qubit 0. This is done by apply an \(X\) gate to flip the qubit from \(\ket{0}\) state to \(\ket{1}\) state. We modify the U_trot_tb function in the previous part slightly to record the Trotterized circuits at all Trotter (time) steps over a given simulation time:

+
def U_trot_circuits(delta_t, trotter_steps, num_qubits):
+    """
+    Record a list of Trotterized circuits at all Trotter steps 
+    separated by delta_t.
+    
+    Args:
+        delta_t (float): Duration of individual time steps.
+        trotter_steps (array): Array of intermediate time steps.
+        num_qubits (int): The total number of qubits.
+
+    Returns:
+        circuits (list): A list of Trotterized quantum circuits.
+    """
+    
+    t = Parameter("t")
+    circuits = []
+
+    for n_steps in trotter_steps:
+        qr = QuantumRegister(num_qubits)
+        cr = ClassicalRegister(num_qubits)
+        qc = QuantumCircuit(qr, cr)
+
+        qc.x(0) # Add an excitation to site 0
+
+        for _ in range(n_steps):
+            qc.append(Trot_qc(num_qubits, t).to_instruction(), qr)
+        qc = qc.bind_parameters({t: delta_t})
+        circuits.append(qc)
+    return circuits
+

We can now track the propagation of the particle by keeping track of the probability of finding it on each qubit at different time steps. To simulate this process with a simulator, we will make use of the statevector_simulator backend in Qiskit’s Aer module. For this, we make some additional imports here.

+
from qiskit import transpile, Aer, IBMQ, execute
+from copy import deepcopy
+

Here we define a function that extracts the probabilities of each qubit being in the \(\ket{1}\) state at different times using the output state from the statevector_simulator.

+
def probability_density(delta_t, trotter_steps, num_qubits):
+    """
+    Calculate the probabilities of finding the excitation 
+    on each qubit at different time steps.
+
+    Args:
+        delta_t (float): Duration of individual time steps.
+        trotter_steps (array): Array of intermediate times.
+        num_qubits (int): The total number of qubits.
+
+    Returns:
+        probability_density (array): The probability density of 
+        the excitation at all Trotter steps.
+    """
+
+    backend_sim = Aer.get_backend('statevector_simulator')
+    circuits = U_trot_circuits(delta_t, trotter_steps, num_qubits)
+    probability_density=[]
+    
+    for circ in circuits:
+        transpiled_circ=transpile(circ, backend_sim, optimization_level=3)
+        job_sim = backend_sim.run(transpiled_circ)
+
+        # Grab the results from the job.
+        result_sim = job_sim.result()
+        outputstate = result_sim.get_statevector(transpiled_circ, decimals=5)
+        
+        ps = []
+        # Extract the probability of finding the excitation on each qubit. 
+        # (e.g. for 5 qubits, we need "00001", "00010", "00100", "01000", "10000")
+        for i in range(num_qubits):
+            ps.append(np.abs(outputstate[2**i])**2)
+        probability_density.append(ps)
+    probability_density = np.array(probability_density)
+    return probability_density
+

It’s time to simulate the quantum random walk on the 5-site tight-binding lattice and see the results. We choose to evolve the system over 25 steps with a step size of 0.15 for this simulation. We can visualize the results by running the following code,

+
delta_t = 0.15
+trotter_steps = np.arange(1, 25, 1)
+num_qubits = 5
+
+prob_density = probability_density(delta_t, trotter_steps, num_qubits)
+prob_max, prob_min = np.max(prob_density), np.min(prob_density)
+
+plt.figure(figsize=(5,5), facecolor='white')
+plt.pcolormesh(np.arange(0, num_qubits,1), trotter_steps*delta_t, prob_density, vmin=prob_min, vmax=prob_max)
+plt.colorbar()
+plt.xlabel('Qubit index')
+plt.ylabel('Time (1/J)')
+plt.savefig("probs_qwr.svg")
+

which produces the plot below:

+ +

This result is pretty nice as it shows that the particle excitation traverses the lattice and eventually reflects off the opposite end of the 1-D chain. In principle, the quantum random walk propagates in both directions for all the interim sites. However, quantum interferences among these multiple trajectories alter the particle wavepacket as it evolves in time, leading to the unidirectional transport seen above. Furthermore, it is evident that the displacement of the excitation scales linearly with time, agreeing well with the prediction of quantum random walks.

+

Performing the same simulation on a real quantum computer is slightly different. Here we can no longer retrieve the statevectors directly from the outputs. Instead, at each time step we will need to send the circuit to the quantum computer many times (specified by the number of shots) for execution and extract the probabilities based on the output statistics. During the Challenge, we were given the access to one of IBM’s 7-qubit systems ibm_nairobi. We can perform the simulation by calling the following function:

+
def probability_density_exp(delta_t, trotter_steps, num_qubits, shots):
+    # Load your IBM Quantum account
+    IBMQ.load_account()
+    # Get the backend
+    provider = IBMQ.get_provider(hub=<hub_name>, group=<group_name>, project=<project_name>)
+    backend = provider.get_backend('ibm_nairobi')
+
+    # Create transpiled circuits for hardware execution
+    initial_layout = [0 , 1 , 3 , 5 , 4] # Specific to ibm_nairobi topology
+    hardware_transpiled_circuits = []
+
+    for circ in U_trot_circuits(delta_t, trotter_steps, num_qubits):
+        hardware_circ = deepcopy(circ)
+        hardware_circ.measure(range(num_qubits), range(num_qubits))
+        hardware_transpiled_circuits.append(
+            transpile(hardware_circ, backend, initial_layout=initial_layout, optimization_level=3)
+        )
+    
+    # Run the circuits
+    job = execute(hardware_transpiled_circuits, backend=backend, shots=shots)
+    exp_results = job.result()
+
+    probability_density_exp = []
+    for output in exp_results.get_counts():
+        ps = []
+        # Extract the probabilities
+        keys = ['00001', '00010', '00100', '01000', '10000']
+        for key in keys:
+            if key in output:
+                ps.append(output[key]/shots)
+            else:
+                ps.append(0.)
+        
+        probability_density_exp.append(ps)
+    return probability_density_exp
+

Below is the result for one of the simulations on the hardware.

+ +

Comparing this with the result above from the simulator, despite the similarity, the effect of noise and decoherence (especially at later times) on a real quantum hardware is apparent!

+

Anderson localization #

+

Finally, we are coming to Anderson localization. As mentioned before, Anderson localization always happens in 1-D systems when disorder is present. Lattice inhomogeneity causes scattering and leads to quantum interference that tends to inhibit particle propagation, a signature of localization. The wavefunction of a localized particle rapidly decays away from its initial position, effectively confining the particle to a small region of the lattice. This localization phenomenon is a direct consequence of interference between different paths arising from multiple scatterings of the electron by lattice defects. To study this phenomenon, we add back the inhomogeneous on-site potentials to the Hamiltonian, thereby making the lattice sites inequivalent, i.e.,

+

$$ +H_\text{tb}/\hbar = J\sum_{i=0}^3(X_i X_{i+1} + Y_i Y_{i+1}) + \sum_{i=0}^3\epsilon_i Z_i. +$$

+

One simple way to model disorder within the tight-binding system is through the Aubry-Andre (AA) model, where the disorder is replaced by a periodic modulation of the on-site energies, with a spatial period incommensurate with the lattice period. The AA potential is modeled as \(\epsilon_i = W\cos(2\pi\beta i)\), where \(\beta\) determines the quasicrystal periodicity and \(W\) is the disorder strength. Moreover, with the addition of the on-site terms, we also need to modify the Trotterized circuit. Note that exponentiating the \(Z_i\) gates for the time-evolution unitary simply leads to \(R_{Z_i}\) gates acting on individual qubits. So we can define a Trot_qc_disorder circuit based on the Trot_qc circuit from + + part 1:

+
def Trot_qc_disorder(num_qubits, t, deltas):
+    """
+    Generate a Trotterized quantum circuit with disorder.  
+
+    Args:
+        num_qubits (int): The total number of qubits.
+        t (Parameter): The time parameter.
+        deltas (list(Parameter)): The list of disorder parameters.
+    
+    Returns:
+        qiskit.QuantumCircuit: The Trotterized quantum circuit with disorder.
+    """
+
+    Trot_qr_disorder = QuantumRegister(num_qubits)
+    Trot_qc_disorder = QuantumCircuit(Trot_qr_disorder, name='Trot disorder')
+
+    Trot_gate = Trot_qc(num_qubits, t).to_instruction()
+    Trot_qc_disorder.append(Trot_gate, Trot_qr_disorder)
+    for i in range(num_qubits):
+        Trot_qc_disorder.rz(2 * deltas[i] * t, i)
+    return Trot_qc_disorder
+

Let us then define a function that records the Trotterized circuits with finite disorder at all Trotter (time) steps:

+
def U_trot_circuits_disorder(delta_t, trotter_steps, num_qubits, W, beta):
+    """
+    Record a list of Trotterized quantum circuits with disorder 
+    at all Trotter steps.
+
+    Args:
+        delta_t (float): Duration of individual time steps.
+        trotter_steps (array): Array of intermediate times.
+        num_qubits (int): The total number of qubits.
+        W (float): The disorder strength.
+        beta (float): The quasicrystal periodicity of the AA model.
+
+    Returns:
+        disorder_circuits (list): List of Trotterized quantum circuits with disorder.
+    """
+
+    t = Parameter('t')
+    deltas = [Parameter('delta_{:d}'.format(idx)) for idx in range(num_qubits)]
+
+    AA_pattern = np.cos(2*np.pi*beta*np.arange(num_qubits))
+    disorders = W * AA_pattern
+    disorder_circuits = []
+
+    for n_steps in trotter_steps:
+        qr = QuantumRegister(num_qubits)
+        cr = ClassicalRegister(num_qubits)
+        qc = QuantumCircuit(qr, cr)
+
+        qc.x(0)
+
+        for _ in range(n_steps):
+            qc.append(Trot_qc_disorder(num_qubits, t, deltas), qr)
+            
+        qc = qc.bind_parameters({t: delta_t})
+        qc = qc.bind_parameters({deltas[idx]: disorders[idx] for idx in range(num_qubits)})
+        disorder_circuits.append(qc)
+    return disorder_circuits
+

Like in the previous section, we will simulate the particle propagation with disorder on a simulator. Here is how it looks like:

+ +

Comparing with the quantum random walk result, it is clear that in the presence of the AA disorder, the particle tends to be localized in its initial position (qubit 0) as time evolves. So we successfully see the effect of Anderson localization in this 1-D system! Again, running the same simulation on a quantum computer we see a degradation in quality of the results due to noise, but we can still reach the same conclusion in this case:

+ +

Conclusion #

+

It’s been a long post to get to this point, but just to conclude, we have successfully simulated the particle propagation in a 1-D quantum chain with and without disorder on both a simulator and a real quantum computer provided by IBM. In the case of no disorder, we saw behaviors of a quantum random walk, while is distinct from a classical random walk. In the presence of disorder, we saw the effect of Anderson localization, i.e., the particle tends to localize in its initial position over time. In the next and final post of this series, we will look into a more complex example of localization beyond the single-particle picture we have been adhering to so far, that is, many-body localization. The question there is: does localization still happen when we take into account particle interactions? See you in the next one!

+
+

References #

+
    +
  1. +

    P. W. Anderson, Absence of Diffusion in Certain Random Lattices. Phys. Rev. 109, 1492 (1958).

    +
  2. +
  3. +

    E. Abrahams, P. W. Anderson, D. C. Licciardello, and T. V. Ramakrishnan, Scaling Theory of Localization: Absence of Quantum Diffusion in Two Dimensions. Phys. Rev. Lett. 42, 673 (1979).

    +
  4. +
  5. +

    K. Manouchehri and J. B. Wang, Solid State Implementation of Quantum Random Walks on General Graphs. AIP Conf. Proc. 1074, 56 (2008).

    +
  6. +
  7. +

    J.Kempe, Quantum random walks - an introductory overview. arXiv:quant-ph/0303081 (2003).

    +
  8. +
+ +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/ibm-spring-challenge-2/probs_disorder.svg b/public/blog/ibm-spring-challenge-2/probs_disorder.svg new file mode 100644 index 0000000..17cd3c7 --- /dev/null +++ b/public/blog/ibm-spring-challenge-2/probs_disorder.svg @@ -0,0 +1,1613 @@ + + + + + + + + 2022-06-19T11:33:35.300198 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-2/probs_disorder_exp.png b/public/blog/ibm-spring-challenge-2/probs_disorder_exp.png new file mode 100644 index 0000000..7dd67fa Binary files /dev/null and b/public/blog/ibm-spring-challenge-2/probs_disorder_exp.png differ diff --git a/public/blog/ibm-spring-challenge-2/probs_qrw.svg b/public/blog/ibm-spring-challenge-2/probs_qrw.svg new file mode 100644 index 0000000..1d3191f --- /dev/null +++ b/public/blog/ibm-spring-challenge-2/probs_qrw.svg @@ -0,0 +1,1613 @@ + + + + + + + + 2022-06-19T08:55:47.607771 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-2/probs_qrw_exp.png b/public/blog/ibm-spring-challenge-2/probs_qrw_exp.png new file mode 100644 index 0000000..47b53c9 Binary files /dev/null and b/public/blog/ibm-spring-challenge-2/probs_qrw_exp.png differ diff --git a/public/blog/ibm-spring-challenge-2/random_walks.png b/public/blog/ibm-spring-challenge-2/random_walks.png new file mode 100644 index 0000000..f0b99e0 Binary files /dev/null and b/public/blog/ibm-spring-challenge-2/random_walks.png differ diff --git a/public/blog/ibm-spring-challenge-2/rw_dist.svg b/public/blog/ibm-spring-challenge-2/rw_dist.svg new file mode 100644 index 0000000..3edcb9a --- /dev/null +++ b/public/blog/ibm-spring-challenge-2/rw_dist.svg @@ -0,0 +1,1158 @@ + + + + + + + + 2022-06-19T00:19:58.392900 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/XXZ_phase.png b/public/blog/ibm-spring-challenge-3/XXZ_phase.png new file mode 100644 index 0000000..d77d857 Binary files /dev/null and b/public/blog/ibm-spring-challenge-3/XXZ_phase.png differ diff --git a/public/blog/ibm-spring-challenge-3/index.html b/public/blog/ibm-spring-challenge-3/index.html new file mode 100644 index 0000000..9e57e25 --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/index.html @@ -0,0 +1,1162 @@ + + + + + + + + + + + + Quantum simulation of many-body physics - III · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Quantum simulation of many-body physics - III +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Quantum Computing + + Physics + + + +
+ + + +
+
+
+ + + +
+ + + +

This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. Just a quick recap here: In the first post we set up the quantum system that we wanted to investigate using a 1-D tight-binding model, and we discussed how to utilize the Trotterization procedure to implement the time-evolution of the system on a gate-based quantum computer. In the second post, using the tools developed previously, we simulated the propagation of one particle excitation on a 1-D quantum chain with and without disorder on both a simulator and a real quantum computer. We saw the behavior of a quantum random walk when there is no disorder and Anderson localization when disorder is present. We emphasize that the tight-binding model that we have been working with so far does not include particle-particle interactions. So Anderson localization is really just a single-particle, i.e., non-interacting, effect. Then naturally we are prompted to ask the question of what happens when we do take interactions into account. This leads to the rich physics of many-body localization (MBL) that we will touch on in this post. Please feel free to check out + + part I and + + II before continuing.

+

Thermalization vs. Localization #

+

To talk about many-body localization, it is beneficial to first introduce the concept of thermalization, or thermal equilibrium, following Ref. [1]. Thermalization in a closed classical system hinges on the powerful ergodic hypothesis, which states that over a long period of time all microstates of the system are accessed with equal probability. However, this notion of ergodicity does not directly apply to quantum systems. Here is a simple example to see why. Let us consider an isolated quantum many-body system with Hamiltonian \(H\). The generic initial non-equilibrium state \(\ket{\psi(0)}\) can be expanded over the basis of many-body eigenstates \(\ket{\alpha}\) as \(\ket{\psi(0)} = \sum_\alpha A_\alpha \ket{\alpha}\). After the quantum evolution over an arbitrarily long time \(t\), the state becomes

+

$$ +\ket{\psi(t)} = e^{-iHt} \ket{\psi(0)} = \sum_\alpha A_\alpha e^{-iE_\alpha t} \ket{\alpha}, +$$

+

where \(E_\alpha\) is the energy of the eigenstate \(\ket{\alpha}\). Then the probability of finding the system in a given eigenstate \(\ket{\alpha}\), \(p_\alpha = \lvert A_\alpha\rvert^2\), is set by the choice of the initial state and does not change over time. So unlike the classical case, the time evolution of a quantum system does not uniformly sample all states in the Hilbert space. Therefore, for quantum ergodicity, we should instead demand that starting from a generic initial state the system’s observables (few-body operators) settle to values given by the microcanonical ensembles at sufficiently long times. The infinite-time average of a physical observable \(O\) is given by

+

$$ +\langle O \rangle = \lim_{T\to\infty} \frac{1}{T}\int_0^T dt\ \langle\psi(t)\vert O\vert \psi(t)\rangle = \sum_\alpha p_\alpha \langle\alpha\vert O\vert \alpha\rangle. +$$

+

Since \(p_\alpha\) are fixed by the initial state, the natural way to ensure that an observable \(O\) reaches a thermal expectation value at long times for generic initial states is to assume that the expectation values in individual eigenstates \(\langle\alpha\vert O\vert \alpha\rangle\) agree with the microcanonical ensemble. This is the essence of the eigenstate thermalization hypothesis (ETH), which is an important concept in this subject. More precisely, the ETH states that in ergodic systems individual many-body eigenstates have thermal observables that are identical to microcanonical ensemble values at energy \(E = E_\alpha\), i.e., \(\langle\alpha\vert O\vert \alpha\rangle \approx \langle O\rangle_\text{mc}(E)\). The microcanonical ensemble average can be written as

+

$$ +\langle O\rangle_\text{mc}(E) = \lim_{\Delta E\to 0}\frac{1}{N(E, \Delta E)}\sum_{\alpha: E_\alpha\in [E-\Delta E, E+\Delta E]} \langle\alpha\vert O\vert \alpha\rangle, +$$

+

where \(N(E, \Delta E)\) is the number of eigenstates in the system that are within \(\Delta E\) of energy \(E\).

+

After a fairly long digression, rather than diving further into the glory details of the ETH and its implications, we will come back to, in some sense, the other end of the spectrum, MBL, which is known to violate the ETH and hence does not thermalize. Generally speaking, thermalization requires that different parts of ergodic systems exchange energy and particles, and consequently leads to conduction. On the other hand, localization leads to the absence of diffusion, suppressing transport. We have seen the example of Anderson localization, where a disorder potential can completely change the nature of single-particle eigenstates in a non-interacting system. However, interactions between particles are inevitable in realistic systems. It is conceivable that interactions may open up new transport channels, e.g., a high-energy localized state may decay to produce excitations at lower energies, potentially restoring transport. Therefore, to understand the fate of localization in the presence of particle interaction is not a trivial problem. In particular, Basko, Aleiner, and Altshuler (BAA) first studied the stability of the Anderson insulator against short-ranged interactions and concluded that the interacting model enters a localized phase termed the MBL phase in arbitrary dimensions below a certain critical temperature [2]. Later, by studying a 1-D disordered fermionic chain, it was pointed out that the MBL phase can persist even at infinite temperature [3]. More recent developments however challenged the conclusion of BAA. It was argued that in high dimensions \(d>1\) small thermal inclusions can trigger avalanches in the system that destroy the MBL phase [4, 5]. The reconciliation of these two results is still an open problem.

+

The Heisenberg model #

+

Following the history of this field, the introduction of the fermionic and spin-chain lattice models has definitely opened the door to studying many interesting properties of MBL in (classical) numerical simulations. This is exactly the system we have built up in the previous parts of the Challenge. Here we will do something different from the setup in the original IBM Challenge Problem 3. On top of the tight-binding model used to study Anderson localization in + + part II, we will add an additional \(ZZ\)-interaction term. So the tight-binding Hamiltonian is given by

+

\begin{equation} +H_\text{tb}/\hbar = J\sum_{i=0}^{n-2} (X_i X_{i+1} + Y_i Y_{i+1}) + U \sum_{i=0}^{n-2} Z_i Z_{i+1} +\sum_{i=0}^{n-2}\epsilon_i Z_i,\quad +\end{equation}

+

where \(n\) is the number of sites in the 1-D chain. Readers with a condensed matter physics background may recognize that this is exactly the so-called Heisenberg XXZ model. In fact, the Heisenberg model has become the paradigmatic model for studying MBL physics (among many other phenomena). The reason for the additional term should be obvious by doing the Jordan-Wigner transformation, which maps the spin-chain Hamiltonian above to a spinless fermionic chain in the second-quantization form given by

+

$$ +H_\text{tb}/\hbar = J\sum_{i=0}^{n-2} (c_i^\dag c_{i+1} + \text{h.c.}) + U \sum_{i=0}^{n-2} n_i n_{i+1} + \sum_{i=0}^{n-2} \epsilon_i n_i, +$$

+

where \(n_i \equiv c_i^\dag c_i\) is the density operator for site \(i\). Hence, we see that the additional \(U\)-term gives rise to the two-body interaction between neighboring sites. Without it, the tight-binding model is a free-fermion model, which is suited for the study of Anderson localization but not many-body localization. So here we will simulate the MBL phase in a disordered Heisenberg XXZ spin chain. We will again set \(J = 1\) and the model thus has two free parameters: the interaction strength \(U\) and the disorder strength \(W\). Recall that \(W\) controls the onsite potentials through the Aubry-Andre model, \(\epsilon_i = W\cos(2\pi\beta i)\), with \(\beta\) being related to the quasicrystal periodicity.

+

One interesting aspect of the 1-D Heisenberg XXZ model is its phase diagram. In the limit \(U\to 0\) with some finite \(W\), i.e., when there is no interaction, this model is equivalent to free fermions moving in a disordered potential and therefore, the states are Anderson localized. Turning on the interaction will result in the MBL phase. Furthermore, for fixed and not very strong disorder (\(W/U \sim 1\)), it was found that tuning the interaction strength \(U\) above some critical value \(U^\ast\) will lead to delocalization. On the other hand, if we fix \(U\) and increase the disorder strength \(W\), we will see a transition from a delocalized (thermal) phase to the MBL phase when \(W\) goes above a critical value \(W^\ast\). Therefore, in 1-D interacting systems there exists a metal-insulator transition, which is distinct from non-interacting systems that always Anderson localize in the thermodynamic limit, as mentioned in the + + previous post. A schematic illustrating the phase diagram of the XXZ spin chain is shown below.

+
+ +
Phase diagram of Heisenberg XXZ spin chain as a function of interaction (top) and disorder strength (bottom). Here Jz denotes the interaction strength, equivalent to U in our formalism. Figure taken from Ref. [1].
+
+

Putting things into action #

+

Okay, enough theory. Let’s actually build the quantum circuit for the Heisenberg model and simulate its dynamics. In this case, we will simulate three particles in a 12-site spin chain, where particle excitations are represented by \(\ket{1}\) and empty sites represented by \(\ket{0}\). Like before, to better visualize (de)localization, we would like to track the probability of each site being in the \(\ket{1}\) state over the course of the entire Trotterized time evolution. In addition, we also keep track of two other quantities. One is the imbalance, which is one of the signatures of the breakdown of thermalization. The system imbalance is defined as

+

$$ +\mathcal I = \Bigg\langle \frac{N_e - N_o}{N_e + N_o} \Bigg\rangle, +$$

+

where \(N_e\) and \(N_o\) are the populations at the even and odd sites of the system, respectively, and the expectation value is defined with respect to a particular quantum state, i.e. \(\langle \cdots \rangle = \langle \psi \lvert \cdots \rvert \psi \rangle\). In a thermalized system, we expect each site of the lattice to be occupied by the same average number of particles after reaching steady state. Therefore, the imbalance is close to zero. However, when localization happens, we should expect a deviation from zero. Here we define a function that calculates the imbalance for a given state:

+
def get_imbalance(state):
+    """
+    Calculate the imbalance of a state.
+    
+    Args:
+        state (qiskit.quantum_info.Statevector): The state vector.
+
+    Returns:
+        imbalance_val (float): The imbalance of the state.
+    """
+    imbalance_val = 0
+    state_dict = state.to_dict()
+    
+    for basis, amp in state_dict.items():
+        Ne, No = 0, 0
+        # Make sure to skip calculating the |00...0> state
+        for i in range(len(basis)):
+            if i % 2 == 0 and basis[i] == '1':
+                Ne += 1
+            elif i % 2 == 1 and basis[i] == '1':
+                No += 1
+        if Ne + No != 0:
+            imbalance_val += np.abs(amp)**2 * (Ne - No) / (Ne + No)
+    return imbalance_val
+

The other quantity to probe is the entanglement entropy formed in the lattice as a result of particle propagation. One can imagine that while the created particle excitations are initially separable from the the rest of the lattice, their propagation will lead to the creation and distribution of entanglement throughout the lattice. For simplicity, we will only keep track of the entanglement entropy of part of the system, say the first lattice site. This can be quantified by its von Neumann entropy, which is defined as

+

$$ +\mathcal S_\text{vn}(\rho_A) = -\text{tr}(\rho_A \ln\rho_A), +$$

+

where \(A\) refers to the subsystem of interest (i.e., the first lattice site), and \(\rho_A = \text{tr}_{B}\rho\) is the reduced density matrix of the subsystem \(A\) after “tracing out” the rest of the system which we call \(B\). If the subsytem \(A\) is fully entangled with the rest of the system, \(\mathcal S _\text{vn}(\rho_A) = \ln 2\), whereas if the subsytem is completely separable with respect to the rest, \(\mathcal S _\text{vn}(\rho_A) = 0\). One can probe entanglement at a larger scale by using more sophisticated measures such as the concurrences and global entanglement, but we will not pursue these here.

+

Let us now get straight into the simulation. Some necessary imports here:

+
import numpy as np
+import matplotlib.pyplot as plt
+from qiskit import QuantumCircuit, QuantumRegister, transpile, Aer
+from qiskit.circuit import Parameter, Instruction
+import qiskit.quantum_info as qi
+from tqdm.notebook import tqdm
+

Similar to what was done in + + part I, we will first define the Trotterized quantum circuit for MBL based on the tight-binding Hamiltonian Eq. (1) above.

+
def Trot_qc_mbl(num_qubits, t, J, deltas):
+    """
+    Creates the Trotterized quantum circuit at a given time for 
+    the 1-D Heisenberg XXZ model.
+
+    Args:
+        num_qubits (int): The number of qubits in the circuit.
+        t (Parameter): time.
+        J (Parameter): The interaction strength.
+        deltas (List[Parameter]): The list of the disorder 
+        parameters.
+
+    Returns:
+        qiskit.circuit.QuantumCircuit: The Trotterized 
+        quantum circuit.
+    """
+
+    def ZZ_gate(J, t):
+        ZZ_qr = QuantumRegister(2)
+        ZZ_qc = QuantumCircuit(ZZ_qr, name='ZZ')
+        ZZ_qc.cnot(0,1)
+        ZZ_qc.rz(2 * J * t, 1)
+        ZZ_qc.cnot(0,1)
+        # Convert custom quantum circuit into a gate
+        ZZ = ZZ_qc.to_instruction()
+        return ZZ
+
+    def XX_gate(t):
+        XX_qr = QuantumRegister(2)
+        XX_qc = QuantumCircuit(XX_qr, name='XX')
+        XX_qc.ry(np.pi/2, [0,1])
+        XX_qc.append(ZZ_gate(1, t), [0,1])
+        XX_qc.ry(-np.pi/2, [0,1])
+        XX = XX_qc.to_instruction()
+        return XX
+
+    def YY_gate(t):
+        YY_qr = QuantumRegister(2)
+        YY_qc = QuantumCircuit(YY_qr, name='YY')
+        YY_qc.rx(-np.pi/2, [0,1])
+        YY_qc.append(ZZ_gate(1, t), [0,1])
+        YY_qc.rx(np.pi/2, [0,1])
+        YY = YY_qc.to_instruction()
+        return YY
+    
+    Trot_qr = QuantumRegister(num_qubits)
+    qc = QuantumCircuit(Trot_qr, name='Trot')
+
+    for i in range(num_qubits - 1):
+        qc.append(XX_gate(t), [Trot_qr[i], Trot_qr[i+1]])
+        qc.append(YY_gate(t), [Trot_qr[i], Trot_qr[i+1]])
+        qc.append(ZZ_gate(J, t), [Trot_qr[i], Trot_qr[i+1]])
+    
+    for i in range(num_qubits):
+        qc.rz(2 * deltas[i] * t, i)
+        
+    return qc
+

Next we define the function that records the Trotterized circuits at all time steps. Note that we will start with 3 particle excitations at sties 0, 4, and 8.

+
def U_trot_circuits_mbl(delta_t, trotter_steps, num_qubits, U, W, beta):
+    """
+    Record a list of Trotterized quantum circuits for many body localization 
+    at all Trotter steps.
+
+    Args:
+        delta_t (float): Duration of individual time steps.
+        trotter_steps (array): Array of intermediate times.
+        num_qubits (int): The total number of qubits.
+        U (float): The interaction strength.
+        W (float): The disorder strength.
+        beta (float): The quasicrystal periodicity of the AA model.
+
+    Returns:
+        disorder_circuits (list): List of Trotterized quantum 
+        circuits for MBL.
+    """
+
+    t = Parameter('t')
+    J = Parameter('J')
+    deltas = [Parameter('delta_{:d}'.format(idx)) for idx in range(num_qubits)]
+
+
+    AA_pattern = np.cos(2*np.pi*beta*np.arange(num_qubits))
+    disorders = W * AA_pattern
+    mbl_circuits = []
+
+    for n_steps in trotter_steps:
+        qr = QuantumRegister(num_qubits)
+        cr = ClassicalRegister(num_qubits)
+        qc = QuantumCircuit(qr, cr)
+
+        qc.x([0, 4, 8])  # three particle excitations
+
+        for _ in range(n_steps):
+            qc.append(Trot_qc_mbl(num_qubits, t, J, deltas), qr)
+            
+        qc = qc.bind_parameters({t: delta_t})
+        qc = qc.bind_parameters({deltas[idx]: disorders[idx] for idx in range(num_qubits)})
+        qc = qc.bind_parameters({J: U})
+        mbl_circuits.append(qc)
+    return mbl_circuits
+

We first fix the value of the interaction strength \(U = 1.0\) and simulate the system at four different values of disorder strength \(W = [0.2,\ 2,\ 4,\ 8]\).

+
delta_t = 0.15
+trotter_steps = np.arange(1, 25, 1) 
+num_qubits = 12
+U = 1.0
+beta = (np.sqrt(5)-1)/2
+
+circuits = {}
+Ws = [0.2, 2, 4, 8]
+
+for W in Ws:
+    circuits[W] = U_trot_circuits_mbl(
+        delta_t=delta_t, 
+        trotter_steps=trotter_steps, 
+        num_qubits=num_qubits, 
+        U=U, 
+        W=W, 
+        beta=beta
+    )
+

We can then simulate these Trotterized circuits on Qiskit’s statevector_simulator backend and track the time evolution of the probability of finding a particle for all the lattice sites, the imbalance of the system, and the von Neumann entropy of the first site:

+
backend_sim = Aer.get_backend('statevector_simulator')
+
+probability_densities = {}
+state_vector_imbalances = {}
+vn_entropies = {}
+
+for W in tqdm(Ws):
+    probability_densities[W] = []
+    state_vector_imbalances[W] = []
+    vn_entropies[W] = []
+    
+    for circ in circuits[W]:
+
+        transpiled_circ = transpile(circ, backend_sim, optimization_level=3)
+        job_sim = backend_sim.run(transpiled_circ)
+        # Grab the results from the job.
+        result_sim = job_sim.result()
+        outputstate = result_sim.get_statevector(transpiled_circ, decimals=6)
+
+        # extract the probability densities
+        ps = []
+        for idx in range(num_qubits):
+            ps.append(np.abs(qi.partial_trace(outputstate, [i for i in range(num_qubits) if i!=idx]))[1,1]**2)
+        
+        # extract the density matrix of qubit 0 by tracing out all other qubits
+        entropy = 0
+        rho_0 = qi.partial_trace(outputstate, range(1, num_qubits))
+        entropy += qi.entropy(rho_0, base=np.exp(1))
+        
+        # calculate the imbalance of the system
+        imbalance = 0        
+        imbalance += get_imbalance(outputstate)
+        
+        vn_entropies[W].append(entropy)
+        probability_densities[W].append(ps)
+        state_vector_imbalances[W].append(imbalance)
+

Below we show the results of this simulation. First is the probability densities at different disorder strengths.

+ +

We see that with weak disorder the system is delocalized but as \(W\) increases, MBL kicks in and the particles are localized around their initial positions over time. Next we look at the imbalance as a function of time.

+ +

Again, as expected, when \(W\) is small, the system tends to thermalize and the average imbalance is close to 0. But at strong disorder, we see a large deviation from 0, indicated by the green and red curves in the plot. Finally, here is the result of the von Neumann entropy.

+ +

We see the average entanglement entropy over time decreases as the disorder strength increases since the system is transitioning into the MBL phase.

+

As the final simulation, we will fix the disorder strength \(W = 3.5\) and vary the interaction strength \(U = [0.2,\ 1,\ 3,\ 5]\) to see how the behavior of the system changes. The execution is similar to the one above, so I won’t bore you with basically the same codes again. Let us directly look at the results.

+
+ +
Probability densities at different interaction strengths.
+
+
+ +
Evolution of the imbalance at different interaction strengths.
+
+
+ +
Evolution of the von Neumann entropy of site 0 at different interaction strengths.
+
+

Based on the phase diagram discussed in the previous section, we expect that the system will transition from MBL to delocalization as \(U\) increases, when the disorder is not very strong. This can be observed in the probability densities, where the sign of delocalization can be seen starting from \(U = 3\), especially on the first qubit. This is also supported by considering the average imbalance and entanglement entropy at different interaction strengths. Although it is not as clear as the previous case with a fixed \(U\) and varying \(W\), we can still see that overall the magnitude of imbalance is smaller when the system becomes delocalized (i.e., with larger \(U\)), while the entanglement entropy gets larger. These simulation results agree with the theoretical expectations.

+

Conclusion #

+

Here we conclude the quantum simulations of many-body localization as well as the blogging about the IBM Quantum Spring Challenge 2022 as a whole. We have explored parts of the phase diagram of a 1-D disordered Heisenberg XXZ chain. We saw the somewhat competing effect between particle interaction and disorder, leading to transition between thermal and MBL phases. Our quantum simulations have successfully captured some of the key features of this phase diagram. However, it is fair to say that the simulations showcased here barely scratch the surface of the fascinating physics of MBL and non-equilibrium quantum systems as a whole. There are other profound topics of the MBL systems which we did not touch upon and some of them are under active investigation, including the emergent integrability and even a whole new class of MBL-protected phases of matter.

+

With that, I want to thank you for taking the time to follow along and I hope you enjoyed this journey into quantum simulations of many-body physics as much as I did!

+

References #

+
    +
  1. +

    D. A. Abanin, E. Altman, I. Bloch, and M. Serbyn, Colloquium: Many-body localization, thermalization, and entanglement. Rev. Mod. Phys. 91, 021001 (2019).

    +
  2. +
  3. +

    B. Basko, A. Aleiner, and A. Altshuler, Metal-insulator transition in a weakly interacting many-electron system with localized single-particle states. Ann. Phys. 321, 1126 (2006).

    +
  4. +
  5. +

    V. Oganesyan and D. V. Huse, Localization of interacting fermions at high temperature. Phys. Rev. B 75, 155111 (2007).

    +
  6. +
  7. +

    W. De Roeck and F. Huveneers, Stability and instability towards delocalization in many-body localization systems. Phys. Rev. B 95, 155129 (2017).

    +
  8. +
  9. +

    D. J. Luitz, F. Huveneers, and W. De Roeck, How a Small Quantum Bath Can Thermalize Long Localized Chains. Phys. Rev. Lett. 119. 150602 (2017).

    +
  10. +
+ + +
+
+ +
+ + + + +
+ + +
+ + diff --git a/public/blog/ibm-spring-challenge-3/mbl_entropy_U.svg b/public/blog/ibm-spring-challenge-3/mbl_entropy_U.svg new file mode 100644 index 0000000..a0a54e1 --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_entropy_U.svg @@ -0,0 +1,1138 @@ + + + + + + + + 2022-06-26T18:23:48.796179 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/mbl_entropy_W.svg b/public/blog/ibm-spring-challenge-3/mbl_entropy_W.svg new file mode 100644 index 0000000..60c002a --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_entropy_W.svg @@ -0,0 +1,1193 @@ + + + + + + + + 2022-06-26T18:22:04.480988 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/mbl_imbal_U.svg b/public/blog/ibm-spring-challenge-3/mbl_imbal_U.svg new file mode 100644 index 0000000..56ffa4a --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_imbal_U.svg @@ -0,0 +1,1138 @@ + + + + + + + + 2022-06-26T18:23:39.842124 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/mbl_imbal_W.svg b/public/blog/ibm-spring-challenge-3/mbl_imbal_W.svg new file mode 100644 index 0000000..355a498 --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_imbal_W.svg @@ -0,0 +1,1109 @@ + + + + + + + + 2022-06-26T18:21:35.354095 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/mbl_probs_U.svg b/public/blog/ibm-spring-challenge-3/mbl_probs_U.svg new file mode 100644 index 0000000..57abcfd --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_probs_U.svg @@ -0,0 +1,8774 @@ + + + + + + + + 2022-06-26T18:12:52.021015 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/ibm-spring-challenge-3/mbl_probs_W.svg b/public/blog/ibm-spring-challenge-3/mbl_probs_W.svg new file mode 100644 index 0000000..6e74d04 --- /dev/null +++ b/public/blog/ibm-spring-challenge-3/mbl_probs_W.svg @@ -0,0 +1,8773 @@ + + + + + + + + 2022-06-26T18:08:20.055344 + image/svg+xml + + + Matplotlib v3.5.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/blog/index.html b/public/blog/index.html new file mode 100644 index 0000000..8182867 --- /dev/null +++ b/public/blog/index.html @@ -0,0 +1,899 @@ + + + + + + + + + + + + Blog · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ + +
+ +

Blog

+
+
+ +
+ +
+
+ +
+ + +

+ 2023 +

+
+ + + + + + + +

+ 2022 +

+
+ + +
+

+ + Adding blog comments + + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + Software + + + +
+ + + +
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + +
+ + +
+ + diff --git a/public/blog/index.xml b/public/blog/index.xml new file mode 100644 index 0000000..e677e92 --- /dev/null +++ b/public/blog/index.xml @@ -0,0 +1,55 @@ + + + + Blog on Ruihao Li + http://localhost:1313/blog/ + Recent content in Blog on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Mon, 09 Jan 2023 00:00:00 +0000 + + + Supercharging the Pythonic Metropolis Monte Carlo + http://localhost:1313/blog/2d-ising-model/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/blog/2d-ising-model/ + Okay, I&rsquo;ll admit that this is neither a super exciting nor a new topic to write about. + + + Adding blog comments + http://localhost:1313/blog/blog-comments/ + Sun, 03 Jul 2022 00:00:00 +0000 + http://localhost:1313/blog/blog-comments/ + Comments widget by Utterances. + + + Quantum simulation of many-body physics - III + http://localhost:1313/blog/ibm-spring-challenge-3/ + Sun, 26 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-3/ + This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. + + + Quantum simulation of many-body physics - II + http://localhost:1313/blog/ibm-spring-challenge-2/ + Sat, 18 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-2/ + As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. + + + Quantum simulation of many-body physics - I + http://localhost:1313/blog/ibm-spring-challenge-1/ + Sat, 04 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-1/ + A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. + + + Fish shell and customization + http://localhost:1313/blog/fish-shell-customization/ + Sun, 08 May 2022 00:00:00 +0000 + http://localhost:1313/blog/fish-shell-customization/ + A quick peek at the shell interface. + + + diff --git a/public/blog/page/1/index.html b/public/blog/page/1/index.html new file mode 100644 index 0000000..a541f84 --- /dev/null +++ b/public/blog/page/1/index.html @@ -0,0 +1,10 @@ + + + + http://localhost:1313/blog/ + + + + + + diff --git a/public/categories/index.html b/public/categories/index.html new file mode 100644 index 0000000..ca0d717 --- /dev/null +++ b/public/categories/index.html @@ -0,0 +1,414 @@ + + + + + + + + + + + + Categories · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+ +

Categories

+
+ +
+ +
+ + +
+ + +
+ + diff --git a/public/categories/index.xml b/public/categories/index.xml new file mode 100644 index 0000000..47496c1 --- /dev/null +++ b/public/categories/index.xml @@ -0,0 +1,12 @@ + + + + Categories on Ruihao Li + http://localhost:1313/categories/ + Recent content in Categories on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + + + diff --git a/public/css/main.bundle.min.54e933516f1551be16435e45ba8771caa2806e96a2841173800d419d5d0beeff32beaf2441e660d025fc433626ec52c15cc926630d0b9ec549eed5072c1920ed.css b/public/css/main.bundle.min.54e933516f1551be16435e45ba8771caa2806e96a2841173800d419d5d0beeff32beaf2441e660d025fc433626ec52c15cc926630d0b9ec549eed5072c1920ed.css new file mode 100644 index 0000000..e59f052 --- /dev/null +++ b/public/css/main.bundle.min.54e933516f1551be16435e45ba8771caa2806e96a2841173800d419d5d0beeff32beaf2441e660d025fc433626ec52c15cc926630d0b9ec549eed5072c1920ed.css @@ -0,0 +1 @@ +:root{--color-neutral:255, 255, 255;--color-neutral-50:250, 250, 249;--color-neutral-100:245, 245, 244;--color-neutral-200:231, 229, 228;--color-neutral-300:214, 211, 209;--color-neutral-400:168, 162, 158;--color-neutral-500:120, 113, 108;--color-neutral-600:87, 83, 78;--color-neutral-700:68, 64, 60;--color-neutral-800:41, 37, 36;--color-neutral-900:28, 25, 23;--color-primary-50:255, 247, 237;--color-primary-100:255, 237, 213;--color-primary-200:254, 215, 170;--color-primary-300:253, 186, 116;--color-primary-400:251, 146, 60;--color-primary-500:249, 115, 22;--color-primary-600:234, 88, 12;--color-primary-700:194, 65, 12;--color-primary-800:154, 52, 18;--color-primary-900:124, 45, 18;--color-secondary-50:255, 241, 242;--color-secondary-100:255, 228, 230;--color-secondary-200:254, 205, 211;--color-secondary-300:253, 164, 175;--color-secondary-400:251, 113, 133;--color-secondary-500:244, 63, 94;--color-secondary-600:225, 29, 72;--color-secondary-700:190, 18, 60;--color-secondary-800:159, 18, 57;--color-secondary-900:136, 19, 55}/*!Congo v2.3.0 | MIT License | https://github.com/jpanther/congo*//*!tailwindcss v3.1.4 | MIT License | https://tailwindcss.com*/*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:initial}::before,::after{--tw-content:''}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}*,::before,::after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgb(59 130 246 / 0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where([class~=lead]):not(:where([class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~=not-prose] *)){color:var(--tw-prose-links);text-decoration:underline;font-weight:500;-webkit-text-decoration-color:rgba(var(--color-primary-300),1);text-decoration-color:rgba(var(--color-primary-300),1)}.prose :where(a):not(:where([class~=not-prose] *)):hover{color:rgba(var(--color-neutral),1);text-decoration:none;background-color:rgba(var(--color-primary-600),1);border-radius:.09rem}.prose :where(strong):not(:where([class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(ol):not(:where([class~=not-prose] *)){list-style-type:decimal;padding-left:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=As]):not(:where([class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=as]):not(:where([class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=Is]):not(:where([class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=is]):not(:where([class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose] *)){list-style-type:disc;padding-left:1.625em}.prose :where(ol>li):not(:where([class~=not-prose] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul>li):not(:where([class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(hr):not(:where([class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-left-width:.25rem;border-left-color:var(--tw-prose-quote-borders);quotes:"\201C""\201D""\2018""\2019";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose] *))::before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose] *))::after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~=not-prose] *)){font-weight:900}.prose :where(h2):not(:where([class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~=not-prose] *)){font-weight:800}.prose :where(h3):not(:where([class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose] *)){font-weight:700}.prose :where(h4):not(:where([class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose] *)){font-weight:700}.prose :where(figure>*):not(:where([class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose :where(code):not(:where([class~=not-prose] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em}.prose :where(code):not(:where([class~=not-prose] *))::before{content:"`"}.prose :where(code):not(:where([class~=not-prose] *))::after{content:"`"}.prose :where(a code):not(:where([class~=not-prose] *)){color:var(--tw-prose-code)}.prose :where(pre):not(:where([class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding-top:.8571429em;padding-right:1.1428571em;padding-bottom:.8571429em;padding-left:1.1428571em}.prose :where(pre code):not(:where([class~=not-prose] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~=not-prose] *))::before{content:none}.prose :where(pre code):not(:where([class~=not-prose] *))::after{content:none}.prose :where(table):not(:where([class~=not-prose] *)){width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose :where(tbody tr):not(:where([class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose] *)){vertical-align:baseline;padding-top:.5714286em;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose{--tw-prose-body:rgba(var(--color-neutral-700), 1);--tw-prose-headings:rgba(var(--color-neutral-800), 1);--tw-prose-lead:rgba(var(--color-neutral-500), 1);--tw-prose-links:rgba(var(--color-primary-700), 1);--tw-prose-bold:rgba(var(--color-neutral-900), 1);--tw-prose-counters:rgba(var(--color-neutral-800), 1);--tw-prose-bullets:rgba(var(--color-neutral-500), 1);--tw-prose-hr:rgba(var(--color-neutral-200), 1);--tw-prose-quotes:rgba(var(--color-neutral-700), 1);--tw-prose-quote-borders:rgba(var(--color-primary-200), 1);--tw-prose-captions:rgba(var(--color-neutral-500), 1);--tw-prose-code:rgba(var(--color-secondary-700), 1);--tw-prose-pre-code:rgba(var(--color-neutral-700), 1);--tw-prose-pre-bg:rgba(var(--color-neutral-50), 1);--tw-prose-th-borders:rgba(var(--color-neutral-500), 1);--tw-prose-td-borders:rgba(var(--color-neutral-300), 1);--tw-prose-invert-body:rgba(var(--color-neutral-300), 1);--tw-prose-invert-headings:rgba(var(--color-neutral-50), 1);--tw-prose-invert-lead:rgba(var(--color-neutral-500), 1);--tw-prose-invert-links:rgba(var(--color-primary-400), 1);--tw-prose-invert-bold:rgba(var(--color-neutral), 1);--tw-prose-invert-counters:rgba(var(--color-neutral-400), 1);--tw-prose-invert-bullets:rgba(var(--color-neutral-600), 1);--tw-prose-invert-hr:rgba(var(--color-neutral-500), 1);--tw-prose-invert-quotes:rgba(var(--color-neutral-200), 1);--tw-prose-invert-quote-borders:rgba(var(--color-primary-900), 1);--tw-prose-invert-captions:rgba(var(--color-neutral-400), 1);--tw-prose-invert-code:rgba(var(--color-secondary-400), 1);--tw-prose-invert-pre-code:rgba(var(--color-neutral-200), 1);--tw-prose-invert-pre-bg:rgba(var(--color-neutral-700), 1);--tw-prose-invert-th-borders:rgba(var(--color-neutral-500), 1);--tw-prose-invert-td-borders:rgba(var(--color-neutral-700), 1);font-size:1rem;line-height:1.75}.prose :where(p):not(:where([class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(img):not(:where([class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(video):not(:where([class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(figure):not(:where([class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(h2 code):not(:where([class~=not-prose] *)){font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose] *)){font-size:.9em}.prose :where(li):not(:where([class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose] *)){padding-left:.375em}.prose :where(ul>li):not(:where([class~=not-prose] *)){padding-left:.375em}.prose>:where(ul>li p):not(:where([class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose>:where(ul>li>*:first-child):not(:where([class~=not-prose] *)){margin-top:1.25em}.prose>:where(ul>li>*:last-child):not(:where([class~=not-prose] *)){margin-bottom:1.25em}.prose>:where(ol>li>*:first-child):not(:where([class~=not-prose] *)){margin-top:1.25em}.prose>:where(ol>li>*:last-child):not(:where([class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(hr+*):not(:where([class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~=not-prose] *)){padding-right:0}.prose :where(tbody td:first-child):not(:where([class~=not-prose] *)){padding-left:0}.prose :where(tbody td:last-child):not(:where([class~=not-prose] *)){padding-right:0}.prose>:where(:first-child):not(:where([class~=not-prose] *)){margin-top:0}.prose>:where(:last-child):not(:where([class~=not-prose] *)){margin-bottom:0}.prose :where(kbd):not(:where([class~=not-prose] *)){background-color:rgba(var(--color-neutral-200),1);padding:.1rem .4rem;border-radius:.25rem;font-size:.9rem;font-weight:600}.prose :where(mark):not(:where([class~=not-prose] *)){color:rgba(var(--color-neutral-800),1);background-color:rgba(var(--color-secondary-200),1);padding:.1rem .2rem;border-radius:.12rem}body a,body button{transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.icon svg{height:1em;width:1em}#search-query::-webkit-search-cancel-button,#search-query::-webkit-search-decoration,#search-query::-webkit-search-results-button,#search-query::-webkit-search-results-decoration{display:none}body:has(#menu-controller:checked){position:fixed;overflow-y:scroll}#menu-button:has(#menu-controller:checked){visibility:hidden}#menu-controller:checked~#menu-wrapper{visibility:visible;opacity:1}[dir=rtl] .prose blockquote{border-left-width:0;border-right-width:4px;padding-right:1rem}[dir=rtl] .prose ul>li,[dir=rtl] .prose ol>li{margin-right:1.75rem;padding-left:0;padding-right:.5rem}[dir=rtl] .prose ol>li:before,[dir=rtl] .prose ul>li:before{left:auto;right:.25rem}[dir=rtl] .prose thead td:first-child,[dir=rtl] .prose thead th:first-child{padding-right:0}[dir=rtl] .prose thead td:last-child,[dir=rtl] .prose thead th:last-child{padding-left:0}.prose div.min-w-0.max-w-prose>*:first-child{margin-top:.75rem}.toc ul,.toc li{list-style-type:none;padding-left:0;padding-right:0;line-height:1.375}[dir=ltr] .toc ul ul{padding-left:1rem}[dir=rtl] .toc ul ul{padding-right:1rem}.toc a{font-weight:400;--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.dark .toc a{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}[dir=rtl] .toc ul>li{margin-right:0}.highlight-wrapper{display:block}.highlight{position:relative;z-index:0}.highlight:hover>.copy-button{visibility:visible}.copy-button{visibility:hidden;position:absolute;top:0;right:0;z-index:10;width:5rem;cursor:pointer;white-space:nowrap;border-bottom-left-radius:.375rem;border-top-right-radius:.375rem;--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-200),var(--tw-bg-opacity));padding-top:.25rem;padding-bottom:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity));opacity:.9}.dark .copy-button{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-600),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.copy-button:hover,.copy-button:focus,.copy-button:active,.copy-button:active:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.dark .copy-button:hover,.dark .copy-button:focus,.dark .copy-button:active,.dark .copy-button:active:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.copy-textarea{position:absolute;z-index:-10;opacity:.05}.prose .chroma{position:static;border-radius:.375rem;--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-50),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.dark .prose .chroma{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-700),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.chroma .lntd,.chroma .lntd pre{margin:0;border-style:none;padding:0;vertical-align:top}.chroma .lntable{display:block;width:auto;overflow:hidden;padding-left:1rem;padding-right:1rem;padding-top:.75rem;padding-bottom:.75rem;font-size:1rem;line-height:1.5rem;border-spacing:0}.chroma .hl{margin-left:-1rem;margin-right:-1rem;display:block;width:auto;--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity));padding-left:1rem;padding-right:1rem}.dark .chroma .hl{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.chroma .lntd .hl{margin:0;padding:0}.chroma .lnt,.chroma .ln{margin-right:.4em;padding-left:.4em;padding-right:.4em;padding-top:0;padding-bottom:0;--tw-text-opacity:1;color:rgba(var(--color-neutral-600),var(--tw-text-opacity))}.dark .chroma .lnt,.dark .chroma .ln{--tw-text-opacity:1;color:rgba(var(--color-neutral-300),var(--tw-text-opacity))}.chroma .k,.chroma .kd,.chroma .kn,.chroma .kp,.chroma .kr,.chroma .nc,.chroma .fm,.chroma .nn,.chroma .vc,.chroma .o{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.dark .chroma .k,.dark .chroma .kd,.dark .chroma .kn,.dark .chroma .kp,.dark .chroma .kr,.dark .chroma .nc,.dark .chroma .fm,.dark .chroma .nn,.dark .chroma .vc,.dark .chroma .o{--tw-text-opacity:1;color:rgba(var(--color-primary-300),var(--tw-text-opacity))}.chroma .kc{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.dark .chroma .kc{--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .kt,.chroma .nv,.chroma .vi,.chroma .vm,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .il,.chroma .mo{--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.dark .chroma .kt,.dark .chroma .nv,.dark .chroma .vi,.dark .chroma .vm,.dark .chroma .m,.dark .chroma .mb,.dark .chroma .mf,.dark .chroma .mh,.dark .chroma .mi,.dark .chroma .il,.dark .chroma .mo{--tw-text-opacity:1;color:rgba(var(--color-secondary-600),var(--tw-text-opacity))}.chroma .n,.chroma .nd,.chroma .ni,.chroma .nl{--tw-text-opacity:1;color:rgba(var(--color-secondary-900),var(--tw-text-opacity))}.dark .chroma .n,.dark .chroma .nd,.dark .chroma .ni,.dark .chroma .nl{--tw-text-opacity:1;color:rgba(var(--color-secondary-200),var(--tw-text-opacity))}.chroma .na,.chroma .nb,.chroma .bp,.chroma .nx,.chroma .py,.chroma .nt{--tw-text-opacity:1;color:rgba(var(--color-secondary-800),var(--tw-text-opacity))}.dark .chroma .na,.dark .chroma .nb,.dark .chroma .bp,.dark .chroma .nx,.dark .chroma .py,.dark .chroma .nt{--tw-text-opacity:1;color:rgba(var(--color-secondary-300),var(--tw-text-opacity))}.chroma .no,.chroma .ne,.chroma .vg{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.dark .chroma .no,.dark .chroma .ne,.dark .chroma .vg{--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .nf{--tw-text-opacity:1;color:rgba(var(--color-secondary-600),var(--tw-text-opacity))}.dark .chroma .nf{--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .l,.chroma .ld,.chroma .s,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .dl,.chroma .sd,.chroma .s2,.chroma .sh,.chroma .si,.chroma .sx,.chroma .s1,.chroma .gi,.chroma .go,.chroma .gp{--tw-text-opacity:1;color:rgba(var(--color-primary-800),var(--tw-text-opacity))}.dark .chroma .l,.dark .chroma .ld,.dark .chroma .s,.dark .chroma .sa,.dark .chroma .sb,.dark .chroma .sc,.dark .chroma .dl,.dark .chroma .sd,.dark .chroma .s2,.dark .chroma .sh,.dark .chroma .si,.dark .chroma .sx,.dark .chroma .s1,.dark .chroma .gi,.dark .chroma .go,.dark .chroma .gp{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.chroma .se{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-secondary-400),var(--tw-text-opacity))}.dark .chroma .se{--tw-text-opacity:1;color:rgba(var(--color-secondary-500),var(--tw-text-opacity))}.chroma .sr,.chroma .ss{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-primary-800),var(--tw-text-opacity))}.dark .chroma .sr,.dark .chroma .ss{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.chroma .ow{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark .chroma .ow{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.chroma .c,.chroma .cm,.chroma .c1,.chroma .cs,.chroma .cp,.chroma .cpf{font-style:italic;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.dark .chroma .c,.dark .chroma .cm,.dark .chroma .c1,.dark .chroma .cs,.dark .chroma .cp,.dark .chroma .cpf{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.chroma .ch{font-weight:600;font-style:italic;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.dark .chroma .ch{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.chroma .ge{font-style:italic}.chroma .gh{font-weight:600;--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .gs{font-weight:600}.chroma .gu,.chroma .gt{--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.chroma .gl{-webkit-text-decoration-line:underline;text-decoration-line:underline}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:-webkit-sticky;position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.top-\[100vh\]{top:100vh}.bottom-0{bottom:0}.top-\[calc\(100vh-5\.5rem\)\]{top:calc(100vh - 5.5rem)}.top-20{top:5rem}.top-0{top:0}.z-50{z-index:50}.z-10{z-index:10}.z-40{z-index:40}.z-30{z-index:30}.order-first{order:-9999}.m-auto{margin:auto}.m-1{margin:.25rem}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.mx-4{margin-left:1rem;margin-right:1rem}.mb-3{margin-bottom:.75rem}.mt-8{margin-top:2rem}.mb-12{margin-bottom:3rem}.mt-0{margin-top:0}.mt-12{margin-top:3rem}.mt-10{margin-top:2.5rem}.mt-6{margin-top:1.5rem}.mr-3{margin-right:.75rem}.ml-3{margin-left:.75rem}.mt-\[0\.1rem\]{margin-top:.1rem}.\!mt-0{margin-top:0!important}.\!mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.-mb-1{margin-bottom:-.25rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.\!mb-9{margin-bottom:2.25rem!important}.mt-1{margin-top:.25rem}.mb-\[2px\]{margin-bottom:2px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-screen{height:100vh}.h-12{height:3rem}.h-24{height:6rem}.h-8{height:2rem}.h-full{height:100%}.h-36{height:9rem}.max-h-\[10rem\]{max-height:10rem}.min-h-0{min-height:0}.w-12{width:3rem}.w-36{width:9rem}.w-full{width:100%}.w-24{width:6rem}.w-screen{width:100vw}.w-8{width:2rem}.w-6{width:1.5rem}.min-w-0{min-width:0}.min-w-\[1\.8rem\]{min-width:1.8rem}.min-w-\[2\.4rem\]{min-width:2.4rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-prose{max-width:65ch}.max-w-3xl{max-width:48rem}.max-w-\[10rem\]{max-width:10rem}.flex-none{flex:none}.flex-auto{flex:auto}.grow{flex-grow:1}.-translate-y-8{--tw-translate-y:-2rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.place-self-center{place-self:center}.self-center{align-self:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.scroll-smooth{scroll-behavior:smooth}.rounded-full{border-radius:9999px}.rounded-md{border-radius:.375rem}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.\!rounded-md{border-radius:.375rem!important}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.border{border-width:1px}.border-t{border-top-width:1px}.border-dotted{border-style:dotted}.border-neutral-400{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-400),var(--tw-border-opacity))}.border-neutral-300{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-300),var(--tw-border-opacity))}.border-neutral-200{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-200),var(--tw-border-opacity))}.border-primary-400{--tw-border-opacity:1;border-color:rgba(var(--color-primary-400),var(--tw-border-opacity))}.bg-neutral{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral),var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-200),var(--tw-bg-opacity))}.bg-neutral\/50{background-color:rgba(var(--color-neutral),.5)}.bg-neutral-500\/50{background-color:rgba(var(--color-neutral-500),.5)}.bg-transparent{background-color:transparent}.bg-neutral-100{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-100),var(--tw-bg-opacity))}.bg-neutral-300{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-300),var(--tw-bg-opacity))}.bg-primary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.bg-neutral-100\/50{background-color:rgba(var(--color-neutral-100),.5)}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-left{-o-object-position:left;object-position:left}.p-4{padding:1rem}.p-1{padding:.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-0{padding-left:0;padding-right:0}.py-8{padding-top:2rem;padding-bottom:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-\[1px\]{padding-top:1px;padding-bottom:1px}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pt-8{padding-top:2rem}.pt-3{padding-top:.75rem}.pl-2{padding-left:.5rem}.pb-4{padding-bottom:1rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-text-bottom{vertical-align:text-bottom}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xs{font-size:.75rem;line-height:1rem}.text-\[0\.6rem\]{font-size:.6rem}.font-extrabold{font-weight:800}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-normal{font-weight:400}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-7{line-height:1.75rem}.leading-6{line-height:1.5rem}.leading-3{line-height:.75rem}.text-neutral-400{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.text-neutral-900{--tw-text-opacity:1;color:rgba(var(--color-neutral-900),var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.text-neutral-700{--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}.text-neutral-500{--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:rgba(var(--color-primary-500),var(--tw-text-opacity))}.text-neutral-800{--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.text-primary-700{--tw-text-opacity:1;color:rgba(var(--color-primary-700),var(--tw-text-opacity))}.text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.\!text-neutral{--tw-text-opacity:1 !important;color:rgba(var(--color-neutral),var(--tw-text-opacity))!important}.\!no-underline{-webkit-text-decoration-line:none!important;text-decoration-line:none!important}.decoration-primary-500{-webkit-text-decoration-color:rgba(var(--color-primary-500),1);text-decoration-color:rgba(var(--color-primary-500),1)}.decoration-neutral-300{-webkit-text-decoration-color:rgba(var(--color-neutral-300),1);text-decoration-color:rgba(var(--color-neutral-300),1)}.opacity-0{opacity:0}.shadow-lg{--tw-shadow:0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:150ms}.first\:mt-8:first-child{margin-top:2rem}.hover\:border-primary-300:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-300),var(--tw-border-opacity))}.hover\:bg-primary-600:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.hover\:bg-primary-100:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.hover\:bg-primary-500:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500),var(--tw-bg-opacity))}.hover\:\!bg-primary-500:hover{--tw-bg-opacity:1 !important;background-color:rgba(var(--color-primary-500),var(--tw-bg-opacity))!important}.hover\:text-primary-600:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-700),var(--tw-text-opacity))}.hover\:text-primary-500:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-500),var(--tw-text-opacity))}.hover\:text-neutral:hover{--tw-text-opacity:1;color:rgba(var(--color-neutral),var(--tw-text-opacity))}.hover\:underline:hover{-webkit-text-decoration-line:underline;text-decoration-line:underline}.hover\:decoration-primary-400:hover{-webkit-text-decoration-color:rgba(var(--color-primary-400),1);text-decoration-color:rgba(var(--color-primary-400),1)}.hover\:decoration-2:hover{text-decoration-thickness:2px}.hover\:underline-offset-2:hover{text-underline-offset:2px}.focus\:translate-y-0:focus{--tw-translate-y:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.focus\:bg-primary-100:focus{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}.focus\:outline-dotted:focus{outline-style:dotted}.focus\:outline-2:focus{outline-width:2px}.focus\:outline-transparent:focus{outline-color:transparent}.group:hover .group-hover\:text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600),var(--tw-text-opacity))}.group:hover .group-hover\:text-primary-300{--tw-text-opacity:1;color:rgba(var(--color-primary-300),var(--tw-text-opacity))}.group:hover .group-hover\:underline{-webkit-text-decoration-line:underline;text-decoration-line:underline}.group:hover .group-hover\:decoration-primary-500{-webkit-text-decoration-color:rgba(var(--color-primary-500),1);text-decoration-color:rgba(var(--color-primary-500),1)}.group:hover .group-hover\:opacity-100{opacity:1}[dir=ltr] .ltr\:right-0{right:0}[dir=ltr] .ltr\:-left-6{left:-1.5rem}[dir=ltr] .ltr\:ml-2{margin-left:.5rem}[dir=ltr] .ltr\:mr-4{margin-right:1rem}[dir=ltr] .ltr\:ml-1{margin-left:.25rem}[dir=ltr] .ltr\:mr-14{margin-right:3.5rem}[dir=ltr] .ltr\:-ml-5{margin-left:-1.25rem}[dir=ltr] .ltr\:block{display:block}[dir=ltr] .ltr\:inline{display:inline}[dir=ltr] .ltr\:hidden{display:none}[dir=ltr] .ltr\:border-l{border-left-width:1px}[dir=ltr] .ltr\:pr-2{padding-right:.5rem}[dir=ltr] .ltr\:pl-5{padding-left:1.25rem}[dir=ltr] .ltr\:pr-3{padding-right:.75rem}[dir=ltr] .ltr\:text-right{text-align:right}[dir=rtl] .rtl\:left-0{left:0}[dir=rtl] .rtl\:-right-6{right:-1.5rem}[dir=rtl] .rtl\:mr-2{margin-right:.5rem}[dir=rtl] .rtl\:ml-4{margin-left:1rem}[dir=rtl] .rtl\:mr-1{margin-right:.25rem}[dir=rtl] .rtl\:ml-14{margin-left:3.5rem}[dir=rtl] .rtl\:-mr-5{margin-right:-1.25rem}[dir=rtl] .rtl\:block{display:block}[dir=rtl] .rtl\:inline{display:inline}[dir=rtl] .rtl\:hidden{display:none}[dir=rtl] .rtl\:border-r{border-right-width:1px}[dir=rtl] .rtl\:pl-2{padding-left:.5rem}[dir=rtl] .rtl\:pr-5{padding-right:1.25rem}[dir=rtl] .rtl\:pl-3{padding-left:.75rem}[dir=rtl] .rtl\:text-left{text-align:left}.dark .dark\:prose-invert{--tw-prose-body:var(--tw-prose-invert-body);--tw-prose-headings:var(--tw-prose-invert-headings);--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:var(--tw-prose-invert-links);--tw-prose-bold:var(--tw-prose-invert-bold);--tw-prose-counters:var(--tw-prose-invert-counters);--tw-prose-bullets:var(--tw-prose-invert-bullets);--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:var(--tw-prose-invert-quotes);--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.dark .dark\:prose-invert :where(a):not(:where([class~=not-prose] *)){-webkit-text-decoration-color:rgba(var(--color-neutral-600),1);text-decoration-color:rgba(var(--color-neutral-600),1)}.dark .dark\:prose-invert :where(kbd):not(:where([class~=not-prose] *)){color:rgba(var(--color-neutral-200),1);background-color:rgba(var(--color-neutral-700),1)}.dark .dark\:prose-invert :where(mark):not(:where([class~=not-prose] *)){background-color:rgba(var(--color-secondary-400),1)}.dark .dark\:inline{display:inline}.dark .dark\:hidden{display:none}.dark .dark\:border-neutral-600{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-600),var(--tw-border-opacity))}.dark .dark\:border-primary-600{--tw-border-opacity:1;border-color:rgba(var(--color-primary-600),var(--tw-border-opacity))}.dark .dark\:border-neutral-700{--tw-border-opacity:1;border-color:rgba(var(--color-neutral-700),var(--tw-border-opacity))}.dark .dark\:bg-neutral-800{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-800),var(--tw-bg-opacity))}.dark .dark\:bg-neutral-600{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-600),var(--tw-bg-opacity))}.dark .dark\:bg-neutral-800\/50{background-color:rgba(var(--color-neutral-800),.5)}.dark .dark\:bg-primary-400{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400),var(--tw-bg-opacity))}.dark .dark\:bg-neutral-900\/50{background-color:rgba(var(--color-neutral-900),.5)}.dark .dark\:bg-neutral-700{--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-700),var(--tw-bg-opacity))}.dark .dark\:bg-primary-900{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.dark .dark\:bg-primary-800{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-800),var(--tw-bg-opacity))}.dark .dark\:text-neutral-500{--tw-text-opacity:1;color:rgba(var(--color-neutral-500),var(--tw-text-opacity))}.dark .dark\:text-neutral{--tw-text-opacity:1;color:rgba(var(--color-neutral),var(--tw-text-opacity))}.dark .dark\:text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark .dark\:text-neutral-300{--tw-text-opacity:1;color:rgba(var(--color-neutral-300),var(--tw-text-opacity))}.dark .dark\:text-neutral-400{--tw-text-opacity:1;color:rgba(var(--color-neutral-400),var(--tw-text-opacity))}.dark .dark\:text-neutral-800{--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.dark .dark\:text-neutral-100{--tw-text-opacity:1;color:rgba(var(--color-neutral-100),var(--tw-text-opacity))}.dark .dark\:hover\:border-primary-600:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-600),var(--tw-border-opacity))}.dark .dark\:hover\:bg-primary-900:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.dark .dark\:hover\:bg-primary-400:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400),var(--tw-bg-opacity))}.dark .dark\:hover\:\!bg-primary-700:hover{--tw-bg-opacity:1 !important;background-color:rgba(var(--color-primary-700),var(--tw-bg-opacity))!important}.dark .dark\:hover\:text-primary-400:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark .dark\:hover\:text-neutral-800:hover{--tw-text-opacity:1;color:rgba(var(--color-neutral-800),var(--tw-text-opacity))}.dark .dark\:focus\:bg-primary-900:focus{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900),var(--tw-bg-opacity))}.dark .group:hover .dark\:group-hover\:text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400),var(--tw-text-opacity))}.dark .group:hover .dark\:group-hover\:text-neutral-700{--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity))}@media print{.print\:hidden{display:none}}@media(min-width:640px){.sm\:mb-0{margin-bottom:0}.sm\:w-1\/2{width:50%}.sm\:flex-row{flex-direction:row}.sm\:p-6{padding:1.5rem}.sm\:px-14{padding-left:3.5rem;padding-right:3.5rem}.sm\:py-10{padding-top:2.5rem;padding-bottom:2.5rem}.sm\:pt-10{padding-top:2.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}[dir=ltr] .ltr\:sm\:mr-7{margin-right:1.75rem}[dir=ltr] .ltr\:sm\:last\:mr-0:last-child{margin-right:0}[dir=rtl] .rtl\:sm\:ml-7{margin-left:1.75rem}[dir=rtl] .rtl\:sm\:last\:ml-0:last-child{margin-left:0}}@media(min-width:768px){.md\:w-1\/3{width:33.333333%}.md\:p-\[10vh\]{padding:10vh}.md\:px-24{padding-left:6rem;padding-right:6rem}}@media(min-width:1024px){.lg\:sticky{position:-webkit-sticky;position:sticky}.lg\:top-10{top:2.5rem}.lg\:order-last{order:9999}.lg\:hidden{display:none}.lg\:flex{display:flex}.lg\:w-1\/4{width:25%}.lg\:max-w-xs{max-width:20rem}.lg\:flex-row{flex-direction:row}.lg\:p-\[12vh\]{padding:12vh}.lg\:px-32{padding-left:8rem;padding-right:8rem}[dir=ltr] .ltr\:lg\:pl-8{padding-left:2rem}[dir=rtl] .rtl\:lg\:pr-8{padding-right:2rem}}@media(min-width:1280px){.xl\:w-1\/5{width:20%}}html{font-size:14pt;font-weight:100;font-family:nunito,sans-serif,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji}code,kbd,samp,pre{font-family:source code pro,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,liberation mono,courier new,monospace}.center{display:block;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0}.center_scaled{display:block;margin-left:auto;margin-right:auto;width:90%}.center_scaled_smaller{display:block;margin-left:auto;margin-right:auto;width:70%}.max-w-prose{max-width:72ch} \ No newline at end of file diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000..d9b5f78 Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000..c4f6c1c Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..90db64e Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/files/CERCA_Fall_18.pdf b/public/files/CERCA_Fall_18.pdf new file mode 100644 index 0000000..bbe3368 Binary files /dev/null and b/public/files/CERCA_Fall_18.pdf differ diff --git a/public/files/CERCA_Spring_19.pdf b/public/files/CERCA_Spring_19.pdf new file mode 100755 index 0000000..07c7530 Binary files /dev/null and b/public/files/CERCA_Spring_19.pdf differ diff --git a/public/files/CMP_JC_Spring_22.pdf b/public/files/CMP_JC_Spring_22.pdf new file mode 100644 index 0000000..4d303b4 Binary files /dev/null and b/public/files/CMP_JC_Spring_22.pdf differ diff --git a/public/files/Honours_Thesis.pdf b/public/files/Honours_Thesis.pdf new file mode 100755 index 0000000..2dd9085 Binary files /dev/null and b/public/files/Honours_Thesis.pdf differ diff --git a/public/files/Honours_talk_16.pdf b/public/files/Honours_talk_16.pdf new file mode 100755 index 0000000..640794a Binary files /dev/null and b/public/files/Honours_talk_16.pdf differ diff --git a/public/files/IBM_Certified_Associate_Developer.pdf b/public/files/IBM_Certified_Associate_Developer.pdf new file mode 100644 index 0000000..55aa57a Binary files /dev/null and b/public/files/IBM_Certified_Associate_Developer.pdf differ diff --git a/public/files/PCBAP_course_16.pdf b/public/files/PCBAP_course_16.pdf new file mode 100755 index 0000000..ccffe85 Binary files /dev/null and b/public/files/PCBAP_course_16.pdf differ diff --git a/public/files/QCHack2022_Certificate.pdf b/public/files/QCHack2022_Certificate.pdf new file mode 100644 index 0000000..63b5d5a Binary files /dev/null and b/public/files/QCHack2022_Certificate.pdf differ diff --git a/public/files/QFT_course_16.pdf b/public/files/QFT_course_16.pdf new file mode 100755 index 0000000..9430ff7 Binary files /dev/null and b/public/files/QFT_course_16.pdf differ diff --git a/public/files/QFT_in_curved_spacetime.pdf b/public/files/QFT_in_curved_spacetime.pdf new file mode 100755 index 0000000..2f7aef0 Binary files /dev/null and b/public/files/QFT_in_curved_spacetime.pdf differ diff --git a/public/files/QHack_Coding_Challenge_Certificate.pdf b/public/files/QHack_Coding_Challenge_Certificate.pdf new file mode 100644 index 0000000..8e0bb2d Binary files /dev/null and b/public/files/QHack_Coding_Challenge_Certificate.pdf differ diff --git a/public/files/QML_slides.pdf b/public/files/QML_slides.pdf new file mode 100644 index 0000000..4888094 Binary files /dev/null and b/public/files/QML_slides.pdf differ diff --git a/public/files/QOSF_Meeting.pdf b/public/files/QOSF_Meeting.pdf new file mode 100644 index 0000000..c7c618e Binary files /dev/null and b/public/files/QOSF_Meeting.pdf differ diff --git a/public/files/RL_resume_23.pdf b/public/files/RL_resume_23.pdf new file mode 100644 index 0000000..c43d7fd Binary files /dev/null and b/public/files/RL_resume_23.pdf differ diff --git a/public/files/Ruihao_Li_APS_22.pdf b/public/files/Ruihao_Li_APS_22.pdf new file mode 100644 index 0000000..47606d4 Binary files /dev/null and b/public/files/Ruihao_Li_APS_22.pdf differ diff --git a/public/files/Ruihao_Li_MMM_20.pdf b/public/files/Ruihao_Li_MMM_20.pdf new file mode 100644 index 0000000..b0ddf4d Binary files /dev/null and b/public/files/Ruihao_Li_MMM_20.pdf differ diff --git a/public/files/disco_diffusion.png b/public/files/disco_diffusion.png new file mode 100644 index 0000000..d64c938 Binary files /dev/null and b/public/files/disco_diffusion.png differ diff --git a/public/files/research_0622.svg b/public/files/research_0622.svg new file mode 100644 index 0000000..41a00e8 --- /dev/null +++ b/public/files/research_0622.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_192x192_fill_q75_box_smart1.jpeg b/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_192x192_fill_q75_box_smart1.jpeg new file mode 100644 index 0000000..3c187bd Binary files /dev/null and b/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_192x192_fill_q75_box_smart1.jpeg differ diff --git a/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_288x288_fill_q75_box_smart1.jpeg b/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_288x288_fill_q75_box_smart1.jpeg new file mode 100644 index 0000000..9b316c4 Binary files /dev/null and b/public/img/profile_hu273fe6bdf66b9fb1d54edabf60bda5ee_1824411_288x288_fill_q75_box_smart1.jpeg differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..6b8ff09 --- /dev/null +++ b/public/index.html @@ -0,0 +1,617 @@ + + + + + + + + + + + + + Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ + + +
+
+ + + + + Ruihao Li + + +

+ Ruihao Li +

+ +

+ Quantum Computing Researcher +

+ +
+ + + + +
+
+
+
+ +
+ +

Hi there! 👋 +I am currently a Quantum Research Data Scientist at Center for Computational Life Sciences, Lerner Research Institute, Cleveland Clinic. +I am a physicist by training, with a Ph.D. from Case Western Reserve University. +I work on interesting quantum computing problems in physics and life sciences. +Beyond what I do in my + + research, I am also broadly interested in emerging AI technologies.

+ + +
+

+ +About + + + +      + + +Research + + +

+
+
+
+ + +
+ + + + +
+ + +
+ + diff --git a/public/index.json b/public/index.json new file mode 100644 index 0000000..44914ee --- /dev/null +++ b/public/index.json @@ -0,0 +1 @@ +[{"content":" Hi there! 👋 I am currently a Quantum Research Data Scientist at Center for Computational Life Sciences, Lerner Research Institute, Cleveland Clinic. I am a physicist by training, with a Ph.D. from Case Western Reserve University. I work on interesting quantum computing problems in physics and life sciences. Beyond what I do in my research, I am also broadly interested in emerging AI technologies.\nAbout Research ","date":"9 January 2023","permalink":"/","section":"","summary":"Hi there!","title":""},{"content":"","date":"9 January 2023","permalink":"/blog/","section":"Blog","summary":"","title":"Blog"},{"content":"","date":"9 January 2023","permalink":"/tags/physics/","section":"Tags","summary":"","title":"Physics"},{"content":"","date":"9 January 2023","permalink":"/tags/python/","section":"Tags","summary":"","title":"Python"},{"content":" Okay, I\u0026rsquo;ll admit that this is neither a super exciting nor a new topic to write about. But I\u0026rsquo;ve been looking into some ways to simulate/prepare thermal states these days and the Metropolis Monte Carlo algorithm (which is also often referred to as the Metropolis-Hastings algorithm) is probably one of the most well-known methods to do so. Before fully stepping into the quantum realm (see Refs. [1] and [2] for quantum generalizations of this method), I thought I might as well try my hand at the classical version first. I have decided to use this technique to simulate the ferromagnetic phase transition of the famous 2D Ising model in statistical physics. Instead of focusing on the physics or the algorithm itself, the main discussion of this post will revolve around how to use Numba and Cython to \u0026ldquo;supercharge\u0026rdquo; the Pythonic implementation.\nMetropolising the Ising model # 2D Ising model with animated spin flips (figure taken from here). Let us first say something about our objective here. Given a two-dimensional Ising model on an $L\\times L$ square lattice, that is, $L^2$ spins which can only take values $+1$ (spin-up or red) or $-1$ (spin-down or blue) as displayed in the figure above, we want to simulate the thermal state of the system at finite temperature and extract a few thermal expectation values such as energy and magnetization along the way. Based on the evolution of net magnetization with an increasing temperature, we should observe a phase transition from a ferromagnetic (with finite magnetization) to a non-magnetic state (with zero magnetization) at some critical temperature $T_C$. Note that in 1D such phase transition will not happen due to the Peierls argument that dates back to the 1930s (see an explanation here). In its simplest form, the Ising Hamiltonian of the system is given by $$ H = -J\\sum_{\\braket{i,j}}\\sigma_i\\sigma_j, $$ where $\\braket{i, j}$ denotes all pairs of neighboring spins on the lattice and $J$ is the coupling strength between any two spins.\nTo compute any thermal expectation, we need to know the probability distribution of different spin configurations, which, in this case, is the Boltzmann distribution since the system is essentially a canonical ensemble at equilibrium: $$ P_S(\\beta) = \\frac{e^{-\\beta E_S}}{Z}, $$ where $\\beta = 1/k_B T$ is sometimes called the inverse temperature (for simplicity we will set the Boltzmann constant $k_B = 1$ hereafter) and $E_S$ is the energy of the spin configuration $S$, which can be computed from the Hamiltonian. $Z$ is the partition function defined as $$ Z = \\sum_S e^{-\\beta E_S}. $$ In particular, for $L^2$ spins, there are totally $2^{L^2}$ possible spin configurations. The partition function can be computed by summing over all these configurations, which is a computationally intractable task, especially for larger systems. However, we can use the Metropolis-Hastings algorithm to sample the distribution $P_S(\\beta)$ and estimate the expectation values of interest. The basic idea is to start with a random spin configuration and then propose a new configuration by flipping a single spin. If the new configuration has a lower energy, we simply accept it. Otherwise, we accept it with probability $e^{-\\beta(E_\\text{new}-E_\\text{old})}$, where $E_\\text{new}$ and $E_\\text{old}$ are the energies of the new and old configurations, respectively. This process is repeated for a large number of times until the sampled configurations are (almost) statistically independent and the distribution converges to the Boltzmann distribution. The expectation values are then computed from the sampled configurations by simply taking $$ \\braket{O(\\beta)} = \\sum_S O_S P_S(\\beta) $$ for any observable $O$. The Metropolis-Hastings algorithm is a Markov chain Monte Carlo (MCMC) method, which means that the new configuration is only dependent on the old configuration in the previous step and not on the entire history of the chain. This is a very important property of the algorithm, which allows us to parallelize the sampling process and speed up the computation. Here is a nice blog post by Gregory Gundersen justifying why this simple algorithm works if you want to have a deeper understanding of it.\nOf course, the Metropolis algorithm is not perfect. You can imagine that in each step flipping just one spin could be inefficient. At low temperatures, spin flips are rare because the acceptance probability is low. So we would need to perform more steps to sample the distribution. More severely, as the system approaches the critical temperature, the spin-spin correlation length diverges, so the spins tend to form large aligned domains. This leads to a phenomenon called the critical slowing down, which reflects the difficulty in flipping a spin within a correlated spin cluster. One way to overcome this hurdle is to use a cluster-flipping algorithm which flips multiple spins at once. An example of this is the Wolff algorithm [3] but in this post we will just focus on the Metropolis algorithm.\nPythonic implementation # Without further ado, let us implement the Metropolis algorithm for the 2D Ising model in Python. To start with, we can randomly generate the initial spin configuration. We can build a class called Ising with core methods to generate an initial spin configuration, compute the system\u0026rsquo;s total energy and net magnetization, and of course, update the spin configuration based on the Metropolis algorithm. Since the implementation is pretty straightforward, I will just attach the code below:\nimport numpy as np class Ising: \u0026#34;\u0026#34;\u0026#34; Pure Python implementation of Metropolis Monte Carlo Simulation of the 2D Ising model (square lattice). \u0026#34;\u0026#34;\u0026#34; def __init__(self, J, L, T): \u0026#34;\u0026#34;\u0026#34; Initialize the Ising model. Args: J (float): Coupling constant L (int): Linear size of the lattice T (float): Temperature \u0026#34;\u0026#34;\u0026#34; self.J = J self.L = L self.T = T self.spin_config = self.generate_spin_config() def generate_spin_config(self): \u0026#34;\u0026#34;\u0026#34; Generate a random spin configuration. \u0026#34;\u0026#34;\u0026#34; return np.random.choice([-1, 1], size=(self.L, self.L)) def compute_energy(self): \u0026#34;\u0026#34;\u0026#34; Compute the energy of the spin configuration. \u0026#34;\u0026#34;\u0026#34; energy = 0 for i in range(self.L): for j in range(self.L): # Periodic boundary conditions energy += ( -self.J * self.spin_config[i, j] * ( self.spin_config[i, (j + 1) % self.L] + self.spin_config[(i + 1) % self.L, j] + self.spin_config[i, (j - 1) % self.L] + self.spin_config[(i - 1) % self.L, j] ) ) return energy / 2 def compute_magnetization(self): \u0026#34;\u0026#34;\u0026#34; Compute the net absolute magnetization of the spin configuration. \u0026#34;\u0026#34;\u0026#34; return np.abs(np.sum(self.spin_config)) def mc_update(self): \u0026#34;\u0026#34;\u0026#34; Perform L^2 Metropolis steps to update the spin configuration. \u0026#34;\u0026#34;\u0026#34; for _ in range(self.L**2): # Pick a random site i = np.random.randint(self.L) j = np.random.randint(self.L) # Compute the change in energy delta_E = ( 2 * self.J * self.spin_config[i, j] * ( self.spin_config[i, (j + 1) % self.L] + self.spin_config[(i + 1) % self.L, j] + self.spin_config[i, (j - 1) % self.L] + self.spin_config[(i - 1) % self.L, j] ) ) # Flip the spin if the energy decreases or if the Metropolis # criterion is satisfied if delta_E \u0026lt;= 0: self.spin_config[i, j] *= -1 elif np.random.random() \u0026lt; np.exp(-delta_E / self.T): self.spin_config[i, j] *= -1 As one can see from mc_update(), one full update corresponds to repeating the Metropolis step $L^2$ times. The next configuration to be used in the Monte Carlo method is obtained after one full update. To set up the simulation, we will need to specify the values of the coupling strength $J$, the length of the square lattice $L$, as well as the temperature range within which to compute the expectation values $(T_\\text{low}, T_\\text{high})$. Furthermore, as mentioned before, we first need to perform enough Metropolis updates (specified by equil_steps) to sample the equilibrium distribution, after which we again update the system mc_steps times in total to build up the statistics for measuring the expectation values. We also define skip_steps which sets the number of lattice updates between any two consecutive measurements. Therefore, we can define the following function that outputs the energy expectation, magnetization expectation, and the final spin configuration at a range of temperatures:\ndef run_ising(J, L, T_low, T_high, nT, equil_steps, mc_steps, skip_steps): \u0026#34;\u0026#34;\u0026#34; Run the Monte Carlo simulation for a range of temperatures. Args: J (float): Coupling constant L (int): Linear size of the lattice T_low (float): Lower bound of the temperature range T_high (float): Upper bound of the temperature range nT (int): Number of temperatures to simulate equil_steps (int): Number of Monte Carlo steps to perform for equilibration mc_steps (int): Number of Monte Carlo steps to perform during measurement skip_steps (int): Number of Monte Carlo steps to skip between measurements Returns: (np.array, np.array, np.array): Arrays of energies (per site), magnetizations (per site), and spin configurations \u0026#34;\u0026#34;\u0026#34; T_array = np.linspace(T_low, T_high, nT) # Initialize arrays to store the energies and magnetizations E_array = np.zeros(nT) M_array = np.zeros(nT) # Initialize arrays to store the final spin configurations for each T spin_config_array = np.zeros((nT, L, L)) # Loop over temperatures for i in range(nT): Et = Mt = 0 # Initialize the Ising model ising = Ising(J, L, T_array[i]) # Equilibrate the system for _ in range(equil_steps): ising.mc_update() # Perform Monte Carlo steps after equilibration for j in range(mc_steps): ising.mc_update() # Skip the first few steps if j % skip_steps == 0: Et += ising.compute_energy() Mt += ising.compute_magnetization() # Average the energy and magnetization E_array[i] = Et / (mc_steps // skip_steps) / L ** 2 M_array[i] = Mt / (mc_steps // skip_steps) / L ** 2 # Store the final spin configuration spin_config_array[i] = ising.spin_config return E_array, M_array, spin_config_array Luckily for us, the 2D Ising model has closed-form solution for the energy and magnetization expectations, as well as the critical temperature $T_c$, which can be used to gauge the accuracy of our simulation. We can also have these exact solutions built in to our Ising class. The full code can be found here.\nAcceleration with Numba # If you run the above code, you would find it quite slow even with lattice size as small as $L = 10$, which took around 50 seconds on my MacBook Pro. The main bottleneck of the code is the mc_update() function, which involves $L^2$ evaluations of delta_E in the Metropolis step and is called repeatedly in the Monte Carlo simulation. The mc_update() function above is written in pure Python, which is not very efficient. One easy way to accelerate the code is to use the Numba library. Numba is a just-in-time (JIT) compiler that translates Python code into machine code during runtime (rather than pre-runtime like some compiled languages such as C). As we know, Python is an interpreted language, which means that the source code is converted to bytecode and executed line by line. A (good) JIT compiler helps remove the interpreter overhead and also allows for better optimizations since it has access to dynamic runtime information. What\u0026rsquo;s cool about Numba is that it works at function level and you can simply annotate functions you want to accelerate with the @jit decorators. It works best when a function involves heavy NumPy operations and nested loops. In our case, we should obviously accelerate the mc_update() function, but also compute_energy() and compute_magnetization(). One caveat in this case is that we cannot directly \u0026ldquo;jit\u0026rdquo; instance methods of a class. There are multiple ways to get around it. One is to convert the instance methods to static methods. Another is to use @jitclass to decorate the whole class but it is hard to work with more complex classes. Finally, a way that I find most convenient is to define the functions to be \u0026ldquo;jitted\u0026rdquo; outside the class and then just call them in the corresponding methods. So we would have something like this:\nfrom numba import jit @jit(nopython=True) def compute_energy(spin_config, J): ... @jit(nopython=True) def compute_magnetization(spin_config): ... @jit(nopython=True) def mc_update(spin_config, J, T): ... class Ising_numba: def __init__(self, J, L, T): ... def compute_energy(self): return compute_energy(self.spin_config, self.J) def compute_magnetization(self): return compute_magnetization(self.spin_config) def mc_update(self): mc_update(self.spin_config, self.J, self.T) Note that we have specified nopython=True in the @jit decorator (which is equivalent to using the @njit decorator) to ensure that the function is compiled in \u0026ldquo;nopython\u0026rdquo; mode, which means that the decorated function will run without the Python interpreter. The nopython mode gives the best performance but it also requires that the native types of all variables in the function can be inferred. Quoting from Numba\u0026rsquo;s official documentation: \u0026ldquo;A failure in type inference can be caused by two reasons. The first reason is user error due to incorrect use of a type. This type of error will also trigger an exception in regular python execution. The second reason is due to the use of an unsupported feature, but the code is otherwise valid in regular python execution.\u0026rdquo; If nopython=True is not set, the compilation would fall back to the object mode if type inference fails.\nOverall, Numba is great when it works, leading to huge performance boost (as we will see later), and it has other features which I did not touch upon, such as parallelization and vectorization. However, in its current form, it is still quite limited in its nopython mode as only certain features in Python and NumPy are supported (see a full list here and here). Even when it is possible to make existing Python codes Numba-compatible, one often has to spend time refactoring them in certain ways to make it work.\nAcceleration with Cython # Another popular way of supercharging Python codes is to use Cython. Cython is a superset of Python that allows you to write (slightly modified) Python code with static type declarations and compile it into C code (hence the name). The C code can then be compiled into a Python extension module that can be imported and used in Python. The main advantage of Cython is that it allows you to write codes that resemble Python but at the same time you can use all the features and functions of C (e.g., pointers, structs, etc.) and also take advantage of the C compiler\u0026rsquo;s optimizations. One downside is that it is not as straightforward as Numba since you need to write the code in a different syntax and compilation is always needed before using it. The basic usage of Cython is well documented here. Basically, two steps are needed: (1) write the Cython source code in a .pyx file and (2) compile the .pyx file into a Python extension module. The compilation can be done in two ways: (1) using the cython command line tool or (2) using the cythonize() function in the setuptools package. The second method is more convenient when using with an associated setup.py with the following basic structure:\nfrom setuptools import setup, Extension from Cython.Build import cythonize setup( ... ext_modules = cythonize(Extension( \u0026#34;ising_cython\u0026#34;, sources=[\u0026#34;ising_cython.pyx\u0026#34;], include_dirs=[...], extra_compile_args=[...], extra_link_args=[...], ... )), ... ) Note that the Extension module is used in order to specify compiler options and use extra libraries. You can find the setup.py file used for this project here (inspired by Rajesh Singh\u0026rsquo;s work), where an additional check for OpenMP support is added. Cython comes with OpenMP support for parallel computing and to enable it, you need to supply '-fopenmp' as the argument in extra_compile_args and extra_link_args above. Within the Cython source code, you can use cython.parallel.prange() in place of range() for parallelizing loops. One thing to keep in mind is that the Global Interpreter Lock (GIL) must be released to use this kind of parallelism. One can release the GIL around a block of code using the with nogil: statement. Alternatively, one can specify nogil in a C function header to declare that it is safe to call without the GIL (but this does not guarantee that the function will be run with the GIL released):\ncdef void my_nogil_func(...) nogil: ... For our case, one good place to use parallelism is the outer loop of some nested loops. You can see more about parallelism in Cython here.\nIn addition to parallelism, there are other things one can do to make Cython faster. Two of the most frequently used function decorators to speed things up are @cython.boundscheck(False) (assuming no IndexErrors will be raised) and @cython.wraparound(False) (no negative indexing is used). However, you should make sure you know what they do and check your code carefully before using any of these. One pitfall I encountered as a newbie to C was the use of @cython.cdivision(True). I found that it did help speed things up quite a bit, but upon checking the computed energy and thermal expectations against the ones based on pure Python and Python with Numba, it led to some clearly incorrect results. It turns out that this is due to a different behavior of the operator % in Python and C. Unlike in Python where it represents a modulo operation, in C it is actually the reminder operation. For example, -10 % 3 = 2 in Python but doing the same in C leads to -1. To stick to the Pythonic behavior, I defined a separate function to perform the modulo operation in the cdivision mode:\n@cython.cdivision(True) cdef int mod(int a, int b) nogil: if a \u0026lt; 0: return a % b + b else: return a % b The other thing about cdivision is that it does not do floating point division automatically, i.e., int / int = int. So again, one should watch out for unexpected behaviors like this when using Cython. Two blog posts I came across that provide many useful tips for Cython usage are here and here. For a list of complier directives one can toggle please refer to this document.\nFinally you can find the full source code for my Cython implementation of the 2D Ising model simulation here.\nA few words about results # So how did the Metropolis algorithm do? I ran the simulation with equil_steps = 5000, mc_steps = 10000, skip_steps = 100 for four different system sizes, $L = [10, 20, 40, 80]$. The following plots show the thermal expectations of energy and magnetization as functions of the temperature (from 0.5 to 4.5 with 50 points in total). The red lines correspond to the exact results and the dashed line denotes the exact critical temperature. In the energy plot, the Monte Carlo results match the exact result pretty well, but the magnetization plot shows some more noticeable discrepancies. In both cases, we can see that generally as the system size increases, the Monte Carlo results match the exact results better due to the fact that the exact solutions are obtained in the limit $L\\to\\infty$. At the same time, at low temperatures, there are more points that deviate significantly from the exact results as the system size grows. This is due to the fact that the Metropolis algorithm is not very efficient at low temperatures since the acceptance rate is very low.\nThermal expectations of energy and magnetization as functions of temperature, based on the Metropolis Monte Carlo simulation of the 2D Ising model. We can also look at how the equilibrium spin configuration evolves with an increasing temperature. Here is an animation showing just that (for $L=80$). The behavior is consistent with the phase diagram of the 2D Ising model (also reflected in the magnetization plot above). At low temperatures, the spins tend to align in the same direction, while at high temperatures, they are randomly oriented, leading to an (almost) vanishing net magnetization.\nWhat about the speed? The following plot shows the time it takes (normalized to the time taken by pure Python) to run the full simulation (with the same parameters introduced above) for several different system sizes.\nThermal expectations of energy and magnetization as functions of temperature, based on the Metropolis Monte Carlo simulation of the 2D Ising model. Of course, this is by no means a rigorous benchmark for performance. But it does give us a rough idea of how much faster we can make the Metropolis Monte Carlo using Numba or Cython (50 - 250 times faster)! This is pretty important especially for larger systems when the absolute time used can be cut down significantly.\nReferences # K. Temme, T. J. Osborne, K. G. Vollbrecht, D. Poulin, and F. Verstraete, Quantum Metropolis sampling. Nature 471, 87 (2011).\nM.-H. Yung and A. Aspuru-Guzik, A quantum–quantum Metropolis algorithm. Proc. Natl. Acad. Sci. U.S.A. 109, 754 (2012).\nU. Wolff, Collective Monte Carlo Updating for Spin Systems. Phys. Rev. Lett. 62, 361 (1989).\n","date":"9 January 2023","permalink":"/blog/2d-ising-model/","section":"Blog","summary":"Okay, I\u0026rsquo;ll admit that this is neither a super exciting nor a new topic to write about.","title":"Supercharging the Pythonic Metropolis Monte Carlo"},{"content":"","date":"9 January 2023","permalink":"/tags/","section":"Tags","summary":"","title":"Tags"},{"content":" Comments widget by Utterances. I am adding a comments widget to my blog. Now you can comment under the blog posts whenever as long as you have a GitHub account. I\u0026rsquo;ve always wanted one for the sole purpose of encouraging interactions and discussions. Just a place where you (readers) can quickly jot down your thoughts/comments/questions. Hugo, which is the the framework this website is built on, ships with support for Disqus. I guess Disqus is fine for general uses, but I wanted something more lightweight, free of ads, and has Markdown support. Luckily I came across Utterances today. It\u0026rsquo;s an open-source comments widget that is built on GitHub Issues, developed by Jeremy Danyow (Thank you!). I like its simplistic aesthetics and even better, there are multiple (dark) themes you can choose from. Most importantly, it supports Markdown in the comments. I think it would be even better if there is LaTeX support in the future! The general setup is quite simple and I think the official guide is all you really need.\nWhile setting it up on my website (based on the Congo theme for Hugo) by directly following the instructions, I encountered two small problems. One is the positioning of the comments widget, which is centrally aligned by default but was just sitting a bit too far to the right in my current layout. My way of mitigating this is to add a \u0026lt;div\u0026gt; tag with a class attribute which I call comment to the comments.html file (placed under layouts/partials/), which contains the \u0026lt;script\u0026gt; tag for Utterances. Then inside custom.css (under assets/css/) I added the following:\n.comment { max-width: 60ch; margin-top: 3em; box-shadow: 0 0 5px #ccc; border-radius: 10px; } This places the comments widget in a position to my liking.\nThe other problem is related to where the comment widget shows up. By default, having the comments.html file in the layouts/partials/ directory will make the widget appear in any page with an index.md associated with it. This is not the behavior I want because ideally the comments section should be restricted to blog posts only. There is a simple way to add a knob for this in Congo. First, inside config/_default/params.toml, I added showComment = true under the [article] section. This allows us to have a theme parameter article.showComment that can be set to false if we want to hide the comments section in a particular page. Then to link this knob to the Utterances widget, I inserted {{ if .Params.showComment | default (.Site.Params.article.showComment | default true) }} at the beginning of comments.html.\nThis is what my final comments.html looks like:\n{{ if .Params.showComment | default (.Site.Params.article.showComment | default true) }} \u0026lt;div class=\u0026#34;comment\u0026#34;\u0026gt; \u0026lt;script src=\u0026#34;https://utteranc.es/client.js\u0026#34; repo=\u0026#34;ruihao-li/ruihao-li.github.io\u0026#34; issue-term=\u0026#34;pathname\u0026#34; label=\u0026#34;comment\u0026#34; theme=\u0026#34;gruvbox-dark\u0026#34; crossorigin=\u0026#34;anonymous\u0026#34; async\u0026gt; \u0026lt;/script\u0026gt; \u0026lt;/div\u0026gt; {{ end }} Update # I just updated Congo to v2.3.0 today (July 6, 2022) and it now comes with the showComments support. See the implementation in layouts/_default/single.html, which automatically solves both of my problems mentioned above. So if you are using Congo v2.3.0 and above, ignore everything I said above. To display the Utterances widget in your blog posts, simply provide the script in layouts/partials/comments.html and set the showComments parameter to true in your config/_default/params.toml file.\n","date":"3 July 2022","permalink":"/blog/blog-comments/","section":"Blog","summary":"Comments widget by Utterances.","title":"Adding blog comments"},{"content":"","date":"3 July 2022","permalink":"/tags/software/","section":"Tags","summary":"","title":"Software"},{"content":"","date":"26 June 2022","permalink":"/tags/quantum-computing/","section":"Tags","summary":"","title":"Quantum Computing"},{"content":" This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. Just a quick recap here: In the first post we set up the quantum system that we wanted to investigate using a 1-D tight-binding model, and we discussed how to utilize the Trotterization procedure to implement the time-evolution of the system on a gate-based quantum computer. In the second post, using the tools developed previously, we simulated the propagation of one particle excitation on a 1-D quantum chain with and without disorder on both a simulator and a real quantum computer. We saw the behavior of a quantum random walk when there is no disorder and Anderson localization when disorder is present. We emphasize that the tight-binding model that we have been working with so far does not include particle-particle interactions. So Anderson localization is really just a single-particle, i.e., non-interacting, effect. Then naturally we are prompted to ask the question of what happens when we do take interactions into account. This leads to the rich physics of many-body localization (MBL) that we will touch on in this post. Please feel free to check out part I and II before continuing.\nThermalization vs. Localization # To talk about many-body localization, it is beneficial to first introduce the concept of thermalization, or thermal equilibrium, following Ref. [1]. Thermalization in a closed classical system hinges on the powerful ergodic hypothesis, which states that over a long period of time all microstates of the system are accessed with equal probability. However, this notion of ergodicity does not directly apply to quantum systems. Here is a simple example to see why. Let us consider an isolated quantum many-body system with Hamiltonian \\(H\\). The generic initial non-equilibrium state \\(\\ket{\\psi(0)}\\) can be expanded over the basis of many-body eigenstates \\(\\ket{\\alpha}\\) as \\(\\ket{\\psi(0)} = \\sum_\\alpha A_\\alpha \\ket{\\alpha}\\). After the quantum evolution over an arbitrarily long time \\(t\\), the state becomes\n$$ \\ket{\\psi(t)} = e^{-iHt} \\ket{\\psi(0)} = \\sum_\\alpha A_\\alpha e^{-iE_\\alpha t} \\ket{\\alpha}, $$\nwhere \\(E_\\alpha\\) is the energy of the eigenstate \\(\\ket{\\alpha}\\). Then the probability of finding the system in a given eigenstate \\(\\ket{\\alpha}\\), \\(p_\\alpha = \\lvert A_\\alpha\\rvert^2\\), is set by the choice of the initial state and does not change over time. So unlike the classical case, the time evolution of a quantum system does not uniformly sample all states in the Hilbert space. Therefore, for quantum ergodicity, we should instead demand that starting from a generic initial state the system\u0026rsquo;s observables (few-body operators) settle to values given by the microcanonical ensembles at sufficiently long times. The infinite-time average of a physical observable \\(O\\) is given by\n$$ \\langle O \\rangle = \\lim_{T\\to\\infty} \\frac{1}{T}\\int_0^T dt\\ \\langle\\psi(t)\\vert O\\vert \\psi(t)\\rangle = \\sum_\\alpha p_\\alpha \\langle\\alpha\\vert O\\vert \\alpha\\rangle. $$\nSince \\(p_\\alpha\\) are fixed by the initial state, the natural way to ensure that an observable \\(O\\) reaches a thermal expectation value at long times for generic initial states is to assume that the expectation values in individual eigenstates \\(\\langle\\alpha\\vert O\\vert \\alpha\\rangle\\) agree with the microcanonical ensemble. This is the essence of the eigenstate thermalization hypothesis (ETH), which is an important concept in this subject. More precisely, the ETH states that in ergodic systems individual many-body eigenstates have thermal observables that are identical to microcanonical ensemble values at energy \\(E = E_\\alpha\\), i.e., \\(\\langle\\alpha\\vert O\\vert \\alpha\\rangle \\approx \\langle O\\rangle_\\text{mc}(E)\\). The microcanonical ensemble average can be written as\n$$ \\langle O\\rangle_\\text{mc}(E) = \\lim_{\\Delta E\\to 0}\\frac{1}{N(E, \\Delta E)}\\sum_{\\alpha: E_\\alpha\\in [E-\\Delta E, E+\\Delta E]} \\langle\\alpha\\vert O\\vert \\alpha\\rangle, $$\nwhere \\(N(E, \\Delta E)\\) is the number of eigenstates in the system that are within \\(\\Delta E\\) of energy \\(E\\).\nAfter a fairly long digression, rather than diving further into the glory details of the ETH and its implications, we will come back to, in some sense, the other end of the spectrum, MBL, which is known to violate the ETH and hence does not thermalize. Generally speaking, thermalization requires that different parts of ergodic systems exchange energy and particles, and consequently leads to conduction. On the other hand, localization leads to the absence of diffusion, suppressing transport. We have seen the example of Anderson localization, where a disorder potential can completely change the nature of single-particle eigenstates in a non-interacting system. However, interactions between particles are inevitable in realistic systems. It is conceivable that interactions may open up new transport channels, e.g., a high-energy localized state may decay to produce excitations at lower energies, potentially restoring transport. Therefore, to understand the fate of localization in the presence of particle interaction is not a trivial problem. In particular, Basko, Aleiner, and Altshuler (BAA) first studied the stability of the Anderson insulator against short-ranged interactions and concluded that the interacting model enters a localized phase termed the MBL phase in arbitrary dimensions below a certain critical temperature [2]. Later, by studying a 1-D disordered fermionic chain, it was pointed out that the MBL phase can persist even at infinite temperature [3]. More recent developments however challenged the conclusion of BAA. It was argued that in high dimensions \\(d\u0026gt;1\\) small thermal inclusions can trigger avalanches in the system that destroy the MBL phase [4, 5]. The reconciliation of these two results is still an open problem.\nThe Heisenberg model # Following the history of this field, the introduction of the fermionic and spin-chain lattice models has definitely opened the door to studying many interesting properties of MBL in (classical) numerical simulations. This is exactly the system we have built up in the previous parts of the Challenge. Here we will do something different from the setup in the original IBM Challenge Problem 3. On top of the tight-binding model used to study Anderson localization in part II, we will add an additional \\(ZZ\\)-interaction term. So the tight-binding Hamiltonian is given by\n\\begin{equation} H_\\text{tb}/\\hbar = J\\sum_{i=0}^{n-2} (X_i X_{i+1} + Y_i Y_{i+1}) + U \\sum_{i=0}^{n-2} Z_i Z_{i+1} +\\sum_{i=0}^{n-2}\\epsilon_i Z_i,\\quad \\end{equation}\nwhere \\(n\\) is the number of sites in the 1-D chain. Readers with a condensed matter physics background may recognize that this is exactly the so-called Heisenberg XXZ model. In fact, the Heisenberg model has become the paradigmatic model for studying MBL physics (among many other phenomena). The reason for the additional term should be obvious by doing the Jordan-Wigner transformation, which maps the spin-chain Hamiltonian above to a spinless fermionic chain in the second-quantization form given by\n$$ H_\\text{tb}/\\hbar = J\\sum_{i=0}^{n-2} (c_i^\\dag c_{i+1} + \\text{h.c.}) + U \\sum_{i=0}^{n-2} n_i n_{i+1} + \\sum_{i=0}^{n-2} \\epsilon_i n_i, $$\nwhere \\(n_i \\equiv c_i^\\dag c_i\\) is the density operator for site \\(i\\). Hence, we see that the additional \\(U\\)-term gives rise to the two-body interaction between neighboring sites. Without it, the tight-binding model is a free-fermion model, which is suited for the study of Anderson localization but not many-body localization. So here we will simulate the MBL phase in a disordered Heisenberg XXZ spin chain. We will again set \\(J = 1\\) and the model thus has two free parameters: the interaction strength \\(U\\) and the disorder strength \\(W\\). Recall that \\(W\\) controls the onsite potentials through the Aubry-Andre model, \\(\\epsilon_i = W\\cos(2\\pi\\beta i)\\), with \\(\\beta\\) being related to the quasicrystal periodicity.\nOne interesting aspect of the 1-D Heisenberg XXZ model is its phase diagram. In the limit \\(U\\to 0\\) with some finite \\(W\\), i.e., when there is no interaction, this model is equivalent to free fermions moving in a disordered potential and therefore, the states are Anderson localized. Turning on the interaction will result in the MBL phase. Furthermore, for fixed and not very strong disorder (\\(W/U \\sim 1\\)), it was found that tuning the interaction strength \\(U\\) above some critical value \\(U^\\ast\\) will lead to delocalization. On the other hand, if we fix \\(U\\) and increase the disorder strength \\(W\\), we will see a transition from a delocalized (thermal) phase to the MBL phase when \\(W\\) goes above a critical value \\(W^\\ast\\). Therefore, in 1-D interacting systems there exists a metal-insulator transition, which is distinct from non-interacting systems that always Anderson localize in the thermodynamic limit, as mentioned in the previous post. A schematic illustrating the phase diagram of the XXZ spin chain is shown below.\nPhase diagram of Heisenberg XXZ spin chain as a function of interaction (top) and disorder strength (bottom). Here Jz denotes the interaction strength, equivalent to U in our formalism. Figure taken from Ref. [1]. Putting things into action # Okay, enough theory. Let\u0026rsquo;s actually build the quantum circuit for the Heisenberg model and simulate its dynamics. In this case, we will simulate three particles in a 12-site spin chain, where particle excitations are represented by \\(\\ket{1}\\) and empty sites represented by \\(\\ket{0}\\). Like before, to better visualize (de)localization, we would like to track the probability of each site being in the \\(\\ket{1}\\) state over the course of the entire Trotterized time evolution. In addition, we also keep track of two other quantities. One is the imbalance, which is one of the signatures of the breakdown of thermalization. The system imbalance is defined as\n$$ \\mathcal I = \\Bigg\\langle \\frac{N_e - N_o}{N_e + N_o} \\Bigg\\rangle, $$\nwhere \\(N_e\\) and \\(N_o\\) are the populations at the even and odd sites of the system, respectively, and the expectation value is defined with respect to a particular quantum state, i.e. \\(\\langle \\cdots \\rangle = \\langle \\psi \\lvert \\cdots \\rvert \\psi \\rangle\\). In a thermalized system, we expect each site of the lattice to be occupied by the same average number of particles after reaching steady state. Therefore, the imbalance is close to zero. However, when localization happens, we should expect a deviation from zero. Here we define a function that calculates the imbalance for a given state:\ndef get_imbalance(state): \u0026#34;\u0026#34;\u0026#34; Calculate the imbalance of a state. Args: state (qiskit.quantum_info.Statevector): The state vector. Returns: imbalance_val (float): The imbalance of the state. \u0026#34;\u0026#34;\u0026#34; imbalance_val = 0 state_dict = state.to_dict() for basis, amp in state_dict.items(): Ne, No = 0, 0 # Make sure to skip calculating the |00...0\u0026gt; state for i in range(len(basis)): if i % 2 == 0 and basis[i] == \u0026#39;1\u0026#39;: Ne += 1 elif i % 2 == 1 and basis[i] == \u0026#39;1\u0026#39;: No += 1 if Ne + No != 0: imbalance_val += np.abs(amp)**2 * (Ne - No) / (Ne + No) return imbalance_val The other quantity to probe is the entanglement entropy formed in the lattice as a result of particle propagation. One can imagine that while the created particle excitations are initially separable from the the rest of the lattice, their propagation will lead to the creation and distribution of entanglement throughout the lattice. For simplicity, we will only keep track of the entanglement entropy of part of the system, say the first lattice site. This can be quantified by its von Neumann entropy, which is defined as\n$$ \\mathcal S_\\text{vn}(\\rho_A) = -\\text{tr}(\\rho_A \\ln\\rho_A), $$\nwhere \\(A\\) refers to the subsystem of interest (i.e., the first lattice site), and \\(\\rho_A = \\text{tr}_{B}\\rho\\) is the reduced density matrix of the subsystem \\(A\\) after \u0026ldquo;tracing out\u0026rdquo; the rest of the system which we call \\(B\\). If the subsytem \\(A\\) is fully entangled with the rest of the system, \\(\\mathcal S _\\text{vn}(\\rho_A) = \\ln 2\\), whereas if the subsytem is completely separable with respect to the rest, \\(\\mathcal S _\\text{vn}(\\rho_A) = 0\\). One can probe entanglement at a larger scale by using more sophisticated measures such as the concurrences and global entanglement, but we will not pursue these here.\nLet us now get straight into the simulation. Some necessary imports here:\nimport numpy as np import matplotlib.pyplot as plt from qiskit import QuantumCircuit, QuantumRegister, transpile, Aer from qiskit.circuit import Parameter, Instruction import qiskit.quantum_info as qi from tqdm.notebook import tqdm Similar to what was done in part I, we will first define the Trotterized quantum circuit for MBL based on the tight-binding Hamiltonian Eq. (1) above.\ndef Trot_qc_mbl(num_qubits, t, J, deltas): \u0026#34;\u0026#34;\u0026#34; Creates the Trotterized quantum circuit at a given time for the 1-D Heisenberg XXZ model. Args: num_qubits (int): The number of qubits in the circuit. t (Parameter): time. J (Parameter): The interaction strength. deltas (List[Parameter]): The list of the disorder parameters. Returns: qiskit.circuit.QuantumCircuit: The Trotterized quantum circuit. \u0026#34;\u0026#34;\u0026#34; def ZZ_gate(J, t): ZZ_qr = QuantumRegister(2) ZZ_qc = QuantumCircuit(ZZ_qr, name=\u0026#39;ZZ\u0026#39;) ZZ_qc.cnot(0,1) ZZ_qc.rz(2 * J * t, 1) ZZ_qc.cnot(0,1) # Convert custom quantum circuit into a gate ZZ = ZZ_qc.to_instruction() return ZZ def XX_gate(t): XX_qr = QuantumRegister(2) XX_qc = QuantumCircuit(XX_qr, name=\u0026#39;XX\u0026#39;) XX_qc.ry(np.pi/2, [0,1]) XX_qc.append(ZZ_gate(1, t), [0,1]) XX_qc.ry(-np.pi/2, [0,1]) XX = XX_qc.to_instruction() return XX def YY_gate(t): YY_qr = QuantumRegister(2) YY_qc = QuantumCircuit(YY_qr, name=\u0026#39;YY\u0026#39;) YY_qc.rx(-np.pi/2, [0,1]) YY_qc.append(ZZ_gate(1, t), [0,1]) YY_qc.rx(np.pi/2, [0,1]) YY = YY_qc.to_instruction() return YY Trot_qr = QuantumRegister(num_qubits) qc = QuantumCircuit(Trot_qr, name=\u0026#39;Trot\u0026#39;) for i in range(num_qubits - 1): qc.append(XX_gate(t), [Trot_qr[i], Trot_qr[i+1]]) qc.append(YY_gate(t), [Trot_qr[i], Trot_qr[i+1]]) qc.append(ZZ_gate(J, t), [Trot_qr[i], Trot_qr[i+1]]) for i in range(num_qubits): qc.rz(2 * deltas[i] * t, i) return qc Next we define the function that records the Trotterized circuits at all time steps. Note that we will start with 3 particle excitations at sties 0, 4, and 8.\ndef U_trot_circuits_mbl(delta_t, trotter_steps, num_qubits, U, W, beta): \u0026#34;\u0026#34;\u0026#34; Record a list of Trotterized quantum circuits for many body localization at all Trotter steps. Args: delta_t (float): Duration of individual time steps. trotter_steps (array): Array of intermediate times. num_qubits (int): The total number of qubits. U (float): The interaction strength. W (float): The disorder strength. beta (float): The quasicrystal periodicity of the AA model. Returns: disorder_circuits (list): List of Trotterized quantum circuits for MBL. \u0026#34;\u0026#34;\u0026#34; t = Parameter(\u0026#39;t\u0026#39;) J = Parameter(\u0026#39;J\u0026#39;) deltas = [Parameter(\u0026#39;delta_{:d}\u0026#39;.format(idx)) for idx in range(num_qubits)] AA_pattern = np.cos(2*np.pi*beta*np.arange(num_qubits)) disorders = W * AA_pattern mbl_circuits = [] for n_steps in trotter_steps: qr = QuantumRegister(num_qubits) cr = ClassicalRegister(num_qubits) qc = QuantumCircuit(qr, cr) qc.x([0, 4, 8]) # three particle excitations for _ in range(n_steps): qc.append(Trot_qc_mbl(num_qubits, t, J, deltas), qr) qc = qc.bind_parameters({t: delta_t}) qc = qc.bind_parameters({deltas[idx]: disorders[idx] for idx in range(num_qubits)}) qc = qc.bind_parameters({J: U}) mbl_circuits.append(qc) return mbl_circuits We first fix the value of the interaction strength \\(U = 1.0\\) and simulate the system at four different values of disorder strength \\(W = [0.2,\\ 2,\\ 4,\\ 8]\\).\ndelta_t = 0.15 trotter_steps = np.arange(1, 25, 1) num_qubits = 12 U = 1.0 beta = (np.sqrt(5)-1)/2 circuits = {} Ws = [0.2, 2, 4, 8] for W in Ws: circuits[W] = U_trot_circuits_mbl( delta_t=delta_t, trotter_steps=trotter_steps, num_qubits=num_qubits, U=U, W=W, beta=beta ) We can then simulate these Trotterized circuits on Qiskit\u0026rsquo;s statevector_simulator backend and track the time evolution of the probability of finding a particle for all the lattice sites, the imbalance of the system, and the von Neumann entropy of the first site:\nbackend_sim = Aer.get_backend(\u0026#39;statevector_simulator\u0026#39;) probability_densities = {} state_vector_imbalances = {} vn_entropies = {} for W in tqdm(Ws): probability_densities[W] = [] state_vector_imbalances[W] = [] vn_entropies[W] = [] for circ in circuits[W]: transpiled_circ = transpile(circ, backend_sim, optimization_level=3) job_sim = backend_sim.run(transpiled_circ) # Grab the results from the job. result_sim = job_sim.result() outputstate = result_sim.get_statevector(transpiled_circ, decimals=6) # extract the probability densities ps = [] for idx in range(num_qubits): ps.append(np.abs(qi.partial_trace(outputstate, [i for i in range(num_qubits) if i!=idx]))[1,1]**2) # extract the density matrix of qubit 0 by tracing out all other qubits entropy = 0 rho_0 = qi.partial_trace(outputstate, range(1, num_qubits)) entropy += qi.entropy(rho_0, base=np.exp(1)) # calculate the imbalance of the system imbalance = 0 imbalance += get_imbalance(outputstate) vn_entropies[W].append(entropy) probability_densities[W].append(ps) state_vector_imbalances[W].append(imbalance) Below we show the results of this simulation. First is the probability densities at different disorder strengths.\nWe see that with weak disorder the system is delocalized but as \\(W\\) increases, MBL kicks in and the particles are localized around their initial positions over time. Next we look at the imbalance as a function of time.\nAgain, as expected, when \\(W\\) is small, the system tends to thermalize and the average imbalance is close to 0. But at strong disorder, we see a large deviation from 0, indicated by the green and red curves in the plot. Finally, here is the result of the von Neumann entropy.\nWe see the average entanglement entropy over time decreases as the disorder strength increases since the system is transitioning into the MBL phase.\nAs the final simulation, we will fix the disorder strength \\(W = 3.5\\) and vary the interaction strength \\(U = [0.2,\\ 1,\\ 3,\\ 5]\\) to see how the behavior of the system changes. The execution is similar to the one above, so I won\u0026rsquo;t bore you with basically the same codes again. Let us directly look at the results.\nProbability densities at different interaction strengths. Evolution of the imbalance at different interaction strengths. Evolution of the von Neumann entropy of site 0 at different interaction strengths. Based on the phase diagram discussed in the previous section, we expect that the system will transition from MBL to delocalization as \\(U\\) increases, when the disorder is not very strong. This can be observed in the probability densities, where the sign of delocalization can be seen starting from \\(U = 3\\), especially on the first qubit. This is also supported by considering the average imbalance and entanglement entropy at different interaction strengths. Although it is not as clear as the previous case with a fixed \\(U\\) and varying \\(W\\), we can still see that overall the magnitude of imbalance is smaller when the system becomes delocalized (i.e., with larger \\(U\\)), while the entanglement entropy gets larger. These simulation results agree with the theoretical expectations.\nConclusion # Here we conclude the quantum simulations of many-body localization as well as the blogging about the IBM Quantum Spring Challenge 2022 as a whole. We have explored parts of the phase diagram of a 1-D disordered Heisenberg XXZ chain. We saw the somewhat competing effect between particle interaction and disorder, leading to transition between thermal and MBL phases. Our quantum simulations have successfully captured some of the key features of this phase diagram. However, it is fair to say that the simulations showcased here barely scratch the surface of the fascinating physics of MBL and non-equilibrium quantum systems as a whole. There are other profound topics of the MBL systems which we did not touch upon and some of them are under active investigation, including the emergent integrability and even a whole new class of MBL-protected phases of matter.\nWith that, I want to thank you for taking the time to follow along and I hope you enjoyed this journey into quantum simulations of many-body physics as much as I did!\nReferences # D. A. Abanin, E. Altman, I. Bloch, and M. Serbyn, Colloquium: Many-body localization, thermalization, and entanglement. Rev. Mod. Phys. 91, 021001 (2019).\nB. Basko, A. Aleiner, and A. Altshuler, Metal-insulator transition in a weakly interacting many-electron system with localized single-particle states. Ann. Phys. 321, 1126 (2006).\nV. Oganesyan and D. V. Huse, Localization of interacting fermions at high temperature. Phys. Rev. B 75, 155111 (2007).\nW. De Roeck and F. Huveneers, Stability and instability towards delocalization in many-body localization systems. Phys. Rev. B 95, 155129 (2017).\nD. J. Luitz, F. Huveneers, and W. De Roeck, How a Small Quantum Bath Can Thermalize Long Localized Chains. Phys. Rev. Lett. 119. 150602 (2017).\n","date":"26 June 2022","permalink":"/blog/ibm-spring-challenge-3/","section":"Blog","summary":"This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics.","title":"Quantum simulation of many-body physics - III"},{"content":"As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. In this post, we want to address the question of how a particle such as an electron, propagates through an intrinsically quantum system, i.e., the 1-D quantum chain that we built previously. Remember everything we discussed so far has not taken into account disorder that is generally present in realistic condensed matter systems. Disorder is something that generically breaks some symmetries of the system Hamiltonian and/or leads to deviations from the lattice periodicity. When disorder is present, all the sites in a lattice are no longer equivalent. So another question naturally arises: how would disorder affect the quantum transport? The exploration of this general question has led to wonderful discoveries of various localization effects in disordered systems. Here we will touch on one of them, Anderson localization, which was first discovered by the great physicist Philip W. Anderson in 1958 [1]. One interesting thing to note is that the dimensionality of a system has a direct impact on Anderson localization. For example, according to the scaling theory of localization [2], in 1- and 2-D, a system will be a perfect insulator in the thermodynamic limit (simply put, when the system size is taken to infinity). Therefore, Anderson localization must happen in one- and two-dimensional disordered systems regardless of the disorder strength! However, in 3-D, Anderson localization is a critical phenomenon where the system undergoes a metal-insulator transition (MIT). This means that localization happens only when the disorder strength exceeds a certain threshold. Even though this is certainly one of the most interesting aspects of Anderson localization, we will not explore it here for the sake of simplicity. We will again stick to the 1-D system as in the previous post.\nQuantum random walk # Classical random walk is a random process that is prevalent in many phenomena in nature, such as the motion of macroscopic particles in liquids and gases known as Brownian motion and even the price of a fluctuating stock. In the most rudimentary version of a symmetric classical random walk on a lattice, at each time step, the probabilities of the particle jumping to any of the neighboring sites are the same. In 1-D, this means that the particle can move one site to the left or right with equal probability (50%) each time. A well-established result for a symmetric random walk is that in the continuous-time limit, the probability of finding the particle at time \\(t\\) at position \\(r\\) (from the origin) follows a Gaussian distribution:\n$$ P_\\text{classical}(r, t) = \\frac{1}{\\sqrt{2\\pi t}} e^{-r^2/2t}, $$\nwhere we have assumed the distance of each jump to be 1. Therefore, the standard deviation of this probability distribution scales as \\(\\sigma_\\text{classical}\\propto \\sqrt{t}\\). Since \\(\\langle r \\rangle = 0\\), this suggests that the mean-square-root displacement of the particle, which quantifies the spatial propagation of the particle relative to the origin, also scales diffusively with time as \\(\\sqrt{\\langle r^2\\rangle} \\propto \\sqrt{t}\\).\nSince we are interested in particle propagation in a quantum system, we will need to deal with quantum random walks instead. In this case, the intrinsic quantum nature including superposition and interferences among different wavefunctions will lead to a qualitative difference from the classical counterpart. Here is a somewhat intuitive way to think about the difference between them. Imagine a \u0026ldquo;classical walker\u0026rdquo; who decides whether to step left or right by tossing a coin with two possible outcomes \\(+\\) and \\(-\\), with probabilities \\(P_+\\) and \\(P_-\\), respectively. After each toss, they would look at the result and decide which way to go. So the classical random walk traces a single path within a decision tree. In contrast, a \u0026ldquo;quantum walker\u0026rdquo; flips their coin but never looks at the outcome. Instead, at each step, they step simultaneously to the left and right with some complex amplitudes \\(A_+\\) and \\(A_-\\) corresponding to probabilities \\(P_+ = \\lvert A_+\\rvert^2\\) and \\(P_- = \\lvert A_-\\rvert^2\\). After many iterations the quantum random walk results in an extended wavefunction of the quantum walker that spreads out to all positions in the tree with finite amplitudes. What\u0026rsquo;s more incredible is that these complex amplitudes at different sites add up for any given path and depending on the phase differences, this creates constructive or destructive interferences when measuring the probabilities at the end. A diagram illustrating the ideas above is shown below (taken from [3]).\nDue to the critical differences highlighted above, it can be shown that a symmetric quantum random walk in the continuous-time limit will lead to a probability distribution that follows a Bessel function of the first kind [4]:\n$$ P_\\text{quantum}(r, t) = \\lvert J_r(2t) \\rvert^2. $$\nBelow is a visualization of the two probability distributions for continuous-time classical and quantum random walks:\nMoreover, a quantum random walk exhibits ballistic propagation with the mean-square-root displacement scaling linearly with time, \\(\\sqrt{\\langle r^2\\rangle} \\propto t\\). The quadratic speed-up of quantum random walks versus classical random walks is analogous to the quadratic speed-up of the Grover search algorithm compared to a classical search!\nSimulating a quantum random walk # Let us now simulate the quantum random walk on a 1-D tight-binding chain to see if the result matches the theory prediction above. We will first do this on a simulator and then on a real quantum computer. For this simulation, we consider a 5-site tight-binding lattice whose Hamiltonian is given by\n$$ H_\\text{tb}/\\hbar = J\\sum_{i=0}^3(X_i X_{i+1} + Y_i Y_{i+1}). $$\nAgain, we have set the on-site potentials to be zero to simulate a clean system without disorder and will use \\(J = 1\\) from here onwards [cf. Eq. (2) in part I]. Recall that to simulate the dynamics of a quantum system on a gate-based quantum computer, we employ the Trotterization process to discretize the continuous time evolution. Therefore, we use the Trot_qc function established in part I to build the Trotterized quantum circuit for this 5-site system at any given time. Next, we want to add a particle in the form of an excitation to site 0, i.e., qubit 0. This is done by apply an \\(X\\) gate to flip the qubit from \\(\\ket{0}\\) state to \\(\\ket{1}\\) state. We modify the U_trot_tb function in the previous part slightly to record the Trotterized circuits at all Trotter (time) steps over a given simulation time:\ndef U_trot_circuits(delta_t, trotter_steps, num_qubits): \u0026#34;\u0026#34;\u0026#34; Record a list of Trotterized circuits at all Trotter steps separated by delta_t. Args: delta_t (float): Duration of individual time steps. trotter_steps (array): Array of intermediate time steps. num_qubits (int): The total number of qubits. Returns: circuits (list): A list of Trotterized quantum circuits. \u0026#34;\u0026#34;\u0026#34; t = Parameter(\u0026#34;t\u0026#34;) circuits = [] for n_steps in trotter_steps: qr = QuantumRegister(num_qubits) cr = ClassicalRegister(num_qubits) qc = QuantumCircuit(qr, cr) qc.x(0) # Add an excitation to site 0 for _ in range(n_steps): qc.append(Trot_qc(num_qubits, t).to_instruction(), qr) qc = qc.bind_parameters({t: delta_t}) circuits.append(qc) return circuits We can now track the propagation of the particle by keeping track of the probability of finding it on each qubit at different time steps. To simulate this process with a simulator, we will make use of the statevector_simulator backend in Qiskit\u0026rsquo;s Aer module. For this, we make some additional imports here.\nfrom qiskit import transpile, Aer, IBMQ, execute from copy import deepcopy Here we define a function that extracts the probabilities of each qubit being in the \\(\\ket{1}\\) state at different times using the output state from the statevector_simulator.\ndef probability_density(delta_t, trotter_steps, num_qubits): \u0026#34;\u0026#34;\u0026#34; Calculate the probabilities of finding the excitation on each qubit at different time steps. Args: delta_t (float): Duration of individual time steps. trotter_steps (array): Array of intermediate times. num_qubits (int): The total number of qubits. Returns: probability_density (array): The probability density of the excitation at all Trotter steps. \u0026#34;\u0026#34;\u0026#34; backend_sim = Aer.get_backend(\u0026#39;statevector_simulator\u0026#39;) circuits = U_trot_circuits(delta_t, trotter_steps, num_qubits) probability_density=[] for circ in circuits: transpiled_circ=transpile(circ, backend_sim, optimization_level=3) job_sim = backend_sim.run(transpiled_circ) # Grab the results from the job. result_sim = job_sim.result() outputstate = result_sim.get_statevector(transpiled_circ, decimals=5) ps = [] # Extract the probability of finding the excitation on each qubit. # (e.g. for 5 qubits, we need \u0026#34;00001\u0026#34;, \u0026#34;00010\u0026#34;, \u0026#34;00100\u0026#34;, \u0026#34;01000\u0026#34;, \u0026#34;10000\u0026#34;) for i in range(num_qubits): ps.append(np.abs(outputstate[2**i])**2) probability_density.append(ps) probability_density = np.array(probability_density) return probability_density It\u0026rsquo;s time to simulate the quantum random walk on the 5-site tight-binding lattice and see the results. We choose to evolve the system over 25 steps with a step size of 0.15 for this simulation. We can visualize the results by running the following code,\ndelta_t = 0.15 trotter_steps = np.arange(1, 25, 1) num_qubits = 5 prob_density = probability_density(delta_t, trotter_steps, num_qubits) prob_max, prob_min = np.max(prob_density), np.min(prob_density) plt.figure(figsize=(5,5), facecolor=\u0026#39;white\u0026#39;) plt.pcolormesh(np.arange(0, num_qubits,1), trotter_steps*delta_t, prob_density, vmin=prob_min, vmax=prob_max) plt.colorbar() plt.xlabel(\u0026#39;Qubit index\u0026#39;) plt.ylabel(\u0026#39;Time (1/J)\u0026#39;) plt.savefig(\u0026#34;probs_qwr.svg\u0026#34;) which produces the plot below:\nThis result is pretty nice as it shows that the particle excitation traverses the lattice and eventually reflects off the opposite end of the 1-D chain. In principle, the quantum random walk propagates in both directions for all the interim sites. However, quantum interferences among these multiple trajectories alter the particle wavepacket as it evolves in time, leading to the unidirectional transport seen above. Furthermore, it is evident that the displacement of the excitation scales linearly with time, agreeing well with the prediction of quantum random walks.\nPerforming the same simulation on a real quantum computer is slightly different. Here we can no longer retrieve the statevectors directly from the outputs. Instead, at each time step we will need to send the circuit to the quantum computer many times (specified by the number of shots) for execution and extract the probabilities based on the output statistics. During the Challenge, we were given the access to one of IBM\u0026rsquo;s 7-qubit systems ibm_nairobi. We can perform the simulation by calling the following function:\ndef probability_density_exp(delta_t, trotter_steps, num_qubits, shots): # Load your IBM Quantum account IBMQ.load_account() # Get the backend provider = IBMQ.get_provider(hub=\u0026lt;hub_name\u0026gt;, group=\u0026lt;group_name\u0026gt;, project=\u0026lt;project_name\u0026gt;) backend = provider.get_backend(\u0026#39;ibm_nairobi\u0026#39;) # Create transpiled circuits for hardware execution initial_layout = [0 , 1 , 3 , 5 , 4] # Specific to ibm_nairobi topology hardware_transpiled_circuits = [] for circ in U_trot_circuits(delta_t, trotter_steps, num_qubits): hardware_circ = deepcopy(circ) hardware_circ.measure(range(num_qubits), range(num_qubits)) hardware_transpiled_circuits.append( transpile(hardware_circ, backend, initial_layout=initial_layout, optimization_level=3) ) # Run the circuits job = execute(hardware_transpiled_circuits, backend=backend, shots=shots) exp_results = job.result() probability_density_exp = [] for output in exp_results.get_counts(): ps = [] # Extract the probabilities keys = [\u0026#39;00001\u0026#39;, \u0026#39;00010\u0026#39;, \u0026#39;00100\u0026#39;, \u0026#39;01000\u0026#39;, \u0026#39;10000\u0026#39;] for key in keys: if key in output: ps.append(output[key]/shots) else: ps.append(0.) probability_density_exp.append(ps) return probability_density_exp Below is the result for one of the simulations on the hardware.\nComparing this with the result above from the simulator, despite the similarity, the effect of noise and decoherence (especially at later times) on a real quantum hardware is apparent!\nAnderson localization # Finally, we are coming to Anderson localization. As mentioned before, Anderson localization always happens in 1-D systems when disorder is present. Lattice inhomogeneity causes scattering and leads to quantum interference that tends to inhibit particle propagation, a signature of localization. The wavefunction of a localized particle rapidly decays away from its initial position, effectively confining the particle to a small region of the lattice. This localization phenomenon is a direct consequence of interference between different paths arising from multiple scatterings of the electron by lattice defects. To study this phenomenon, we add back the inhomogeneous on-site potentials to the Hamiltonian, thereby making the lattice sites inequivalent, i.e.,\n$$ H_\\text{tb}/\\hbar = J\\sum_{i=0}^3(X_i X_{i+1} + Y_i Y_{i+1}) + \\sum_{i=0}^3\\epsilon_i Z_i. $$\nOne simple way to model disorder within the tight-binding system is through the Aubry-Andre (AA) model, where the disorder is replaced by a periodic modulation of the on-site energies, with a spatial period incommensurate with the lattice period. The AA potential is modeled as \\(\\epsilon_i = W\\cos(2\\pi\\beta i)\\), where \\(\\beta\\) determines the quasicrystal periodicity and \\(W\\) is the disorder strength. Moreover, with the addition of the on-site terms, we also need to modify the Trotterized circuit. Note that exponentiating the \\(Z_i\\) gates for the time-evolution unitary simply leads to \\(R_{Z_i}\\) gates acting on individual qubits. So we can define a Trot_qc_disorder circuit based on the Trot_qc circuit from part 1:\ndef Trot_qc_disorder(num_qubits, t, deltas): \u0026#34;\u0026#34;\u0026#34; Generate a Trotterized quantum circuit with disorder. Args: num_qubits (int): The total number of qubits. t (Parameter): The time parameter. deltas (list(Parameter)): The list of disorder parameters. Returns: qiskit.QuantumCircuit: The Trotterized quantum circuit with disorder. \u0026#34;\u0026#34;\u0026#34; Trot_qr_disorder = QuantumRegister(num_qubits) Trot_qc_disorder = QuantumCircuit(Trot_qr_disorder, name=\u0026#39;Trot disorder\u0026#39;) Trot_gate = Trot_qc(num_qubits, t).to_instruction() Trot_qc_disorder.append(Trot_gate, Trot_qr_disorder) for i in range(num_qubits): Trot_qc_disorder.rz(2 * deltas[i] * t, i) return Trot_qc_disorder Let us then define a function that records the Trotterized circuits with finite disorder at all Trotter (time) steps:\ndef U_trot_circuits_disorder(delta_t, trotter_steps, num_qubits, W, beta): \u0026#34;\u0026#34;\u0026#34; Record a list of Trotterized quantum circuits with disorder at all Trotter steps. Args: delta_t (float): Duration of individual time steps. trotter_steps (array): Array of intermediate times. num_qubits (int): The total number of qubits. W (float): The disorder strength. beta (float): The quasicrystal periodicity of the AA model. Returns: disorder_circuits (list): List of Trotterized quantum circuits with disorder. \u0026#34;\u0026#34;\u0026#34; t = Parameter(\u0026#39;t\u0026#39;) deltas = [Parameter(\u0026#39;delta_{:d}\u0026#39;.format(idx)) for idx in range(num_qubits)] AA_pattern = np.cos(2*np.pi*beta*np.arange(num_qubits)) disorders = W * AA_pattern disorder_circuits = [] for n_steps in trotter_steps: qr = QuantumRegister(num_qubits) cr = ClassicalRegister(num_qubits) qc = QuantumCircuit(qr, cr) qc.x(0) for _ in range(n_steps): qc.append(Trot_qc_disorder(num_qubits, t, deltas), qr) qc = qc.bind_parameters({t: delta_t}) qc = qc.bind_parameters({deltas[idx]: disorders[idx] for idx in range(num_qubits)}) disorder_circuits.append(qc) return disorder_circuits Like in the previous section, we will simulate the particle propagation with disorder on a simulator. Here is how it looks like:\nComparing with the quantum random walk result, it is clear that in the presence of the AA disorder, the particle tends to be localized in its initial position (qubit 0) as time evolves. So we successfully see the effect of Anderson localization in this 1-D system! Again, running the same simulation on a quantum computer we see a degradation in quality of the results due to noise, but we can still reach the same conclusion in this case:\nConclusion # It\u0026rsquo;s been a long post to get to this point, but just to conclude, we have successfully simulated the particle propagation in a 1-D quantum chain with and without disorder on both a simulator and a real quantum computer provided by IBM. In the case of no disorder, we saw behaviors of a quantum random walk, while is distinct from a classical random walk. In the presence of disorder, we saw the effect of Anderson localization, i.e., the particle tends to localize in its initial position over time. In the next and final post of this series, we will look into a more complex example of localization beyond the single-particle picture we have been adhering to so far, that is, many-body localization. The question there is: does localization still happen when we take into account particle interactions? See you in the next one!\nReferences # P. W. Anderson, Absence of Diffusion in Certain Random Lattices. Phys. Rev. 109, 1492 (1958).\nE. Abrahams, P. W. Anderson, D. C. Licciardello, and T. V. Ramakrishnan, Scaling Theory of Localization: Absence of Quantum Diffusion in Two Dimensions. Phys. Rev. Lett. 42, 673 (1979).\nK. Manouchehri and J. B. Wang, Solid State Implementation of Quantum Random Walks on General Graphs. AIP Conf. Proc. 1074, 56 (2008).\nJ.Kempe, Quantum random walks - an introductory overview. arXiv:quant-ph/0303081 (2003).\n","date":"18 June 2022","permalink":"/blog/ibm-spring-challenge-2/","section":"Blog","summary":"As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers.","title":"Quantum simulation of many-body physics - II"},{"content":"A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. In these problems, we investigated a well-known phenomenon (to the condensed matter physics community, of course) called Anderson localization and one called many-body localization, which I happened to gain some exposure to during the MAGLAB Theory Winter School earlier this year and is still an active topic of research. The majority of this Challenge was about introducing and reproducing some of the results from this nicely written quantum transport paper by Karamlou et al. I will split the full discussion into three parts. This blog post will cover the first part, where we will set up the framework for investigating many-body physics on a quantum computer. This includes building the tight-binding model for a 1-D quantum chain and using Trotterization for simulating dynamics of the quantum states.\nThe other topic of the Quantum Challenge was quantum chemistry calculations with the variational quantum eigensolver (VQE), which I do not intend to discuss this time. Interested readers are encouraged to take a look at the original announcement linked above for more details. Here is the official Github repository if you want to have a go at the challenge problems. Without further ado, let us begin our discussion.\nTight-binding model of a quantum chain # The tight-binding model would be the building block for studying the many-body physics that will be discussed throughout this post. In layman\u0026rsquo;s terms, the tight-binding model describes a solid-state system where most electrons are \u0026ldquo;tightly bound\u0026rdquo; to their nuclei, which sit at the fixed lattice sites. Only a few valence electrons are loosely bound and therefore can \u0026ldquo;hop\u0026rdquo; to the neighboring sites. This hopping action is what leads to an extended Bloch wavefunction, which is the electron wavefunction in the presence of a period lattice potential. The most common way of writing a (spinless) tight-binding model in condensed matter physics would be in the second-quantization form:\n\\begin{equation} H_\\text{tb}/\\hbar = \\sum_{i}\\epsilon_{i} c_i^\\dagger c_i + \\sum_{\\langle i,j\\rangle}J_{ij}\\left( c_i^\\dagger c_j + \\text{h.c.}\\right), \\end{equation}\nwhere \\(c_i^\\dagger\\) and \\(c_i\\) are the creation and annihilation operators for the electron at site \\(i\\), respectively, \\(\\mu_i\\) are the on-site potentials, and \\(J_{ij}\\) are the elements of a symmetric matrix representing the hopping strengths. Moreover, \\(\\langle i,j\\rangle\\) denotes any pair of neighboring sites. To simulate this fermionic system on a gate-based quantum computer which is built on qubits, we need a similar notion for the ladder operators (i.e., creation and annihilation operators) for two-level systems: \\(c^\\dagger \\ket{0} \\to \\ket{1}\\) and \\(c\\ket{1} \\to \\ket{0}\\). One way of representing them would be to use the Pauli gates:\n$$ \\begin{split} \u0026amp; c_i^\\dagger = \\frac{1}{\\sqrt 2}(X_i + iY_i), \\\\ \u0026amp; c_i = \\frac{1}{\\sqrt 2}(X_i - iY_i). \\end{split} $$\nPlugging them into Eq. (1) and assuming the hoppings are homogeneous such that they can be described by a single parameter \\(J\\), we obtain\n\\begin{equation} H_\\text{tb}/\\hbar = \\sum_i \\epsilon_i Z_i + J\\sum_{\\langle i,j\\rangle}(X_i X_j + Y_i Y_j), \\end{equation} where we have neglected a constant term (proportional to the identity operator) that would not have any impact on the dynamics of the system. Note that we have technically performed the inverse of the Jordan-Wigner transformation.\nTrotterization # One of the things we care about in quantum simulations is the time-evolution of the quantum system. This is determined by the unitary operator \\(e^{-iHt/\\hbar}\\) in quantum mechanics, where \\(H\\) is the time-independent Hamiltonian, which is \\(H_\\text{tb}\\) in the case of our 1-D quantum chain. Now, to execute the time evolution unitary on a gate-based quantum computer, one must decompose it into a product of one- and two-qubit gates that can be implemented on the quantum computer. One method to accomplish this is called Trotterization, which essentially performs a discretized approximation to the continuous time evolution. To demonstrate it, let us consider a simple three-site system. The time-evolution unitary of this system is given by $$ \\begin{split} U_\\text{tb}(t) \u0026amp;= \\exp\\left[\\frac{-it}{\\hbar}\\left(H_\\text{tb}^{(0,1)} + H_\\text{tb}^{(1,2)}\\right)\\right] \\\\ \u0026amp;\\approx \\left[\\exp\\left(\\frac{-it}{n\\hbar}H_\\text{tb}^{(0,1)}\\right) \\exp\\left(\\frac{-it}{n\\hbar}H_\\text{tb}^{(1,2)}\\right) \\right]^n, \\end{split} $$ where in the second step we have applied Trotterization and \\(n\\) is the number of Trotter steps, i.e., discrete time steps. Within each two-site subsystem, the Pauli operator pairs \\(X_i X_j\\) and \\(Y_i Y_j\\) commute with each other. Therefore, with \\(J = 1\\) and \\(\\epsilon_i = 0\\), we can write \\(U_\\text{tb}(t)\\) as $$ \\begin{split} U_\\text{tb}(t) \u0026amp;\\approx \\left\\{\\exp\\left[\\frac{-it}{n} \\left(X_0 X_1 + Y_0 Y_1 \\right) \\right] \\exp\\left[\\frac{-it}{n}\\left(X_1 X_2 + Y_1 Y_2 \\right) \\right] \\right\\}^n \\\\ \u0026amp;= \\left[\\exp\\left(\\frac{-it}{n}X_0 X_1\\right) \\exp\\left(\\frac{-it}{n}Y_0 Y_1\\right) \\exp\\left(\\frac{-it}{n}X_1 X_2\\right) \\exp\\left(\\frac{-it}{n}Y_1 Y_2\\right) \\right]^n \\\\ \u0026amp;= \\left[R_{X_0X_1}\\left(\\frac{2t}{n} \\right) R_{Y_0Y_1}\\left(\\frac{2t}{n} \\right) R_{X_1X_2}\\left(\\frac{2t}{n} \\right) R_{Y_1Y_2}\\left(\\frac{2t}{n} \\right) \\right]^n, \\end{split} $$ where \\(R_{X_iX_j}\\) and \\(R_{Y_iY_j}\\) are parametric two-qubit \\(X\\otimes X\\) and \\(Y\\otimes Y\\) interaction gates between qubits \\(i\\) and \\(j\\). They are sometimes referred to as the Ising gates. Please see RXXGate and RYYGate for more details. In general, for an \\(m\\)-qubit system, the time-evolution unitary for each individual Trotter step can then be written as $$ U_\\text{tb}(\\Delta t) \\approx \\prod_{i=0}^{m-2} R_{X_i X_{i+1}}(2\\Delta t) R_{Y_i Y_{i+1}}(2\\Delta t), $$ where \\(\\Delta t = t/n\\) is the discretized time step. The complete evolution over time \\(t\\) is then \\(U_\\text{tb}\\approx [U_\\text{tb}(\\Delta t)]^{t/\\Delta t}\\).\nWe are now just one step shy of implementing \\(U_\\text{tb}(t)\\) on a quantum computer, that is, to further decompose the \\(R_{XX}\\) and \\(R_{YY}\\) gates into a set of gates that are native to the quantum hardware, such as the CNOT gate and single-qubit rotation gates. For this, let us introduce another Ising gate, RZZGate \\(R_{ZZ}\\). It is not hard to verify that this two-qubit gate can be decomposed as a single-qubit rotation gate \\(R_Z = \\exp(-i\\theta Z/2)\\) sandwiched between two CNOT gates. Specifically, \\(R_{ZZ}(\\theta) = \\text{CNOT}\\, R_Z(\\theta)\\, \\text{CNOT}\\). Then by working out the explicit matrix representations, one can show that the \\(R_{XX}\\) gate has the following decomposition,\nwhile the \\(R_{YY}\\) gate is decomposed as\nWith the above setup, we are ready to build the Trotterized quantum circuit for a general \\(n\\)-site quantum chain using Qiskit. First, we need to import some necessary packages.\nimport numpy as np import matplotlib.pyplot as plt from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit.circuit import Parameter import qiskit.quantum_info as qi We then define the Trot_qc function for the Trotterized quantum circuit.\ndef Trot_qc(num_qubits, t=Parameter(\u0026#34;t\u0026#34;)): \u0026#34;\u0026#34;\u0026#34; Creates the Trotterized quantum circuit at a given time for the 1D tight-binding model. Args: num_qubits (int): The number of qubits in the circuit. t (Parameter): time. Returns: qiskit.circuit.QuantumCircuit: The Trotterized quantum circuit. \u0026#34;\u0026#34;\u0026#34; def ZZ_gate(t): ZZ_qr = QuantumRegister(2) ZZ_qc = QuantumCircuit(ZZ_qr, name=\u0026#39;ZZ\u0026#39;) ZZ_qc.cnot(0,1) ZZ_qc.rz(2 * t, 1) ZZ_qc.cnot(0,1) # Convert custom quantum circuit into a gate ZZ = ZZ_qc.to_instruction() return ZZ def XX_gate(t): XX_qr = QuantumRegister(2) XX_qc = QuantumCircuit(XX_qr, name=\u0026#39;XX\u0026#39;) XX_qc.ry(np.pi/2, [0,1]) XX_qc.append(ZZ_gate(t), [0,1]) XX_qc.ry(-np.pi/2, [0,1]) XX = XX_qc.to_instruction() return XX def YY_gate(t): YY_qr = QuantumRegister(2) YY_qc = QuantumCircuit(YY_qr, name=\u0026#39;YY\u0026#39;) YY_qc.rx(-np.pi/2, [0,1]) YY_qc.append(ZZ_gate(t), [0,1]) YY_qc.rx(np.pi/2, [0,1]) YY = YY_qc.to_instruction() return YY Trot_qr = QuantumRegister(num_qubits) qc = QuantumCircuit(Trot_qr, name=\u0026#39;Trot\u0026#39;) for i in range(num_qubits - 1): qc.append(XX_gate(t), [Trot_qr[i], Trot_qr[i+1]]) qc.append(YY_gate(t), [Trot_qr[i], Trot_qr[i+1]]) return qc We can inspect the circuit for 3 qubits by calling the QuantumCircuit.draw() method:\nLast but not least, to see if we have implemented Trotterization correctly, we may compute the process fidelity between the Trotterized quantum channel and the exact time-evolution unitary. We define the exact time-evolution unitary as follows:\nfrom qiskit.opflow import I, X, Y, Z def U_tb(t): \u0026#34;\u0026#34;\u0026#34; Exact time-evolution unitary for 3 qubits. \u0026#34;\u0026#34;\u0026#34; # Interactions (I is the identity matrix; X and Y are Pauli matricies; # ^ is a tensor product) XXs = (I^X^X) + (X^X^I) YYs = (I^Y^Y) + (Y^Y^I) H_tb = XXs + YYs return (t * H_tb).exp_i() On the other hand, the approximate unitary based on Trotterization is constructed as follows:\ndef U_trot_tb(t_target, trotter_steps, num_qubits): \u0026#34;\u0026#34;\u0026#34; Creates the Trotterized time-evolution unitary for a 1-D tight-binding model. Args: t_target (float): The total time evolved. trotter_steps (int): The number of Trotter steps. num_qubits (int): The number of qubits in the circuit. Returns: qiskit.quantum_info.Operator: The operator corresponding to the Trotterized time-evolution unitary. \u0026#34;\u0026#34;\u0026#34; t = Parameter(\u0026#34;t\u0026#34;) qr = QuantumRegister(num_qubits) qc = QuantumCircuit(qr) for _ in range(trotter_steps): qc.append(Trot_qc(num_qubits, t), qr) qc = qc.bind_parameters({t: t_target/trotter_steps}) return qi.Operator(qc) Finally, we can plot how the Trotter error (= 1 - process fidelity) changes as we increase the number of Trotter steps.\nt_target = 0.5 # total time evolved U_target = U_tb(t_target) steps=np.arange(1,101,2) fidelities=[] for n in steps: U_trotter = U_trot_tb(t_target, n, 3) fidelity = qi.process_fidelity(U_trotter, target=U_target) fidelities.append(fidelity) plt.figure(facecolor=\u0026#39;white\u0026#39;) plt.loglog(steps, 1 - np.array(fidelities)) plt.ylabel(\u0026#39;Trotter error\u0026#39;) plt.xlabel(\u0026#39;Trotter steps\u0026#39;) plt.show() Here is how the plot looks like:\nYay 🎉! The trotter error decreases as the number of Trotter steps increases, suggesting that we have indeed implemented Trotterization correctly.\nSo here comes the end of the first part. In the next post, we will see how we can use the Trotterized quantum circuit that we just built to study phenomena including the quantum random walk and Anderson localization on a 1-D quantum chain. Stay tuned!\n","date":"4 June 2022","permalink":"/blog/ibm-spring-challenge-1/","section":"Blog","summary":"A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics.","title":"Quantum simulation of many-body physics - I"},{"content":" A quick peek at the shell interface. This weekend I spent some time tweaking the Terminal on my Mac with iTerm2 and Fish shell. Why did I do it? First of all, I have been quite fed up with the boring black-and-white look of the default Terminal app. In my opinion, the introduction of multiple colors together with glyphs/icons not only makes it look better visually, it also helps one distinguish different contents (e.g. directories, files) more easily. Moreover, I just want more customizations and features like autosuggestions to make working with command lines a little more efficient. So below are the ingredients I used to customize my Terminal and instructions for some key steps.\nIngredients # iTerm2: A popular terminal emulator for macOS Colors: I personally use Solarized Dark Download Solarized Unzip and double click on the the color scheme Solarized Dark.itermcolors under the directory /iterm2-colors-solarized Open iTerm2\u0026rsquo;s Preferences → Profiles → Colors, and select the theme under Color Presets Text: We need one of the Nerd Fonts to render the glyphs/icons; I chose two of them Meslo Nerd Font: Downloaded from the Tide repo; this particular font contains all the glyphs needed Source Code Pro Nerd Font: Installed on Homebrew via brew tap homebrew/cask-fonts (only need to run this once) and then brew install --cask font-source-code-pro; This is the font I\u0026rsquo;d like to use in text Alternatively, all the Powerline Fonts can be installed based on this repo Go to iTerm2\u0026rsquo;s Preferences → Profiles → Text, under Font, choose Source Code Pro (for Powerline) or any font you like; select Use a different font for non-ASCII text, then choose MesloLGS NF under Non-ASCII Font I also resize the New Windows to be 120 columns and 40 rows under the Window panel Fish shell: A great alternative to bash and zsh Installation: brew install fish Set fish as the default shell: Add the shell to /etc/shells with echo /usr/local/bin/fish | sudo tee -a /etc/shells Change the default shell with chsh -s /usr/local/bin/fish Oh My Fish: Package manager for customizing the fish shell Check all the themes contained in Oh My Fish: omf theme I installed the Agnoster theme: omf install agnoster Apply the theme: omf theme agnoster Fisher: Plugin manager for fish See all the plugins and prompts here Exa: Replacement for ls Installation: brew install exa Customized ll and lla: Find fish config file (config.fish) in ~/.config/fish Add the following lines to the config file (I got this trick from the great Takuya Matsuyama): if type -q exa alias ll \u0026#34;exa -l -g --icons\u0026#34; alias lla \u0026#34;ll -a\u0026#34; end OK, there you go! Enjoy the fresh new look!\nUpdate 1 # While setting up fish on a M1 Mac yesterday, I realized that the fish shell path is not the same as in Intel-based Macs. So if you have a Mac with Apple Silicon, after brew install fish you can run:\nfish_add_path /opt/homebrew/bin echo \u0026quot;/opt/homebrew/bin/fish\u0026quot; | sudo tee -a /etc/shells chsh -s /opt/homebrew/bin/fish ","date":"8 May 2022","permalink":"/blog/fish-shell-customization/","section":"Blog","summary":"A quick peek at the shell interface.","title":"Fish shell and customization"},{"content":" AI generated art by Disco Diffusion. A Brief Bio # Welcome! My name is Ruihao Li (李瑞浩). I grew up in Guangdong, China. I received my Bachelor\u0026rsquo;s degree with First Class Honours in physics from The University of Sydney (Australia) in 2016. After that, I began to pursue my Ph.D. in physics at Case Western Reserve University (CWRU) in 2017. I spent the first two years working with Dr. Pavel Fileviez Perez on theories of leptophobic dark matter models. From 2019, I started working with Dr. Shulei Zhang on charge and spin transport in topological quantum materials, especially topological semimetals. I graduated in 2023 and am currently working as a Quantum Research Data Scientist at Center for Computational Life Sciences, Lerner Research Institute, Cleveland Clinic, focusing on developing quantum computing applications in life sciences. I am also actively working on quantum computing projects in physics and am interested in developing open-source tools for research and education. I make use of both analytical and numerical tools for my research, including Mathematica, Python, Julia, etc. See my research for more details.\nOther Interests # Huge fan of basketball, the NBA, and LeBron James 👑 Avid cook from time to time 🥘 Animal videos all day 🐱 Mechanical stuff and tech gadgets ⚙️ ","date":"1 January 0001","permalink":"/about/","section":"","summary":"AI generated art by Disco Diffusion.","title":"About"},{"content":"","date":"1 January 0001","permalink":"/categories/","section":"Categories","summary":"","title":"Categories"},{"content":"Starting from Spring 2022, I am co-organizing a Condensed Matter Physics (CMP) Journal Club at CWRU. Currently we are having biweekly meetings where two speakers will present their papers of choice. We are hosting the meetings both in-person and over Zoom. If you are interested in joining or want to present a recent CMP paper of your own, please do not hesitate to contact me for more details.\nBelow are the papers presented so far:\nDate (2022) Papers Feb 18 Andy Lininger: Goos-Hänchen and Imbert-Fedorov shifts in tilted Weyl semimetals Mandela Mehraeen: Anomalous Hall unidirectional magnetoresistance Mar 11 APS March Meeting rehearsals Mar 25 Ruihao Li: Unpaired Majorana fermions in quantum wires Ozan Dernek: Time-dependent exchange-correlation potential in lieu of self-energy Apr 8 Niloufar Dadkhah: Directly visualizing the momentum-forbidden dark excitons and their dynamics in atomically thin semiconductors Apr 22 Diego García Ovalle (Aix-Marseille Université): Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals ","date":"1 January 0001","permalink":"/journal-club/","section":"Journal Club","summary":"Starting from Spring 2022, I am co-organizing a Condensed Matter Physics (CMP) Journal Club at CWRU.","title":"Journal Club"},{"content":"Title: Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals\nAuthors: Diego García Ovalle - Armando Pezo - Aurélien Manchon (Aix-Marseille Université, CNRS, CINaM, Marseille, France.)\nAbstract:\nWhereas anomalous Hall effect has been thought to only exist in materials presenting a net magnetization, such as ferro- or ferrimagnetic metals, recent progress has revealed that this is not the case. In particular, it has been recently proposed that in nonmagnetic crystals a transverse Hall current can develop at the second order in the electric field. This effect, tagged the nonlinear Hall effect, arises in certain non-centrosymmetric crystals and is driven by the Berry curvature dipole. Weyl Semimetals are particularly promising platforms for the observation of the nonlinear Hall effect because their bulk Fermi surface is composed of Weyl nodes with diverging Berry curvature. Nonetheless, Weyl Semimetals display another intriguing aspect that has remained scarcely addressed so far. Depending on the Weyl cone inclination, their surface feature a wide variety of trivial and non-trivial states, including Fermi pockets, arcs and track states.\nIn this work, adopting a model for noncentrosymmetric Weyl Semimetal, we investigate the impact of these surface states on the nonlinear Hall response. We show that depending on the slab geometry, surface states can have a dramatic impact on the nonlinear Hall effect, resulting in substantial thickness-dependence. We also extend our study to the realistic case of WTe2 thin film using a Wannier-projected tight-binding representation. Finally, we mention the intimate connection that is expected between the nonlinear Hall effect and the Orbital Edelstein Effect of these noncentrosymmetric materials.\nRef: arXiv:2206.08681\n","date":"1 January 0001","permalink":"/journal-club/dgo_abstract/","section":"Journal Club","summary":"Title: Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals","title":"Journal Club"},{"content":" Overview # My current research interests are focused on leveraging near-term quantum computers to solve problems in various domains, which include but are not limited to:\nSimulation of many-body systems: creating exotic phases of matter, simulating phase transitions, improving techniques for Hamiltonian simulation with the help of machine learning, etc. Optimization: exploring quantum optimization algorithms, such as the Quantum Approximate Optimization Algorithm (QAOA), Variational Quantum Eigensolver (VQE), etc. and their applications in life science problems such as protein folding and drug discovery Machine learning: developing and benchmarking quantum machine learning algorithms for electronic health records, medical imaging, etc. Things I have worked on in the past:\nTopological materials: investigating novel spin/charge transport phenomena in topological semimetals, such as Weyl and Dirac semimetals Dark matter models: studying the phenomenology of dark matter models in theories with a gauged baryon symmetry I am always open to collaborations and discussions. Please feel free to reach out to me via the links in my homepage. Publications # Kostas Blekos*, Dean Brand*, Andrea Ceschini*, Chiao-Hui Chou*, Rui-Hao Li*, Komal Pandya*, and Alessandro Summer*, A review on Quantum Approximate Optimization Algorithm and its variants, Phys. Rep. 1068, 1 (2024). R.-H. Li*, P. Shen*, and S. S.-L. Zhang, Tunable spin-charge conversion in topological Dirac semimetals, APL Mater. 10, 041108 (2022). R.-H. Li, O. G. Heinonen, A. A. Burkov, and S. S.-L. Zhang, Nonlinear Hall effect in Weyl semimetals induced by chiral anomaly, Phys. Rev. B 103, 045105 (2021). P. Fileviez Pere*, E. Golias*, R.-H. Li*, C. Murgui*, and A. D. Plascencia*, Anomaly-free dark matter models, Phys. Rev. D 100, 015017 (2019). P. Fileviez Perez*, E. Golias*, R.-H. Li*, and C. Murgui*, Leptophobic dark matter and the baryon number violation scale, Phys. Rev. D 99, 035009 (2019). [*]: denotes equal contribution\nTalks # Introduction to (Qiskit) Quantum Machine Learning (2022) with demo Talk given in Qiskit Fall Fest 2022 at CWRU, which I also co-organized. Introduction to Quantum Approximate Optimization Algorithm (2022) Talk given at the QOSF Mentorship Program meeting. Majorana Zero Modes in a Kitaev Chain (2022) Talk given at the CMP Journal Club at CWRU in Spring 2022. Tunable spin-charge conversion in topological Dirac semimetals (2022) 2022.3: APS March Meeting 2022, Chicago, IL, USA. 2021.8: The 2021 Around-the-Clock Around-the-Globe magnetics Conference (AtC-AtG), Virtual. Chiral-anomaly-induced nonlinear Hall effect in Weyl semimetals (2020) 2020.11: The 65th Annual Conference on Magnetism and Magnetic Materials (MMM 2020), Virtual. 2020.8: The 2020 Around-the-Clock Around-the-Globe magnetics Conference (AtC-AtG), Virtual. (Best Presentation Awards) Fantastic dark matter and where to find them: Indirect Detection (2019) Talk given at the CERCA Weekly Seminar in Spring 2019. Baryon number violation and leptophobic dark matter (2018) Talk given at the CERCA Weekly Seminar in Fall 2018. Quantum corrections in left-right symmetric seesaw mechanisms (2016) Talk given as my Honours year final presentation in Oct, 2016. Miscellaneous Notes # Quantum Field Theory in Curved Spacetime (2018). A short introduction to quantum field theory in curved spacetime. Introduction to Quantum Field Theory (2016). Lecture notes compiled based on the Honours course on Quantum Field Theory. Particle Cosmology and Baryonic Astrophysics (2016). Lecture notes compiled based on the Honours course on Particle Cosmology and Baryonic Astrophysics. ","date":"1 January 0001","permalink":"/research/","section":"Research","summary":"Overview # My current research interests are focused on leveraging near-term quantum computers to solve problems in various domains, which include but are not limited to:","title":"Research"}] \ No newline at end of file diff --git a/public/index.xml b/public/index.xml new file mode 100644 index 0000000..f349579 --- /dev/null +++ b/public/index.xml @@ -0,0 +1,69 @@ + + + + Ruihao Li + http://localhost:1313/ + Recent content on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Mon, 09 Jan 2023 00:00:00 +0000 + + + Supercharging the Pythonic Metropolis Monte Carlo + http://localhost:1313/blog/2d-ising-model/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/blog/2d-ising-model/ + Okay, I&rsquo;ll admit that this is neither a super exciting nor a new topic to write about. + + + Adding blog comments + http://localhost:1313/blog/blog-comments/ + Sun, 03 Jul 2022 00:00:00 +0000 + http://localhost:1313/blog/blog-comments/ + Comments widget by Utterances. + + + Quantum simulation of many-body physics - III + http://localhost:1313/blog/ibm-spring-challenge-3/ + Sun, 26 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-3/ + This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. + + + Quantum simulation of many-body physics - II + http://localhost:1313/blog/ibm-spring-challenge-2/ + Sat, 18 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-2/ + As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. + + + Quantum simulation of many-body physics - I + http://localhost:1313/blog/ibm-spring-challenge-1/ + Sat, 04 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-1/ + A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. + + + Fish shell and customization + http://localhost:1313/blog/fish-shell-customization/ + Sun, 08 May 2022 00:00:00 +0000 + http://localhost:1313/blog/fish-shell-customization/ + A quick peek at the shell interface. + + + About + http://localhost:1313/about/ + Mon, 01 Jan 0001 00:00:00 +0000 + http://localhost:1313/about/ + AI generated art by Disco Diffusion. + + + Journal Club + http://localhost:1313/journal-club/dgo_abstract/ + Mon, 01 Jan 0001 00:00:00 +0000 + http://localhost:1313/journal-club/dgo_abstract/ + Title: Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals + + + diff --git a/public/journal-club/dgo_abstract/index.html b/public/journal-club/dgo_abstract/index.html new file mode 100644 index 0000000..78acc16 --- /dev/null +++ b/public/journal-club/dgo_abstract/index.html @@ -0,0 +1,541 @@ + + + + + + + + + + + + Journal Club · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Journal Club +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+
+
+ +
+

Title: Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals

+

Authors: Diego García Ovalle - Armando Pezo - Aurélien Manchon (Aix-Marseille Université, CNRS, CINaM, Marseille, France.)

+

Abstract:

+

Whereas anomalous Hall effect has been thought to only exist in materials presenting a net magnetization, such as ferro- or ferrimagnetic metals, recent progress has revealed that this is not the case. In particular, it has been recently proposed that in nonmagnetic crystals a transverse Hall current can develop at the second order in the electric field. This effect, tagged the nonlinear Hall effect, arises in certain non-centrosymmetric crystals and is driven by the Berry curvature dipole. Weyl Semimetals are particularly promising platforms for the observation of the nonlinear Hall effect because their bulk Fermi surface is composed of Weyl nodes with diverging Berry curvature. Nonetheless, Weyl Semimetals display another intriguing aspect that has remained scarcely addressed so far. Depending on the Weyl cone inclination, their surface feature a wide variety of trivial and non-trivial states, including Fermi pockets, arcs and track states.

+

In this work, adopting a model for noncentrosymmetric Weyl Semimetal, we investigate the impact of these surface states on the nonlinear Hall response. We show that depending on the slab geometry, surface states can have a dramatic impact on the nonlinear Hall effect, resulting in substantial thickness-dependence. We also extend our study to the realistic case of WTe2 thin film using a Wannier-projected tight-binding representation. Finally, we mention the intimate connection that is expected between the nonlinear Hall effect and the Orbital Edelstein Effect of these noncentrosymmetric materials.

+

Ref: arXiv:2206.08681

+ +
+
+
+ + + + + + + + +
+
+
+ + + +
+
+ + +
+
+ + + + +
+ + +
+ + diff --git a/public/journal-club/index.html b/public/journal-club/index.html new file mode 100644 index 0000000..7e4e795 --- /dev/null +++ b/public/journal-club/index.html @@ -0,0 +1,457 @@ + + + + + + + + + + + + Journal Club · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to main content +
+ + +
+ +
+ +
+
+ +
+
+ +

+ Journal Club +

+
+
+

Starting from Spring 2022, I am co-organizing a Condensed Matter Physics (CMP) Journal Club at CWRU. Currently we are having biweekly meetings where two speakers will present their papers of choice. We are hosting the meetings both in-person and over Zoom. If you are interested in joining or want to present a recent CMP paper of your own, please do not hesitate to contact me for more details.

+

Below are the papers presented so far:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Date (2022)
Papers
Feb 18Andy Lininger: Goos-Hänchen and Imbert-Fedorov shifts in tilted Weyl semimetals
Mandela Mehraeen: Anomalous Hall unidirectional magnetoresistance
Mar 11APS March Meeting rehearsals
Mar 25Ruihao Li: Unpaired Majorana fermions in quantum wires
Ozan Dernek: Time-dependent exchange-correlation potential in lieu of self-energy
Apr 8Niloufar Dadkhah: Directly visualizing the momentum-forbidden dark excitons and their dynamics in atomically thin semiconductors
Apr 22Diego García Ovalle (Aix-Marseille Université): Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals
+ +
+
+ + +
+
+ + +
+ + +
+ + diff --git a/public/journal-club/index.xml b/public/journal-club/index.xml new file mode 100644 index 0000000..1bc997a --- /dev/null +++ b/public/journal-club/index.xml @@ -0,0 +1,19 @@ + + + + Journal Club on Ruihao Li + http://localhost:1313/journal-club/ + Recent content in Journal Club on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + + + Journal Club + http://localhost:1313/journal-club/dgo_abstract/ + Mon, 01 Jan 0001 00:00:00 +0000 + http://localhost:1313/journal-club/dgo_abstract/ + Title: Impact of the Fermi Arc Diversity on the Berry Curvature Dipole in Time Reversal Invariant Weyl Semimetals + + + diff --git a/public/js/appearance.min.badab316c9287a5a42a843e4eb45da65bb3d194a5a0f5fa4a3e516160e67df0b8c65f4f19a8e146436e29d583699e6cb41d6bbe99e05e1dbaa877763bad9f8e2.js b/public/js/appearance.min.badab316c9287a5a42a843e4eb45da65bb3d194a5a0f5fa4a3e516160e67df0b8c65f4f19a8e146436e29d583699e6cb41d6bbe99e05e1dbaa877763bad9f8e2.js new file mode 100644 index 0000000..5bbe124 --- /dev/null +++ b/public/js/appearance.min.badab316c9287a5a42a843e4eb45da65bb3d194a5a0f5fa4a3e516160e67df0b8c65f4f19a8e146436e29d583699e6cb41d6bbe99e05e1dbaa877763bad9f8e2.js @@ -0,0 +1 @@ +const sitePreference=document.documentElement.getAttribute("data-default-appearance"),userPreference=localStorage.getItem("appearance");(sitePreference==="dark"&&userPreference===null||userPreference==="dark")&&document.documentElement.classList.add("dark"),document.documentElement.getAttribute("data-auto-appearance")==="true"&&(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches&&userPreference!=="light"&&document.documentElement.classList.add("dark"),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{e.matches?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")})),window.addEventListener("DOMContentLoaded",e=>{const t=document.getElementById("appearance-switcher");t&&(t.addEventListener("click",()=>{document.documentElement.classList.toggle("dark"),localStorage.setItem("appearance",document.documentElement.classList.contains("dark")?"dark":"light")}),t.addEventListener("contextmenu",e=>{e.preventDefault(),localStorage.removeItem("appearance")}))}) \ No newline at end of file diff --git a/public/js/main.bundle.min.4db1f989a0136272048a7271e40a391bc91156a2f61433cf56b5d495cc15ec95c14017877036007e8afc0f47f257f5f8004f8f4a94e49172749f47560de12281.js b/public/js/main.bundle.min.4db1f989a0136272048a7271e40a391bc91156a2f61433cf56b5d495cc15ec95c14017877036007e8afc0f47f257f5f8004f8f4a94e49172749f47560de12281.js new file mode 100644 index 0000000..5b2e5ad --- /dev/null +++ b/public/js/main.bundle.min.4db1f989a0136272048a7271e40a391bc91156a2f61433cf56b5d495cc15ec95c14017877036007e8afc0f47f257f5f8004f8f4a94e49172749f47560de12281.js @@ -0,0 +1,12 @@ +e=this,t=function(){"use strict";function P(e,t){var n,s=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),s.push.apply(s,n)),s}function u(e){for(var t,n=1;ne.length)&&(t=e.length);for(var n=0,s=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:1,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:3,e=new Map,t=Math.pow(10,s);return{get:function(s){if(o=s.match(ge).length,e.has(o))return e.get(o);var o,a=1/Math.pow(o,.5*n),i=parseFloat(Math.round(a*t)/t);return e.set(o,i),i},clear:function(){e.clear()}}}f=function(){function a(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=n.getFn,i=void 0===s?e.getFn:s,o=n.fieldNormWeight,r=void 0===o?e.fieldNormWeight:o;t(this,a),this.norm=ue(r,3),this.getFn=i,this.isCreated=!1,this.setIndexRecords()}return n(a,[{key:"setSources",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.docs=e}},{key:"setIndexRecords",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.records=e}},{key:"setKeys",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];this.keys=e,this._keysMap={},e.forEach(function(e,n){t._keysMap[e.id]=n})}},{key:"create",value:function(){var e=this;!this.isCreated&&this.docs.length&&(this.isCreated=!0,o(this.docs[0])?this.docs.forEach(function(t,n){e._addString(t,n)}):this.docs.forEach(function(t,n){e._addObject(t,n)}),this.norm.clear())}},{key:"add",value:function(e){var t=this.size();o(e)?this._addString(e,t):this._addObject(e,t)}},{key:"removeAt",value:function(e){this.records.splice(e,1);for(var t=e,n=this.size();t2&&void 0!==arguments[2]?arguments[2]:{},i=o.getFn,r=void 0===i?e.getFn:i,a=o.fieldNormWeight,c=void 0===a?e.fieldNormWeight:a,s=new f({getFn:r,fieldNormWeight:c});return s.setKeys(t.map(z)),s.setSources(n),s.create(),s}function g(t){var s,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},d=n.errors,f=void 0===d?0:d,l=n.currentLocation,u=void 0===l?0:l,a=n.expectedLocation,h=void 0===a?0:a,r=n.distance,c=void 0===r?e.distance:r,i=n.ignoreLocation,m=void 0===i?e.ignoreLocation:i,o=f/t.length;return m?o:(s=Math.abs(h-u),c?o+s/c:s?1:o)}function oe(){for(var i,s=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e.minMatchCharLength,o=[],t=-1,r=-1,n=0,c=s.length;n=a&&o.push([t,r]),t=-1);return s[n-1]&&n-t>=a&&o.push([t,n-1]),o}l=32;function W(e){for(var s,n={},t=0,o=e.length;t1&&void 0!==arguments[1]?arguments[1]:{},h=o.location,C=void 0===h?e.location:h,g=o.threshold,O=void 0===g?e.threshold:g,d=o.distance,A=void 0===d?e.distance:d,m=o.includeMatches,E=void 0===m?e.includeMatches:m,p=o.findAllMatches,x=void 0===p?e.findAllMatches:p,v=o.minMatchCharLength,_=void 0===v?e.minMatchCharLength:v,u=o.isCaseSensitive,j=void 0===u?e.isCaseSensitive:u,b=o.ignoreLocation,w=void 0===b?e.ignoreLocation:b;if(t(this,s),this.options={location:C,threshold:O,distance:A,includeMatches:E,findAllMatches:x,minMatchCharLength:_,isCaseSensitive:j,ignoreLocation:w},this.pattern=j?n:n.toLowerCase(),this.chunks=[],this.pattern.length)if(a=function(e,t){y.chunks.push({pattern:e,alphabet:W(e),startIndex:t})},i=this.pattern.length,i>l){for(var r=0,f=i%l,k=i-f;r3&&void 0!==arguments[3]?arguments[3]:{},B=r.location,V=void 0===B?e.location:B,R=r.distance,C=void 0===R?e.distance:R,N=r.threshold,K=void 0===N?e.threshold:N,F=r.findAllMatches,W=void 0===F?e.findAllMatches:F,D=r.minMatchCharLength,z=void 0===D?e.minMatchCharLength:D,I=r.includeMatches,H=void 0===I?e.includeMatches:I,L=r.ignoreLocation,j=void 0===L?e.ignoreLocation:L;if(n.length>l)throw new Error($(l));for(var y,d=n.length,p=t.length,i=Math.max(0,Math.min(V,p)),m=K,h=i,x=z>1||H,S=x?Array(p):[];(y=t.indexOf(n,h))>-1;)if(P=g(n,{currentLocation:y,expectedLocation:i,distance:C,ignoreLocation:j}),m=Math.min(P,m),h=y+d,x)for(b=0;b=T;o-=1)if(v=o-1,E=s[t.charAt(v)],x&&(S[v]=+!!E),u[o]=(u[o+1]<<1|1)&E,c&&(u[o]|=(w[o+1]|w[o])<<1|1|w[o+1]),u[o]&U&&(A=g(n,{errors:c,currentLocation:v,expectedLocation:i,distance:C,ignoreLocation:j}))<=m){if(m=A,(h=v)<=i)break;T=Math.max(1,2*i-h)}if(g(n,{errors:c+1,currentLocation:i,expectedLocation:i,distance:C,ignoreLocation:j})>m)break;w=u}return _={isMatch:h>=0,score:Math.max(.001,A)},x&&(M=oe(S,z),M.length?H&&(_.indices=M):_.isMatch=!1),_}(t,j,y,{location:b+_,distance:h,threshold:v,findAllMatches:p,minMatchCharLength:m,includeMatches:a,ignoreLocation:f}),r=i.isMatch,w=i.score,c=i.indices;r&&(s=!0),u+=w,r&&c&&(o=[].concat(d(o),d(c)))}),i={isMatch:s,score:s?u/this.chunks.length:1},s&&a&&(i.indices=o),i}}]),s}(),a=function(){function e(n){t(this,e),this.pattern=n}return n(e,[{key:"search",value:function(){}}],[{key:"isMultiMatch",value:function(e){return B(e,this.multiRegex)}},{key:"isSingleMatch",value:function(e){return B(e,this.singleRegex)}}]),e}();function B(e,t){var n=e.match(t);return n?n[1]:null}var a,l,h,f,O,G=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"exact"}},{key:"multiRegex",get:function(){return/^="(.*)"$/}},{key:"singleRegex",get:function(){return/^=(.*)$/}}]),s}(a),Y=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"$/}},{key:"singleRegex",get:function(){return/^!(.*)$/}}]),s}(a),ne=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}],[{key:"type",get:function(){return"prefix-exact"}},{key:"multiRegex",get:function(){return/^\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^\^(.*)$/}}]),s}(a),U=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-prefix-exact"}},{key:"multiRegex",get:function(){return/^!\^"(.*)"$/}},{key:"singleRegex",get:function(){return/^!\^(.*)$/}}]),s}(a),K=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}],[{key:"type",get:function(){return"suffix-exact"}},{key:"multiRegex",get:function(){return/^"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^(.*)\$$/}}]),s}(a),q=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){var t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}],[{key:"type",get:function(){return"inverse-suffix-exact"}},{key:"multiRegex",get:function(){return/^!"(.*)"\$$/}},{key:"singleRegex",get:function(){return/^!(.*)\$$/}}]),s}(a),S=function(s){r(o,s);var i=c(o);function o(n){var f,s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},h=s.location,g=void 0===h?e.location:h,l=s.threshold,p=void 0===l?e.threshold:l,u=s.distance,j=void 0===u?e.distance:u,a=s.includeMatches,_=void 0===a?e.includeMatches:a,d=s.findAllMatches,v=void 0===d?e.findAllMatches:d,m=s.minMatchCharLength,b=void 0===m?e.minMatchCharLength:m,r=s.isCaseSensitive,y=void 0===r?e.isCaseSensitive:r,c=s.ignoreLocation,w=void 0===c?e.ignoreLocation:c;return t(this,o),(f=i.call(this,n))._bitapSearch=new O(n,{location:g,threshold:p,distance:j,includeMatches:_,findAllMatches:v,minMatchCharLength:b,isCaseSensitive:y,ignoreLocation:w}),f}return n(o,[{key:"search",value:function(e){return this._bitapSearch.searchIn(e)}}],[{key:"type",get:function(){return"fuzzy"}},{key:"multiRegex",get:function(){return/^"(.*)"$/}},{key:"singleRegex",get:function(){return/^(.*)$/}}]),o}(a),V=function(e){r(s,e);var o=c(s);function s(e){return t(this,s),o.call(this,e)}return n(s,[{key:"search",value:function(e){for(var t,o,n=0,s=[],i=this.pattern.length;(t=e.indexOf(this.pattern,n))>-1;)n=t+i,s.push([t,n-1]);return o=!!s.length,{isMatch:o,score:o?0:1,indices:s}}}],[{key:"type",get:function(){return"include"}},{key:"multiRegex",get:function(){return/^'"(.*)"$/}},{key:"singleRegex",get:function(){return/^'(.*)$/}}]),s}(a),_=[G,V,ne,U,q,K,Y,S],H=_.length,Z=/ +(?=(?:[^"]*"[^"]*")*[^"]*$)/;function J(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.split("|").map(function(e){for(var a,r,c,l,d=e.trim().split(Z).filter(function(e){return e&&!!e.trim()}),s=[],o=0,h=d.length;o1&&void 0!==arguments[1]?arguments[1]:{},a=o.isCaseSensitive,r=void 0===a?e.isCaseSensitive:a,c=o.includeMatches,j=void 0===c?e.includeMatches:c,d=o.minMatchCharLength,v=void 0===d?e.minMatchCharLength:d,h=o.ignoreLocation,f=void 0===h?e.ignoreLocation:h,m=o.findAllMatches,p=void 0===m?e.findAllMatches:m,i=o.location,g=void 0===i?e.location:i,u=o.threshold,b=void 0===u?e.threshold:u,l=o.distance,y=void 0===l?e.distance:l;t(this,s),this.query=null,this.options={isCaseSensitive:r,includeMatches:j,minMatchCharLength:v,findAllMatches:p,ignoreLocation:f,location:g,threshold:b,distance:y},this.pattern=r?n:n.toLowerCase(),this.query=J(this.pattern,this.options)}return n(s,[{key:"searchIn",value:function(e){if(o=this.query,!o)return{isMatch:!1,score:1};u=this.options,l=u.includeMatches,e=u.isCaseSensitive?e:e.toLowerCase();for(var s,o,i,c,l,u,f,g,n=0,t=[],a=0,r=0,j=o.length;r-1&&(n.refIndex=e.idx),t.matches.push(n)}})}function fe(e,t){t.score=e.score}function pe(t,n){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=o.includeMatches,r=void 0===i?e.includeMatches:i,a=o.includeScore,c=void 0===a?e.includeScore:a,s=[];return r&&s.push(me),c&&s.push(fe),t.map(function(e){var t=e.idx,o={item:n[t],refIndex:t};return s.length&&s.forEach(function(t){t(e,o)}),o})}return h=function(){function a(n){var s=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2?arguments[2]:void 0;t(this,a),this.options=u(u({},e),s),this.options.useExtendedSearch,this._keyStore=new ae(this.options.keys),this.setCollection(n,o)}return n(a,[{key:"setCollection",value:function(e,t){if(this._docs=e,t&&!(t instanceof f))throw new Error("Incorrect 'index' type");this._myIndex=t||D(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}},{key:"add",value:function(e){s(e)&&(this._docs.push(e),this._myIndex.add(e))}},{key:"remove",value:function(){for(var t,o=arguments.length>0&&void 0!==arguments[0]?arguments[0]:function(){return!1},n=[],e=0,s=this._docs.length;e1&&void 0!==arguments[1]?arguments[1]:{},i=a.limit,s=void 0===i?-1:i,t=this.options,r=t.includeMatches,c=t.includeScore,l=t.shouldSort,d=t.sortFn,u=t.ignoreFieldNorm,n=o(e)?o(this._docs[0])?this._searchStringList(e):this._searchObjectList(e):this._searchLogical(e);return he(n,{ignoreFieldNorm:u}),l&&n.sort(d),L(s)&&s>-1&&(n=n.slice(0,s)),pe(n,this._docs,{includeMatches:r,includeScore:c})}},{key:"_searchStringList",value:function(e){var n=b(e,this.options),o=this._myIndex.records,t=[];return o.forEach(function(e){var o=e.v,a=e.i,r=e.n;if(s(o)){var i=n.searchIn(o),c=i.isMatch,l=i.score,d=i.indices;c&&t.push({item:o,idx:a,matches:[{score:l,value:o,norm:r,indices:d}]})}}),t}},{key:"_searchLogical",value:function(e){var n=this,r=function(e,t){var n=(arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}).auto,s=void 0===n||n,a=function e(n){var r,c,d,u,a=Object.keys(n),l=le(n);if(!l&&a.length>1&&!E(n))return e(T(n));if(de(n)){if(r=l?n[N]:a[0],c=l?n[re]:n[r],!o(c))throw new Error(X(r));return d={keyId:C(r),pattern:c},s&&(d.searcher=b(c,t)),d}return u={children:[],operator:a[0]},a.forEach(function(t){var s=n[t];i(s)&&s.forEach(function(t){u.children.push(e(t))})}),u};return E(e)||(e=T(e)),a(e)}(e,this.options),c=function e(t,s,o){if(!t.children){var c,l=t.keyId,u=t.searcher,i=n._findMatches({key:n._keyStore.get(l),value:n._myIndex.getValueForItemAtKeyId(s,l),searcher:u});return i&&i.length?[{idx:o,item:s,matches:i}]:[]}for(var a=[],r=0,h=t.children.length;r1&&void 0!==arguments[1]?arguments[1]:{},o=s.getFn,a=void 0===o?e.getFn:o,i=s.fieldNormWeight,r=void 0===i?e.fieldNormWeight:i,c=t.keys,l=t.records,n=new f({getFn:a,fieldNormWeight:r});return n.setKeys(c),n.setIndexRecords(l),n},h.config=e,function(){m.push.apply(m,arguments)}(te),h},"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Fuse=t();var e,t,fuse,showButton=document.getElementById("search-button"),scriptBundle,copyText,copiedText,hideButton=document.getElementById("close-search-button"),wrapper=document.getElementById("search-wrapper"),modal=document.getElementById("search-modal"),input=document.getElementById("search-query"),output=document.getElementById("search-results"),first=output.firstChild,last=output.lastChild,searchVisible=!1,indexed=!1,hasResults=!1;showButton.addEventListener("click",displaySearch),hideButton.addEventListener("click",hideSearch),wrapper.addEventListener("click",hideSearch),modal.addEventListener("click",function(e){return e.stopPropagation(),e.stopImmediatePropagation(),!1}),document.addEventListener("keydown",function(e){e.key=="/"&&(searchVisible||(e.preventDefault(),displaySearch())),e.key=="Escape"&&hideSearch(),e.key=="ArrowDown"&&searchVisible&&hasResults&&(e.preventDefault(),document.activeElement==input?first.focus():document.activeElement==last?last.focus():document.activeElement.parentElement.nextSibling.firstElementChild.focus()),e.key=="ArrowUp"&&searchVisible&&hasResults&&(e.preventDefault(),document.activeElement==input?input.focus():document.activeElement==first?input.focus():document.activeElement.parentElement.previousSibling.firstElementChild.focus())}),input.onkeyup=function(){executeQuery(this.value)};function displaySearch(){indexed||buildIndex(),searchVisible||(document.body.style.overflow="hidden",wrapper.style.visibility="visible",input.focus(),searchVisible=!0)}function hideSearch(){searchVisible&&(document.body.style.overflow="visible",wrapper.style.visibility="hidden",input.value="",output.innerHTML="",document.activeElement.blur(),searchVisible=!1)}function fetchJSON(e,t){var n=new XMLHttpRequest;n.onreadystatechange=function(){if(n.readyState===4&&n.status===200){var e=JSON.parse(n.responseText);t&&t(e)}},n.open("GET",e),n.send()}function buildIndex(){var e=wrapper.getAttribute("data-url"),e=e.replace(/\/?$/,"/");fetchJSON(e+"index.json",function(e){var t={shouldSort:!0,ignoreLocation:!0,threshold:0,includeMatches:!0,keys:[{name:"title",weight:.8},{name:"section",weight:.2},{name:"summary",weight:.6},{name:"content",weight:.4}]};fuse=new Fuse(e,t),indexed=!0})}function executeQuery(e){let n=fuse.search(e),t="";n.length>0?(n.forEach(function(e){t=t+`
  • + +
    +
    ${e.item.title}
    +
    ${e.item.section}·${e.item.date}
    +
    ${e.item.summary}
    +
    +
    +
    +
    +
  • `}),hasResults=!0):(t="",hasResults=!1),output.innerHTML=t,n.length>0&&(first=output.firstChild.firstElementChild,last=output.lastChild.firstElementChild)}scriptBundle=document.getElementById("script-bundle"),copyText=scriptBundle?scriptBundle.getAttribute("data-copy"):"Copy",copiedText=scriptBundle?scriptBundle.getAttribute("data-copied"):"Copied";function createCopyButton(e){const t=document.createElement("button");t.className="copy-button",t.type="button",t.ariaLabel=copyText,t.innerText=copyText,t.addEventListener("click",()=>copyCodeToClipboard(t,e)),addCopyButtonToDom(t,e)}async function copyCodeToClipboard(e,t){const n=t.querySelector(":last-child > .chroma > code").innerText;try{result=await navigator.permissions.query({name:"clipboard-write"}),result.state=="granted"||result.state=="prompt"?await navigator.clipboard.writeText(n):copyCodeBlockExecCommand(n,t)}catch{copyCodeBlockExecCommand(n,t)}finally{codeWasCopied(e)}}function copyCodeBlockExecCommand(e,t){const n=document.createElement("textArea");n.contentEditable="true",n.readOnly="false",n.className="copy-textarea",n.value=e,t.insertBefore(n,t.firstChild);const s=document.createRange();s.selectNodeContents(n);const o=window.getSelection();o.removeAllRanges(),o.addRange(s),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}function codeWasCopied(e){e.blur(),e.innerText=copiedText,setTimeout(function(){e.innerText=copyText},2e3)}function addCopyButtonToDom(e,t){t.insertBefore(e,t.firstChild);const n=document.createElement("div");n.className="highlight-wrapper",t.parentNode.insertBefore(n,t),n.appendChild(t)}window.addEventListener("DOMContentLoaded",e=>{document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e))}) \ No newline at end of file diff --git a/public/lib/katex/auto-render.min.640fd13eb028f3c0e5c119e7a0d56a28836740d716111cd12b4dcf0da038188262559bc61485906dd582b1479b3197e45a88677e782c0e35f353a3e890ee231b.js b/public/lib/katex/auto-render.min.640fd13eb028f3c0e5c119e7a0d56a28836740d716111cd12b4dcf0da038188262559bc61485906dd582b1479b3197e45a88677e782c0e35f353a3e890ee231b.js new file mode 100644 index 0000000..c169ec6 --- /dev/null +++ b/public/lib/katex/auto-render.min.640fd13eb028f3c0e5c119e7a0d56a28836740d716111cd12b4dcf0da038188262559bc61485906dd582b1479b3197e45a88677e782c0e35f353a3e890ee231b.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format "},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color ",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro ",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness ",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size ",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand ",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function m(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var c=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},h)if(h.hasOwnProperty(t)){var r=h[t];this[t]=void 0!==e[t]?r.processor?r.processor(e[t]):e[t]:m(r)}}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),u=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return p[d[this.id]]},t.sub=function(){return p[f[this.id]]},t.fracNum=function(){return p[g[this.id]]},t.fracDen=function(){return p[v[this.id]]},t.cramp=function(){return p[b[this.id]]},t.text=function(){return p[y[this.id]]},t.isTight=function(){return this.size>=2},e}(),p=[new u(0,0,!1),new u(1,0,!0),new u(2,1,!1),new u(3,1,!0),new u(4,2,!1),new u(5,2,!0),new u(6,3,!1),new u(7,3,!0)],d=[4,5,4,5,6,7,6,7],f=[5,5,5,5,7,7,7,7],g=[2,3,4,5,6,7,6,7],v=[3,3,5,5,7,7,7,7],b=[1,1,3,3,5,5,7,7],y=[0,1,2,3,2,3,2,3],x={DISPLAY:p[0],TEXT:p[2],SCRIPT:p[4],SCRIPTSCRIPT:p[6]},w=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var k=[];function S(e){for(var t=0;t=k[t]&&e<=k[t+1])return!0;return!1}w.forEach((function(e){return e.blocks.forEach((function(e){return k.push.apply(k,e)}))}));var M=80,z={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},A=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t=5?0:e>=3?1:2]){var r=N[t]={cssEmPerMu:B.quad[t]/18};for(var n in B)B.hasOwnProperty(n)&&(r[n]=B[n][t])}return N[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();H.BASESIZE=6;var E=H,L={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},D={ex:!0,em:!0,mu:!0},P=function(e){return"string"!=typeof e&&(e=e.unit),e in L||e in D||"ex"===e},F=function(e,t){var r;if(e.unit in L)r=L[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},V=function(e){return+e.toFixed(4)+"em"},G=function(e){return e.filter((function(e){return e})).join(" ")},U=function(e,t,r){if(this.classes=e||[],this.attributes={},this.height=0,this.depth=0,this.maxFontSize=0,this.style=r||{},t){t.style.isTight()&&this.classes.push("mtight");var n=t.getColor();n&&(this.style.color=n)}},Y=function(e){var t=document.createElement(e);for(var r in t.className=G(this.classes),this.style)this.style.hasOwnProperty(r)&&(t.style[r]=this.style[r]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&t.setAttribute(n,this.attributes[n]);for(var a=0;a"},W=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"span")},t.toMarkup=function(){return X.call(this,"span")},e}(),_=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"a")},t.toMarkup=function(){return X.call(this,"a")},e}(),j=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=$[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=V(this.italic)),this.classes.length>0&&((t=t||document.createElement("span")).className=G(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+=""):a},e}(),K=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),Q=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),ie(oe,le,be,"\u2208","\\in",!0),ie(oe,le,be,"\ue020","\\@not"),ie(oe,le,be,"\u2282","\\subset",!0),ie(oe,le,be,"\u2283","\\supset",!0),ie(oe,le,be,"\u2286","\\subseteq",!0),ie(oe,le,be,"\u2287","\\supseteq",!0),ie(oe,he,be,"\u2288","\\nsubseteq",!0),ie(oe,he,be,"\u2289","\\nsupseteq",!0),ie(oe,le,be,"\u22a8","\\models"),ie(oe,le,be,"\u2190","\\leftarrow",!0),ie(oe,le,be,"\u2264","\\le"),ie(oe,le,be,"\u2264","\\leq",!0),ie(oe,le,be,"<","\\lt",!0),ie(oe,le,be,"\u2192","\\rightarrow",!0),ie(oe,le,be,"\u2192","\\to"),ie(oe,he,be,"\u2271","\\ngeq",!0),ie(oe,he,be,"\u2270","\\nleq",!0),ie(oe,le,ye,"\xa0","\\ "),ie(oe,le,ye,"\xa0","\\space"),ie(oe,le,ye,"\xa0","\\nobreakspace"),ie(se,le,ye,"\xa0","\\ "),ie(se,le,ye,"\xa0"," "),ie(se,le,ye,"\xa0","\\space"),ie(se,le,ye,"\xa0","\\nobreakspace"),ie(oe,le,ye,null,"\\nobreak"),ie(oe,le,ye,null,"\\allowbreak"),ie(oe,le,ve,",",","),ie(oe,le,ve,";",";"),ie(oe,he,ce,"\u22bc","\\barwedge",!0),ie(oe,he,ce,"\u22bb","\\veebar",!0),ie(oe,le,ce,"\u2299","\\odot",!0),ie(oe,le,ce,"\u2295","\\oplus",!0),ie(oe,le,ce,"\u2297","\\otimes",!0),ie(oe,le,xe,"\u2202","\\partial",!0),ie(oe,le,ce,"\u2298","\\oslash",!0),ie(oe,he,ce,"\u229a","\\circledcirc",!0),ie(oe,he,ce,"\u22a1","\\boxdot",!0),ie(oe,le,ce,"\u25b3","\\bigtriangleup"),ie(oe,le,ce,"\u25bd","\\bigtriangledown"),ie(oe,le,ce,"\u2020","\\dagger"),ie(oe,le,ce,"\u22c4","\\diamond"),ie(oe,le,ce,"\u22c6","\\star"),ie(oe,le,ce,"\u25c3","\\triangleleft"),ie(oe,le,ce,"\u25b9","\\triangleright"),ie(oe,le,ge,"{","\\{"),ie(se,le,xe,"{","\\{"),ie(se,le,xe,"{","\\textbraceleft"),ie(oe,le,ue,"}","\\}"),ie(se,le,xe,"}","\\}"),ie(se,le,xe,"}","\\textbraceright"),ie(oe,le,ge,"{","\\lbrace"),ie(oe,le,ue,"}","\\rbrace"),ie(oe,le,ge,"[","\\lbrack",!0),ie(se,le,xe,"[","\\lbrack",!0),ie(oe,le,ue,"]","\\rbrack",!0),ie(se,le,xe,"]","\\rbrack",!0),ie(oe,le,ge,"(","\\lparen",!0),ie(oe,le,ue,")","\\rparen",!0),ie(se,le,xe,"<","\\textless",!0),ie(se,le,xe,">","\\textgreater",!0),ie(oe,le,ge,"\u230a","\\lfloor",!0),ie(oe,le,ue,"\u230b","\\rfloor",!0),ie(oe,le,ge,"\u2308","\\lceil",!0),ie(oe,le,ue,"\u2309","\\rceil",!0),ie(oe,le,xe,"\\","\\backslash"),ie(oe,le,xe,"\u2223","|"),ie(oe,le,xe,"\u2223","\\vert"),ie(se,le,xe,"|","\\textbar",!0),ie(oe,le,xe,"\u2225","\\|"),ie(oe,le,xe,"\u2225","\\Vert"),ie(se,le,xe,"\u2225","\\textbardbl"),ie(se,le,xe,"~","\\textasciitilde"),ie(se,le,xe,"\\","\\textbackslash"),ie(se,le,xe,"^","\\textasciicircum"),ie(oe,le,be,"\u2191","\\uparrow",!0),ie(oe,le,be,"\u21d1","\\Uparrow",!0),ie(oe,le,be,"\u2193","\\downarrow",!0),ie(oe,le,be,"\u21d3","\\Downarrow",!0),ie(oe,le,be,"\u2195","\\updownarrow",!0),ie(oe,le,be,"\u21d5","\\Updownarrow",!0),ie(oe,le,fe,"\u2210","\\coprod"),ie(oe,le,fe,"\u22c1","\\bigvee"),ie(oe,le,fe,"\u22c0","\\bigwedge"),ie(oe,le,fe,"\u2a04","\\biguplus"),ie(oe,le,fe,"\u22c2","\\bigcap"),ie(oe,le,fe,"\u22c3","\\bigcup"),ie(oe,le,fe,"\u222b","\\int"),ie(oe,le,fe,"\u222b","\\intop"),ie(oe,le,fe,"\u222c","\\iint"),ie(oe,le,fe,"\u222d","\\iiint"),ie(oe,le,fe,"\u220f","\\prod"),ie(oe,le,fe,"\u2211","\\sum"),ie(oe,le,fe,"\u2a02","\\bigotimes"),ie(oe,le,fe,"\u2a01","\\bigoplus"),ie(oe,le,fe,"\u2a00","\\bigodot"),ie(oe,le,fe,"\u222e","\\oint"),ie(oe,le,fe,"\u222f","\\oiint"),ie(oe,le,fe,"\u2230","\\oiiint"),ie(oe,le,fe,"\u2a06","\\bigsqcup"),ie(oe,le,fe,"\u222b","\\smallint"),ie(se,le,pe,"\u2026","\\textellipsis"),ie(oe,le,pe,"\u2026","\\mathellipsis"),ie(se,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u22ef","\\@cdots",!0),ie(oe,le,pe,"\u22f1","\\ddots",!0),ie(oe,le,xe,"\u22ee","\\varvdots"),ie(oe,le,me,"\u02ca","\\acute"),ie(oe,le,me,"\u02cb","\\grave"),ie(oe,le,me,"\xa8","\\ddot"),ie(oe,le,me,"~","\\tilde"),ie(oe,le,me,"\u02c9","\\bar"),ie(oe,le,me,"\u02d8","\\breve"),ie(oe,le,me,"\u02c7","\\check"),ie(oe,le,me,"^","\\hat"),ie(oe,le,me,"\u20d7","\\vec"),ie(oe,le,me,"\u02d9","\\dot"),ie(oe,le,me,"\u02da","\\mathring"),ie(oe,le,de,"\ue131","\\@imath"),ie(oe,le,de,"\ue237","\\@jmath"),ie(oe,le,xe,"\u0131","\u0131"),ie(oe,le,xe,"\u0237","\u0237"),ie(se,le,xe,"\u0131","\\i",!0),ie(se,le,xe,"\u0237","\\j",!0),ie(se,le,xe,"\xdf","\\ss",!0),ie(se,le,xe,"\xe6","\\ae",!0),ie(se,le,xe,"\u0153","\\oe",!0),ie(se,le,xe,"\xf8","\\o",!0),ie(se,le,xe,"\xc6","\\AE",!0),ie(se,le,xe,"\u0152","\\OE",!0),ie(se,le,xe,"\xd8","\\O",!0),ie(se,le,me,"\u02ca","\\'"),ie(se,le,me,"\u02cb","\\`"),ie(se,le,me,"\u02c6","\\^"),ie(se,le,me,"\u02dc","\\~"),ie(se,le,me,"\u02c9","\\="),ie(se,le,me,"\u02d8","\\u"),ie(se,le,me,"\u02d9","\\."),ie(se,le,me,"\xb8","\\c"),ie(se,le,me,"\u02da","\\r"),ie(se,le,me,"\u02c7","\\v"),ie(se,le,me,"\xa8",'\\"'),ie(se,le,me,"\u02dd","\\H"),ie(se,le,me,"\u25ef","\\textcircled");var we={"--":!0,"---":!0,"``":!0,"''":!0};ie(se,le,xe,"\u2013","--",!0),ie(se,le,xe,"\u2013","\\textendash"),ie(se,le,xe,"\u2014","---",!0),ie(se,le,xe,"\u2014","\\textemdash"),ie(se,le,xe,"\u2018","`",!0),ie(se,le,xe,"\u2018","\\textquoteleft"),ie(se,le,xe,"\u2019","'",!0),ie(se,le,xe,"\u2019","\\textquoteright"),ie(se,le,xe,"\u201c","``",!0),ie(se,le,xe,"\u201c","\\textquotedblleft"),ie(se,le,xe,"\u201d","''",!0),ie(se,le,xe,"\u201d","\\textquotedblright"),ie(oe,le,xe,"\xb0","\\degree",!0),ie(se,le,xe,"\xb0","\\degree"),ie(se,le,xe,"\xb0","\\textdegree",!0),ie(oe,le,xe,"\xa3","\\pounds"),ie(oe,le,xe,"\xa3","\\mathsterling",!0),ie(se,le,xe,"\xa3","\\pounds"),ie(se,le,xe,"\xa3","\\textsterling",!0),ie(oe,he,xe,"\u2720","\\maltese"),ie(se,he,xe,"\u2720","\\maltese");for(var ke='0123456789/@."',Se=0;Set&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Xe=function(e,t,r,n){var a=new W(e,t,r,n);return Ye(a),a},We=function(e,t,r,n){return new W(e,t,r,n)},_e=function(e){var t=new A(e);return Ye(t),t},je=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},$e={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},Ze={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},Ke={fontMap:$e,makeSymbol:Ge,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&Ve(e,"Main-Bold",t).metrics?Ge(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===ae[t][e].font?Ge(e,"Main-Regular",t,r,n):Ge(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Xe,makeSvgSpan:We,makeLineSpan:function(e,t,r){var n=Xe([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=V(n.height),n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new _(e,t,r,n);return Ye(a),a},makeFragment:_e,wrapFragment:function(e,t){return e instanceof A?Xe([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(kt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(kt(s,t)),r?((i=kt(ft(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var m=mt(["katex-html"],o);if(m.setAttribute("aria-hidden","true"),i){var c=i.children[0];c.style.height=V(m.height+m.depth),m.depth&&(c.style.verticalAlign=V(-m.depth))}return m}function Mt(e){return new A(e)}var zt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=G(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(G(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),At=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Tt={MathNode:zt,TextNode:At,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",V(this.width)),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:Mt},Bt=function(e,t,r){return!ae[t][e]||!ae[t][e].replace||55349===e.charCodeAt(0)||we.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.substr(4,2)||r.font&&"tt"===r.font.substr(4,2))||(e=ae[t][e].replace),new Tt.TextNode(e)},Ct=function(e){return 1===e.length?e[0]:new Tt.MathNode("mrow",e)},qt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(ae[n][a]&&ae[n][a].replace&&(a=ae[n][a].replace),q(a,Ke.fontMap[r].fontName,n)?Ke.fontMap[r].variant:null)},Nt=function(e,t,r){if(1===e.length){var n=Rt(e[0],t);return r&&n instanceof zt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},It=function(e,t,r){return Ct(Nt(e,t,r))},Rt=function(e,t){if(!e)return new Tt.MathNode("mrow");if(it[e.type])return it[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ot(e,t,r,n,a){var i,o=Nt(e,r);i=1===o.length&&o[0]instanceof zt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Tt.MathNode("mrow",o);var s=new Tt.MathNode("annotation",[new Tt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Tt.MathNode("semantics",[i,s]),m=new Tt.MathNode("math",[h]);m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&m.setAttribute("display","block");var c=a?"katex":"katex-mathml";return Ke.makeSpan([c],[m])}var Ht=function(e){return new E({style:e.displayMode?x.DISPLAY:x.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Et=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=Ke.makeSpan(r,[e])}return e},Lt=function(e,t,r){var n,a=Ht(r);if("mathml"===r.output)return Ot(e,t,a,r.displayMode,!0);if("html"===r.output){var i=St(e,a);n=Ke.makeSpan(["katex"],[i])}else{var o=Ot(e,t,a,r.displayMode,!1),s=St(e,a);n=Ke.makeSpan(["katex"],[o,s])}return Et(n,r)},Dt={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Pt={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Ft=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=Ke.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new K(l,{width:"100%",height:V(o)});i=Ke.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=V(o),i},Vt=function(e){var t=new Tt.MathNode("mo",[new Tt.TextNode(Dt[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Gt=function(e,t){var r=function(){var r=4e5,n=e.label.substr(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var m=new J(i),c=new K([m],{width:"100%",height:V(o),viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:Ke.makeSvgSpan([],[c],t),minWidth:0,height:o}}var u,p,d,f=[],g=Pt[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=V(a)),n};function Ut(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Yt(e){var t=Xt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Xt(e){return e&&("atom"===e.type||re.hasOwnProperty(e.type))?e:null}var Wt=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ut(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof W)return e;throw new Error("Expected span but got "+String(e)+".")}(wt(e,t)),e.base=n):r=(n=Ut(e,"accent")).base;var i=wt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=ee(wt(s,t.havingCrampedStyle())).skew}var h,m="\\c"===n.label,c=m?i.height+i.depth:Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Gt(n,t),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+V(2*o)+")",marginLeft:V(2*o)}:void 0}]},t);else{var u,p;"\\vec"===n.label?(u=Ke.staticSvg("vec",t),p=Ke.svgData.vec[1]):((u=ee(u=Ke.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,p=u.width,m&&(c+=u.depth)),h=Ke.makeSpan(["accent-body"],[u]);var d="\\textcircled"===n.label;d&&(h.classes.push("accent-full"),c=i.height);var f=o;d||(f-=p/2),h.style.left=V(f),"\\textcircled"===n.label&&(h.style.top=".2em"),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-c},{type:"elem",elem:h}]},t)}var g=Ke.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=g,a.height=Math.max(g.height,a.height),a.classes[0]="mord",a):g},_t=function(e,t){var r=e.isStretchy?Vt(e.label):new Tt.MathNode("mo",[Bt(e.label,e.mode)]),n=new Tt.MathNode("mover",[Rt(e.base,t),r]);return n.setAttribute("accent","true"),n},jt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));ot({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=lt(t[0]),n=!jt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:function(e,t){var r=t[0],n=e.parser.mode;return"math"===n&&(e.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+e.funcName+" works only in text mode"),n="text"),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=wt(e.base,t),n=Gt(e,t),a="\\utilde"===e.label?.12:0,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Vt(e.label),n=new Tt.MathNode("munder",[Rt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var $t=function(e){var t=new Tt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};ot({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=Ke.wrapFragment(wt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=Ke.wrapFragment(wt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Gt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,m=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(m-=i.depth),r){var c=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:c}]},t)}else s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),Ke.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Vt(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=$t(Rt(e.body,t));if(e.below){var i=$t(Rt(e.below,t));r=new Tt.MathNode("munderover",[n,i,a])}else r=new Tt.MathNode("mover",[n,a])}else if(e.below){var o=$t(Rt(e.below,t));r=new Tt.MathNode("munder",[n,o])}else r=$t(),r=new Tt.MathNode("mover",[n,r]);return r}});var Zt={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},Kt=function(e){return"textord"===e.type&&"@"===e.text};function Jt(e,t,r){var n=Zt[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}ot({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=Ke.wrapFragment(wt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=V(.8-n.depth),n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mrow",[Rt(e.label,t)]);return(r=new Tt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Tt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),ot({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=Ke.wrapFragment(wt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Tt.MathNode("mrow",[Rt(e.fragment,t)])}}),ot({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ut(t[0],"ordgroup").body,i="",o=0;o=1114111)throw new n("\\@char with invalid code point "+i);return l<=65535?s=String.fromCharCode(l):(l-=65536,s=String.fromCharCode(55296+(l>>10),56320+(1023&l))),{type:"textord",mode:r.mode,text:s}}});var Qt=function(e,t){var r=ft(e.body,t.withColor(e.color),!1);return Ke.makeFragment(r)},er=function(e,t){var r=Nt(e.body,t.withColor(e.color)),n=new Tt.MathNode("mstyle",r);return n.setAttribute("mathcolor",e.color),n};ot({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var r=e.parser,n=Ut(t[0],"color-token").color,a=t[1];return{type:"color",mode:r.mode,color:n,body:ht(a)}},htmlBuilder:Qt,mathmlBuilder:er}),ot({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,n=e.breakOnTokenText,a=Ut(t[0],"color-token").color;r.gullet.macros.set("\\current@color",a);var i=r.parseExpression(!0,n);return{type:"color",mode:r.mode,color:a,body:i}},htmlBuilder:Qt,mathmlBuilder:er}),ot({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:1,argTypes:["size"],allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=r[0],i=!n.settings.displayMode||!n.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:n.mode,newLine:i,size:a&&Ut(a,"size").value}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=V(F(e.size,t)))),r},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",V(F(e.size,t)))),r}});var tr={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},rr=function(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new n("Expected a control sequence",e);return t},nr=function(e,t,r,n){var a=e.gullet.macros.get(r.text);null==a&&(r.noexpand=!0,a={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,a,n)};ot({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,r=e.funcName;t.consumeSpaces();var a=t.fetch();if(tr[a.text])return"\\global"!==r&&"\\\\globallong"!==r||(a.text=tr[a.text]),Ut(t.parseFunction(),"internal");throw new n("Invalid token after macro prefix",a)}}),ot({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,a=t.gullet.popToken(),i=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(i))throw new n("Expected a control sequence",a);for(var o,s=0,l=[[]];"{"!==t.gullet.future().text;)if("#"===(a=t.gullet.popToken()).text){if("{"===t.gullet.future().text){o=t.gullet.future(),l[s].push("{");break}if(a=t.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new n('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new n('Argument number "'+a.text+'" out of order');s++,l.push([])}else{if("EOF"===a.text)throw new n("Expected a macro definition");l[s].push(a.text)}var h=t.gullet.consumeArg().tokens;return o&&h.unshift(o),"\\edef"!==r&&"\\xdef"!==r||(h=t.gullet.expandTokens(h)).reverse(),t.gullet.macros.set(i,{tokens:h,numArgs:s,delimiters:l},r===tr[r]),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=rr(t.gullet.popToken());t.gullet.consumeSpaces();var a=function(e){var t=e.gullet.popToken();return"="===t.text&&" "===(t=e.gullet.popToken()).text&&(t=e.gullet.popToken()),t}(t);return nr(t,n,a,"\\\\globallet"===r),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=rr(t.gullet.popToken()),a=t.gullet.popToken(),i=t.gullet.popToken();return nr(t,n,i,"\\\\globalfuture"===r),t.gullet.pushToken(i),t.gullet.pushToken(a),{type:"internal",mode:t.mode}}});var ar=function(e,t,r){var n=q(ae.math[e]&&ae.math[e].replace||e,t,r);if(!n)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return n},ir=function(e,t,r,n){var a=r.havingBaseStyle(t),i=Ke.makeSpan(n.concat(a.sizingClasses(r)),[e],r),o=a.sizeMultiplier/r.sizeMultiplier;return i.height*=o,i.depth*=o,i.maxFontSize=a.sizeMultiplier,i},or=function(e,t,r){var n=t.havingBaseStyle(r),a=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=V(a),e.height-=a,e.depth+=a},sr=function(e,t,r,n,a,i){var o=function(e,t,r,n){return Ke.makeSymbol(e,"Size"+t+"-Regular",r,n)}(e,t,a,n),s=ir(Ke.makeSpan(["delimsizing","size"+t],[o],n),x.TEXT,n,i);return r&&or(s,n,x.TEXT),s},lr=function(e,t,r){var n;return n="Size1-Regular"===t?"delim-size1":"delim-size4",{type:"elem",elem:Ke.makeSpan(["delimsizinginner",n],[Ke.makeSpan([],[Ke.makeSymbol(e,t,r)])])}},hr=function(e,t,r){var n=T["Size4-Regular"][e.charCodeAt(0)]?T["Size4-Regular"][e.charCodeAt(0)][4]:T["Size1-Regular"][e.charCodeAt(0)][4],a=new J("inner",function(e,t){switch(e){case"\u239c":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"\u2223":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"\u2225":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"\u239f":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"\u23a2":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"\u23a5":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"\u23aa":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"\u23d0":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"\u2016":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),i=new K([a],{width:V(n),height:V(t),style:"width:"+V(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),o=Ke.makeSvgSpan([],[i],r);return o.height=t,o.style.height=V(t),o.style.width=V(n),{type:"elem",elem:o}},mr={type:"kern",size:-.008},cr=["|","\\lvert","\\rvert","\\vert"],ur=["\\|","\\lVert","\\rVert","\\Vert"],pr=function(e,t,r,n,a,i){var o,s,h,m;o=h=m=e,s=null;var c="Size1-Regular";"\\uparrow"===e?h=m="\u23d0":"\\Uparrow"===e?h=m="\u2016":"\\downarrow"===e?o=h="\u23d0":"\\Downarrow"===e?o=h="\u2016":"\\updownarrow"===e?(o="\\uparrow",h="\u23d0",m="\\downarrow"):"\\Updownarrow"===e?(o="\\Uparrow",h="\u2016",m="\\Downarrow"):l.contains(cr,e)?h="\u2223":l.contains(ur,e)?h="\u2225":"["===e||"\\lbrack"===e?(o="\u23a1",h="\u23a2",m="\u23a3",c="Size4-Regular"):"]"===e||"\\rbrack"===e?(o="\u23a4",h="\u23a5",m="\u23a6",c="Size4-Regular"):"\\lfloor"===e||"\u230a"===e?(h=o="\u23a2",m="\u23a3",c="Size4-Regular"):"\\lceil"===e||"\u2308"===e?(o="\u23a1",h=m="\u23a2",c="Size4-Regular"):"\\rfloor"===e||"\u230b"===e?(h=o="\u23a5",m="\u23a6",c="Size4-Regular"):"\\rceil"===e||"\u2309"===e?(o="\u23a4",h=m="\u23a5",c="Size4-Regular"):"("===e||"\\lparen"===e?(o="\u239b",h="\u239c",m="\u239d",c="Size4-Regular"):")"===e||"\\rparen"===e?(o="\u239e",h="\u239f",m="\u23a0",c="Size4-Regular"):"\\{"===e||"\\lbrace"===e?(o="\u23a7",s="\u23a8",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(o="\u23ab",s="\u23ac",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lgroup"===e||"\u27ee"===e?(o="\u23a7",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\rgroup"===e||"\u27ef"===e?(o="\u23ab",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lmoustache"===e||"\u23b0"===e?(o="\u23a7",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\rmoustache"!==e&&"\u23b1"!==e||(o="\u23ab",m="\u23a9",h="\u23aa",c="Size4-Regular");var u=ar(o,c,a),p=u.height+u.depth,d=ar(h,c,a),f=d.height+d.depth,g=ar(m,c,a),v=g.height+g.depth,b=0,y=1;if(null!==s){var w=ar(s,c,a);b=w.height+w.depth,y=2}var k=p+v+b,S=k+Math.max(0,Math.ceil((t-k)/(y*f)))*y*f,M=n.fontMetrics().axisHeight;r&&(M*=n.sizeMultiplier);var z=S/2-M,A=[];if(A.push(lr(m,c,a)),A.push(mr),null===s){var T=S-p-v+.016;A.push(hr(h,T,n))}else{var B=(S-p-v-b)/2+.016;A.push(hr(h,B,n)),A.push(mr),A.push(lr(s,c,a)),A.push(mr),A.push(hr(h,B,n))}A.push(mr),A.push(lr(o,c,a));var C=n.havingBaseStyle(x.TEXT),q=Ke.makeVList({positionType:"bottom",positionData:z,children:A},C);return ir(Ke.makeSpan(["delimsizing","mult"],[q],C),x.TEXT,n,i)},dr=.08,fr=function(e,t,r,n,a){var i=function(e,t,r){t*=1e3;var n="";switch(e){case"sqrtMain":n=function(e,t){return"M95,"+(622+e+t)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize1":n=function(e,t){return"M263,"+(601+e+t)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize2":n=function(e,t){return"M983 "+(10+e+t)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize3":n=function(e,t){return"M424,"+(2398+e+t)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" "+t+"\nh400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize4":n=function(e,t){return"M473,"+(2713+e+t)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"}(t,M);break;case"sqrtTall":n=function(e,t,r){return"M702 "+(e+t)+"H400000"+(40+e)+"\nH742v"+(r-54-t-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 "+t+"H400000v"+(40+e)+"H742z"}(t,M,r)}return n}(e,n,r),o=new J(e,i),s=new K([o],{width:"400em",height:V(t),viewBox:"0 0 400000 "+r,preserveAspectRatio:"xMinYMin slice"});return Ke.makeSvgSpan(["hide-tail"],[s],a)},gr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","\\surd"],vr=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1"],br=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],yr=[0,1.2,1.8,2.4,3],xr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],wr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"stack"}],kr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],Sr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},Mr=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},zr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(br,e)?xr:l.contains(gr,e)?kr:wr;var s=Mr(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=Ke.makeSymbol(e,"Main-Regular",a,n),s=ir(o,t,n,i);return r&&or(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?sr(e,s.size,r,n,a,i):pr(e,t,r,n,a,i)},Ar={sqrtImage:function(e,t){var r,n,a=t.havingBaseSizing(),i=Mr("\\surd",e*a.sizeMultiplier,kr,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,m=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=fr("sqrtMain",l=(1+s+dr)/o,m=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(m=1080*yr[i.size],h=(yr[i.size]+s)/o,l=(yr[i.size]+s+dr)/o,(r=fr("sqrtSize"+i.size,l,m,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+dr,h=e+s,m=Math.floor(1e3*e+s)+80,(r=fr("sqrtTall",l,m,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=V(l),{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},sizedDelim:function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(gr,e)||l.contains(br,e))return sr(e,t,!1,r,a,i);if(l.contains(vr,e))return pr(e,yr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},sizeToMaxHeight:yr,customSizedDelim:zr,leftRightDelim:function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return zr(e,h,!0,n,a,i)}},Tr={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Br=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Cr(e,t){var r=Xt(e);if(r&&l.contains(Br,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function qr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}ot({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Cr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Tr[e.funcName].size,mclass:Tr[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?Ke.makeSpan([e.mclass]):Ar.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(Bt(e.delim,e.mode));var r=new Tt.MathNode("mo",t);"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true");var n=V(Ar.sizeToMaxHeight[e.size]);return r.setAttribute("minsize",n),r.setAttribute("maxsize",n),r}}),ot({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Cr(t[0],e).text,color:r}}}),ot({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Cr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ut(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){qr(e);for(var r,n,a=ft(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[Rt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};ot({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=Ut(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),ot({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Rr={};function Or(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l1||!c)&&g.pop(),b.length0&&(y+=.25),m.push({pos:y,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=b)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,y+=S,z.pos=y,y+=M+B,h[r]=z,w(o[r+1])}var C,q,N=y/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],O=[];if(e.tags&&e.tags.some((function(e){return e})))for(r=0;r=s)){var W=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(W=l.deflt(P.pregap,p))&&((C=Ke.makeSpan(["arraycolsep"],[])).style.width=V(W),R.push(C));var _=[];for(r=0;r0){for(var K=Ke.makeLineSpan("hline",t,c),J=Ke.makeLineSpan("hdashline",t,c),Q=[{type:"elem",elem:h,shift:0}];m.length>0;){var ee=m.pop(),te=ee.pos-N;ee.isDashed?Q.push({type:"elem",elem:J,shift:te}):Q.push({type:"elem",elem:K,shift:te})}h=Ke.makeVList({positionType:"individualShift",children:Q},t)}if(0===O.length)return Ke.makeSpan(["mord"],[h],t);var re=Ke.makeVList({positionType:"individualShift",children:O},t);return re=Ke.makeSpan(["tag"],[re],t),Ke.makeFragment([h,re])},Xr={c:"center ",l:"left ",r:"right "},Wr=function(e,t){for(var r=[],n=new Tt.MathNode("mtd",[],["mtr-glue"]),a=new Tt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(c+="top ",g=1),"separator"===p[p.length-1].type&&(c+="bottom ",v-=1);for(var b=g;b0?"left ":"",c+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o="split"===e.envName,s=Gr(e.parser,{cols:a,addJot:!0,autoTag:o?void 0:Vr(e.envName),emptySingleRow:!0,colSeparationType:i,maxNumCols:o?2:void 0,leqno:e.parser.settings.leqno},"display"),l=0,h={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var m="",c=0;c0&&u&&(f=1),a[p]={type:"align",align:d,pregap:f,postgap:0}}return s.colSeparationType=u?"align":"alignat",s};Or({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Gr(e.parser,a,Ur(e.envName))},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Gr(e.parser,a,Ur(e.envName)),s=Math.max.apply(Math,[0].concat(o.body.map((function(e){return e.length}))));return o.cols=new Array(s).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Gr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Gr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Gr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Ur(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:_r,htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Fr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Vr(e.envName),emptySingleRow:!0,leqno:e.parser.settings.leqno};return Gr(e.parser,t,"display")},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:_r,htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Fr(e);var t={autoTag:Vr(e.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Gr(e.parser,t,"display")},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Fr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[c]);for(var d=0;d<2;d++){for(var f=!0,g=c+1;g=x.SCRIPT.id?r.text():x.DISPLAY:"text"===e&&r.size===x.DISPLAY.size?r=x.TEXT:"script"===e?r=x.SCRIPT:"scriptscript"===e&&(r=x.SCRIPTSCRIPT),r},nn=function(e,t){var r,n=rn(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=wt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*c:7*c,d=t.fontMetrics().denom1):(m>0?(u=t.fontMetrics().num2,p=c):(u=t.fontMetrics().num3,p=3*c),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*m)0&&(t="."===(t=e)?null:t),t};ot({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=lt(t[0]),s="atom"===o.type&&"open"===o.family?sn(o.text):null,l=lt(t[1]),h="atom"===l.type&&"close"===l.family?sn(l.text):null,m=Ut(t[2],"size"),c=null;r=!!m.isBlank||(c=m.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ut(p.body[0],"textord");u=on[Number(d.text)]}}else p=Ut(p,"textord"),u=on[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:c,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:nn,mathmlBuilder:an}),ot({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ut(t[0],"size").value,token:n}}}),ot({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ut(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:nn,mathmlBuilder:an});var ln=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?wt(e.sup,t.havingStyle(a.sup()),t):wt(e.sub,t.havingStyle(a.sub()),t),n=Ut(e.base,"horizBrace")):n=Ut(e,"horizBrace");var i,o=wt(n.base,t.havingBaseStyle(x.DISPLAY)),s=Gt(n,t);if(n.isOver?(i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=Ke.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):Ke.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};ot({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:ln,mathmlBuilder:function(e,t){var r=Vt(e.label);return new Tt.MathNode(e.isOver?"mover":"munder",[Rt(e.base,t),r])}}),ot({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ut(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ht(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ft(e.body,t,!1);return Ke.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=It(e.body,t);return r instanceof zt||(r=new zt("mrow",[r])),r.setAttribute("href",e.href),r}}),ot({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ut(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=F(e.totalheight,t)-r);var a=0;e.width.number>0&&(a=F(e.width,t));var i={height:V(r+n)};a>0&&(i.width=V(a)),n>0&&(i.verticalAlign=V(-n));var o=new j(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=F(e.height,t),a=0;if(e.totalheight.number>0&&(a=F(e.totalheight,t)-n,r.setAttribute("valign",V(-a))),r.setAttribute("height",V(n+a)),e.width.number>0){var i=F(e.width,t);r.setAttribute("width",V(i))}return r.setAttribute("src",e.src),r}}),ot({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ut(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return Ke.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=F(e.dimension,t);return new Tt.SpaceNode(r)}}),ot({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=Ke.makeSpan([],[wt(e.body,t)]),r=Ke.makeSpan(["inner"],[r],t)):r=Ke.makeSpan(["inner"],[wt(e.body,t)]);var n=Ke.makeSpan(["fix"],[]),a=Ke.makeSpan([e.alignment],[r,n],t),i=Ke.makeSpan(["strut"]);return i.style.height=V(a.height+a.depth),a.depth&&(i.style.verticalAlign=V(-a.depth)),a.children.unshift(i),a=Ke.makeSpan(["thinbox"],[a],t),Ke.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),ot({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),ot({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var mn=function(e,t){switch(t.style.size){case x.DISPLAY.size:return e.display;case x.TEXT.size:return e.text;case x.SCRIPT.size:return e.script;case x.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};ot({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ht(t[0]),text:ht(t[1]),script:ht(t[2]),scriptscript:ht(t[3])}},htmlBuilder:function(e,t){var r=mn(e,t),n=ft(r,t,!1);return Ke.makeFragment(n)},mathmlBuilder:function(e,t){var r=mn(e,t);return It(r,t)}});var cn=function(e,t,r,n,a,i,o){e=Ke.makeSpan([],[e]);var s,h,m,c=r&&l.isCharacterBox(r);if(t){var u=wt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=wt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;m=Ke.makeVList({positionType:"bottom",positionData:d,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:V(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:V(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;m=Ke.makeVList({positionType:"top",positionData:f,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:V(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;m=Ke.makeVList({positionType:"bottom",positionData:g,children:[{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:V(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}var v=[m];if(s&&0!==i&&!c){var b=Ke.makeSpan(["mspace"],[],n);b.style.marginRight=V(i),v.unshift(b)}return Ke.makeSpan(["mop","op-limits"],v,n)},un=["\\smallint"],pn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ut(e.base,"op"),i=!0):a=Ut(e,"op");var o,s=t.style,h=!1;if(s.size===x.DISPLAY.size&&a.symbol&&!l.contains(un,a.name)&&(h=!0),a.symbol){var m=h?"Size2-Regular":"Size1-Regular",c="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(c=a.name.substr(1),a.name="oiint"===c?"\\iint":"\\iiint"),o=Ke.makeSymbol(a.name,m,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),c.length>0){var u=o.italic,p=Ke.staticSvg(c+"Size"+(h?"2":"1"),t);o=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+c,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ft(a.body,t,!0);1===d.length&&d[0]instanceof Z?(o=d[0]).classes[0]="mop":o=Ke.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ft(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height",V(a)):(s.setAttribute("height",V(a)),s.setAttribute("depth",V(-a))),s.setAttribute("voffset",V(a)),s}});var yn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];ot({type:"sizing",names:yn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:yn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return bn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=Nt(e.body,r),a=new Tt.MathNode("mstyle",n);return a.setAttribute("mathsize",V(r.sizeMultiplier)),a}}),ot({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ut(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+c-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=V(m);var p=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(x.SCRIPTSCRIPT),f=wt(e.index,d,t),g=.6*(p.height-p.depth),v=Ke.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),b=Ke.makeSpan(["root"],[v]);return Ke.makeSpan(["mord","sqrt"],[b,p],t)}return Ke.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Tt.MathNode("mroot",[Rt(r,t),Rt(n,t)]):new Tt.MathNode("msqrt",[Rt(r,t)])}});var xn={display:x.DISPLAY,text:x.TEXT,script:x.SCRIPT,scriptscript:x.SCRIPTSCRIPT};ot({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r).withFont("");return bn(e.body,n,t)},mathmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r),a=Nt(e.body,n),i=new Tt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var wn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===x.DISPLAY.size||r.alwaysHandleSupSub)?pn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===x.DISPLAY.size||r.limits)?vn:null:"accent"===r.type?l.isCharacterBox(r.base)?Wt:null:"horizBrace"===r.type&&!e.sub===r.isOver?ln:null:null};st({type:"supsub",htmlBuilder:function(e,t){var r=wn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,m=wt(o,t),c=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=wt(s,f,t),d||(u=m.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=wt(h,g,t),d||(p=m.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===x.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;var v,b=t.sizeMultiplier,y=V(.5/c.ptPerEm/b),w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(m instanceof Z||k)&&(w=V(-m.italic))}if(n&&a){u=Math.max(u,i,n.depth+.25*c.xHeight),p=Math.max(p,c.sub2);var S=4*c.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:y,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:y}];v=Ke.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,c.sub1,a.height-.8*c.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:y}];v=Ke.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*c.xHeight),v=Ke.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:y}]},t)}var T=yt(m,"right")||"mord";return Ke.makeSpan([T],[m,Ke.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Rt(e.base,t)];if(e.sub&&i.push(Rt(e.sub,t)),e.sup&&i.push(Rt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===x.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===x.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===x.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===x.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===x.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===x.DISPLAY)?"mover":"msup"}return new Tt.MathNode(a,i)}}),st({type:"atom",htmlBuilder:function(e,t){return Ke.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[Bt(e.text,e.mode)]);if("bin"===e.family){var n=qt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var kn={mi:"italic",mn:"normal",mtext:"normal"};st({type:"mathord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mi",[Bt(e.text,e.mode,t)]),n=qt(e,t)||"italic";return n!==kn[r.type]&&r.setAttribute("mathvariant",n),r}}),st({type:"textord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=Bt(e.text,e.mode,t),a=qt(e,t)||"normal";return r="text"===e.mode?new Tt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Tt.MathNode("mn",[n]):"\\prime"===e.text?new Tt.MathNode("mo",[n]):new Tt.MathNode("mi",[n]),a!==kn[r.type]&&r.setAttribute("mathvariant",a),r}});var Sn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Mn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};st({type:"spacing",htmlBuilder:function(e,t){if(Mn.hasOwnProperty(e.text)){var r=Mn[e.text].className||"";if("text"===e.mode){var a=Ke.makeOrd(e,t,"textord");return a.classes.push(r),a}return Ke.makeSpan(["mspace",r],[Ke.mathsym(e.text,e.mode,t)],t)}if(Sn.hasOwnProperty(e.text))return Ke.makeSpan(["mspace",Sn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!Mn.hasOwnProperty(e.text)){if(Sn.hasOwnProperty(e.text))return new Tt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Tt.MathNode("mtext",[new Tt.TextNode("\xa0")])}});var zn=function(){var e=new Tt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};st({type:"tag",mathmlBuilder:function(e,t){var r=new Tt.MathNode("mtable",[new Tt.MathNode("mtr",[zn(),new Tt.MathNode("mtd",[It(e.body,t)]),zn(),new Tt.MathNode("mtd",[It(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var An={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Tn={"\\textbf":"textbf","\\textmd":"textmd"},Bn={"\\textit":"textit","\\textup":"textup"},Cn=function(e,t){var r=e.font;return r?An[r]?t.withTextFontFamily(An[r]):Tn[r]?t.withTextFontWeight(Tn[r]):t.withTextFontShape(Bn[r]):t};ot({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ht(a),font:n}},htmlBuilder:function(e,t){var r=Cn(e,t),n=ft(e.body,r,!0);return Ke.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Cn(e,t);return It(e.body,r)}}),ot({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=Ke.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[new Tt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Tt.MathNode("munder",[Rt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),ot({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return Ke.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Tt.MathNode("mpadded",[Rt(e.body,t)],["vcenter"])}}),ot({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=qn(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0;)this.endGroup()},t.has=function(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)},t.get=function(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]},t.set=function(e,t,r){if(void 0===r&&(r=!1),r){for(var n=0;n0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}null==t?delete this.current[e]:this.current[e]=t},e}(),Hn=Hr;Er("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Er("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Er("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Er("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Er("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Er("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Er("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var En={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Er("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=En[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=En[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Er("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Dn?t=Dn[r]:("\\not"===r.substr(0,4)||r in ae.math&&l.contains(["bin","rel"],ae.math[r].group))&&(t="\\dotsb"),t}));var Pn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Er("\\dotso",(function(e){return e.future().text in Pn?"\\ldots\\,":"\\ldots"})),Er("\\dotsc",(function(e){var t=e.future().text;return t in Pn&&","!==t?"\\ldots\\,":"\\ldots"})),Er("\\cdots",(function(e){return e.future().text in Pn?"\\@cdots\\,":"\\@cdots"})),Er("\\dotsb","\\cdots"),Er("\\dotsm","\\cdots"),Er("\\dotsi","\\!\\cdots"),Er("\\dotsx","\\ldots\\,"),Er("\\DOTSI","\\relax"),Er("\\DOTSB","\\relax"),Er("\\DOTSX","\\relax"),Er("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Er("\\,","\\tmspace+{3mu}{.1667em}"),Er("\\thinspace","\\,"),Er("\\>","\\mskip{4mu}"),Er("\\:","\\tmspace+{4mu}{.2222em}"),Er("\\medspace","\\:"),Er("\\;","\\tmspace+{5mu}{.2777em}"),Er("\\thickspace","\\;"),Er("\\!","\\tmspace-{3mu}{.1667em}"),Er("\\negthinspace","\\!"),Er("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Er("\\negthickspace","\\tmspace-{5mu}{.277em}"),Er("\\enspace","\\kern.5em "),Er("\\enskip","\\hskip.5em\\relax"),Er("\\quad","\\hskip1em\\relax"),Er("\\qquad","\\hskip2em\\relax"),Er("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Er("\\tag@paren","\\tag@literal{({#1})}"),Er("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Er("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Er("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Er("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Er("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Er("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),Er("\\newline","\\\\\\relax"),Er("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Fn=V(T["Main-Regular"]["T".charCodeAt(0)][1]-.7*T["Main-Regular"]["A".charCodeAt(0)][1]);Er("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Er("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Er("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Er("\\@hspace","\\hskip #1\\relax"),Er("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Er("\\ordinarycolon",":"),Er("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Er("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Er("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Er("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Er("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Er("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Er("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Er("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Er("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Er("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Er("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Er("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Er("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Er("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Er("\u2237","\\dblcolon"),Er("\u2239","\\eqcolon"),Er("\u2254","\\coloneqq"),Er("\u2255","\\eqqcolon"),Er("\u2a74","\\Coloneqq"),Er("\\ratio","\\vcentcolon"),Er("\\coloncolon","\\dblcolon"),Er("\\colonequals","\\coloneqq"),Er("\\coloncolonequals","\\Coloneqq"),Er("\\equalscolon","\\eqqcolon"),Er("\\equalscoloncolon","\\Eqqcolon"),Er("\\colonminus","\\coloneq"),Er("\\coloncolonminus","\\Coloneq"),Er("\\minuscolon","\\eqcolon"),Er("\\minuscoloncolon","\\Eqcolon"),Er("\\coloncolonapprox","\\Colonapprox"),Er("\\coloncolonsim","\\Colonsim"),Er("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Er("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Er("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Er("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Er("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Er("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Er("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Er("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Er("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Er("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Er("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Er("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Er("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Er("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Er("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Er("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Er("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Er("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Er("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Er("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Er("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Er("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Er("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Er("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Er("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Er("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Er("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Er("\\imath","\\html@mathml{\\@imath}{\u0131}"),Er("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Er("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Er("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Er("\u27e6","\\llbracket"),Er("\u27e7","\\rrbracket"),Er("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Er("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Er("\u2983","\\lBrace"),Er("\u2984","\\rBrace"),Er("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Er("\u29b5","\\minuso"),Er("\\darr","\\downarrow"),Er("\\dArr","\\Downarrow"),Er("\\Darr","\\Downarrow"),Er("\\lang","\\langle"),Er("\\rang","\\rangle"),Er("\\uarr","\\uparrow"),Er("\\uArr","\\Uparrow"),Er("\\Uarr","\\Uparrow"),Er("\\N","\\mathbb{N}"),Er("\\R","\\mathbb{R}"),Er("\\Z","\\mathbb{Z}"),Er("\\alef","\\aleph"),Er("\\alefsym","\\aleph"),Er("\\Alpha","\\mathrm{A}"),Er("\\Beta","\\mathrm{B}"),Er("\\bull","\\bullet"),Er("\\Chi","\\mathrm{X}"),Er("\\clubs","\\clubsuit"),Er("\\cnums","\\mathbb{C}"),Er("\\Complex","\\mathbb{C}"),Er("\\Dagger","\\ddagger"),Er("\\diamonds","\\diamondsuit"),Er("\\empty","\\emptyset"),Er("\\Epsilon","\\mathrm{E}"),Er("\\Eta","\\mathrm{H}"),Er("\\exist","\\exists"),Er("\\harr","\\leftrightarrow"),Er("\\hArr","\\Leftrightarrow"),Er("\\Harr","\\Leftrightarrow"),Er("\\hearts","\\heartsuit"),Er("\\image","\\Im"),Er("\\infin","\\infty"),Er("\\Iota","\\mathrm{I}"),Er("\\isin","\\in"),Er("\\Kappa","\\mathrm{K}"),Er("\\larr","\\leftarrow"),Er("\\lArr","\\Leftarrow"),Er("\\Larr","\\Leftarrow"),Er("\\lrarr","\\leftrightarrow"),Er("\\lrArr","\\Leftrightarrow"),Er("\\Lrarr","\\Leftrightarrow"),Er("\\Mu","\\mathrm{M}"),Er("\\natnums","\\mathbb{N}"),Er("\\Nu","\\mathrm{N}"),Er("\\Omicron","\\mathrm{O}"),Er("\\plusmn","\\pm"),Er("\\rarr","\\rightarrow"),Er("\\rArr","\\Rightarrow"),Er("\\Rarr","\\Rightarrow"),Er("\\real","\\Re"),Er("\\reals","\\mathbb{R}"),Er("\\Reals","\\mathbb{R}"),Er("\\Rho","\\mathrm{P}"),Er("\\sdot","\\cdot"),Er("\\sect","\\S"),Er("\\spades","\\spadesuit"),Er("\\sub","\\subset"),Er("\\sube","\\subseteq"),Er("\\supe","\\supseteq"),Er("\\Tau","\\mathrm{T}"),Er("\\thetasym","\\vartheta"),Er("\\weierp","\\wp"),Er("\\Zeta","\\mathrm{Z}"),Er("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Er("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Er("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Er("\\bra","\\mathinner{\\langle{#1}|}"),Er("\\ket","\\mathinner{|{#1}\\rangle}"),Er("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Er("\\Bra","\\left\\langle#1\\right|"),Er("\\Ket","\\left|#1\\right\\rangle");var Vn=function(e){return function(t){var r=t.consumeArg().tokens,n=t.consumeArg().tokens,a=t.consumeArg().tokens,i=t.consumeArg().tokens,o=t.macros.get("|"),s=t.macros.get("\\|");t.macros.beginGroup();var l=function(t){return function(r){e&&(r.macros.set("|",o),a.length&&r.macros.set("\\|",s));var i=t;!t&&a.length&&("|"===r.future().text&&(r.popToken(),i=!0));return{tokens:i?a:n,numArgs:0}}};t.macros.set("|",l(!1)),a.length&&t.macros.set("\\|",l(!0));var h=t.consumeArg().tokens,m=t.expandTokens([].concat(i,h,r));return t.macros.endGroup(),{tokens:m.reverse(),numArgs:0}}};Er("\\bra@ket",Vn(!1)),Er("\\bra@set",Vn(!0)),Er("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),Er("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),Er("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),Er("\\angln","{\\angl n}"),Er("\\blue","\\textcolor{##6495ed}{#1}"),Er("\\orange","\\textcolor{##ffa500}{#1}"),Er("\\pink","\\textcolor{##ff00af}{#1}"),Er("\\red","\\textcolor{##df0030}{#1}"),Er("\\green","\\textcolor{##28ae7b}{#1}"),Er("\\gray","\\textcolor{gray}{#1}"),Er("\\purple","\\textcolor{##9d38bd}{#1}"),Er("\\blueA","\\textcolor{##ccfaff}{#1}"),Er("\\blueB","\\textcolor{##80f6ff}{#1}"),Er("\\blueC","\\textcolor{##63d9ea}{#1}"),Er("\\blueD","\\textcolor{##11accd}{#1}"),Er("\\blueE","\\textcolor{##0c7f99}{#1}"),Er("\\tealA","\\textcolor{##94fff5}{#1}"),Er("\\tealB","\\textcolor{##26edd5}{#1}"),Er("\\tealC","\\textcolor{##01d1c1}{#1}"),Er("\\tealD","\\textcolor{##01a995}{#1}"),Er("\\tealE","\\textcolor{##208170}{#1}"),Er("\\greenA","\\textcolor{##b6ffb0}{#1}"),Er("\\greenB","\\textcolor{##8af281}{#1}"),Er("\\greenC","\\textcolor{##74cf70}{#1}"),Er("\\greenD","\\textcolor{##1fab54}{#1}"),Er("\\greenE","\\textcolor{##0d923f}{#1}"),Er("\\goldA","\\textcolor{##ffd0a9}{#1}"),Er("\\goldB","\\textcolor{##ffbb71}{#1}"),Er("\\goldC","\\textcolor{##ff9c39}{#1}"),Er("\\goldD","\\textcolor{##e07d10}{#1}"),Er("\\goldE","\\textcolor{##a75a05}{#1}"),Er("\\redA","\\textcolor{##fca9a9}{#1}"),Er("\\redB","\\textcolor{##ff8482}{#1}"),Er("\\redC","\\textcolor{##f9685d}{#1}"),Er("\\redD","\\textcolor{##e84d39}{#1}"),Er("\\redE","\\textcolor{##bc2612}{#1}"),Er("\\maroonA","\\textcolor{##ffbde0}{#1}"),Er("\\maroonB","\\textcolor{##ff92c6}{#1}"),Er("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Er("\\maroonD","\\textcolor{##ca337c}{#1}"),Er("\\maroonE","\\textcolor{##9e034e}{#1}"),Er("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Er("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Er("\\purpleC","\\textcolor{##aa87ff}{#1}"),Er("\\purpleD","\\textcolor{##7854ab}{#1}"),Er("\\purpleE","\\textcolor{##543b78}{#1}"),Er("\\mintA","\\textcolor{##f5f9e8}{#1}"),Er("\\mintB","\\textcolor{##edf2df}{#1}"),Er("\\mintC","\\textcolor{##e0e5cc}{#1}"),Er("\\grayA","\\textcolor{##f6f7f7}{#1}"),Er("\\grayB","\\textcolor{##f0f1f2}{#1}"),Er("\\grayC","\\textcolor{##e3e5e6}{#1}"),Er("\\grayD","\\textcolor{##d6d8da}{#1}"),Er("\\grayE","\\textcolor{##babec2}{#1}"),Er("\\grayF","\\textcolor{##888d93}{#1}"),Er("\\grayG","\\textcolor{##626569}{#1}"),Er("\\grayH","\\textcolor{##3b3e40}{#1}"),Er("\\grayI","\\textcolor{##21242c}{#1}"),Er("\\kaBlue","\\textcolor{##314453}{#1}"),Er("\\kaGreen","\\textcolor{##71B307}{#1}");var Gn={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},Un=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new On(Hn,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Rn(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Dr("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof Dr)return e.treatAsRelax&&(e.text="\\relax"),this.stack.pop()}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Dr(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof Dr&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Rn(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||Nn.hasOwnProperty(e)||ae.math.hasOwnProperty(e)||ae.text.hasOwnProperty(e)||Gn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:Nn.hasOwnProperty(e)&&!Nn[e].primitive},e}(),Yn=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,Xn=Object.freeze({"\u208a":"+","\u208b":"-","\u208c":"=","\u208d":"(","\u208e":")","\u2080":"0","\u2081":"1","\u2082":"2","\u2083":"3","\u2084":"4","\u2085":"5","\u2086":"6","\u2087":"7","\u2088":"8","\u2089":"9","\u2090":"a","\u2091":"e","\u2095":"h","\u1d62":"i","\u2c7c":"j","\u2096":"k","\u2097":"l","\u2098":"m","\u2099":"n","\u2092":"o","\u209a":"p","\u1d63":"r","\u209b":"s","\u209c":"t","\u1d64":"u","\u1d65":"v","\u2093":"x","\u1d66":"\u03b2","\u1d67":"\u03b3","\u1d68":"\u03c1","\u1d69":"\u03d5","\u1d6a":"\u03c7","\u207a":"+","\u207b":"-","\u207c":"=","\u207d":"(","\u207e":")","\u2070":"0","\xb9":"1","\xb2":"2","\xb3":"3","\u2074":"4","\u2075":"5","\u2076":"6","\u2077":"7","\u2078":"8","\u2079":"9","\u1d2c":"A","\u1d2e":"B","\u1d30":"D","\u1d31":"E","\u1d33":"G","\u1d34":"H","\u1d35":"I","\u1d36":"J","\u1d37":"K","\u1d38":"L","\u1d39":"M","\u1d3a":"N","\u1d3c":"O","\u1d3e":"P","\u1d3f":"R","\u1d40":"T","\u1d41":"U","\u2c7d":"V","\u1d42":"W","\u1d43":"a","\u1d47":"b","\u1d9c":"c","\u1d48":"d","\u1d49":"e","\u1da0":"f","\u1d4d":"g","\u02b0":"h","\u2071":"i","\u02b2":"j","\u1d4f":"k","\u02e1":"l","\u1d50":"m","\u207f":"n","\u1d52":"o","\u1d56":"p","\u02b3":"r","\u02e2":"s","\u1d57":"t","\u1d58":"u","\u1d5b":"v","\u02b7":"w","\u02e3":"x","\u02b8":"y","\u1dbb":"z","\u1d5d":"\u03b2","\u1d5e":"\u03b3","\u1d5f":"\u03b4","\u1d60":"\u03d5","\u1d61":"\u03c7","\u1dbf":"\u03b8"}),Wn={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},_n={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},jn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Un(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},t.subparse=function(e){var t=this.nextToken;this.consume(),this.gullet.pushToken(new Dr("}")),this.gullet.pushTokens(e);var r=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,r},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&Nn[a.text]&&Nn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=ae[this.mode][t].group,h=Lr.range(e);if(te.hasOwnProperty(l)){var m=l;s={type:"atom",mode:this.mode,family:m,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(S(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Lr.range(e),text:t}}if(this.consume(),o)for(var c=0;c.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} diff --git a/public/research/index.html b/public/research/index.html new file mode 100644 index 0000000..5eefdec --- /dev/null +++ b/public/research/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + Research · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + + +
    + +

    Research

    +
    +
    + +
    + +

    Overview #

    +

    My current research interests are focused on leveraging near-term quantum computers to solve problems in various domains, which include but are not limited to:

    +
      +
    • Simulation of many-body systems: creating exotic phases of matter, simulating phase transitions, improving techniques for Hamiltonian simulation with the help of machine learning, etc.
    • +
    • Optimization: exploring quantum optimization algorithms, such as the Quantum Approximate Optimization Algorithm (QAOA), Variational Quantum Eigensolver (VQE), etc. and their applications in life science problems such as protein folding and drug discovery
    • +
    • Machine learning: developing and benchmarking quantum machine learning algorithms for electronic health records, medical imaging, etc.
    • +
    +

    Things I have worked on in the past:

    +
      +
    • Topological materials: investigating novel spin/charge transport phenomena in topological semimetals, such as Weyl and Dirac semimetals
    • +
    • Dark matter models: studying the phenomenology of dark matter models in theories with a gauged baryon symmetry
    • +
    +
    +
    + + + + + + + + + + + I am always open to collaborations and discussions. Please feel free to reach out to me via the links in my + + homepage. +
    + + +
    +

    Publications #

    +
      +
    1. Kostas Blekos*, Dean Brand*, Andrea Ceschini*, Chiao-Hui Chou*, Rui-Hao Li*, Komal Pandya*, and Alessandro Summer*, A review on Quantum Approximate Optimization Algorithm and its variants, Phys. Rep. 1068, 1 (2024).
    2. +
    3. R.-H. Li*, P. Shen*, and S. S.-L. Zhang, Tunable spin-charge conversion in topological Dirac semimetals, APL Mater. 10, 041108 (2022).
    4. +
    5. R.-H. Li, O. G. Heinonen, A. A. Burkov, and S. S.-L. Zhang, Nonlinear Hall effect in Weyl semimetals induced by chiral anomaly, Phys. Rev. B 103, 045105 (2021).
    6. +
    7. P. Fileviez Pere*, E. Golias*, R.-H. Li*, C. Murgui*, and A. D. Plascencia*, Anomaly-free dark matter models, Phys. Rev. D 100, 015017 (2019).
    8. +
    9. P. Fileviez Perez*, E. Golias*, R.-H. Li*, and C. Murgui*, Leptophobic dark matter and the baryon number violation scale, Phys. Rev. D 99, 035009 (2019).
    10. +
    +

    [*]: denotes equal contribution

    +
    +

    Talks #

    + +
    +

    Miscellaneous Notes #

    + + +
    +
    + + + + + + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/research/index.xml b/public/research/index.xml new file mode 100644 index 0000000..e74d23a --- /dev/null +++ b/public/research/index.xml @@ -0,0 +1,12 @@ + + + + Research on Ruihao Li + http://localhost:1313/research/ + Recent content in Research on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + + + diff --git a/public/research/research_0622.svg b/public/research/research_0622.svg new file mode 100644 index 0000000..41a00e8 --- /dev/null +++ b/public/research/research_0622.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..5759686 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: / +Sitemap: http://localhost:1313/sitemap.xml diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..45dc8a2 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..9b09de6 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,97 @@ + + + + + + http://localhost:1313/ + 2023-01-09T00:00:00+00:00 + + + + + + http://localhost:1313/blog/ + 2023-01-09T00:00:00+00:00 + + + + + + + + + + http://localhost:1313/blog/2d-ising-model/ + 2023-01-09T00:00:00+00:00 + + + + + + + + http://localhost:1313/blog/blog-comments/ + 2022-07-03T00:00:00+00:00 + + + + + + + + + + http://localhost:1313/blog/ibm-spring-challenge-3/ + 2022-06-26T00:00:00+00:00 + + + + + + http://localhost:1313/blog/ibm-spring-challenge-2/ + 2022-06-18T00:00:00+00:00 + + + + + + http://localhost:1313/blog/ibm-spring-challenge-1/ + 2022-06-04T00:00:00+00:00 + + + + + + http://localhost:1313/blog/fish-shell-customization/ + 2022-05-08T00:00:00+00:00 + + + + + + http://localhost:1313/about/ + + + + + + + + http://localhost:1313/journal-club/ + + + + + + http://localhost:1313/journal-club/dgo_abstract/ + + + + + + http://localhost:1313/research/ + + + + diff --git a/public/tags/index.html b/public/tags/index.html new file mode 100644 index 0000000..96435f4 --- /dev/null +++ b/public/tags/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + Tags · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +
    + +

    Tags

    +
    + +
    + + + +
    +

    + Python + + · + + 1 + + +

    +
    + + + + + +
    + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/tags/index.xml b/public/tags/index.xml new file mode 100644 index 0000000..8ed92e0 --- /dev/null +++ b/public/tags/index.xml @@ -0,0 +1,41 @@ + + + + Tags on Ruihao Li + http://localhost:1313/tags/ + Recent content in Tags on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Mon, 09 Jan 2023 00:00:00 +0000 + + + Physics + http://localhost:1313/tags/physics/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/tags/physics/ + + + + Python + http://localhost:1313/tags/python/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/tags/python/ + + + + Software + http://localhost:1313/tags/software/ + Sun, 03 Jul 2022 00:00:00 +0000 + http://localhost:1313/tags/software/ + + + + Quantum Computing + http://localhost:1313/tags/quantum-computing/ + Sun, 26 Jun 2022 00:00:00 +0000 + http://localhost:1313/tags/quantum-computing/ + + + + diff --git a/public/tags/physics/index.html b/public/tags/physics/index.html new file mode 100644 index 0000000..677fda5 --- /dev/null +++ b/public/tags/physics/index.html @@ -0,0 +1,745 @@ + + + + + + + + + + + + Physics · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +
    + +

    Physics

    +
    + +
    + + +

    + 2023 +

    +
    + + + + + + + +

    + 2022 +

    +
    + + + + + + + + + + + + +
    + + + + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/tags/physics/index.xml b/public/tags/physics/index.xml new file mode 100644 index 0000000..d7fb49d --- /dev/null +++ b/public/tags/physics/index.xml @@ -0,0 +1,41 @@ + + + + Physics on Ruihao Li + http://localhost:1313/tags/physics/ + Recent content in Physics on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Mon, 09 Jan 2023 00:00:00 +0000 + + + Supercharging the Pythonic Metropolis Monte Carlo + http://localhost:1313/blog/2d-ising-model/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/blog/2d-ising-model/ + Okay, I&rsquo;ll admit that this is neither a super exciting nor a new topic to write about. + + + Quantum simulation of many-body physics - III + http://localhost:1313/blog/ibm-spring-challenge-3/ + Sun, 26 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-3/ + This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. + + + Quantum simulation of many-body physics - II + http://localhost:1313/blog/ibm-spring-challenge-2/ + Sat, 18 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-2/ + As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. + + + Quantum simulation of many-body physics - I + http://localhost:1313/blog/ibm-spring-challenge-1/ + Sat, 04 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-1/ + A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. + + + diff --git a/public/tags/physics/page/1/index.html b/public/tags/physics/page/1/index.html new file mode 100644 index 0000000..3f492d1 --- /dev/null +++ b/public/tags/physics/page/1/index.html @@ -0,0 +1,10 @@ + + + + http://localhost:1313/tags/physics/ + + + + + + diff --git a/public/tags/python/index.html b/public/tags/python/index.html new file mode 100644 index 0000000..6e321ae --- /dev/null +++ b/public/tags/python/index.html @@ -0,0 +1,503 @@ + + + + + + + + + + + + Python · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +
    + +

    Python

    +
    + +
    + + +

    + 2023 +

    +
    + + + + + + +
    + + + + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/tags/python/index.xml b/public/tags/python/index.xml new file mode 100644 index 0000000..7f7c73f --- /dev/null +++ b/public/tags/python/index.xml @@ -0,0 +1,20 @@ + + + + Python on Ruihao Li + http://localhost:1313/tags/python/ + Recent content in Python on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Mon, 09 Jan 2023 00:00:00 +0000 + + + Supercharging the Pythonic Metropolis Monte Carlo + http://localhost:1313/blog/2d-ising-model/ + Mon, 09 Jan 2023 00:00:00 +0000 + http://localhost:1313/blog/2d-ising-model/ + Okay, I&rsquo;ll admit that this is neither a super exciting nor a new topic to write about. + + + diff --git a/public/tags/python/page/1/index.html b/public/tags/python/page/1/index.html new file mode 100644 index 0000000..d318f1b --- /dev/null +++ b/public/tags/python/page/1/index.html @@ -0,0 +1,10 @@ + + + + http://localhost:1313/tags/python/ + + + + + + diff --git a/public/tags/quantum-computing/index.html b/public/tags/quantum-computing/index.html new file mode 100644 index 0000000..08a62b8 --- /dev/null +++ b/public/tags/quantum-computing/index.html @@ -0,0 +1,659 @@ + + + + + + + + + + + + Quantum Computing · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +
    + +

    Quantum Computing

    +
    + +
    + + +

    + 2022 +

    +
    + + + + + + + + + + + + +
    + + + + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/tags/quantum-computing/index.xml b/public/tags/quantum-computing/index.xml new file mode 100644 index 0000000..444bfbc --- /dev/null +++ b/public/tags/quantum-computing/index.xml @@ -0,0 +1,34 @@ + + + + Quantum Computing on Ruihao Li + http://localhost:1313/tags/quantum-computing/ + Recent content in Quantum Computing on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Sun, 26 Jun 2022 00:00:00 +0000 + + + Quantum simulation of many-body physics - III + http://localhost:1313/blog/ibm-spring-challenge-3/ + Sun, 26 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-3/ + This is the third and final blog post of the 2022 IBM Spring Challenge series where I introduce some basic concepts and implementations of quantum simulation of many-body physics. + + + Quantum simulation of many-body physics - II + http://localhost:1313/blog/ibm-spring-challenge-2/ + Sat, 18 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-2/ + As promised in the previous blog post, we will now continue our journey into the world of many-body physics simulations with quantum computers. + + + Quantum simulation of many-body physics - I + http://localhost:1313/blog/ibm-spring-challenge-1/ + Sat, 04 Jun 2022 00:00:00 +0000 + http://localhost:1313/blog/ibm-spring-challenge-1/ + A few weeks ago I participated in the IBM Quantum Spring Challenge 2022, which was a fun challenge to do because one of the topics covered is actually close to my heart, which is on quantum simulations of many-body systems in condensed matter physics. + + + diff --git a/public/tags/quantum-computing/page/1/index.html b/public/tags/quantum-computing/page/1/index.html new file mode 100644 index 0000000..256b911 --- /dev/null +++ b/public/tags/quantum-computing/page/1/index.html @@ -0,0 +1,10 @@ + + + + http://localhost:1313/tags/quantum-computing/ + + + + + + diff --git a/public/tags/software/index.html b/public/tags/software/index.html new file mode 100644 index 0000000..dabd912 --- /dev/null +++ b/public/tags/software/index.html @@ -0,0 +1,569 @@ + + + + + + + + + + + + Software · Ruihao Li + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    + +
    + +

    Software

    +
    + +
    + + +

    + 2022 +

    +
    + + +
    +

    + + Adding blog comments + + + +

    +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + +
    + + + +
    + + + + + + Software + + + +
    + + + +
    + +
    + + + + + + +
    + + + + + +
    + + +
    +
    + + +

    + © + 2024 + Ruihao Li +

    + + + +

    + + + Powered by Hugo & Congo +

    + +
    + + +
    + +
    + +
    + + +
    + + +
    + + diff --git a/public/tags/software/index.xml b/public/tags/software/index.xml new file mode 100644 index 0000000..ca02ead --- /dev/null +++ b/public/tags/software/index.xml @@ -0,0 +1,27 @@ + + + + Software on Ruihao Li + http://localhost:1313/tags/software/ + Recent content in Software on Ruihao Li + Hugo -- gohugo.io + en + © 2022-2023 Ruihao Li + Sun, 03 Jul 2022 00:00:00 +0000 + + + Adding blog comments + http://localhost:1313/blog/blog-comments/ + Sun, 03 Jul 2022 00:00:00 +0000 + http://localhost:1313/blog/blog-comments/ + Comments widget by Utterances. + + + Fish shell and customization + http://localhost:1313/blog/fish-shell-customization/ + Sun, 08 May 2022 00:00:00 +0000 + http://localhost:1313/blog/fish-shell-customization/ + A quick peek at the shell interface. + + + diff --git a/public/tags/software/page/1/index.html b/public/tags/software/page/1/index.html new file mode 100644 index 0000000..1a19278 --- /dev/null +++ b/public/tags/software/page/1/index.html @@ -0,0 +1,10 @@ + + + + http://localhost:1313/tags/software/ + + + + + +