14. Introducción.#
en este ejemplo, se trata de encontra los lados de un rectángulo para maximizar el área, dado el perímetro. Este ejemplo es muy apropiado para las personas que quieran iniciar su aprendizaje en Ocean SDK, y además si quieren profundizar en conocimientos relacionados con lo que se expone en este apratado, lo pueden encontrar en el siguiente enlace:
https://docs.dwavesys.com/docs/latest/c_gs_workflow.html
Igualmente se aconseja ver el contenido del siguiente enlace:
https://docs.ocean.dwavesys.com/en/stable/docs_dimod/intro/intro_symbolic_math.html
En el siguiente bloque procedemosa definir dos variable de tipo entero que llamamos i y j, ambas con un límite superior igual a 4. POsteriormente obtenemos una instancia de la clase ConstrainedQuadraticModel()
from dimod import ConstrainedQuadraticModel, Integer
# Definimos la variables de tipo entero que llamamos i y j
i = Integer('i', upper_bound=4)
j = Integer('j', upper_bound=4)
cqm = ConstrainedQuadraticModel()
# Veamos el typo de variable que es i (similar sería para j)
type(i)
dimod.quadratic.quadratic_model.QuadraticModel
Como queremos obtener el área del rectángulo definimos la variable objetive que es igual al producto de las dos variables definidas anteriormente. Pero como queremeos maximizar el área, y Ocean sólo permite obtener mínimos, lo que hacemos es cambiar el signo del producto.
Igualmente definimos la restricción de que el perímetro sea menor o igual que 8
# Definimos la función objetivo
objetive = - i*j
# definimos la restricción de que el perímetro sea menor o igual que 8
constraint = 2*i+2*j <= 8
print(objetive.to_polystring())
-i*j
print(constraint.lhs.to_polystring() )
#print(constraint.to_polystring()) # Esto da error
2*i + 2*j
El área del rectángulo está dada por la multiplicación del lado i por lado j. El objetivo es maximizar el área,i∗j. Debido a que los muestreadores D-Wave minimizan, el objetivo debe tener su valor más bajo cuando se alcanza este objetivo. Objetivo−i∗jtiene su valor mínimo cuandoi∗j, el área, es mayor:
cqm.set_objective(-i*j)
Añadimos la restricción 2i+2j<=8
cqm.add_constraint(2*i+2*j <= 8, "Max perimeter")
'Max perimeter'
Creamos una instancia de un muestreador de CQM híbrido y enviamos el problema para que lo solucione un sampler remoto proporcionado por el servicio de nube cuántica de Leap:
from dwave.system import LeapHybridCQMSampler
sampler = LeapHybridCQMSampler()
sampleset = sampler.sample_cqm(cqm)
print(sampleset.first)
Sample(sample={'i': 4.0, 'j': 4.0}, energy=-16.0, num_occurrences=1, is_satisfied=array([False]), is_feasible=False)
NOTA. Es importante ver que la primera solución encontrada es una solución factible pues como podemos ver en la salida anterior una de las propiedades que muestra es la siguiente: is_feasible=True. Pero no siempre es así, puesto que con este tipo de solvers se pueden encontra soluciones que no cumplen alguna de las condiciones puestas en las restricciones. Entonces, para obtener soluciones factibles, lo que hay que hacer es utilizar el método filter, tal y como el lector puede ver en el siguiente enlace: dwavesystems/dwave-system#460.
Veamos cómo se comporta la operación con este tipo de variables declaradas como enteras anteriormente. Por ejemplo, definamos la siguiente relación
relacion= 4.4*i+2.1*j+4*i*j
relacion
QuadraticModel({'i': 4.4, 'j': 2.1}, {('j', 'i'): 4.0}, 0.0, {'i': 'INTEGER', 'j': 'INTEGER'}, dtype='float64')
Como podemos observar, el objeto que se obtiene sigue siendo del tipo ‘QuadraticModel’ teniendo términos independientes así como otros que interactúan entre ellos.
Igualmente, se pueden añadir términos cuadráticos como por ejemplo \(4.1i^2\), de la siguiente manera
3.27*i+7.1*i*i
QuadraticModel({'i': 3.27}, {('i', 'i'): 7.1}, 0.0, {'i': 'INTEGER'}, dtype='float64')