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
A PyTorch implementation of "CoAtNet: Marrying Convolution and Attention for All Data Sizes".

CoAtNet Overview This is a PyTorch implementation of CoAtNet specified in "CoAtNet: Marrying Convolution and Attention for All Data Sizes", arXiv 2021

Justin Wu 268 Jan 07, 2023
A real-time speech emotion recognition application using Scikit-learn and gradio

Speech-Emotion-Recognition-App A real-time speech emotion recognition application using Scikit-learn and gradio. Requirements librosa==0.6.3 numpy sou

Son Tran 6 Oct 04, 2022
Unofficial Tensorflow Implementation of ConvNeXt from A ConvNet for the 2020s

Tensorflow Implementation of "A ConvNet for the 2020s" This is the unofficial Tensorflow Implementation of ConvNeXt from "A ConvNet for the 2020s" pap

DK 11 Oct 12, 2022
Implementation of "Generalizable Neural Performer: Learning Robust Radiance Fields for Human Novel View Synthesis"

Generalizable Neural Performer: Learning Robust Radiance Fields for Human Novel View Synthesis Abstract: This work targets at using a general deep lea

163 Dec 14, 2022
Small utility to demangle Nim symbols in callgrind files

nim_callgrind A small utility to demangle Nim symbols from callgrind files. Usage Run your (Nim) program with something like this: valgrind --tool=cal

kraptor 3 Feb 15, 2022
A Decentralized Omnidirectional Visual-Inertial-UWB State Estimation System for Aerial Swar.

Omni-swarm A Decentralized Omnidirectional Visual-Inertial-UWB State Estimation System for Aerial Swarm Introduction Omni-swarm is a decentralized omn

HKUST Aerial Robotics Group 99 Dec 23, 2022
Alpha-IoU: A Family of Power Intersection over Union Losses for Bounding Box Regression

Alpha-IoU: A Family of Power Intersection over Union Losses for Bounding Box Regression YOLOv5 with alpha-IoU losses implemented in PyTorch. Example r

Jacobi(Jiabo He) 147 Dec 05, 2022
DETReg: Unsupervised Pretraining with Region Priors for Object Detection

DETReg: Unsupervised Pretraining with Region Priors for Object Detection Amir Bar, Xin Wang, Vadim Kantorov, Colorado J Reed, Roei Herzig, Gal Chechik

Amir Bar 283 Dec 27, 2022
Code repository for our paper "Learning to Generate Scene Graph from Natural Language Supervision" in ICCV 2021

Scene Graph Generation from Natural Language Supervision This repository includes the Pytorch code for our paper "Learning to Generate Scene Graph fro

Yiwu Zhong 64 Dec 24, 2022
[AAAI22] Reliable Propagation-Correction Modulation for Video Object Segmentation

Reliable Propagation-Correction Modulation for Video Object Segmentation (AAAI22) Preview version paper of this work is available at: https://arxiv.or

Xiaohao Xu 70 Dec 04, 2022
The code from the paper Character Transformations for Non-Autoregressive GEC Tagging

Character Transformations for Non-Autoregressive GEC Tagging Milan Straka, Jakub Náplava, Jana Straková Charles University Faculty of Mathematics and

ÚFAL 5 Dec 10, 2022
A best practice for tensorflow project template architecture.

A best practice for tensorflow project template architecture.

Mahmoud Gamal Salem 3.6k Dec 22, 2022
Serverless proxy for Spark cluster

Hydrosphere Mist Hydrosphere Mist is a serverless proxy for Spark cluster. Mist provides a new functional programming framework and deployment model f

hydrosphere.io 317 Dec 01, 2022
A data annotation pipeline to generate high-quality, large-scale speech datasets with machine pre-labeling and fully manual auditing.

About This repository provides data and code for the paper: Scalable Data Annotation Pipeline for High-Quality Large Speech Datasets Development (subm

Appen Repos 86 Dec 07, 2022
MAterial del programa Misión TIC 2022

Mision TIC 2022 Esta iniciativa, aparece como respuesta frente a los retos de la Cuarta Revolución Industrial, y tiene como objetivo la formación de 1

6 May 25, 2022
Implementation of paper "Graph Condensation for Graph Neural Networks"

GCond A PyTorch implementation of paper "Graph Condensation for Graph Neural Networks" Code will be released soon. Stay tuned :) Abstract We propose a

Wei Jin 66 Dec 04, 2022
Convolutional neural network that analyzes self-generated images in a variety of languages to find etymological similarities

This project is a convolutional neural network (CNN) that analyzes self-generated images in a variety of languages to find etymological similarities. Specifically, the goal is to prove that computer

1 Feb 03, 2022
Multi-objective constrained optimization for energy applications via tree ensembles

Multi-objective constrained optimization for energy applications via tree ensembles

C⚙G - Imperial College London 1 Nov 19, 2021
SCNet: Learning Semantic Correspondence

SCNet Code Region matching code is contributed by Kai Han ([email protected]). Dense

Kai Han 34 Sep 06, 2022
[ICCV 2021 (oral)] Planar Surface Reconstruction from Sparse Views

Planar Surface Reconstruction From Sparse Views Linyi Jin, Shengyi Qian, Andrew Owens, David F. Fouhey University of Michigan ICCV 2021 (Oral) This re

Linyi Jin 89 Jan 05, 2023