Research using Cirq!

Overview

ReCirq

Research using Cirq!

This project contains modules for running quantum computing applications and experiments through Cirq and Quantum Engine. By way of example, we also document best practices for setting up robust experimental pipelines.

Installation and Documentation

ReCirq is not available as a PyPI package. Please clone this repository and install from source:

cd recirq/
pip install .

Documentation is available at https://quantumai.google/cirq/experiments.

See Also

This code leverages Cirq as a quantum programming language and SDK. For those interested in using quantum computers to solve problems in chemistry and materials science, please see OpenFermion

ReCirq is not an official Google product. Copyright 2020 Google.

How to cite ReCirq

DOI

ReCirq is uploaded to Zenodo automatically. Click the badge above to see all citation formats for all versions or use the following BibTex:

@software{quantum_ai_team_and_collaborators_2020_4091470,
  author       = {{Quantum AI team and collaborators}},
  title        = {ReCirq},
  month        = Oct,
  year         = 2020,
  publisher    = {Zenodo},
  doi          = {10.5281/zenodo.4091470},
  url          = {https://doi.org/10.5281/zenodo.4091470}
}
Comments
  • Optimizations to reduce qubits based on non-entangled squares

    Optimizations to reduce qubits based on non-entangled squares

    Reduce number of qubits used in the following cases:

    • SPLIT_SLIDE and MERGE_SLIDE: if an arm of the slide/merge only has one path qubit then that qubit could be used directly as the path qubit, instead of adding a new ancilla qubit;
    • CAPTURE: don't create a capture ancilla if the attacker is known to be there and there is only one path qubit.
    chess cla: yes 
    opened by madcpf 35
  • Polish Fermi-Hubbard experiment example.

    Polish Fermi-Hubbard experiment example.

    • Add Hamiltonian and charge/spin densities.
    • Add frontmatter (run on Colab, download notebook, etc.)
    • Used standard install/import scheme.
    • Remove unused imports.
    • Add a bit more explanatory text.
    • Minor typo fixes, changes, etc.
    documentation fermi_hubbard 
    opened by rmlarose 10
  • GridDevice migration

    GridDevice migration

    • Migrated device.qubits callsites
      • A None check is added if device is a cirq.Device.
    • Migrated
    • Removed gateset parameters

    The first commit conflicts with https://github.com/quantumlib/ReCirq/pull/306 in that the solution is to check for device.metadata is None rather than requiring GridDevice. Either approach SGTM.

    Couldn't test locally because pytket.routing is missing. @mpharrigan does https://github.com/quantumlib/ReCirq/pull/306 fix this?

    opened by verult 9
  • Use pip-compile to pin ReCirq requirements.

    Use pip-compile to pin ReCirq requirements.

    Pinning the requirements required fixing versions of the following packages: pytket-cirq==0.3 and pytket=0.5.2 due to the latest pytket relying on openfermion~=0.11 and hfvqe relying on openfermion~=1.0.0.

    Also the following requirements were added:

    • pytest (for efficient test suite running)
    • numpy (used in various tests but wasn't explicitly required)
    • pip-compile (for automated requirements generation)
    devops 
    opened by PawelPamula 9
  • Move Rabi Oscillations Experiment from Cirq to ReCirq

    Move Rabi Oscillations Experiment from Cirq to ReCirq

    This experiment has some code in cirq-core/cirq/experiments, along with a docs notebook. Both have been moved here, into recirq/rabi_oscillations and docs/rabi_oscillations respectively

    documentation 
    opened by augustehirth 8
  • Merge 'docs' branch into 'master'

    Merge 'docs' branch into 'master'

    Mostly file moves and renames. Some Markdown fixes.

    Some Sphinx-specific files moved into dev_tools/docs/sphinx/ —just in case you need them and can probably delete from repo when you are ready.

    documentation 
    opened by lamberta 8
  • Update to Cirq 0.12

    Update to Cirq 0.12

    A new Cirq has been released. I will track any outstanding migration issues here.

    • [ ] bump cirq version number
    • [ ] ERROR: cirq 0.11.1 has requirement cirq-core==0.11.1, but you'll have cirq-core 0.12.0 which is incompatible. ERROR: cirq 0.11.1 has requirement cirq-google==0.11.1, but you'll have cirq-google 0.12.0 which is incompatible. I think this is from openfermion https://github.com/quantumlib/OpenFermion/issues/743. ~~pip install seems to work anyway: the above is a warning.~~ newer pips hang in a very bad way, I think related to this and pytket
    • [x] cirq_google.gate_set breaking change
    • [x] segfault in docker when running tests. Seems to be a pytket issue. Pinning to not-the-latest-version
    • [x] https://github.com/quantumlib/ReCirq/issues/214 -- not blocking. I just found it when manually testing all the pre-filled-in notebooks
    • [x] molecular_data notebook issue. This is due to a change in h5py and no recent release of openfermionpyscf. Pinning h5py works for now but may cause environment issues later if other projects require a newer h5py.
    cirq 
    opened by mpharrigan 6
  • Upgrade to Cirq 0.11

    Upgrade to Cirq 0.11

    • [x] ERROR: openfermion 1.0.1 has requirement cirq==0.10.0, but you'll have cirq 0.11.0 which is incompatible. https://github.com/quantumlib/OpenFermion/issues/736
    • [x] If you plow ahead, it legitimately breaks because it requires the changes from https://github.com/quantumlib/OpenFermion/pull/727/ Merged May 12 but latest release is March 6.
    • [x] What's the difference between openfermion 1.0.0 and 1.0.1? There's no tag for the latter. edit: there's a tag now, but:
    • [ ] ~~The tag for openfermion 1.0.1 points to the wrong commit.~~
    • [x] PyTket breakage with cirq.Rx https://github.com/quantumlib/ReCirq/pull/182/ the updated test in this PR is blocked by pinning to Cirq 0.11, so we can't merge yet.
    • [x] PyTket updates https://github.com/quantumlib/ReCirq/pull/182/
    • [x] Can no longer load in cirq.TrialResult -- https://github.com/quantumlib/Cirq/issues/4318
    • [x] cirq.TrialResult loading bugfix release with https://github.com/quantumlib/Cirq/pull/4319#issuecomment-885303444
    • [x] Scipy removed wrap_function https://github.com/quantumlib/ReCirq/pull/184
    cirq 
    opened by mpharrigan 6
  • Fix PyTket

    Fix PyTket

    There's something fishy going on with the pytket notebook. When running in the doc build system it says

    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-1-2f5bab2028d6> in <module>
         13     return pytket.device.Device({}, {}, arc)
         14 
    ---> 15 tk_circuit = pytket.cirq.cirq_to_tk(circuit)
         16 tk_device = _device_to_tket_device()
    
    AttributeError: module 'pytket' has no attribute 'cirq'
    AttributeError: module 'pytket' has no attribute 'cirq'
    

    and when I try to execute it in colab it complains about a bad sympy version

    ERROR: pytket 0.7.1.1 has requirement sympy~=1.6, but you'll have sympy 1.1.1 which is incompatible.
    

    and when I run the import pytket part, the kernel dies with some information in the logs:

    AttributeError: module 'sympy.core.core' has no attribute 'numbers'
    
    opened by mpharrigan 6
  • Move qaoa tutorials

    Move qaoa tutorials

    Moving 3 QAOA related tutorials from the Cirq docs to ReCirq. Note that these three are just docs only: they don't use any of the additional code in ReCirq.

    If it is preferred that these three files remain in the Cirq repo, then this PR would change to only add the following to the docs/_toc.yaml file:

    - title: "QAOA Max-Cut"
      path: /cirq/tutorials/qaoa
    - title: "QAOA: Ising Model"
      path: /cirq/tutorials/educators/qaoa_ising
    - title: "Binary Paintshop"
      path: /cirq/tutorials/ionq/binary_paintshop
    

    Since this would constitute the table of contents file for ReCirq linking out of the ReCirq repo, back to files in the Cirq repo. I thought it might be better to just move these three tutorials instead.

    opened by augustehirth 5
  • Prepare for Cirq 0.12

    Prepare for Cirq 0.12

    Towards #200.

    This is blocked by openfermion and/or pytket releasing versions that support Cirq 0.12, although if you manually install Cirq 0.12 with these changes and an older pip that is ok with conflicting version specs, everything seems to work.

    • Most changes are fixing deprecation warnings
    • The one fix where recirq was fully broken was changing the cirq_google.gate_sets import
    • Manually tested notebooks, including pre-filled-out ones
    cla: yes cirq 
    opened by mpharrigan 5
  • CVE-2007-4559 Patch

    CVE-2007-4559 Patch

    Patching CVE-2007-4559

    Hi, we are security researchers from the Advanced Research Center at Trellix. We have began a campaign to patch a widespread bug named CVE-2007-4559. CVE-2007-4559 is a 15 year old bug in the Python tarfile package. By using extract() or extractall() on a tarfile object without sanitizing input, a maliciously crafted .tar file could perform a directory path traversal attack. We found at least one unsantized extractall() in your codebase and are providing a patch for you via pull request. The patch essentially checks to see if all tarfile members will be extracted safely and throws an exception otherwise. We encourage you to use this patch or your own solution to secure against CVE-2007-4559. Further technical information about the vulnerability can be found in this blog.

    If you have further questions you may contact us through this projects lead researcher Kasimir Schulz.

    opened by TrellixVulnTeam 1
  • QAOA run-problem-generation Error

    QAOA run-problem-generation Error

    I am running the "run-problem-generation.py" in https://github.com/quantumlib/ReCirq/blob/dcc4da9892b4e22c386e05242552660b3c558f8e/recirq/qaoa/experiments/run-problem-generation.py#L1-L60

    and got the following error:

    Traceback (most recent call last):
      File "c:\Users\hmy98\iCloudDrive\Desktop\Test_Generator\qaoa_tutorial.py", line 60, in <module>
        main()
      File "c:\Users\hmy98\iCloudDrive\Desktop\Test_Generator\qaoa_tutorial.py", line 52, in main
        generate_hardware_grid_problem(task)
      File "C:\Users\hmy98\iCloudDrive\Desktop\Test_Generator\venv\lib\site-packages\recirq\qaoa\experiments\problem_generation_tasks.py", line 174, in generate_hardware_grid_problem        
        problem = _get_all_hardware_grid_problems(
      File "C:\Users\hmy98\iCloudDrive\Desktop\Test_Generator\venv\lib\site-packages\recirq\qaoa\experiments\problem_generation_tasks.py", line 156, in _get_all_hardware_grid_problems       
        device_graph = _get_device_graph(device_name=device_name)
      File "C:\Users\hmy98\iCloudDrive\Desktop\Test_Generator\venv\lib\site-packages\recirq\qaoa\experiments\problem_generation_tasks.py", line 121, in _get_device_graph
        device_graph = ccr.gridqubits_to_graph_device(device.qubits)
    AttributeError: 'GridDevice' object has no attribute 'qubits'
    
    opened by hmy98213 0
  • hfvqe example error compute_opdm

    hfvqe example error compute_opdm

    I'm trying to run the example here:

    https://github.com/quantumlib/ReCirq/blob/master/docs/hfvqe/quickstart.ipynb

    
    import numpy as np
    import cirq
    
    from recirq.hfvqe.gradient_hf import rhf_func_generator
    from recirq.hfvqe.opdm_functionals import OpdmFunctional
    from recirq.hfvqe.analysis import (
        compute_opdm, mcweeny_purification,
        resample_opdm, fidelity_witness,
        fidelity)
    from recirq.hfvqe.third_party.higham import fixed_trace_positive_projection
    from recirq.hfvqe.molecular_example import make_h6_1_3
    
    rhf_objective, molecule, parameters, obi, tbi = make_h6_1_3()
    ansatz, energy, gradient = rhf_func_generator(rhf_objective)
    
    # settings for quantum resources
    qubits = [cirq.GridQubit(0, x) for x in range(molecule.n_orbitals)]
    sampler = cirq.Simulator(dtype=np.complex128)  # this can be a QuantumEngine
    
    # OpdmFunctional contains an interface for running experiments
    opdm_func = OpdmFunctional(qubits=qubits,
                               sampler=sampler,
                               constant=molecule.nuclear_repulsion,
                               one_body_integrals=obi,
                               two_body_integrals=tbi,
                               # only simulate spin-up electrons:
                               num_electrons=molecule.n_electrons // 2,
                               clean_xxyy=True,
                               purification=True
                               )
    
    
    # 1.
    # default to 250_000 shots for each circuit.
    # 7 circuits total, printed for your viewing pleasure
    # return value is a dictionary with circuit results for each permutation
    measurement_data = opdm_func.calculate_data(parameters)
    
    # 2.
    opdm, var_dict = compute_opdm(measurement_data, return_variance=True)
    opdm_pure = mcweeny_purification(opdm)
    
    # 3.
    raw_energies = []
    raw_fidelity_witness = []
    purified_eneriges = []
    purified_fidelity_witness = []
    purified_fidelity = []
    true_unitary = ansatz(parameters)
    nocc = molecule.n_electrons // 2
    nvirt = molecule.n_orbitals - nocc
    initial_fock_state = [1] * nocc + [0] * nvirt
    
    # 1000 repetitions of the measurement
    for _ in range(1000):  
        new_opdm = resample_opdm(opdm, var_dict)
        raw_energies.append(opdm_func.energy_from_opdm(new_opdm))
        raw_fidelity_witness.append(
            fidelity_witness(target_unitary=true_unitary,
                             omega=initial_fock_state,
                             measured_opdm=new_opdm)
        )
        # fix positivity and trace of sampled 1-RDM if strictly outside
        # feasible set
        w, v = np.linalg.eigh(new_opdm)
        if len(np.where(w < 0)[0]) > 0:
            new_opdm = fixed_trace_positive_projection(new_opdm, nocc)
    
        new_opdm_pure = mcweeny_purification(new_opdm)
        purified_eneriges.append(opdm_func.energy_from_opdm(new_opdm_pure))
        purified_fidelity_witness.append(
            fidelity_witness(target_unitary=true_unitary,
                             omega=initial_fock_state,
                             measured_opdm=new_opdm_pure)
        )
        purified_fidelity.append(
            fidelity(target_unitary=true_unitary,
                     measured_opdm=new_opdm_pure)
        )
    print("Canonical Hartree-Fock energy ", molecule.hf_energy)
    print("True energy ", energy(parameters))
    print("Raw energy ", opdm_func.energy_from_opdm(opdm),
          "+- ", np.std(raw_energies))
    print("Raw fidelity witness ", np.mean(raw_fidelity_witness).real,
          "+- ", np.std(raw_fidelity_witness))
    print("purified energy ", opdm_func.energy_from_opdm(opdm_pure),
          "+- ", np.std(purified_eneriges))
    print("Purified fidelity witness ", np.mean(purified_fidelity_witness).real,
          "+- ", np.std(purified_fidelity_witness))
    print("Purified fidelity ", np.mean(purified_fidelity).real,
          "+- ", np.std(purified_fidelity))
    
    
    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/pandas/core/indexes/base.py:3621, in Index.get_loc(self, key, method, tolerance)
       3620 try:
    -> 3621     return self._engine.get_loc(casted_key)
       3622 except KeyError as err:
    
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/pandas/_libs/index.pyx:136, in pandas._libs.index.IndexEngine.get_loc()
    
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/pandas/_libs/index.pyx:163, in pandas._libs.index.IndexEngine.get_loc()
    
    File pandas/_libs/hashtable_class_helper.pxi:5198, in pandas._libs.hashtable.PyObjectHashTable.get_item()
    
    File pandas/_libs/hashtable_class_helper.pxi:5206, in pandas._libs.hashtable.PyObjectHashTable.get_item()
    
    KeyError: '(0, 1)'
    
    The above exception was the direct cause of the following exception:
    
    KeyError                                  Traceback (most recent call last)
    Input In [6], in <cell line: 8>()
          5 measurement_data = opdm_func.calculate_data(parameters)
          7 # 2.
    ----> 8 opdm, var_dict = compute_opdm(measurement_data, return_variance=True)
          9 opdm_pure = mcweeny_purification(opdm)
         11 # 3.
    
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/recirq/hfvqe/analysis.py:66, in compute_opdm(results_dict, return_variance)
         64     q0, q1 = qubits[pair_idx:pair_idx + 2]
         65     qA, qB = permutation[pair_idx:pair_idx + 2]
    ---> 66     opdm[qA, qB] += np.mean(data[q1] - data[q0], axis=0) * 0.5
         67     opdm[qB, qA] += np.mean(data[q1] - data[q0], axis=0) * 0.5
         69 if return_variance:
         70     # get covariance matrices
    
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/pandas/core/frame.py:3505, in DataFrame.__getitem__(self, key)
       3503 if self.columns.nlevels > 1:
       3504     return self._getitem_multilevel(key)
    -> 3505 indexer = self.columns.get_loc(key)
       3506 if is_integer(indexer):
       3507     indexer = [indexer]
    
    File ~/.conda/envs/qiskit/lib/python3.10/site-packages/pandas/core/indexes/base.py:3623, in Index.get_loc(self, key, method, tolerance)
       3621     return self._engine.get_loc(casted_key)
       3622 except KeyError as err:
    -> 3623     raise KeyError(key) from err
       3624 except TypeError:
       3625     # If we have a listlike key, _check_indexing_error will raise
       3626     #  InvalidIndexError. Otherwise we fall through and re-raise
       3627     #  the TypeError.
       3628     self._check_indexing_error(key)
    
    KeyError: '(0, 1)'
    

    seems like this might be a cirq/recirq version issue? Here are my versions

    cirq-core                     0.15.0
    cirq-google                   0.15.0
    
    recirq                        0.1.dev0
    
    
    opened by jasonlarkin 0
  • [loschmidt] Update analysis

    [loschmidt] Update analysis

    • include job timestamp
    • re-think aggregation strategy

    Background: the analysis code extracts the results into a pandas dataframe. You need to aggregate the quantities to make plots and create fits.

    Previously: I knew additional columns (i.e. fields) would be added over time to the results dataframe. I thought I could be clever with the aggregation to make the addition of new fields automatic. This was done with the groupby_all_except function which inverts the api of groupby.

    Then: we actually need a custom aggregation for the job_finished_time field. Every time the dataframe gets aggregated down, I've chosen to pick the "last" time of the group. You can imagine choosing the first or average. In any event: the groupby_all_except approach didn't make this magically work. One still needs to plumb through the new field with care.

    This PR: make our groupby columns and the aggregation functions / output columns explicit everywhere. Going forward, this shouldn't behave badly if a new field is added. Although if you want to actually have the new field show up after using the aggregation/fitting functions you have to add it to the [...]_y_cols mapping in each relevant function.

    otoc ftb/bl 
    opened by mpharrigan 1
  • SK Model QAOA application benchmark

    SK Model QAOA application benchmark

    • SKModelQAOASpec and sk_model_qaoa_spec_to_exe wraps existing QAOA code into the cirq_google.workflow tools so this can serve as an algorithmic benchmark.
    • scripts and recirq.algorithmic_benchmark_library entry to follow
    • Small changes to the circuit generation code to support generating lightly-compiled executables so the benchmark can target multiple gatesets following https://github.com/quantumlib/Cirq/pull/5336
    qaoa ftb/bl 
    opened by mpharrigan 0
Releases(v2020-10)
Owner
quantumlib
Google's open source code library for the quantum world
quantumlib
FrankMocap: A Strong and Easy-to-use Single View 3D Hand+Body Pose Estimator

FrankMocap pursues an easy-to-use single view 3D motion capture system developed by Facebook AI Research (FAIR). FrankMocap provides state-of-the-art 3D pose estimation outputs for body, hand, and bo

Facebook Research 1.9k Jan 07, 2023
Merlion: A Machine Learning Framework for Time Series Intelligence

Merlion: A Machine Learning Library for Time Series Table of Contents Introduction Installation Documentation Getting Started Anomaly Detection Foreca

Salesforce 2.8k Dec 30, 2022
Global-Local Context Network for Person Search

Global-Local Context Network for Person Search Abstract: Person search aims to jointly localize and identify a query person from natural, uncropped im

Peng Zheng 15 Oct 17, 2022
CSWin Transformer: A General Vision Transformer Backbone with Cross-Shaped

CSWin-Transformer This repo is the official implementation of "CSWin Transformer: A General Vision Transformer Backbone with Cross-Shaped Windows". Th

Microsoft 409 Jan 06, 2023
Code release for "Self-Tuning for Data-Efficient Deep Learning" (ICML 2021)

Self-Tuning for Data-Efficient Deep Learning This repository contains the implementation code for paper: Self-Tuning for Data-Efficient Deep Learning

THUML @ Tsinghua University 101 Dec 11, 2022
GND-Nets (Graph Neural Diffusion Networks) in TensorFlow.

GNDC For submission to IEEE TKDE. Overview Here we provide the implementation of GND-Nets (Graph Neural Diffusion Networks) in TensorFlow. The reposit

Wei Ye 3 Aug 08, 2022
Dahua Camera and Doorbell Home Assistant Integration

Home Assistant Dahua Integration The Dahua Home Assistant integration allows you to integrate your Dahua cameras and doorbells in Home Assistant. It's

Ronnie 216 Dec 26, 2022
Securetar - A streaming wrapper around python tarfile and allow secure handling files and support encryption

Secure Tar Secure Tarfile library It's a streaming wrapper around python tarfile

Pascal Vizeli 2 Dec 09, 2022
DatasetGAN: Efficient Labeled Data Factory with Minimal Human Effort

DatasetGAN This is the official code and data release for: DatasetGAN: Efficient Labeled Data Factory with Minimal Human Effort Yuxuan Zhang*, Huan Li

302 Jan 05, 2023
DC3: A Learning Method for Optimization with Hard Constraints

DC3: A learning method for optimization with hard constraints This repository is by Priya L. Donti, David Rolnick, and J. Zico Kolter and contains the

CMU Locus Lab 57 Dec 26, 2022
Code for the SIGIR 2022 paper "Hybrid Transformer with Multi-level Fusion for Multimodal Knowledge Graph Completion"

MKGFormer Code for the SIGIR 2022 paper "Hybrid Transformer with Multi-level Fusion for Multimodal Knowledge Graph Completion" Model Architecture Illu

ZJUNLP 68 Dec 28, 2022
Code Repository for The Kaggle Book, Published by Packt Publishing

The Kaggle Book Data analysis and machine learning for competitive data science Code Repository for The Kaggle Book, Published by Packt Publishing "Lu

Packt 1.6k Jan 07, 2023
Toontown: Galaxy, a new Toontown game based on Disney's Toontown Online

Toontown: Galaxy The official archive repo for Toontown: Galaxy, a new Toontown

1 Feb 15, 2022
Open source hardware and software platform to build a small scale self driving car.

Donkeycar is minimalist and modular self driving library for Python. It is developed for hobbyists and students with a focus on allowing fast experimentation and easy community contributions.

Autorope 2.4k Jan 04, 2023
"NAS-Bench-301 and the Case for Surrogate Benchmarks for Neural Architecture Search".

NAS-Bench-301 This repository containts code for the paper: "NAS-Bench-301 and the Case for Surrogate Benchmarks for Neural Architecture Search". The

AutoML-Freiburg-Hannover 57 Nov 30, 2022
Sandbox for training deep learning networks

Deep learning networks This repo is used to research convolutional networks primarily for computer vision tasks. For this purpose, the repo contains (

Oleg Sémery 2.7k Jan 01, 2023
ICON: Implicit Clothed humans Obtained from Normals

ICON: Implicit Clothed humans Obtained from Normals arXiv, December 2021. Yuliang Xiu · Jinlong Yang · Dimitrios Tzionas · Michael J. Black Table of C

Yuliang Xiu 1.1k Dec 30, 2022
Wav2Vec for speech recognition, classification, and audio classification

Soxan در زبان پارسی به نام سخن This repository consists of models, scripts, and notebooks that help you to use all the benefits of Wav2Vec 2.0 in your

Mehrdad Farahani 140 Dec 15, 2022
Retina blood vessel segmentation with a convolutional neural network

Retina blood vessel segmentation with a convolution neural network (U-net) This repository contains the implementation of a convolutional neural netwo

Orobix 1.2k Jan 06, 2023
Tutorial on scikit-learn and IPython for parallel machine learning

Parallel Machine Learning with scikit-learn and IPython Video recording of this tutorial given at PyCon in 2013. The tutorial material has been rearra

Olivier Grisel 1.6k Dec 26, 2022