{"id":13520236,"url":"https://github.com/Miatto-research-group/bolt","last_synced_at":"2025-03-31T16:30:54.810Z","repository":{"id":48086245,"uuid":"337751733","full_name":"Miatto-research-group/bolt","owner":"Miatto-research-group","description":"A blazing fast 🚀 optimizer for quantum interferometers","archived":false,"fork":false,"pushed_at":"2021-08-04T16:02:06.000Z","size":129,"stargazers_count":2,"open_issues_count":1,"forks_count":10,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-08T23:35:07.334Z","etag":null,"topics":["interferometer","optimization","quantum","quantum-algorithms"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Miatto-research-group.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-10T14:37:04.000Z","updated_at":"2022-02-10T15:08:31.000Z","dependencies_parsed_at":"2022-07-28T23:09:31.570Z","dependency_job_id":null,"html_url":"https://github.com/Miatto-research-group/bolt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Miatto-research-group%2Fbolt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Miatto-research-group%2Fbolt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Miatto-research-group%2Fbolt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Miatto-research-group%2Fbolt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Miatto-research-group","download_url":"https://codeload.github.com/Miatto-research-group/bolt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":213468388,"owners_count":15591699,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["interferometer","optimization","quantum","quantum-algorithms"],"created_at":"2024-08-01T05:02:15.000Z","updated_at":"2024-08-01T05:12:58.307Z","avatar_url":"https://github.com/Miatto-research-group.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"### What is `bolt`?\n\n`bolt` is a \\*very fast\\* library that allows one to simulate and optimize interferometers at the quantum level. \n\n### How can it be so fast?\n`bolt` does its magic by computing only the input-output amplitudes of the interferometer that are needed, rather than computing the entire transformation tensor up to a given Fock space cutoff `N` (i.e. *all* of the amplitudes). \n\nThen, it performs the gradient optimization in the Lie algebra of the unitary group, which allows it to update the covariance matrix directly, without worrying about decomposing the interferometer into some arrangement of beam splitters and phase shifters.\n\nIt also (optionally) implements the natural gradient in the Orthogonal group, for an even faster convergence.\n\n### How to use\n\n#### 1. Create input and output states\nThe `State` class is a dictionary of ket:amplitude pairs:\n```python\nfrom bolt import State, IOSpec\n\n_in = State({(1,1,1,0,0,0):1.0}) # |1,1,1,0,0,0\u003e\n_out = State({(1,0,1,0,1,0):1.0}) # |1,0,1,0,1,0\u003e\n\n# IOSpec is an input-output relation (pure state in -\u003e pure state out)\nio = IOSpec(input_state = _in, output_state = _out)\n```\n\n#### 2. Create a `Requirements` object for multiple input-output relations\nThe `Requirements` class collects all of the required input-output relations that we require from the interferometer.\nGenerally, an interferometer that satisfies all of the required relations does not exist, but the optimizer will try to find one\nthat satisfies them with the highest probability.\n```python\nfrom bolt import Requirements\n\n# format: {IOSpec:weight, etc...}\nreq = Requirements({io:1.0})\n```\n\n#### 3. Find the interferometer that best satisfies the requirements\nNote that the *first time* the optimizer is called, the various `numba` functions in the code are compiled.\nSubsequent calls will start immediately, until you restart the ipython kernel.\n```python\nfrom bolt import Optimizer\nopt = Optimizer(lr = 0.01, max_steps=500)\n\ncov_matrix = opt(req)\nprint(f'The search took {opt.elapsed:.3f} seconds')\n\nimport matplotlib.pyplot as plt\nplt.plot(opt.losses)\n```\n\n### Did you blink?\nLet's increase the complexity (16 modes, 12 photons). It should still be reasonably fast (44 it/s on my laptop):\n```python\nfrom bolt import State, IOSpec, Requirements, Optimizer\n\n_in = State({(1,1,3,1,2,0,0,0,0,0,0,3,0,0,1,0):1.0}) # |1,1,3,1,2,0,0,0,0,0,0,3,0,0,1,0\u003e\n_out = State({(1,0,1,0,2,0,1,2,1,0,0,2,0,1,1,0):1.0}) # |1,0,1,0,2,0,1,2,1,0,0,2,0,1,1,0\u003e\n\nio = IOSpec(input_state = _in, output_state = _out)\nreq = Requirements({io:1.0})\n\nopt = Optimizer(lr = 0.02)\ncov_matrix = opt(req)\n```\n\n### All possible output amplitudes\n`Bolt` can generate the complete output state as well:\n```python\nfrom bolt.utils import all_outputs\nfrom scipy.stats import unitary_group\nfrom bolt import State\n\nstate_in = State({(0,8,0,8):np.sqrt(1/4), (8,0,8,0):np.sqrt(1/4), (8,0,0,8):np.sqrt(1/4), (0,8,8,0):np.sqrt(1/4)})\nV = unitary_group.rvs(state_in.num_modes) # interferometer unitary\n\nout,_ = all_outputs(state_in, V, grad=False)\n```\n\n### Fun Experiments\nNote that at times the optimizer gets stuck in a local minimum. Run the optimization a few times to assess how often this happens.\n\n#### Bell state analyzer\nStates from Eq. (2) in [PRA 94, 042331 (2011)](https://pdfs.semanticscholar.org/392a/3f99eb07c919da782831939082fa4eaac802.pdf).\n```python\nimport numpy as np\nfrom bolt import State, IOSpec, Requirements, Optimizer\n\npsip = State({(1,0,0,1):np.sqrt(1/2), (0,1,1,0):np.sqrt(1/2)})\npsim = State({(1,0,0,1):np.sqrt(1/2), (0,1,1,0):-np.sqrt(1/2)}) \nphip = State({(1,0,1,0):np.sqrt(1/2), (0,1,0,1):np.sqrt(1/2)}) \nphim = State({(1,0,1,0):np.sqrt(1/2), (0,1,0,1):-np.sqrt(1/2)})\n\nio1 = IOSpec(psip, State({(1,1,0,0):np.sqrt(1/2), (0,0,1,1):np.sqrt(1/2)}))\nio2 = IOSpec(psim, State({(1,0,0,1):np.sqrt(1/2), (0,1,1,0):-np.sqrt(1/2)}))\nio3 = IOSpec(phip, State({(2,0,0,0):1/2, (0,2,0,0):1/2, (0,0,2,0):1/2, (0,0,0,2):1/2}))\nio4 = IOSpec(phim, State({(2,0,0,0):1/2, (0,0,2,0):1/2, (0,2,0,0):-1/2, (0,0,0,2):-1/2}))\n\nreq = Requirements({io1:1.0, io2:1.0, io3:1.0, io4:1.0})\nopt = Optimizer(lr = 0.01)\ncov_matrix = opt(req)\nprint(f'The search took {opt.elapsed:.3f} seconds')\n\nimport matplotlib.pyplot as plt\nplt.plot(opt.losses);\n```\n\n#### GHZ state generation\nHere we find out that we can generate a GHZ state with probability 1/2.\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom bolt import State, IOSpec, Requirements, Optimizer\n\nin_111 = State({(1,1,1,0,0,0):1.0}) \n\nout_GHZ = State({(1,0,1,0,1,0):np.sqrt(1/2), (0,1,0,1,0,1):np.sqrt(1/2)}) \n\n\nio = IOSpec(in_111, out_GHZ)\nreq = Requirements({io:1.0})\nopt = Optimizer(lr = 0.01)\ncov_matrix = opt(req)\n\nprint(f'The search took {opt.elapsed:.3f} seconds')\nplt.plot(opt.losses);\n```\n\n#### GHZ state generation with natural gradient\nLet's push the limits with 11 photons and 22 modes, while using the natural gradient.\nCompare with the Lie Algebra implementation and notice the difference.\nNote that the natural gradient may be a bit sensible to the learning rate.\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom bolt import State, IOSpec, Requirements, Optimizer\n\np = 11\nin_ = State({(1,)*p + (0,)*p:1.0}) \n\nout_GHZ = State({(1,0)*p:np.sqrt(1/2), (0,1)*p:np.sqrt(1/2)}) \n\n\nio = IOSpec(in_, out_GHZ)\nreq = Requirements({io:1.0})\nopt = Optimizer(lr = 0.02, natural=True) # change to natural=False for Lie Algebra implementation\ncov_matrix = opt(req)\n\nprint(f'The search took {opt.elapsed:.3f} seconds')\nplt.plot(opt.losses[1:]);\n```\n\n#### Get all possible outputs given a input state and a specfic interferometer\nSometimes, you are not aiming to find out a optimized interferometer and you only want to find out with a setup interferometer, which state will appear on the output state and what is the probability of it. You can then try with this:\n\n```python\nfrom bolt import Interferometer\nfrom bolt import State\nimport numpy as np\n\n#Alternative interferometer you can define as you wish\nS2 = 1/2*np.array([[1,1j,1j,-1],[1j,1,-1,1j],[1j,-1,1,1j],[-1,1j,1j,1]],dtype=np.complex128)\n\n#Alternative input state\nstate_in = State({(2,0,0,2):np.sqrt(1/2),(0,2,2,0):np.sqrt(1/2)})\n\n#Define your Interferometer\nintf = Interferometer(S2)\n#Get your results!\nintf.getalloutputs(state_in)\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMiatto-research-group%2Fbolt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMiatto-research-group%2Fbolt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMiatto-research-group%2Fbolt/lists"}