<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def get_qc(name: str, *, as_qvm: bool = None, noisy: bool = None, connection: ForestConnection = None) -> QuantumComputer: """ Get a quantum computer. A quantum computer is an object of type :py:class:`QuantumComputer` and can be backed either by a QVM simulator ("Quantum/Quil Virtual Machine") or a physical Rigetti QPU ("Quantum Processing Unit") made of superconducting qubits. You can choose the quantum computer to target through a combination of its name and optional flags. There are multiple ways to get the same quantum computer. The following are equivalent:: and will construct a simulator of an Aspen-1 lattice with a noise model based on device characteristics. We also provide a means for constructing generic quantum simulators that are not related to a given piece of Rigetti hardware:: Finally, you can get request a QVM with "no" topology of a given number of qubits (technically, it's a fully connected graph among the given number of qubits) with:: These less-realistic, fully-connected QVMs will also be more lenient on what types of programs they will ``run``. Specifically, you do not need to do any compilation. For the other, realistic QVMs you must use :py:func:`qc.compile` or :py:func:`qc.compiler.native_quil_to_executable` prior to :py:func:`qc.run`. The Rigetti QVM must be downloaded from https://www.rigetti.com/forest and run as a server alongside your python program. To use pyQuil's built-in QVM, replace all ``"-qvm"`` suffixes with ``"-pyqvm"``:: Redundant flags are acceptable, but conflicting flags will raise an exception:: Use :py:func:`list_quantum_computers` to retrieve a list of known qc names. This method is provided as a convenience to quickly construct and use QVM's and QPU's. Power users may wish to have more control over the specification of a quantum computer (e.g. custom noise models, bespoke topologies, etc.). This is possible by constructing a :py:class:`QuantumComputer` object by hand. Please refer to the documentation on :py:class:`QuantumComputer` for more information. :param name: The name of the desired quantum computer. This should correspond to a name returned by :py:func:`list_quantum_computers`. Names ending in "-qvm" will return a QVM. Names ending in "-pyqvm" will return a :py:class:`PyQVM`. Names ending in "-noisy-qvm" will return a QVM with a noise model. Otherwise, we will return a QPU with the given name. :param as_qvm: An optional flag to force construction of a QVM (instead of a QPU). If specified and set to ``True``, a QVM-backed quantum computer will be returned regardless of the name's suffix :param noisy: An optional flag to force inclusion of a noise model. If specified and set to ``True``, a quantum computer with a noise model will be returned regardless of the name's suffix. The noise model for QVMs based on a real QPU is an empirically parameterized model based on real device noise characteristics. The generic QVM noise model is simple T1 and T2 noise plus readout error. See :py:func:`~pyquil.noise.decoherence_noise_with_asymmetric_ro`. :param connection: An optional :py:class:`ForestConnection` object. If not specified, the default values for URL endpoints will be used. If you deign to change any of these parameters, pass your own :py:class:`ForestConnection` object. :return: A pre-configured QuantumComputer """

    # 1. Parse name, check for redundant options, canonicalize names.
    prefix, qvm_type, noisy = _parse_name(name, as_qvm, noisy)
    del as_qvm  # do not use after _parse_name
    name = _canonicalize_name(prefix, qvm_type, noisy)

    # 2. Check for unrestricted {n}q-qvm
    ma = re.fullmatch(r'(\d+)q', prefix)
    if ma is not None:
        n_qubits = int(ma.group(1))
        if qvm_type is None:
            raise ValueError("Please name a valid device or run as a QVM")
        return _get_unrestricted_qvm(name=name, connection=connection,
                                     noisy=noisy, n_qubits=n_qubits, qvm_type=qvm_type)

    # 3. Check for "9q-square" qvm
    if prefix == '9q-generic' or prefix == '9q-square':
        if prefix == '9q-generic':
            warnings.warn("Please prefer '9q-square' instead of '9q-generic'", DeprecationWarning)

        if qvm_type is None:
            raise ValueError("The device '9q-square' is only available as a QVM")
        return _get_9q_square_qvm(name=name, connection=connection, noisy=noisy, qvm_type=qvm_type)

    # 4. Not a special case, query the web for information about this device.
    device = get_lattice(prefix)
    if qvm_type is not None:
        # 4.1 QVM based on a real device.
        return _get_qvm_based_on_real_device(name=name, device=device,
                                             noisy=noisy, connection=connection, qvm_type=qvm_type)
    else:
        # 4.2 A real device
        if noisy is not None and noisy:
            warnings.warn("You have specified `noisy=True`, but you're getting a QPU. This flag "
                          "is meant for controlling noise models on QVMs.")
        return QuantumComputer(name=name,
                               qam=QPU(
                                   endpoint=pyquil_config.qpu_url,
                                   user=pyquil_config.user_id),
                               device=device,
                               compiler=QPUCompiler(
                                   quilc_endpoint=pyquil_config.quilc_url,
                                   qpu_compiler_endpoint=pyquil_config.qpu_compiler_url,
                                   device=device,
                                   name=prefix))