Guía de Migración de Qiskit Nature v0.5#

Este tutorial te guiará a través del proceso de migración de tu código de Qiskit Nature v0.4 a v0.5

Descripción General#

Comencemos con una descripción general del diseño refactorizado. Un motivador importante para la refactorización de Qiskit Nature fue el objetivo de preparar a Qiskit Nature para más y más estrechas integraciones con otros códigos computacionales clásicos. Para lograr esto de la manera más modular y mantenible, tuvimos que desacoplar la representación de nuestro BaseProblem de nuestras clases BaseDriver.

Esto condujo al siguiente diseño abstracto del paquete Qiskit Nature: Qiskit Nature 0.5

Como puedes ver, el paquete se divide lógicamente en dos conceptos:

  1. problemas: los cuales son representaciones de problemas científicos a los que uno busca una solución

  2. algoritmos: lo cuales proporcionan los medios para encontrar soluciones a dichos problemas

En cada uno de estos casos, Qiskit Nature tiene tres pilares:

  1. problemas:

    1. Problema de Estructura Electrónica: representa el problema de la ecuación electrónica de Schrödinger de sistemas moleculares

    2. Problema de Estructura Vibracional: representando el problema planteado por el Hamiltoniano de Watson de los sistemas moleculares

    3. Problema del Modelo de Retícula: representación de problemas definidos en retículas

  2. algoritmos:

    1. Solucionador de Estado Fundamental: para encontrar el estado fundamental de un problema

    2. Solucionador de Estados Excitados: para encontrar estados excitados de un problema

    3. Simulación Hamiltoniana: para simular la dinámica de un problema (planeado para v0.6)

Algunos de estos conceptos ya estaban presentes en versiones anteriores de Qiskit Nature, pero no estaban tan claramente separados. Además, la integración con códigos clásicos ha sido muy restrictiva en versiones anteriores, limitando no solo las aplicaciones potenciales de dichas integraciones, sino también las capacidades de nuestra representación BaseProblem y su uso en el resto del paquete.

Cómo usar esta guía#

Esta guía se divide en varios archivos, lo que te permiten descubrir los cambios entre v0.4 y v0.5 en cada submódulo a medida que encuentres la necesidad. Eso significa que no necesitas leer todos los detalles a la vez y se recomienda encarecidamente saltarse los innecesarios.

En términos generales, la refactorización reubicó en gran medida cualquier código de qiskit_nature.X.second_quantization a qiskit_nature.second_q.X. Esto debería ayudarte a navegar por el código fuente en la mayoría de los casos. Sin embargo, en algunos casos específicos, hemos recategorizado módulos/clases específicos, por lo que te recomendamos que consultes las guías para obtener más detalles a continuación.

Para comprender a qué archivos debes prestar atención, revisa detenidamente la siguiente lista de temas:

Algunas notas generales importantes#

Demasiados argumentos posicionales#

Con Qiskit Nature v0.5, comenzamos a requerir que ciertos argumentos en la API pública sean argumentos solo de palabras clave. Este cambio estuvo motivado por las siguientes ventajas:

  • legibilidad mejorada: en el ejemplo dado a continuación, queda inmediatamente claro lo que hace un argumento dado

  • compatibilidad hacia adelante mejorada: agregar más argumentos en el futuro será mucho más simple porque los argumentos de palabras clave no dependen del orden

Eso significa que, incluso si solo necesitas actualizar la ruta de importación durante tu proceso de migración, puedes encontrar errores como los siguientes:

Previamente#

from qiskit_nature.mappers.second_quantization import LogarithmicMapper

mapper = LogarithmicMapper(2)

Ahora actualizamos la ruta de importación a la nueva ubicación y obtenemos un error:

from qiskit_nature.second_q.mappers import LogarithmicMapper

mapper = LogarithmicMapper(2)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-2-74b842b89d77> in <module>
      1 from qiskit_nature.second_q.mappers import LogarithmicMapper
      2
----> 3 mapper = LogarithmicMapper(2)


TypeError: __init__() takes 1 positional argument but 2 were given

Si esto te sucede, te sugerimos que simplemente consultes la documentación de la clase que estás tratando de usar. Es muy probable que solo sea necesario cambiar de usar un argumento posicionalmente a usarlo con una palabra clave. Por ejemplo así:

Nuevo#

from qiskit_nature.second_q.mappers import LogarithmicMapper

mapper = LogarithmicMapper(padding=2)

Número inesperado de orbitales o qubits#

Con Qiskit Nature v0.5, hemos cambiado toda la pila de usar num_spin_orbitals a usar num_spatial_orbitals. La motivación detrás de esto fue que el comportamiento al especificar un número impar de orbitales de espín estaba mal definido y no estaba protegido, lo que podría causar resultados sorpresivos. Al cambiar a la cantidad de orbitales espaciales (que luego se multiplican por 2 para obtener la cantidad total de orbitales de espín), este problema ya no puede surgir.

Entonces, si encuentras una cantidad inesperada de orbitales y/o qubits en tus resultados, asegúrate de verificar si necesitas actualizar tu entrada. Por ejemplo, como se muestra a continuación:

Previamente#

from qiskit_nature.circuit.library import HartreeFock
from qiskit_nature.converters.second_quantization import QubitConverter
from qiskit_nature.mappers.second_quantization import JordanWignerMapper

converter = QubitConverter(JordanWignerMapper())

init_state = HartreeFock(num_spin_orbitals=6, num_particles=(2, 1), qubit_converter=converter)
print(init_state.draw())
     ┌───┐
q_0: ┤ X ├
     ├───┤
q_1: ┤ X ├
     └───┘
q_2: ─────
     ┌───┐
q_3: ┤ X ├
     └───┘
q_4: ─────

q_5: ─────

Nuevo#

from qiskit_nature.second_q.circuit.library import HartreeFock
from qiskit_nature.second_q.mappers import JordanWignerMapper, QubitConverter

converter = QubitConverter(JordanWignerMapper())

init_state = HartreeFock(num_spatial_orbitals=3, num_particles=(2, 1), qubit_converter=converter)
print(init_state.draw())
     ┌───┐
q_0: ┤ X ├
     ├───┤
q_1: ┤ X ├
     └───┘
q_2: ─────
     ┌───┐
q_3: ┤ X ├
     └───┘
q_4: ─────

q_5: ─────