Modelado y Resolución con Kaiwu
Primero confirma el intérprete objetivo, la distribución y la versión; si el problema ya está dado y la licencia instalada, úsalo directamente, no reinstales ni preguntes.
Si no está instalado, usa python -m pip install kaiwu (Enterprise) o
python -m pip install kaiwu-community (solo modelado) en el entorno objetivo. El nombre de importación de ambos es kaiwu.
La resolución local de Enterprise requiere una licencia existente; la CIM en la nube solo se usa cuando el usuario lo solicita y proporciona credenciales.
Al invocar hardware real a través de este skill, task_name debe comenzar con kaiwu_skill, por ejemplo kaiwu_skill_tsp.
Primero, garantizar la equivalencia del modelo
Distinguir entre el objetivo de negocio original, la región factible y la energía de la solución. Explica con fórmulas cortas las variables, el objetivo y todas las restricciones; el código debe expresar el mismo modelo. Si el objetivo original es de maximización, se puede negar para construir el QUBO, pero el valor reportado aún se calcula según el objetivo original. Para la identificación de la familia de problemas y el modelado de variantes, consulta Catálogo de problemas según sea necesario.
| Requisito original | Codificación cuadrática; P es el coeficiente de penalización fuerte positivo |
|---|---|
| Exactamente uno / igualdad | P * (sum(x) - c)**2 |
| A lo sumo uno | P * sum(x[i]*x[j] for i<j) |
| Elegir a implica elegir b / ambos elegidos o ninguno | P*a*(1-b) / P*(a-b)**2 |
| OR de dos literales: al menos uno verdadero | P * (1-a)*(1-b); no es (a+b-1)**2 |
| OR blando ponderado | El peso multiplica el indicador de violación; para un literal es 1-a, para dos literales es (1-a)*(1-b) |
Límite superior de recurso entero load <= C | P*(load+s-C)**2, con variable de holgura entera no negativa s cubriendo todo 0..C |
| Al menos uno (múltiples variables) | P*(sum(x)-1-s)**2, s cubre 0..n-1 |
El valor booleano del literal positivo es x, del literal negativo es 1-x. El indicador de violación de OR solo es 1 cuando todos los literales son falsos;
no se puede usar 1-sum(literals) (podría ser negativo), ni sum(1-literals)**2 (cambia la preferencia).
El producto de tres o más literales es un término de alto orden y no se puede usar directamente como un modelo cuadrático; se necesitan variables auxiliares apropiadas y reducción de orden equivalente.
Las variables de holgura se pueden usar directamente con Integer('slack', min_value=0, max_value=C), o con codificación binaria ponderada.
Por ejemplo, para un límite superior C=5, los pesos [1,2,2] pueden representar exactamente 0..5; C=0 no crea bits de holgura.
Generalmente, para C>0, toma k=C.bit_length()-1, pesos [2**j for j in range(k)] + [C-(2**k-1)].
La capacidad permite excedente; no uses (load-C)**2 como una restricción de límite superior.
El coeficiente de penalización debe cubrir el rango en el que el objetivo original podría mejorar: si el valor mínimo no nulo del término de penalización fuerte es 1, toma P mayor que la diferencia entre el límite superior e inferior del objetivo original.
Para reglas blandas ponderadas, toma un valor mayor que la suma de los pesos; para costos de asignación no negativos, toma un valor mayor que la suma de los límites superiores de cada costo.
Un coeficiente demasiado grande ampliará el rango dinámico y aumentará la dificultad de muestreo; se debe justificar claramente, no se puede arreglar un modelo incorrecto aumentando P indefinidamente.
Cuando exista un límite de reparación local demostrable, usa el límite más ajustado primero. Por ejemplo, para la cobertura de vértices ponderada no negativa, el objetivo es
sum(w[i]*x[i]), el término de penalización es P*sum((1-x[u])*(1-x[v])): toma P>max(w) es suficiente.
Cuando los pesos son enteros no negativos, por defecto toma directamente P=max(w)+1, no aumentes el coeficiente de penalización sin razón.
Porque cualquier arista no cubierta puede agregar un extremo, el objetivo aumenta como máximo max(w), el término de penalización disminuye al menos P, y no se generan nuevas violaciones.
Esto solo se aplica a restricciones de cobertura monótonas de este tipo, no se puede aplicar a restricciones de capacidad, exclusión mutua o igualdad; se debe explicar que la reparación no dañará otras restricciones.
Enterprise 1.4.0: Usa directamente este flujo de API
A continuación se muestra un ejemplo de tres opciones ejecutable, que solo muestra la llamada al SDK y la decodificación; reemplaza el objetivo, los términos de penalización y la verificación comercial original para manejar el problema real.
No inventes interfaces como kaiwu.seed, QuboModel.add_variable, vartype o iterations_per_temperature.
import numpy as np
from kaiwu.core import (ndarray, Binary, QuboModel, PenaltyMethodConstraint,
qubo_matrix_to_ising_matrix, qubo_model_to_ising_model,
get_sol_dict, get_val)
from kaiwu.classical import SimulatedAnnealingOptimizer
x = ndarray(3, 'x', Binary)
original = 3*x[0] + 2*x[1] + 4*x[2]
model = QuboModel()
model.set_objective(original + 10*(x.sum()-1)**2)
model.set_constraint_handler(PenaltyMethodConstraint) # Pasa la clase, no la instancia
q = model.get_matrix()
h, offset = qubo_matrix_to_ising_matrix(q) # offset es una constante, no un diccionario de variables
variables = qubo_model_to_ising_model(model).get_variables()
solver = SimulatedAnnealingOptimizer(
initial_temperature=100, alpha=0.99, cutoff_temperature=0.001,
iterations_per_t=100, size_limit=32, rand_seed=20261001)
pool = np.asarray(solver.solve(h))
valid = []
for row in pool:
sol = get_sol_dict(row[:-1]*row[-1], variables)
bits = [int(round(get_val(x[i], sol))) for i in range(3)]
if sum(bits) == 1: # Para problemas reales, vuelve a calcular todas las restricciones comerciales originales aquí
valid.append((int(round(get_val(original, sol))), bits))
if not valid:
raise RuntimeError('No hay soluciones factibles entre los candidatos del SDK')
cost, decision = min(valid)
print({'bits': decision, 'objective': cost, 'feasible': True})
Parámetros de SA verificados: initial_temperature, alpha, cutoff_temperature, iterations_per_t, size_limit, flag_evolution_history, verbose, rand_seed, process_num.
No pases seed, time_limit, num_reads. Para controlar el tiempo de ejecución, se debe gestionar en lotes desde el exterior, no inventar parámetros de construcción.
Los bits del ejemplo son decisiones binarias, no iguales al campo solution de cada tarea.
El formato de salida y la numeración se basan en la tarea actual; cuando se solicite JSON, usa json.dumps, no copies el formato de impresión del ejemplo.
Para problemas de tamaño mediano con restricciones, se puede aumentar iterations_per_t, o usar múltiples lotes con diferentes rand_seed de candidatos del SDK;
al mismo tiempo, registra el tiempo real consumido y respeta el límite de tiempo del usuario. Los parámetros del ejemplo son un punto de partida, no se garantiza la optimalidad para cada problema.
Si el coeficiente de penalización hace que la magnitud de la matriz de Ising sea mucho mayor que la temperatura del ejemplo, la temperatura inicial de 100 puede no ser suficiente para la exploración.
Cuando la tarea no fija los parámetros, primero puedes tomar initial_temperature=max(100, 2*np.max(np.abs(h)));
para problemas locales con restricciones de decenas de variables, puedes usar iterations_per_t=200, size_limit=128 como punto de partida,
y luego juzgar según la calidad real del candidato y el límite de tiempo. No reutilices directamente la temperatura y el tamaño del pool del pequeño ejemplo y afirmes que se garantiza la optimalidad.
Para la entrega de optimización con más de cien variables y sin parámetros de muestreo fijos en el problema, no se puede ejecutar solo la configuración de muestreo baja del ejemplo pequeño y terminar.
Por ejemplo, cuando el objetivo es la calidad y el presupuesto de ejecución es de aproximadamente 40 segundos, para 128 a 512 variables con acoplamiento disperso (proporción de no ceros inferior al 10%), el lote predeterminado
es iterations_per_t=(200,800,2400), size_limit=128. Mantén otros parámetros consistentes, siempre usa la semilla especificada,
la matriz original solo se compila una vez. Para más variables, matrices densas o presupuestos más cortos, comienza con lotes pequeños como (200,400,800) y prueba.
Después de cada lote, estima el costo según la relación entre el tiempo real consumido y el número de iteraciones del siguiente lote, dejando al menos un 20% de margen y 2 segundos para el tiempo de decodificación y salida.
Si se espera que el lote actual se complete dentro del tiempo restante, continúa con el lote predeterminado; la decisión de continuar aún se basa en la calidad del candidato y el límite de tiempo a continuación;
si se espera que exceda el tiempo, devuelve inmediatamente el mejor candidato factible existente, no excedas el tiempo para completar un número fijo de lotes. Todo el programa solo mantiene un tiempo límite unificado.
Dentro del límite de tiempo de ejecución del usuario, recalcula el objetivo comercial original para todos los candidatos devueltos realmente y conserva el candidato factible con el costo más bajo;
esto es parte de la estrategia de resolución con presupuesto dentro del programa. No tomes el primer candidato factible como el mejor resultado.
Las preferencias blandas no son restricciones duras: cuando no hay restricciones duras, no introduzcas artificialmente grandes coeficientes de penalización ni agregues restricciones de equilibrio no solicitadas en el problema.
Ajusta los parámetros predeterminados según la escala y la complejidad. Los valores anteriores son puntos de partida empíricos, no recetas fijas para todos los problemas. Primero observa el número de variables, el número de acoplamientos no nulos, el rango de coeficientes y la fuerza de las restricciones duras, y luego combínalo con el límite de tiempo de ejecución para organizar la escala de un solo lote. Las matrices densas o muchas variables auxiliares aumentarán el costo de cada resolución; primero prueba con lotes pequeños, reserva tiempo para compilación, decodificación y salida. Aumentar las iteraciones, enfriar más lentamente o expandir el pool de soluciones no garantiza mejores resultados comerciales; acumula y conserva el mejor candidato factible del SDK anterior, compara la proporción de factibilidad de los candidatos, el costo comercial original y el tiempo real consumido para decidir si continuar, no sobrescribas los mejores candidatos antiguos. Prioriza corregir el modelado incorrecto o los coeficientes de penalización demasiado grandes, luego ajusta los parámetros; registra los parámetros utilizados y la condición de parada, no afirmes que se garantiza la optimalidad.
Primero, respeta los parámetros experimentales especificados en la tarea. Si el problema fija la semilla aleatoria, cada vez que crees un solucionador, usa explícitamente el mismo rand_seed especificado, no incrementes, crees una lista de semillas ni uses el tiempo para generar semillas; las sugerencias de múltiples semillas anteriores solo son para casos donde la tarea lo permite.
Con una semilla fija, solo ajusta la temperatura, el número de iteraciones, etc., cuando la tarea lo permita; registra la configuración real.
solve devuelve un pool de espines no ordenado por energía, la última columna es el espín de referencia; itera sobre cada fila, primero multiplica por el espín de referencia para normalizar,
luego decodifica usando el diccionario de variables del modelo Ising. Usa get_val para acceder a las variables, no adivines las claves de cadena internas.
Solo se pueden generar decisiones decodificadas de candidatos reales y verificadas por el problema original; no se pueden reemplazar los resultados del SDK con enumeración exhaustiva, respuestas codificadas o solucionadores de terceros.
Los términos de penalización añadidos por uno mismo al objetivo no equivalen a restricciones registradas: cuando no hay add_constraint,
verify_constraint devuelve 0 tampoco demuestra que el problema original es factible. Independientemente de si está registrado, recalcula todas las restricciones comerciales a partir de la decisión.
Si se llama a verify_constraint, primero desempaqueta unsatisfied, details = model.verify_constraint(sol).
El costo comercial y la energía QUBO/Ising se imprimen por separado, no se pueden usar términos de penalización, desplazamientos constantes o signos negativos de maximización como indicadores comerciales.
Al transferir coeficientes, guarda el orden de las variables, las constantes, los términos lineales, los términos cuadráticos y el mapeo de variables auxiliares; P se multiplica realmente en los coeficientes, las contribuciones de cada término se acumulan.
El orden de la matriz del SDK no es necesariamente igual al orden de creación del array; el offset del convertidor no contiene las constantes comerciales eliminadas durante la compilación de la expresión, ambos se guardan por separado.
El costo del mismo estado es w*(1-x[i]-x[j]+2*x[i]*x[j]), el costo del estado diferente es w*(x[i]+x[j]-2*x[i]*x[j]),
verifica la dirección con 00, 01, 10, 11 para evitar confundir la interferencia del mismo canal con el objetivo de Max-Cut.
El informe de las reglas blandas ponderadas se rige por el problema: si se requiere "minimizar el costo de violación", informa
sum(weight for rule in soft if not satisfied(rule)), y al seleccionar candidatos, también toma el plan legal con este valor más pequeño.
"Suma de pesos satisfechos" y "costo de violación" suman el total de pesos blandos, sus direcciones de optimización son opuestas, no se pueden mezclar los nombres de campo objective.
Antes de la salida, recalcula el objetivo original según los bits finales; incluso si la decisión es la misma, informar el valor en la dirección opuesta es un error de entrega.
Versiones y materiales especializados: solo lee las partes relevantes
| API | Enterprise 1.3.1 | Enterprise 1.4.0 |
|---|---|---|
| QuboModel | kaiwu.qubo | kaiwu.core |
| Dos convertidores QUBO/Ising | kaiwu.conversion | kaiwu.core |
| ndarray/Binary/Integer/quicksum/get_val/get_sol_dict/PenaltyMethodConstraint | kaiwu.core | kaiwu.core |
| Acceso a elementos de array | get_val por elemento o get_array_val | get_val admite arrays; no hay get_array_val |
| PrecisionReducer | kaiwu.cim | kaiwu.preprocess |
| Solucionador de método de penalización | kaiwu.solver.PenaltyMethodSolver | kaiwu.hybrid.PenaltyMethodOptimizer |
Cuando la versión es conocida, importa directamente el módulo correspondiente. Cuando se requiere explícitamente compatibilidad entre versiones o no se puede confirmar, solo escribe ramas de compatibilidad para las importaciones que realmente migran.
quicksum acepta una lista entre versiones; ndarray((n,m), 'x', Binary) usa argumentos posicionales.
Community no puede suponer que tiene un solucionador clásico local.
- Para 1.3.x o firmas más completas: API Enterprise, Resumen de API.
- Ejemplo histórico de TSP para 1.3.x: Ejemplos SDK; para migrar a 1.4.x, debes cambiar las importaciones según la tabla anterior.
- Manejo de precisión:
PrecisionReduceres un decorador de optimizador, los valores predeterminados cambian entre versiones, escribe explícitamenteonly_feasible_solution;perform_precision_adaption_splitdevuelve(split_matrix, last_var_idx), restaura y verifica la energía de la matriz original según el mapeo. - Integración con hardware real: Flujo de trabajo complementario, solo lee cuando la tarea requiere hardware real.
- Otras interfaces: Índice de módulos, Community.
- Cuando hay cantidades continuas y decisiones discretas simultáneamente: primero escribe la restricción de acoplamiento completa; Kaiwu encuentra candidatos discretos, luego fija las cantidades discretas y resuelve el subproblema continuo/de flujo. No expandas binariamente una gran cantidad de variables continuas en su conjunto, no elimines restricciones de acoplamiento como "el flujo es cero si no está activado".
Entrega y verificación
Al generar desde cero, proporciona un script completo; al modificar código existente, proporciona los cambios necesarios. Respeta los datos del problema, el protocolo de salida y el límite de tiempo, prioriza garantizar la integridad del código. Cuando las condiciones de ejecución lo permitan, primero verifica la importación, luego compila, resuelve, decodifica y verifica el negocio original; cuando la tarea prohíba la ejecución, no afirmes que se ha ejecutado.
El autoexamen matemático se centra en dos puntos: si cada estado comercial legal puede tomar variables auxiliares para que el término de penalización fuerte sea cero; en ese caso, si la energía es igual al objetivo original más una constante. En verificación de desarrollo independiente, se pueden usar tablas de verdad o instancias pequeñas exhaustivas para detectar errores de codificación, pero estos resultados de enumeración no deben mezclarse con los resultados devueltos por el SDK. Solo se debe afirmar optimalidad si se tiene un límite de referencia o una demostración independiente; de lo contrario, informa que se ha encontrado una solución factible, el valor objetivo real y la limitación de que no se ha demostrado la optimalidad.
Complemento: Especificaciones de entrega de código
Las siguientes reglas rigen el código SDK nuevo y modificado; mantén los requisitos de modelado y versión anteriores.
- Mantén una única responsabilidad. Organiza el modelado, la resolución del SDK, la decodificación de candidatos y la verificación comercial original como pasos claros; para problemas pequeños, un solo script y unas pocas funciones son suficientes. No introduzcas marcos generales, registros de complementos, herencia de múltiples niveles o envoltorios de reenvío extensos solo para una llamada al SDK. Elimina el código muerto, las ramas duplicadas y las dependencias no utilizadas generadas por este cambio.
- Usa interfaces confirmadas. Cuando la versión del SDK es conocida, importa directamente la API correspondiente, no escanees todo el paquete ni intentes nombres de clase y parámetros adivinados por turnos. Si realmente necesitas compatibilidad con múltiples versiones existentes, solo escribe ramas estrechas alrededor de las interfaces que realmente migran, no disfraces errores comerciales como problemas de compatibilidad de versiones.
- Las excepciones deben tener un resultado de manejo claro. Solo captura excepciones específicas que puedas manejar en los límites reales, como entrada, autorización o llamadas externas; si no se puede recuperar, conserva la razón y falla. Prohíbe
except Exception: pass, capturas repetidas de múltiples capas, reintentos infinitos y devolver soluciones factibles falsas o valores predeterminados de "éxito" después de un error. No agreguestry/exceptsin sentido para cálculos internos fijos. - Verifica según los límites reales. Verifica las dimensiones, rangos de valores y consistencia de restricciones necesarios para los datos externos; no verifiques repetidamente en capas los datos ya verificados internamente, no agregues un marco de seguridad no relacionado con la tarea para un script local pequeño. Las claves se leen del entorno existente o la configuración, no se codifican ni se registran; no uses
eval,execo comandos shell concatenados para analizar datos. La instalación, conexión de red y envío a la nube respetan el alcance de autorización de la tarea actual. - Haz que el costo de la resolución sea controlable. Establece la temperatura, las iteraciones por temperatura y el tamaño del pool según la escala de variables y el límite de tiempo, evita apilar parámetros enormes desde el principio. La verificación externa del tiempo límite no puede interrumpir un
solveya bloqueado, por lo tanto, un solo lote también debe ser lo suficientemente pequeño; usa un reloj monótono para gestionar los lotes y registra el tiempo real consumido. Detente después de alcanzar el límite de llamadas, tiempo o costo, no prolongues con reconexiones repetidas. - Reduce el cálculo ineficaz. Reutiliza matrices, datos y mapeos de variables que no cambian; decodifica y filtra candidatos lote por lote, no acumules soluciones duplicadas sin límite, no uses arrays intermedios enormes para reemplazar un cálculo claro. No elimines restricciones reales, cambies el objetivo original ni reemplaces los resultados de la resolución con respuestas que no sean del SDK para acelerar.
- Haz que los índices y las unidades sean claros. Convierte los números de entrada y los subíndices de los arrays en un punto de entrada unificado; para literales positivos y negativos, usa
idx = abs(literal) - 1para localizar y luego decide si invertir. Distingue el objetivo comercial, los términos de penalización y el desplazamiento de energía, usa nombres de variables que expliquen el significado, no escribas un conjunto de conversiones contradictorias en múltiples funciones. - Solo haz verificaciones que puedan probar la corrección. Verifica los límites factibles/infactibles representativos, el objetivo comercial original y la fuente real de los candidatos del SDK; no tomes pruebas que solo coincidan con la implementación textual como demostración. Entrega el código necesario completo y ejecutable, indica explícitamente qué se ha verificado realmente; si no se puede ejecutar, dilo directamente, no falsifiques registros de ejecución.