Índice
BasisProto
(mensaje)BasisStatusProto
(enumeración)DualRayProto
(mensaje)DualSolutionProto
(mensaje)EmphasisProto
(enumeración)FeasibilityStatusProto
(enumeración)IndicatorConstraintProto
(mensaje)LPAlgorithmProto
(enumeración)LimitProto
(enumeración)LinearConstraintsProto
(mensaje)LinearExpressionProto
(mensaje)ModelProto
(mensaje)ModelSolveParametersProto
(mensaje)ObjectiveBoundsProto
(mensaje)ObjectiveProto
(mensaje)PrimalRayProto
(mensaje)PrimalSolutionProto
(mensaje)ProblemStatusProto
(mensaje)QuadraticConstraintProto
(mensaje)SecondOrderConeConstraintProto
(mensaje)SolutionHintProto
(mensaje)SolutionProto
(mensaje)SolutionStatusProto
(enumeración)SolveParametersProto
(mensaje)SolveResultProto
(mensaje)SolveStatsProto
(mensaje)SolverTypeProto
(enumeración)SosConstraintProto
(mensaje)SparseBasisStatusVector
(mensaje)SparseDoubleMatrixProto
(mensaje)SparseDoubleVectorProto
(mensaje)SparseInt32VectorProto
(mensaje)SparseVectorFilterProto
(mensaje)TerminationProto
(mensaje)TerminationReasonProto
(enumeración)VariablesProto
(mensaje)
BasisProto
Caracterización combinatoria de una solución de un programa lineal.
El método simplex para resolver programas lineales siempre devuelve una "solución viable básica" que se puede describir de manera combinatoria mediante una base. Una base asigna un BasisStatusProto para cada variable y restricción lineal.
P.ej., considera un formato estándar LP: min c * x s.t. A * x = b x >= 0 que tenga más variables que restricciones y con la clasificación A de fila completa.
Deja que n sea el número de variables y m el número de restricciones lineales. Se puede crear una base válida para este problema de la siguiente manera: * Todas las restricciones tendrán un estado base FIXED. * Elige m variables de modo que las columnas de A sean independientes de forma lineal y asigne el estado BÁSICO. * Asigna el estado AT_LOWER para las variables n-m restantes.
La solución básica para esta base es la solución única de A * x = b que tiene todas las variables con el estado AT_LOWER fijadas a sus límites inferiores (todas en cero). La solución resultante se denomina solución factible básica si también cumple con x >= 0.
Campos | |
---|---|
constraint_status |
Estado básico de la restricción. Requisitos: * constraint_status.ids es igual a LinearConstraints.ids. |
variable_status |
Estado básico de la variable. Requisitos: * constraint_status.ids es igual a VariablesProto.ids. |
basic_dual_feasibility |
Esta es una función avanzada que utiliza MathOpt para caracterizar la viabilidad de las soluciones de LP deficientes (las soluciones óptimas siempre tendrán el estado SOLUTION_STATUS_FEASIBLE). En el caso de las LP de un solo lado, debe ser igual al estado de viabilidad de la solución doble asociada. En el caso de los LP de dos lados, puede ser diferente en algunos casos extremos (por ejemplo, resoluciones incompletas con simplex primario). Si proporcionas una base inicial a través de ModelSolveParametersProto.initial_basis, este valor se ignora. Solo es relevante para la base que muestra SolutionProto.basis. |
BasisStatusProto
Estado de una variable o restricción según el LP.
Enumeradores | |
---|---|
BASIS_STATUS_UNSPECIFIED |
Valor de la guardia que representa sin estado. |
BASIS_STATUS_FREE |
La variable o restricción es gratuita (no tiene límites finitos). |
BASIS_STATUS_AT_LOWER_BOUND |
La variable o restricción se encuentra en su límite inferior (que debe ser finito). |
BASIS_STATUS_AT_UPPER_BOUND |
La variable o restricción se encuentra en su límite superior (que debe ser finito). |
BASIS_STATUS_FIXED_VALUE |
La variable o restricción tiene límites inferiores y superiores finitos idénticos. |
BASIS_STATUS_BASIC |
La variable o restricción es básica. |
DualRayProto
Una dirección de mejora ilimitada hacia el doble de una optimización: problema; equivalente, un certificado de inviabilidad primaria.
P. ej., considera el par de programas lineales de par doble primario: (Primal) (Dual) mín c * x máx. b * y s.t. A * x >= b s.t. y * A + r = c x >= 0 y, r >= 0. La raya doble es el par (y, r) que satisface: b * y > 0 y * A + r = 0 y, r >= 0 Observa que sumar un múltiplo positivo de (y, r) a la solución dual factible mantiene la viabilidad doble y mejora el objetivo (esto demuestra que el doble es no delimitado). El rayo doble también demuestra que el problema principal es inviable.
En el mensaje DualRay que aparece a continuación, y es doble_valores y r es costos_reducidos.
Campos | |
---|---|
dual_values |
Requisitos: * doble_values.ids son elementos de LinearConstraints.ids. * dos_valores.valores deben ser finitos. |
reduced_costs |
Requisitos: * reduces_costs.ids son elementos de VariablesProto.ids. * reduce_costs.values debe ser finito. |
DualSolutionProto
Una solución para el doble de un problema de optimización.
P. ej., considera el par de programas lineales de par doble primario: (Primal) (Dual) mín c * x máx. b * y s.t. A * x >= b s.t. y * A + r = c x >= 0 y, r >= 0. La solución dual es el par (y, r). Es factible si cumple con las restricciones de (Dual) anteriores.
En el siguiente mensaje, y es doble_valores, r es costos_reducidos y b * y es un valor objetivo.
Campos | |
---|---|
dual_values |
Requisitos: * doble_values.ids son elementos de LinearConstraints.ids. * dos_valores.valores deben ser finitos. |
reduced_costs |
Requisitos: * reduces_costs.ids son elementos de VariablesProto.ids. * reduce_costs.values debe ser finito. |
feasibility_status |
Estado de viabilidad de la solución según el solucionador subyacente. |
objective_value |
|
EmphasisProto
El nivel de esfuerzo aplicado a una tarea opcional mientras se resuelve (consulta resolveParametersProto para usarla).
El énfasis se usa para configurar una función del solucionador de la siguiente manera: * Si un solucionador no admite la función, solo UNSPECIFIED siempre será válido; cualquier otro parámetro de configuración generalmente será un error de argumento no válido (algunos solucionadores también pueden aceptar OFF). * Si el solucionador admite la función: - Cuando se establece en UNSPECIFIED, se usa el valor predeterminado subyacente. - Si no se puede desactivar la función, la opción OFF mostrará un error. - Si la función está habilitada de forma predeterminada, la configuración predeterminada del solucionador se suele asignar a MEDIA. - Si la función es compatible, las opciones LOW, MEDIUM, HIGH y VERY HIGH nunca mostrarán errores y se asignarán a la mejor coincidencia.
Enumeradores | |
---|---|
EMPHASIS_UNSPECIFIED |
|
EMPHASIS_OFF |
|
EMPHASIS_LOW |
|
EMPHASIS_MEDIUM |
|
EMPHASIS_HIGH |
|
EMPHASIS_VERY_HIGH |
FeasibilityStatusProto
Es el estado de viabilidad del problema, según lo reclamado por el solucionador (el solvente no es necesario que devuelva un certificado para el reclamo).
Enumeradores | |
---|---|
FEASIBILITY_STATUS_UNSPECIFIED |
Valor de la guardia que representa sin estado. |
FEASIBILITY_STATUS_UNDETERMINED |
El solucionador no reclama un estado. |
FEASIBILITY_STATUS_FEASIBLE |
El solucionador afirma que el problema es factible. |
FEASIBILITY_STATUS_INFEASIBLE |
El solucionador afirma que el problema es inviable. |
IndicatorConstraintProto
Datos para representar una restricción de indicador único con el formato: Variable(indicator_id) = (activate_on_zero ? 0 : 1) ⇒ límite_inferior <= expresión <= límite_superior.
Si se borra una variable involucrada en esta restricción (ya sea el indicador o aparece en expression
), se trata como si se hubiera establecido en cero. En particular, borrar la variable indicadora significa que la restricción del indicador es vacía si activate_on_zero
es falsa y que es equivalente a una restricción lineal si activate_on_zero
es verdadera.
Campos | |
---|---|
activate_on_zero |
Si es verdadero, si la variable indicadora toma el valor 0, se debe mantener la restricción implícita. De lo contrario, si la variable indicadora toma el valor 1, se debe mantener la restricción implícita. |
expression |
Debe ser una expresión lineal válida con respecto al modelo que la contiene: * Todas las condiciones indicadas en |
lower_bound |
Debe tener el valor en [-inf, inf; no puede ser NaN. |
upper_bound |
Debe tener el valor en (-inf, inf]; no puede ser NaN. |
name |
Los mensajes superiores pueden tener requisitos de exclusividad para este campo; p.ej., consulta |
indicator_id |
Un ID correspondiente a una variable binaria o no establecido. Si no la estableces, se ignorará la restricción del indicador. Si se configura, se requiere lo siguiente: * VariablesProto.integers[indicator_id] = true, * VariablesProto.lower_bounds[indicator_id] >= 0, * VariablesProto.upper_bounds[indicator_id] <= 1. MathOpt no valida estas condiciones, pero si no se cumplen, el solucionador mostrará un error cuando se resuelva. |
LPAlgorithmProto
Selecciona un algoritmo para resolver programas lineales.
Enumeradores | |
---|---|
LP_ALGORITHM_UNSPECIFIED |
|
LP_ALGORITHM_PRIMAL_SIMPLEX |
El método simplex (primal). Por lo general, puede proporcionar soluciones primarias y dobles, rayos primarios y duales sobre problemas primarios y duales no delimitados, y una base. |
LP_ALGORITHM_DUAL_SIMPLEX |
Método simplex doble Por lo general, puede proporcionar soluciones primarias y dobles, rayos primarios y duales sobre problemas primarios y duales no delimitados, y una base. |
LP_ALGORITHM_BARRIER |
El método de barrera, también llamado método de punto interno (IPM). Por lo general, puede proporcionar soluciones primarias y dobles. Algunas implementaciones también pueden producir rayos sobre problemas ilimitados o inviables. No se proporciona una base, a menos que el solucionador subyacente realice un “crossover” y finalice con simplex. |
LP_ALGORITHM_FIRST_ORDER |
Algoritmo basado en un método de primer orden. Estas suelen producir soluciones primarias y dobles, y posiblemente también certificados de inviabilidad primaria o doble. Por lo general, los métodos de primer orden ofrecen soluciones con menor precisión, por lo que los usuarios deben asegurarse de establecer parámetros de calidad de las soluciones (p.ej., tolerancias) y validar las soluciones. |
LimitProto
Cuando una resolve() se detiene antes de tiempo con CancellationReasonProto FEASIBLE o NO_SOLUTION_FOUND, es el límite específico que se alcanzó.
Enumeradores | |
---|---|
LIMIT_UNSPECIFIED |
Se utiliza como valor nulo cuando no se establece un límite (por ejemplo, TERMINATION_REASON_OPTIMAL). |
LIMIT_UNDETERMINED |
El solucionador de problemas subyacente no expone qué límite se alcanzó. |
LIMIT_ITERATION |
Un algoritmo iterativo se detuvo después de realizar la cantidad máxima de iteraciones (p.ej., iteraciones simplex o de barrera). |
LIMIT_TIME |
El algoritmo se detuvo después de un tiempo de procesamiento especificado por el usuario. |
LIMIT_NODE |
Un algoritmo de rama y vinculado se detuvo porque exploró una cantidad máxima de nodos en el árbol de ramas y vínculos. |
LIMIT_SOLUTION |
El algoritmo se detuvo porque encontró la cantidad requerida de soluciones. Esto se suele usar en MIP para que el solucionador devuelva la primera solución factible que encuentre. |
LIMIT_MEMORY |
El algoritmo se detuvo porque se quedó sin memoria. |
LIMIT_CUTOFF |
El solucionador se ejecutó con un corte (p.ej., se estableció resolveParameters.cutoff_limit) en el objetivo, lo que indica que el usuario no quería una solución peor que el corte y el solucionador concluyó que no había soluciones al menos tan buenas como el corte. Por lo general, no se proporciona información adicional sobre la solución. |
LIMIT_OBJECTIVE |
El algoritmo se detuvo porque encontró una solución o un límite mejor que un límite establecido por el usuario (consulta ResolverParameters.objective_limit y ResolverParameters.best_bound_limit). |
LIMIT_NORM |
El algoritmo se detuvo porque la norma de una iteración se volvió demasiado grande. |
LIMIT_INTERRUPTED |
El algoritmo se detuvo debido a un indicador de interrupción o a una solicitud de interrupción del usuario. |
LIMIT_SLOW_PROGRESS |
El algoritmo se detuvo porque no pudo seguir avanzando hacia la solución. |
LIMIT_OTHER |
Se detuvo el algoritmo debido a un límite no cubierto por una de las opciones anteriores. Ten en cuenta que LIMIT_UNDETERMINED se usa cuando no se puede determinar el motivo y LIMIT_OTHER se usa cuando el motivo es conocido, pero no se ajusta a ninguna de las alternativas anteriores. Es posible que FinishedProto.detail contenga información adicional sobre el límite. |
LinearConstraintsProto
Como se usa a continuación, definimos "#linear constraints" = size(LinearConstraintsProto.ids).
Campos | |
---|---|
ids[] |
Debe ser no negativo y estrictamente creciente. No se puede usar el valor max(int64). |
lower_bounds[] |
Debe tener una longitud igual a las restricciones #linear, valores en [-inf, inf). |
upper_bounds[] |
Debe tener una longitud igual a las restricciones #linear, valores en (-inf, inf]. |
names[] |
Si no está configurado, se supone que son todas cadenas vacías. De lo contrario, debe tener una longitud igual a las restricciones #linear. Todos los nombres que no estén vacíos deben ser distintos. |
LinearExpressionProto
Es una representación dispersa de una expresión lineal (una suma ponderada de variables más un desplazamiento constante).
Campos | |
---|---|
ids[] |
Son los IDs de las variables. Debe estar ordenada (en orden ascendente) con todos los elementos distintos. |
coefficients[] |
Deben tener la misma longitud que los IDs. Los valores deben ser finitos no pueden ser NaN. |
offset |
Debe ser finito y no puede ser NaN. |
ModelProto
Un problema de optimización. MathOpt admite lo siguiente: - Variables de decisión continuas y de números enteros con límites finitos opcionales. - Objetivos lineales y cuadráticos (objetivos únicos o múltiples), minimizados o maximizados. - Una serie de tipos de restricciones, incluidas las siguientes: * Restricciones lineales * Restricciones cuadráticas * Restricciones de conos de segundo orden * Restricciones lógicas > Restricciones de SOS1 y SOS2 > Restricciones de indicadores
De forma predeterminada, las restricciones se representan en mapas de "ID a datos". Sin embargo, representamos restricciones lineales en un formato de “struct-de-arrays” más eficiente.
Campos | |
---|---|
name |
|
variables |
|
objective |
El objetivo principal del modelo. |
auxiliary_objectives |
Objetivos auxiliares para usar en modelos multiobjetivo. Los IDs de clave de mapa deben estar en [0, max(int64)). Cada prioridad y cada nombre no vacío deben ser únicos y también distintos del |
linear_constraints |
|
linear_constraint_matrix |
Los coeficientes de las variables para las restricciones lineales. Si se borra una variable involucrada en esta restricción, se trata como si se hubiera establecido en cero. Requisitos: * linear_constraint_matrix.row_ids son elementos de linear_constraints.ids. * linear_constraint_matrix.column_ids son elementos de variables.ids. * Las entradas de matriz no especificadas son cero. * linear_constraint_matrix.values debe ser finita. |
quadratic_constraints |
Restricciones cuadráticas en el modelo. |
second_order_cone_constraints |
Restricciones de cono de segundo orden en el modelo. |
sos1_constraints |
SOS1 en el modelo, que limitan como máximo un |
sos2_constraints |
Restricciones de SOS2 en el modelo, que limitan que, como máximo, dos entradas de |
indicator_constraints |
Restricciones de indicadores en el modelo, que exigen que, si una “variable de indicador” binaria se establezca en uno, entonces se debe mantener una “restricción implícita”. |
ModelSolveParametersProto
Campos | |
---|---|
variable_values_filter |
Filtro que se aplica a todos los contenedores dispersos que se muestran y que tienen la clave de variables en PrimalSolutionProto y PrimalRayProto (PrimalSolutionProto.variable_values, PrimalRayProto.variable_values). Requisitos: * filter_ids son elementos de VariablesProto.ids. |
dual_values_filter |
Filtro que se aplica a todos los contenedores dispersos que se muestran y que están vinculados por restricciones lineales en DualSolutionProto y DualRay (DualSolutionProto.dual_values, DualRay.dual_values). Requisitos: * filter_ids son elementos de LinearConstraints.ids. |
reduced_costs_filter |
Filtro que se aplica a todos los contenedores dispersos que se muestran y que usan claves por variables en DualSolutionProto y DualRay (DualSolutionProto.reduced_costs, DualRay.reduced_costs). Requisitos: * filter_ids son elementos de VariablesProto.ids. |
initial_basis |
Base inicial opcional para los solucionadores de LP simplex con inicio semicaliente. Si se establece, se espera que sea válido de acuerdo con |
solution_hints[] |
Sugerencias de soluciones opcionales. Si el solucionador subyacente solo acepta una única sugerencia, se usa la primera. |
branching_priorities |
Prioridades de ramificación opcionales. Las variables con valores más altos se ramificarán primero. Las variables para las que no se establecen prioridades obtienen la prioridad predeterminada del solucionador (por lo general, cero). Requisitos: * Branching_priorities.values debe ser finito. * branching_priorities.ids debe ser elementos de VariablesProto.ids. |
ObjectiveBoundsProto
Límites en el valor objetivo óptimo.
Campos | |
---|---|
primal_bound |
El solucionador afirma que el valor óptimo es igual o mejor (más pequeño para la minimización y mayor para la maximización) que primal_bound hasta la tolerancia de viabilidad primaria de los solucionadores (consulta la siguiente advertencia): * primal_bound es trivial (+inf para la minimización y la maximización -inf) cuando el solucionador no afirma tener tal límite. * El atributo primal_bound puede estar más cerca del valor óptimo que el objetivo de la mejor solución principal posible. En particular, primal_bound puede no ser trivial, incluso cuando no se muestran soluciones principales posibles. Advertencia: La afirmación exacta es que existe una solución principal que: * es numéricamente factible (es decir, factible hasta la tolerancia de los solucionadores) y * tiene un valor objetivo primal_bound. Esta solución numéricamente factible puede ser ligeramente inviable, en cuyo caso primal_bound podría ser estrictamente mejor que el valor óptimo. Traducir una tolerancia de viabilidad prima a una tolerancia sobre primal_bound no es trivial, en especial cuando la tolerancia de viabilidad es relativamente grande (p.ej., cuando se resuelve con PDLP). |
dual_bound |
El solucionador indica que el valor óptimo es igual o peor (más grande para la minimización y menor para la maximización) que el doble_vinculación hasta la tolerancia de viabilidad doble del solucionador (consulta la siguiente advertencia): * El límite doble es trivial (-inf para la minimización y +inf maximización) cuando el solucionador no afirma tener tal límite. De manera similar a primal_bound, esto puede ocurrir con algunos solucionadores, incluso cuando se devuelven valores óptimos. Por lo general, los solucionadores de MIP informan un límite incluso si es impreciso. * para los problemas continuos Dual_bound puede estar más cerca del valor óptimo que el objetivo de la mejor solución dual factible. Para MIP, uno de los primeros valores no triviales de Dual_bound suele ser el valor óptimo de la relajación de LP del MIP. * Dual_bound debe ser mejor (más pequeño para la minimización y mayor para la maximización) que primal_bound hasta las tolerancias de los solucionadores (consulta la advertencia a continuación). Advertencia: * Para los problemas continuos, la afirmación precisa es que existe una solución dual que: * es numéricamente factible (es decir, factible hasta la tolerancia del solucionador) y * tiene un valor objetivo dual_bound. Esta solución numéricamente factible puede ser ligeramente inviable, en cuyo caso dual_bound puede ser estrictamente peor que el valor óptimo y primal_bound. De manera similar al caso principal, traducir una tolerancia de viabilidad doble a una tolerancia en Dual_bound no es trivial, en especial cuando la tolerancia de viabilidad es relativamente grande. Sin embargo, algunos solucionadores proporcionan una versión corregida de Dual_bound que puede ser numéricamente más segura. Se puede acceder a esta versión corregida a través del resultado específico del solucionador (p.ej., para PDLP, pdlp_output.convergence_information.corrected_dual_objective). * En el caso de los solucionadores de MIP, Dual_bound puede asociarse con una solución dual para lograr cierta relajación continua (p.ej., relajación con el LP), pero suele ser una consecuencia compleja de la ejecución de la resolución y, por lo general, es más imprecisa que los límites informados por los solucionadores de problemas de LP. |
ObjectiveProto
Campos | |
---|---|
maximize |
false es minimizar, verdadero es maximizar |
offset |
Debe ser finito y no NaN. |
linear_coefficients |
Términos de ObjectiveProto que son lineales en las variables de decisión. Requisitos: * linear_coeficientes.ids es elementos de VariablesProto.ids. * VariablesProto no especificadas corresponden a cero. * linear_coeficientes.values debe ser finito. * linear_coeficientes.values puede ser cero, pero esto solo desperdicia espacio. |
quadratic_coefficients |
Términos objetivos que son cuadráticos en las variables de decisión. Además de los requisitos de los mensajes SparseDoubleMatrixProto: * Cada elemento de quadratic_coeficientes.row_ids y cada elemento de quadratic_coefficiencys.column_ids deben ser elementos de VariablesProto.ids. * La matriz debe ser un valor triangular superior: para cada i, coeficientes_cuadraticos.row_ids[i] <= coeficientes_cuadraticos.columnas_id[i]. Notas: * Los términos que no se almacenaron explícitamente tienen un coeficiente cero. * Los elementos de coeficientes_cuadráticos.coeficientes pueden ser cero, pero esto solo desperdicia espacio. |
name |
Los mensajes principales pueden tener requisitos de singularidad en este campo; p.ej., consulta ModelProto.objectives y AuxiliaryObjectivesUpdatesProto.new_objectives. |
priority |
Para problemas multiobjetivo, la prioridad de este objetivo con respecto a los demás (menor es más importante). Este valor no debe ser negativo. Además, cada prioridad objetiva en el modelo debe ser distinta en el momento de la resolución. Esta condición no se valida a nivel de proto, por lo que los modelos pueden tener objetivos temporalmente con la misma prioridad. |
PrimalRayProto
una dirección de mejora ilimitada para un problema de optimización; es decir, un certificado de inviabilidad para el doble del problema de optimización.
Por ejemplo, considera un programa lineal simple: mín. c * x s.t. A * x >= b x >= 0. Un rayo primario es una x que satisface: c * x < 0 A * x >= 0 x >= 0. Observa que, aun así, un rayo positivo es mejor que la solución posible, pero es mejor que el rayo prima. Un rayo primario también demuestra que el problema de optimización dual es inviable.
En el mensaje PrimalRay que aparece a continuación, variable_values es x.
Campos | |
---|---|
variable_values |
Requisitos: * Los variables_values.ids son elementos de VariablesProto.ids. * variable_values.values debe ser finito. |
PrimalSolutionProto
Una solución a un problema de optimización.
P. ej., considera un programa lineal simple: mín. c * x s.t. A * x >= b x >= 0. Una solución principal es asignar valores a x. Es factible si satisface A * x >= b y x >= 0 desde arriba. En el mensaje PrimalSolutionProto que aparece a continuación, variable_values es x y objetivo_valor es c * x.
Campos | |
---|---|
variable_values |
Requisitos: * Los variables_values.ids son elementos de VariablesProto.ids. * variable_values.values debe ser finito. |
objective_value |
Valor del objetivo calculado por el solucionador subyacente. No puede ser infinito ni NaN. |
auxiliary_objective_values |
Valores objetivos auxiliares calculados por el solucionador subyacente. Las claves deben ser IDs de objetivos auxiliares válidos. Los valores no pueden ser infinitos ni NaN. |
feasibility_status |
Estado de viabilidad de la solución según el solucionador subyacente. |
ProblemStatusProto
Estado de viabilidad del problema principal y su doble (o el dual de una relajación continua) según lo afirma el solucionador. No es necesario que el solucionador muestre un certificado para la reclamación (p.ej., el solucionador puede afirmar que tiene una viabilidad primordial sin devolver una solución primal factible). Este estado combinado proporciona una descripción completa de las afirmaciones de un solucionador sobre la viabilidad y la ilimitación del problema resuelto. Por ejemplo:
- un estado factible para problemas primarios y duales indica que el primario es factible y limitado, y probablemente tenga una solución óptima (garantizada para problemas sin restricciones no lineales).
- un estado primal factible y un estado doble inviable indica que el problema principal no está delimitado (es decir, tiene soluciones arbitrariamente buenas).
Ten en cuenta que un estado doble inviable por sí solo (es decir, acompañado de un estado primitivo indeterminado) no implica que el problema principal esté ilimitado, ya que podríamos tener ambos problemas inviables. Además, si bien un estado primal y doble factible puede implicar la existencia de una solución óptima, no garantiza que el solucionador haya encontrado esa solución óptima.
Campos | |
---|---|
primal_status |
Estado del problema principal. |
dual_status |
Estado del problema dual (o del problema dual de una relajación continua) |
primal_or_dual_infeasible |
Si es verdadero, el solucionador afirma que el problema principal o dual es inviable, pero no sabe cuál (o si ambos son inviables). Puede ser verdadero solo cuando primal_problem_status = dual_problem_status = kUndeterminad. Esta información adicional suele ser necesaria cuando el procesamiento previo determina que no existe una solución óptima para el problema (pero no puede determinar si se debe a la inviabilidad, la no delimitación o ambas). |
QuadraticConstraintProto
Una única restricción cuadrática con la forma: lb <= suma{linear_terms} + suma{quadratic_terms} <= ub.
Si se borra una variable involucrada en esta restricción, se trata como si se hubiera establecido en cero.
Campos | |
---|---|
linear_terms |
Términos que son lineales en las variables de decisión. Además de los requisitos de los mensajes SparseDoubleVectorProto, exigimos lo siguiente: * linear_terms.ids son elementos de VariablesProto.ids. * linear_terms.values debe ser finito y no NaN. Notas: * Los IDs de variables omitidos tienen un coeficiente correspondiente de cero. * linear_terms.values puede ser cero, pero esto simplemente desperdicia espacio. |
quadratic_terms |
Términos que son cuadráticos en las variables de decisión. Además de los requisitos para los mensajes SparseDoubleMatrixProto, necesitamos lo siguiente: * Cada elemento de quadratic_terms.row_ids y cada elemento de quadratic_terms.column_ids deben ser elementos de VariablesProto.ids. * La matriz debe ser triangular superior: para cada i, quadratic_terms.row_ids[i] <= quadratic_terms.column_ids[i]. Notas: * Los términos que no se almacenaron explícitamente tienen un coeficiente cero. * Los elementos de quadratic_terms.coeficientes pueden ser cero, pero esto solo desperdicia espacio. |
lower_bound |
Debe tener un valor en [-inf, inf) y ser menor o igual que |
upper_bound |
Debe tener un valor en (-inf, inf] y ser mayor o igual que |
name |
Los mensajes superiores pueden tener requisitos de singularidad en este campo; p.ej., consulta ModelProto.quadratic_constraints y QuadraticConstraintUpdatesProto.new_constraints. |
SecondOrderConeConstraintProto
Una restricción de cono de segundo orden de la siguiente forma:
||arguments_to_norm
||_2 <= upper_bound
,
En el ejemplo anterior, upper_bound
y cada elemento de arguments_to_norm
son expresiones lineales.
Si se borra una variable involucrada en esta restricción, se trata como si se hubiera establecido en cero.
Campos | |
---|---|
upper_bound |
|
arguments_to_norm[] |
|
name |
Los mensajes superiores pueden tener requisitos de exclusividad para este campo; p.ej., consulta |
SolutionHintProto
Una solución inicial sugerida para el solucionador.
Por lo general, los solucionadores de MIP solo quieren información primaria (variable_values
), mientras que los solucionadores de LP quieren información primaria y doble (dual_values
).
Muchos solucionadores de MIP pueden trabajar con (1) soluciones parciales que no especifican todas las variables o (2) soluciones inviables. En estos casos, los solucionadores suelen resolver un subMIP para completar o corregir la sugerencia.
La forma en que el solucionador utiliza la sugerencia, si corresponde, depende en gran medida del solucionador, el tipo de problema y el algoritmo utilizado. La forma más confiable de garantizar que tu sugerencia tenga un efecto es leer los registros de resolución subyacentes con y sin la sugerencia.
Por lo general, los solucionadores de LP basados en Simplex prefieren una base inicial a una sugerencia de solución (de lo contrario, necesitan pasar la pista para convertirla en una solución básica viable).
Campos | |
---|---|
variable_values |
Es una asignación posiblemente parcial de los valores a las variables principales del problema. Los requisitos independientes del solucionador para este submensaje son los siguientes: * variable_values.ids son elementos de VariablesProto.ids. * variable_values.values debe ser finito. |
dual_values |
Es una asignación (potencialmente parcial) de valores a las restricciones lineales del problema. Requisitos: * dual_values.ids son elementos de LinearConstraintsProto.ids. * dos_valores.valores deben ser finitos. |
SolutionProto
Lo que se incluye en una solución depende del tipo de problema y solucionador. Los patrones comunes actuales son el 1. Los solucionadores de MIP solo muestran una solución principal. 2. Los solucionadores de LP simplex suelen mostrar una base y las soluciones primarias y dobles asociadas a ella. 3. Otros solucionadores de problemas continuos a menudo muestran una solución principal y doble que se conectan en una forma que depende de la resolución.
Requisitos: * Se debe establecer al menos un campo; una solución no puede estar vacía.
Campos | |
---|---|
primal_solution |
|
dual_solution |
|
basis |
SolutionStatusProto
Viabilidad de una solución principal o dual, según lo reclamado por la resolución.
Enumeradores | |
---|---|
SOLUTION_STATUS_UNSPECIFIED |
Valor de la guardia que representa sin estado. |
SOLUTION_STATUS_UNDETERMINED |
El solucionador no afirma un estado de viabilidad. |
SOLUTION_STATUS_FEASIBLE |
El solucionador afirma que la solución es factible. |
SOLUTION_STATUS_INFEASIBLE |
El solucionador afirma que la solución es inviable. |
SolveParametersProto
Son los parámetros para controlar una sola resolución.
Contiene ambos parámetros comunes a todas las soluciones (p.ej., time_limit) y parámetros para una resolución específica (p.ej., gscip). Si se establece un valor en el campo común y en el específico de resolución, se utiliza el parámetro específico de resolución.
Los parámetros comunes opcionales y sin configurar, o una enumeración con un valor sin especificar, indican que se utiliza el solucionador predeterminado.
Se ignoran los parámetros específicos del solucionador para otros solucionadores que no sean el en uso.
Los parámetros que dependen del modelo (p.ej., la prioridad de ramificación se establece para cada variable) se pasan a ModelSolveParametersProto.
Campos | |
---|---|
time_limit |
Tiempo máximo que un solucionador debe dedicar al problema (o infinito si no se establece). Este valor no es un límite estricto. El tiempo de resolución puede superar ligeramente este valor. Este parámetro siempre se pasa al solucionador subyacente; no se usa el valor predeterminado del solucionador. |
enable_output |
Habilita la impresión de los seguimientos de la implementación del solucionador. La ubicación de esos seguimientos depende del solucionador. Para SCIP y Gurobi, estas serán las transmisiones de salida estándar. Para Glop y CP-SAT, se utilizará LOG(INFO). Ten en cuenta que, si el solucionador admite la devolución de llamada de mensajes y el usuario registra una devolución de llamada para él, se ignorará este valor del parámetro y no se imprimirá ningún seguimiento. |
lp_algorithm |
Es el algoritmo para resolver un programa lineal. Si es LP_ALGORITHM_UNSPECIFIED, usa el algoritmo predeterminado de resolución. En el caso de los problemas que no son programas lineales, pero en los que la programación lineal es una subrutina, los solucionadores pueden usar este valor. P.ej., los solucionadores de MIP suelen usar esto solo para la resolución raíz de LP (de lo contrario, usan doble simplex). |
presolve |
El esfuerzo por simplificar el problema antes de iniciar el algoritmo principal o el nivel de esfuerzo predeterminado del solucionador si es POINTS_UNSPECIFIED. |
cuts |
Esfuérzate por lograr una mayor relajación del LP (solo MIP) o el nivel de esfuerzo predeterminado del solucionador si es POINTS_UNSPECIFIED. NOTA: Inhabilitar los cortes puede evitar que las devoluciones de llamada tengan la oportunidad de agregar cortes en MIP_NODE. Este comportamiento es específico para la resolución. |
heuristics |
Esfuerzo por encontrar soluciones posibles más allá de las que se encuentran en el procedimiento de búsqueda completo (solo MIP) o el nivel de esfuerzo predeterminado del solucionador si el valor es DURATION_UNSPECIFIED. |
scaling |
Esfuérzate por reescalar el problema para mejorar la estabilidad numérica o el nivel de esfuerzo predeterminado del solucionador si es FILE_UNSPECIFIED. |
iteration_limit |
Límite en las iteraciones del algoritmo subyacente (p.ej., tablas dinámicas simples). El comportamiento específico depende del solucionador y el algoritmo que se use, pero a menudo puede dar un límite de resolución determinista (es posible que se necesite más configuración, p.ej., un subproceso). Por lo general, es compatible con los solucionadores de LP, QP y MIP, pero para los solucionadores de MIP, consulta también node_limit. |
node_limit |
Límite en el número de subproblemas resueltos en la búsqueda enumerativa (p.ej., de ramas y delimitadas). En muchos solucionadores de problemas, se puede usar para limitar el procesamiento de forma determinista (es posible que se necesite configuración adicional, p.ej., un subproceso). Por lo general, para los solucionadores de MIP, consulta también iteration_limit. |
cutoff_limit |
El solucionador se detiene antes si puede demostrar que no existen soluciones primarias tan buenas como el límite. En una parada anticipada, el solucionador devuelve el motivo de finalización NO_SOLUTION_FOUND y con CUTOFF límite, y no se requiere que brinde información adicional sobre la solución. No tiene efecto en el valor que se muestra si no hay una parada anticipada. Se recomienda que uses una tolerancia si deseas que se devuelvan soluciones con un objetivo exactamente igual al corte. Consulta la guía del usuario para obtener más detalles y una comparación con best_bound_limit. |
objective_limit |
El solucionador se detiene antes de encontrar una solución al menos esta buena, con el motivo de finalización FÁSIBLE y un límite OBJETIVO. |
best_bound_limit |
El solucionador se detiene antes de que demuestre que el mejor vínculo es al menos este bueno, con el motivo de terminación FEASIBLE o NO_SOLUTION_FOUND y el límite Objective. Consulta la guía del usuario para obtener más detalles y una comparación con cutoff_limit. |
solution_limit |
El solucionador se detiene antes de encontrar esta cantidad de soluciones factibles, con el motivo de finalización FEASIBLE y el límite de SOLUCIÓN. Si se establece, debe ser mayor que cero. A menudo, se usa para lograr que el solucionador se detenga en la primera solución factible encontrada. Ten en cuenta que no hay garantía sobre el valor objetivo para ninguna de las soluciones mostradas. Por lo general, los solucionadores no devuelven más soluciones que el límite de soluciones, pero MathOpt no lo aplica de manera forzosa. Consulta también b/214041169. Actualmente, se admite para Gurobi y SCIP, y solo para CP-SAT con el valor 1. |
threads |
Si se configura, debe ser >= 1. |
random_seed |
Es el origen del generador de números pseudoaleatorios en el solucionador subyacente. Ten en cuenta que todos los solucionadores de problemas usan números pseudoaleatorios para seleccionar elementos como perturbación en el algoritmo LP, reglas de empate y correcciones heurísticas. La variación de esto puede tener un impacto notable en el comportamiento del solucionador. Aunque todos los solucionadores tienen un concepto de origen, ten en cuenta que los valores válidos dependen del solucionador real. - Gurobi: [0:GRB_MAXINT] (que a partir de Gurobi 9.0 es 2x10^9). - GSCIP: [0:2147483647] (que es MAX_INT, kint32max o 2^31-1). - GLOP: [0:2147483647] (igual que el anterior). En todos los casos, el solucionador recibirá un valor igual a: MAX(0, MIN(MAX_VALID_VALUE_FOR_SOLVER, random_seed)). |
absolute_gap_tolerance |
Una tolerancia de optimización absoluta (principalmente) para los solucionadores de MIP. El GAP absoluto es el valor absoluto de la diferencia entre: * el valor objetivo de la mejor solución posible encontrada, * el límite doble producido por la búsqueda. El solucionador puede detenerse una vez que el GAP absoluto sea, como máximo, la tolerancia de espacio_gap (cuando se configura) y mostrar TERMINATION_REASON_OPTIMAL. Debe ser >= 0 si se configura. Consulta tambiénrelative_gap_tolerancia. |
relative_gap_tolerance |
Una tolerancia de optimización relativa (principalmente) para los solucionadores de MIP. El GAP relativo es una versión normalizada del GAP absoluto (definido en tolerancia de brecha_absoluta), en la que la normalización depende de la resolución, p.ej., el GAP absoluto dividido por el valor objetivo de la mejor solución posible encontrada. El solucionador puede detenerse una vez que el GAP relativo es, como máximo, Relativa_gap_tolerancia (cuando se configura) y mostrar TERMINATION_REASON_OPTIMAL. Debe ser >= 0 si se configura. Consulta también absoluta_gap_tolerancia. |
solution_pool_size |
Mantén hasta |
SolveResultProto
El contrato de cuando las soluciones/rayos primarios/birales son complejos; consulta rescindir_reasons.md para obtener una descripción completa.
Hasta que se concrete un contrato exacto, es más seguro simplemente comprobar si existe una solución o un rayo, en lugar de confiar en el motivo de la rescisión.
Campos | |
---|---|
termination |
La razón por la que se detuvo la resolución. |
solutions[] |
El contrato general para el orden de las soluciones que los futuros solucionadores deben implementar es ordenar según: 1. Son las soluciones con una solución principal factible, ordenadas primero por el mejor objetivo principal. 2. Las soluciones con una solución doble factible, ordenadas por mejor objetivo dual (desconocida es la peor) 3. Todas las soluciones restantes se pueden mostrar en cualquier orden. |
primal_rays[] |
Instrucciones de mejora primaria no delimitada o certificados de inviabilidad doble. Por lo general, se proporciona para FinishedReasonProtos UNBOUNDED y DUAL_INFEASIBLE. |
dual_rays[] |
Instrucciones de mejora dual no delimitada o, de forma equivalente, certificados de inviabilidad primaria. Por lo general, se proporciona para FinishedReasonProto INFEASIBLE. |
solve_stats |
Estadísticas sobre el proceso de resolución, p.ej. tiempo de ejecución, iteraciones. |
SolveStatsProto
Campos | |
---|---|
solve_time |
Tiempo transcurrido según la medición de math_opt, aproximadamente el tiempo dentro de la resolución::Solve(). Nota: Esto no incluye el trabajo realizado para crear el modelo. |
problem_status |
Estados de viabilidad para problemas primarios y dobles. |
simplex_iterations |
|
barrier_iterations |
|
first_order_iterations |
|
node_count |
|
SolverTypeProto
Los solucionadores que admite MathOpt.
Enumeradores | |
---|---|
SOLVER_TYPE_UNSPECIFIED |
|
SOLVER_TYPE_GSCIP |
Resolución del solucionador de programas de números enteros con restricciones (SCIP) (tercero). Admite LP, MIP y problemas cuadráticos de números enteros no convexos. Sin embargo, no se muestran datos duales de LP. Se prefiere GLOP para LP. |
SOLVER_TYPE_GUROBI |
solucionador de problemas Gurobi (tercero). Admite LP, MIP y problemas cuadráticos de números enteros no convexos. Por lo general, es la opción más rápida, pero tiene licencias especiales. |
SOLVER_TYPE_GLOP |
El solucionador de problemas Glop de Google Admite LP con métodos simplex primarios y dobles. |
SOLVER_TYPE_CP_SAT |
El solucionador de problemas CP-SAT de Google Admite problemas en los que todas las variables son números enteros y están delimitadas (o implícitamente después de una resolución preestablecida). Compatibilidad experimental para reescalar y discretizar problemas con variables continuas. |
SOLVER_TYPE_PDLP |
El solucionador de problemas de PDLP de Google. Admite LP y objetivos cuadráticos diagonales convexos. Usa métodos de primer orden en lugar de simplex. Puede resolver problemas muy grandes. |
SOLVER_TYPE_GLPK |
GNU Linear Programming Kit (GLPK) (tercero). Admite MIP y LP. Seguridad del subproceso: GLPK usa almacenamiento local de subprocesos para las asignaciones de memoria. Como consecuencia, las instancias de solucionador deben destruirse en el mismo subproceso que se crean; de lo contrario, GLPK fallará. Parece correcto llamar a la herramienta Resolver::Solve() desde otro subproceso distinto del que se usó para crear la resolución, pero no está documentado en GLPK y se debe evitar. Al resolver un LP con el agente de resolución, solo se devuelve una solución (y los rayos no delimitados) si se encuentra una óptima. De lo contrario, no se mostrará nada. Consulta glpk-5.0/doc/glpk.pdf, página #40 disponible en glpk-5.0.tar.gz para conocer más detalles. |
SOLVER_TYPE_OSQP |
El solucionador de problemas del programa cuadrático de división de operadores (OSQP) (de terceros). Admite problemas continuos con restricciones lineales y objetivos cuadráticos lineales o convexos. Usa un método de primer orden. |
SOLVER_TYPE_ECOS |
La resolución cónica incorporada (ECOS) (tercero). Compatible con problemas de LP y SOCP. Usa métodos de punto interior (barrera). |
SOLVER_TYPE_SCS |
La resolución cónica de división (SCS) (tercero). Compatible con problemas de LP y SOCP. Usa un método de primer orden. |
SOLVER_TYPE_HIGHS |
El recurso de resolución de HiGHS (tercero). Es compatible con los problemas del LP y el MIP (no se implementaron QP convexos). |
SOLVER_TYPE_SANTORINI |
Implementación de referencia de MathOpt de un solucionador de problemas MIP. Lento o no se recomienda para la producción. No es un solucionador de problemas de LP (no se devuelve información dual). |
SosConstraintProto
Datos para representar una sola restricción de SOS1 o SOS2.
Si se borra una variable involucrada en esta restricción, se trata como si se hubiera establecido en cero.
Campos | |
---|---|
expressions[] |
Las expresiones sobre las que se aplica la restricción SOS: * SOS1: Como máximo, un elemento toma un valor distinto de cero. * SOS2: Como máximo, dos elementos tienen valores distintos de cero y deben ser adyacentes en el orden repetido. |
weights[] |
Puede estar vacío o con la misma longitud que las expresiones. Si este campo está vacío, los pesos predeterminados son 1, 2, ... Si están presentes, las entradas deben ser únicas. |
name |
Los mensajes superiores pueden tener requisitos de exclusividad en este campo; p.ej., consulta ModelProto.sos1_constraints y SosConstraintUpdatesProto.new_constraints. |
SparseBasisStatusVector
Representación dispersa de un vector de estados básicos.
Campos | |
---|---|
ids[] |
Debe estar ordenada (en orden ascendente) con todos los elementos distintos. |
values[] |
Deben tener la misma longitud que los IDs. |
SparseDoubleMatrixProto
Representación dispersa de una matriz de dobles.
La matriz se almacena como triples de ID de fila, ID de columna y coeficiente. Estos tres vectores deben tener la misma longitud. Para todo i, la tupla (row_ids[i], column_ids[i]) debe ser distinta. Las entradas deben estar en orden mayor de fila.
Campos | |
---|---|
row_ids[] |
|
column_ids[] |
|
coefficients[] |
Es posible que no contenga NaN. |
SparseDoubleVectorProto
Representación dispersa de un vector de dobles.
Campos | |
---|---|
ids[] |
Debe estar ordenada (en orden ascendente) con todos los elementos distintos. |
values[] |
Deben tener la misma longitud que los IDs. Es posible que no contenga NaN. |
SparseInt32VectorProto
Es una representación dispersa de un vector de números enteros.
Campos | |
---|---|
ids[] |
Debe estar ordenada (en orden ascendente) con todos los elementos distintos. |
values[] |
Deben tener la misma longitud que los IDs. |
SparseVectorFilterProto
Este mensaje permite consultar o establecer partes específicas de un SparseXxxxVector. El comportamiento predeterminado es no filtrar nada. Un uso común es consultar solo partes de soluciones (solo valores que no sean cero o solo un conjunto de valores de variables seleccionado a mano).
Campos | |
---|---|
skip_zero_values |
Para SparseBoolVectorProto, "zero" es |
filter_by_ids |
Cuando es verdadero, solo muestra los valores correspondientes a los ID enumerados en filter_ids. |
filtered_ids[] |
La lista de IDs que se deben usar cuando filter_by_ids es verdadero. Debe estar vacío cuando filter_by_ids es falso. NOTA: Si está vacío y filter_by_ids es verdadero, indicas que no quieres ninguna información en el resultado. |
TerminationProto
Toda la información sobre por qué se cerró una llamada a resolve().
Campos | |
---|---|
reason |
Información adicional en |
limit |
Sea LIMIT_UNSPECIFIED, a menos que el motivo sea TERMINATION_REASON_FEASIBLE o TERMINATION_REASON_NO_SOLUTION_FOUND. No todos los solucionadores de problemas siempre pueden determinar el límite que causó la rescisión. Cuando no se puede determinar la causa, se usa LIMIT_UNDETERMINED. |
detail |
Por lo general, se proporciona información adicional específica sobre la finalización. |
problem_status |
Estados de viabilidad para problemas primarios y dobles. A partir del 18 de julio de 2023, es posible que falte este mensaje. Si falta, se puede encontrar problem_status en resolveResultProto.solve_stats. |
objective_bounds |
Límites en el valor objetivo óptimo. A partir del 18 de julio de 2023, es posible que falte este mensaje. Si falta, puede encontrarse objetivo_bounds.primal_bound y se puede encontrar en resolveResultProto.solve.stats.best_primal_bound y objetivo_bounds.dual_bound en resolveResultProto.solve.stats.best_dual_bound |
TerminationReasonProto
Razón por la que finaliza una llamada a resolve().
Enumeradores | |
---|---|
TERMINATION_REASON_UNSPECIFIED |
|
TERMINATION_REASON_OPTIMAL |
Se encontró una solución demostrablemente óptima (hasta tolerancias numéricas). |
TERMINATION_REASON_INFEASIBLE |
El problema principal no tiene soluciones viables. |
TERMINATION_REASON_UNBOUNDED |
El problema principal es factible y las soluciones arbitrariamente buenas se pueden encontrar a lo largo de un rayo primario. |
TERMINATION_REASON_INFEASIBLE_OR_UNBOUNDED |
El problema principal es inviable o ilimitado. Puedes encontrar más detalles sobre el estado del problema en solve_stats.problem_status. Ten en cuenta que aquí se podría mostrar el estado ilimitado de Gurobi. |
TERMINATION_REASON_IMPRECISE |
El problema se resolvió en uno de los criterios anteriores (Optimal, Infeasible, Unbounded o InfeasibleOrUnbounded), pero no se cumplieron una o más tolerancias. Algunas soluciones o rayos primarios y dobles estarán presentes, pero serán un poco inviables o (si el problema era casi óptimo) puede ser una brecha entre el objetivo de la mejor solución y el mejor vínculo al objetivo. Los usuarios aún pueden consultar soluciones/rayos primarios y dobles, y estadísticas de soluciones, pero son responsables de lidiar con la imprecisión numérica. |
TERMINATION_REASON_FEASIBLE |
El optimizador alcanzó algún tipo de límite y se devuelve una solución principal factible. Consulta resolveResultProto.limit_detail para obtener una descripción detallada del tipo de límite que se alcanzó. |
TERMINATION_REASON_NO_SOLUTION_FOUND |
El optimizador alcanzó algún tipo de límite y no encontró una solución principal factible. Consulta resolveResultProto.limit_detail para obtener una descripción detallada del tipo de límite que se alcanzó. |
TERMINATION_REASON_NUMERICAL_ERROR |
El algoritmo se detuvo porque detectó un error numérico irrecuperable. No hay información disponible sobre la solución. |
TERMINATION_REASON_OTHER_ERROR |
Se detuvo el algoritmo debido a un error que no se relaciona con ninguno de los estados definidos anteriormente. No hay información disponible sobre la solución. |
VariablesProto
Como se usa a continuación, definimos "#variables" = size(VariablesProto.ids).
Campos | |
---|---|
ids[] |
Debe ser no negativo y estrictamente creciente. No se puede usar el valor max(int64). |
lower_bounds[] |
Debe tener una longitud igual a #variables, valores en [-inf, inf). |
upper_bounds[] |
Debe tener una longitud igual a #variables, valores en (-inf, inf]. |
integers[] |
Debe tener una longitud igual a #variables. El valor es falso para las variables continuas y verdadero para las variables con números enteros. |
names[] |
Si no está configurado, se supone que son todas cadenas vacías. De lo contrario, debe tener una longitud igual a #variables. Todos los nombres que no estén vacíos deben ser distintos. |