FoundryProductsTechnologyCompanyInvestor relationsResource libraryNews
Contact us
Resource library
    Resource library home
    Developer resources
      Entropy quantum optimization
        Dirac Quick Start
        Dirac-3 Developer Beginner Guide
        Multibody formulation
        QUBO formulation
        QLCBO formulation
        QBoost formulation
        qci-client software package
        eqc-direct software package
        eqc-models software package
          Getting Started
          Basic Usage
          eqc_models
          Dependencies
      Quantum random number generation
      Reservoir computing
    Applications
    Lessons
    Research and publications
    Support

Couldn’t find what you are looking for? Reach out to technical support.

Contact support
Privacy PolicyCookie PolicyTerms of UseForward Looking StatementsAccessibility Statement
Terms and Conditions of SaleEnd User License Agreement

© 2018-2026 Quantum Computing Inc.

Download

Default

Source code for eqc_models.solvers.mip

  • import logging
  • import numpy as np
  • from eqc_models.base.base import EqcModel
  • from eqc_models.base.binaries import make_binary_penalty
  • from eqc_models.base.polynomial import PolynomialModel
  • log = logging.getLogger(name=__name__)
  • [docs]
  • class MIPMixin:
  • """
  • Implements a solve method which intercepts the operator and builds a new
  • model with added terms for restriction of discrete variables with an
  • upper bound of 1 to take on only values 0 or 1 at minima.
  • Following the submission of a new model with the added penalties,
  • the solutions are updated to exclude added slack variables.
  • This is only supported with continuous-capable devices.
  • """
  • [docs]
  • def solve(self, model : EqcModel, *args, **kwargs):
  • if model.is_discrete is None:
  • raise ValueError("Model solved with an MIP solver must have certain variables labeled discrete")
  • elif len([b for b in model.is_discrete if b])==0:
  • raise ValueError("Model solved with an MIP solver must have certain variables labeled discrete")
  • if kwargs.get("sum_constraint", None) is None:
  • raise ValueError("sum_constraint must be specified for MIP model sampling")
  • # get a polynomial
  • poly = model.polynomial
  • if hasattr(poly.coefficients, "tolist"):
  • coefficients = poly.coefficients.tolist()
  • else:
  • coefficients = list(poly.coefficients)
  • indices = poly.indices
  • old_n = model.n
  • log.debug("Model coefficients %d", len(coefficients))
  • log.debug("Model indices %d", len(indices))
  • log.debug("Model size %d", old_n)
  • if "penalty_multiplier" in kwargs:
  • penalty_multiplier = kwargs["penalty_multiplier"]
  • del kwargs["penalty_multiplier"]
  • else:
  • penalty_multiplier = getattr(model, "penalty_multiplier", 1)
  • log.debug("Binary enforcement penalty multiplier %f", penalty_multiplier)
  • bin_slacks = []
  • offset = 0
  • variables = model.variables
  • addtl_upper_bound = []
  • for i, v in enumerate(model.variables):
  • if model.is_discrete[i]:
  • bin_slacks.append(f"bin_slacks_{v}")
  • penalty_coeff, penalty_indices, penalty_offset = make_binary_penalty(i+1, len(variables)+len(bin_slacks), penalty_multiplier=penalty_multiplier)
  • log.debug("Adding penalties coeff: %s indices %s offset %s", penalty_coeff, penalty_indices, penalty_offset)
  • coefficients += penalty_coeff
  • indices += penalty_indices
  • offset += penalty_offset
  • addtl_upper_bound.append(1)
  • assert len(coefficients) == len(indices)
  • variables = variables + bin_slacks
  • log.debug("New model binary penalty slacks: %s", bin_slacks)
  • new_model = PolynomialModel(coefficients, indices)
  • new_model.variables = variables
  • log.debug("New model variables: %s", variables)
  • new_model.upper_bound = np.array(model.upper_bound.tolist() + addtl_upper_bound)
  • new_model.machine_slacks = model.machine_slacks
  • coefficients, indices = new_model.H
  • log.debug("New model coefficients %d", len(coefficients))
  • log.debug("New model indices %d", len(indices))
  • log.debug("New model size: %d", new_model.n)
  • response = super().solve(new_model, *args, **kwargs)
  • # translate the response into results
  • results = self.makeResults(new_model, response)
  • log.debug(results)
  • # update the results to relect the original model
  • solutions = results.solutions
  • for i in range(len(solutions)):
  • log.debug("SolutionResults solution: %s", solutions[i])
  • if hasattr(model, "evaluateObjective"):
  • new_objectives = np.zeros((len(solutions),), dtype=np.float32)
  • else:
  • new_objectives = None
  • if hasattr(model, "evaluatePenalties"):
  • new_penalties = np.zeros((len(solutions),), dtype=np.float32)
  • else:
  • new_penalties = None
  • new_solutions = []
  • new_energies = []
  • num_vars = len(solutions[0]) - len(bin_slacks)
  • log.debug("Num_vars %f", num_vars)
  • machine_slacks = model.machine_slacks
  • for i, solution in enumerate(solutions):
  • log.debug("%d - Raw solution %s", i, solution)
  • new_sol = [v for v in solution[:num_vars]]
  • new_sol = np.array(new_sol)
  • if machine_slacks > 0:
  • new_sol[-machine_slacks:] = solution[-machine_slacks:]
  • log.debug("%d - New solution %s", i, new_sol)
  • if new_objectives is not None:
  • try:
  • new_objectives[i:i+1] = model.evaluateObjective(new_sol)
  • except NotImplementedError as err:
  • pass
  • if new_penalties is not None:
  • try:
  • new_penalties[i:i+1] = model.evaluatePenalties(new_sol)
  • except NotImplementedError as err:
  • pass
  • new_solutions.append(new_sol)
  • new_energies.append(model.evaluate(new_sol))
  • results.solutions = new_solutions
  • results.penalties = new_penalties
  • results.objectives = new_objectives
  • results.energies = new_energies
  • return results
Previous page

Content

  • Source code for eqc_models.solvers.mip