Skip to content

Instantly share code, notes, and snippets.

@quantum-kittens
Created August 11, 2020 08:14
Show Gist options
  • Save quantum-kittens/f66aed24b8a40fc1237fe336f8d9a67a to your computer and use it in GitHub Desktop.
Save quantum-kittens/f66aed24b8a40fc1237fe336f8d9a67a to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The Quantum Chai Maker\n",
"\n",
"Hey there! You're likely here because you love tea as much as I do. But did you know there's a whole world of flavors to explore? Let's use quantum computing to spice up your tea recipes, pun intended! \n",
"\n",
"Quantum computing is great for this flavor journey because it's probability based: every possible outcome (read, ingredient) has some probability of being selected!\n",
"\n",
"Here are the ingredients the Quantum Chai Maker will choose from:\n",
"\n",
"\n",
"| Tea | Mild Spices | Zesty Spices | Herbs | Misc. Flavors |\n",
"|---|---|---|---|---|\n",
"| black | cardamom (elaichi) | ginger (adrak) | peppermint | orange peel |\n",
"| green | fennel seeds (saunf) | black peppercorns | lemongrass | rose petals |\n",
"| | star anise | white peppercorns | licorice root (mulethi) | lemon |\n",
"| | bay leaves | cumin seeds (zeera) | chamomile | almond shavings/extract |\n",
"| | cloves (laung) | allspice | spearmint | cocoa |\n",
"| | cinnamon | carom seeds (ajwain) | coriander | coconut butter |\n",
"| | nutmeg | turmeric (haldi) | lavender | jasmine |\n",
"| | saffron (kesar) | paprika (lal mirch) | Indian ginseng (ashwaghandha) | |\n",
"| | vanilla bean/extract | | | |\n",
"| | holy basil (tulsi) | | | |\n",
"\n",
"\n",
"There are two types of tea to choose from, and four flavor categories. Some Hindi translations are provided in parentheses.\n",
"\n",
"### What the QCM does:\n",
"\n",
"1. Chooses between green and black tea.\n",
"2. Selects ingredient categories. Any number of categories and category combinations can be selected, from just one to all four.\n",
"3. Chooses the number of ingredients it wants from each of its selected categories.\n",
"4. Provides a special list of ingredients!\n",
"\n",
"Some points to note before you dive in:\n",
"\n",
"- **Sweeteners:** Sweeteners haven't been added, I've left that up to you. But here are some options: white sugar, brown sugar, agave syrup, honey, maple syrup, cane sugar, and stevia.\n",
"- **Milk:** Milk hasn't been added either. I recommend milk with black tea if you're looking for something more along the lines of desi chai. Some people who brew desi chai enjoy 'cooking' the milk and tea together if they're using dairy milk. If you're using other types of milk (soya, almond, etc.) I suggest you add the milk after brewing the tea. \n",
"- **Zesty spices:** Generally all flavorings should be used in small amounts so that none become overpowering, but take extra care with the spices in the 'Zesty Spices' category. \n",
"- **Qiskit:** We use IBM's Qiskit for the quantum computing parts. If you'd like to run it locally, you can install it: https://qiskit.org/documentation/install.html.\n",
"\n",
"If you're curious about the quantum concepts used to build this, I've added splashes of information in blocks and comments. If you're just here to make some tea, simply `shift+enter` your way to the end!\n",
"\n",
"**Disclaimer: Some combinations may turn out to be less than appealing. After all, we're working with probabilities, eh? You can choose which ingredients to use once the Chai Maker gives you a list! So, let's just agree to not blame me for any, erm, unpleasantness, shall we?**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The Code \n",
"\n",
"First, we have to import and install all the important stuff. We use IBM's Qiskit for the quantum computing parts. All circuits will be simulated with their `qasm_simulator` but feel free to modify the code to run it on a real backend!"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"!pip install qiskit\n",
"\n",
"from IPython.display import clear_output\n",
"clear_output()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from qiskit import *\n",
"import math\n",
"import numpy as np\n",
"import random\n",
"import itertools"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's store the ingredients in neat little lists."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"teas = ['black', 'green']\n",
"\n",
"mild_spices = ['cardamom (elaichi)', 'fennel seeds (saunf)', 'star anise', 'bay leaves', 'cloves (laung)', 'cinnamon', 'nutmeg', 'saffron (kesar)', 'vanilla bean/extract', 'holy basil (tulsi)']\n",
"\n",
"zesty_spices = [ 'ginger (adrak)', 'black peppercorns', 'white peppercorns', 'cumin seeds (zeera)', 'allspice', 'carom seeds (ajwain)', 'turmeric (haldi)', 'paprika (lal mirch)']\n",
"\n",
"herbs = ['peppermint', 'lemongrass', 'licorice root', 'chamomile', 'spearmint', 'coriander', 'lavender' ]\n",
"\n",
"misc_flavors = ['orange peel', 'rose petals', 'lemon', 'almond shavings/extract', 'cocoa', 'coconut butter', 'jasmine']\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to choose between green and black tea, we make use of one of the four Bell states, which are really nifty maximally entangled two qubit states used in some pretty cool applications!\n",
"\n",
"Specifically, we use the state:\n",
"\n",
"$\\mathcal{B} = \\frac{1}{\\sqrt{2}} (|01\\rangle + |10\\rangle)$\n",
"\n",
"The equation shows a superposition of two states: $|01\\rangle$ and $|10\\rangle$, where the first position within the $|\\rangle$ corresponds to the first qubit, and the second position corresponds to the second qubit.\n",
"\n",
"This means the two qubits are entangled such that if the first qubit is measured to be 0, the second qubit will definitely be a 1. And vice versa.\n",
"\n",
"In the context of tea, we're basically saying:\n",
"\n",
"$|$not_green, black$\\rangle + |$green, not_black$\\rangle$\n",
"\n",
"A measurement will result in just one of these two possibilities."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def which_tea():\n",
" # creates the Bell state (|01> + |10>)/sqrt(2) to choose between black and green tea\n",
" circ = QuantumCircuit(2,2) # create a quantum circuit with 2 qubits and 2 classical bits\n",
" circ.h(0) # Hadamard gate on qubit 0\n",
" circ.cx(0,1) # controlled x with qubit 0 as control and qubit 1 as target\n",
" circ.x(0) # x on qubit 0\n",
" circ.measure([0,1],[0,1]) # each qubit is measured, and the total outcome is either 01 or 10\n",
" job = qiskit.execute(circ, qiskit.BasicAer.get_backend('qasm_simulator') ) # run on qasm_simulator\n",
" result = job.result().get_counts() # result is a dict, with key = classical bit outcomes, value = number of counts\n",
" max_res = max(result, key=result.get) # find the result with the highest count\n",
" return teas[int(max_res,2)-1] #convert to decimal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For the rest of the decisions, we will simply make use of superposition. When a Hadamard gate operates on a qubit in the $|0\\rangle$ state we get:\n",
"\n",
"$H|0\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + |1\\rangle)$\n",
"\n",
"This means that upon measurement, the outcome is equally likely to be a 0 as it is a 1. There are two possible outcomes.\n",
"\n",
"If we have multiple qubits, we can have even more possible outcomes! Specifically, if we have $n$ qubits, there are $2^n$ possible outcomes.\n",
"\n",
"Suppose we want to choose a number between 0 and 7, that is, we have a choice among 8 numbers. If we use 3 qubits that are each in the above superposed state, then we have 8 possibilities at our disposal: 000, 001, 010, 011, 100, 101, 110, 111. Upon measurement, we get one of them. And if we convert them from binary to decimal, we get exatcly what we are looking for: a number between 0 and 7!"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def run_QuantumCirc(n): # creates and runs a quantum circuit with a Hadamard operating on each qubit\n",
" qr = qiskit.QuantumRegister(n) # create quantum register with n qubits\n",
" cr = qiskit.ClassicalRegister(n) # create classical register with n bits\n",
" circ = qiskit.QuantumCircuit(qr, cr) # create circuit with the two registers\n",
" circ.h(qr) # perform Hadamard on each qubit\n",
" circ.measure(qr,cr) # each qubit is measured, and the outcome for one qubit is either 0 or 1\n",
" job = qiskit.execute(circ, qiskit.BasicAer.get_backend('qasm_simulator') ) \n",
" result = job.result().get_counts() \n",
" return result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now comes the ingredient selection! "
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def select_ingredients(category): # runs a quantum circuit to select the number of ingredients in a category\n",
" num_choices = len(category)\n",
" if math.log(num_choices,2)%int(math.log(num_choices,2)) == 0: # checks whether log(num_choices) to the base 2 is a whole number\n",
" n = int(math.log(num_choices,2)) # n = number of qubits\n",
" result = run_QuantumCirc(n)\n",
" max_res = max(result, key=result.get) \n",
" else: \n",
" n = int(math.log(num_choices,2))+1 # adds 1 to log(N) to the base 2 to get total number of qubits needed\n",
" result = run_QuantumCirc(n)\n",
" max_res = max(result, key=result.get)\n",
" while(int(max_res,2) > num_choices-1): # find max that is less than num_choices\n",
" result.pop(str(max_res))\n",
" max_res = max(result, key=result.get)\n",
" selections = []\n",
" random.shuffle(category) # randomly shuffles the category list\n",
" for i in range(int(max_res,2)+1): # int(max_res,2)+1 is in decimal; it's the number of ingredients in the category that you will be using \n",
" selections.append(category[i]) # returns the first int(max_res,2)+1 entries in the shuffled list\n",
" return selections\n",
"\n",
"def ingredient_compatibilities(final_ingredients): # removes what I feel are flavor incomptibilities. This is solely my opinion. comment out any you don't agree with!\n",
" if tea == 'green' and 'cocoa' in final_ingredients: \n",
" final_ingredients.remove('cocoa')\n",
" if tea == 'black' and 'chamomile' in final_ingredients: \n",
" final_ingredients.remove('chamomile')\n",
" if tea == 'black' and 'jasmine' in final_ingredients: \n",
" final_ingredients.remove('jasmine')\n",
" if 'paprika' and 'jasmine' in final_ingredients: \n",
" final_ingredients.remove('jasmine')\n",
" return final_ingredients\n",
"\n",
"def choose_categories(tea): # chooses which ingredient categories your ingredients will come from, we use simple qubit superposition state |0>+|1>\n",
" n = 4 #There are 4 ingredient categories\n",
" categories_dict = {'0': select_ingredients(mild_spices), '1': select_ingredients(herbs), '2': select_ingredients(misc_flavors), '3': select_ingredients(zesty_spices)}\n",
" max_res = '0000'\n",
" final_ingredients = []\n",
" while len(final_ingredients) == 0: # to make sure we don't return an empty list\n",
" while max_res == '0000': # run it until we get SOME ingredients! No one wants 0 ingredients. That'd be utterly boring.\n",
" result = run_QuantumCirc(n)\n",
" max_res = max(result, key=result.get) \n",
" for ind in range(n):\n",
" if max_res[ind] == '1':\n",
" final_ingredients.append(categories_dict[str(ind)])\n",
" \n",
" final_ingredients = list(itertools.chain.from_iterable(final_ingredients))\n",
" final_ingredients = ingredient_compatibilities(final_ingredients)\n",
"\n",
" return final_ingredients"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Your quantum chai is black tea with the following ingredients:\n",
"['cinnamon', 'fennel seeds (saunf)', 'bay leaves', 'lavender', 'peppermint', 'lemongrass', 'coconut butter', 'paprika (lal mirch)', 'tumeric (haldi)', 'white peppercorns', 'black peppercorns', 'carom seeds (ajwain)', 'cumin seeds (zeera)']\n",
"\n",
"Happy drinking!\n"
]
}
],
"source": [
"tea = which_tea()\n",
"print(f\"\"\"\n",
"Your quantum chai is {tea} tea with the following ingredients:\n",
"{choose_categories(tea)}\n",
"\n",
"Happy drinking!\"\"\")\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment