Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[tool.black]
line-length = 100
target-version = ['py36', 'py37', 'py38', 'py39']
72 changes: 20 additions & 52 deletions qiskit_optimization/algorithms/admm_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,7 @@ def __init__(
self.warm_start = warm_start

def __repr__(self) -> str:
props = ", ".join(
["{}={}".format(key, value) for (key, value) in vars(self).items()]
)
props = ", ".join(["{}={}".format(key, value) for (key, value) in vars(self).items()])
return "{0}({1})".format(type(self).__name__, props)


Expand Down Expand Up @@ -203,9 +201,7 @@ def __init__(
state: the internal computation state of ADMM.
status: Termination status of an optimization algorithm
"""
super().__init__(
x=x, fval=fval, variables=variables, status=status, raw_results=state
)
super().__init__(x=x, fval=fval, variables=variables, status=status, raw_results=state)

@property
def state(self) -> ADMMState:
Expand Down Expand Up @@ -246,9 +242,7 @@ def __init__(
self._params = params or ADMMParameters()

# create optimizers if not specified
self._qubo_optimizer = qubo_optimizer or MinimumEigenOptimizer(
NumPyMinimumEigensolver()
)
self._qubo_optimizer = qubo_optimizer or MinimumEigenOptimizer(NumPyMinimumEigensolver())
self._continuous_optimizer = continuous_optimizer or SlsqpOptimizer()

# internal state where we'll keep intermediate solution
Expand All @@ -273,9 +267,7 @@ def get_compatibility_msg(self, problem: QuadraticProgram) -> Optional[str]:

# 1. get bin/int and continuous variable indices
bin_int_indices = self._get_variable_indices(problem, Variable.Type.BINARY)
continuous_indices = self._get_variable_indices(
problem, Variable.Type.CONTINUOUS
)
continuous_indices = self._get_variable_indices(problem, Variable.Type.CONTINUOUS)

# 2. binary and continuous variables are separable in objective
for bin_int_index in bin_int_indices:
Expand Down Expand Up @@ -319,9 +311,7 @@ def solve(self, problem: QuadraticProgram) -> ADMMOptimizationResult:
self._state = ADMMState(problem, self._params.rho_initial)

# parse problem and convert to an ADMM specific representation.
self._state.binary_indices = self._get_variable_indices(
problem, Variable.Type.BINARY
)
self._state.binary_indices = self._get_variable_indices(problem, Variable.Type.BINARY)
self._state.continuous_indices = self._get_variable_indices(
problem, Variable.Type.CONTINUOUS
)
Expand Down Expand Up @@ -448,9 +438,7 @@ def _turn_to_minimization(
problem.objective.sense = QuadraticObjective.Sense.MINIMIZE
problem.objective.constant = (-1) * problem.objective.constant
problem.objective.linear = (-1) * problem.objective.linear.coefficients
problem.objective.quadratic = (
-1
) * problem.objective.quadratic.coefficients
problem.objective.quadratic = (-1) * problem.objective.quadratic.coefficients
return problem, sense

@staticmethod
Expand Down Expand Up @@ -492,9 +480,7 @@ def _revert_solution_indexes(
Returns:
A solution array.
"""
solution = np.zeros(
len(self._state.binary_indices) + len(self._state.continuous_indices)
)
solution = np.zeros(len(self._state.binary_indices) + len(self._state.continuous_indices))
# restore solution at the original index location
solution.put(self._state.binary_indices, binary_vars)
solution.put(self._state.continuous_indices, continuous_vars)
Expand Down Expand Up @@ -532,14 +518,10 @@ def _convert_problem_representation(self) -> None:

# objective
self._state.q0 = self._get_q(self._state.step1_absolute_indices)
c0_vec = self._state.op.objective.linear.to_array()[
self._state.step1_absolute_indices
]
c0_vec = self._state.op.objective.linear.to_array()[self._state.step1_absolute_indices]
self._state.c0 = c0_vec
self._state.q1 = self._get_q(self._state.continuous_indices)
self._state.c1 = self._state.op.objective.linear.to_array()[
self._state.continuous_indices
]
self._state.c1 = self._state.op.objective.linear.to_array()[self._state.continuous_indices]
# equality constraints with binary vars only
self._state.a0, self._state.b0 = self._get_a0_b0()

Expand All @@ -561,9 +543,7 @@ def _get_step1_indices(self) -> Tuple[List[int], List[int]]:
# either in the linear or quadratic terms
if (
self._state.op.objective.linear[binary_index] != 0
or np.abs(
self._state.op.objective.quadratic.coefficients[binary_index, :]
).sum()
or np.abs(self._state.op.objective.quadratic.coefficients[binary_index, :]).sum()
!= 0
):
# add the variable if it was not added before
Expand Down Expand Up @@ -649,11 +629,7 @@ def _get_a0_b0(self) -> Tuple[np.ndarray, np.ndarray]:
vector = []

for constraint in self._state.binary_equality_constraints:
row = (
constraint.linear.to_array()
.take(self._state.step1_absolute_indices)
.tolist()
)
row = constraint.linear.to_array().take(self._state.step1_absolute_indices).tolist()

matrix.append(row)
vector.append(constraint.rhs)
Expand All @@ -662,9 +638,7 @@ def _get_a0_b0(self) -> Tuple[np.ndarray, np.ndarray]:
np_matrix = np.array(matrix)
np_vector = np.array(vector)
else:
np_matrix = np.array([0] * len(self._state.step1_absolute_indices)).reshape(
(1, -1)
)
np_matrix = np.array([0] * len(self._state.step1_absolute_indices)).reshape((1, -1))
np_vector = np.zeros(shape=(1,))

return np_matrix, np_vector
Expand All @@ -686,9 +660,7 @@ def _create_step1_problem(self) -> QuadraticProgram:
# prepare and set quadratic objective.
quadratic_objective = (
self._state.q0
+ self._params.factor_c
/ 2
* np.dot(self._state.a0.transpose(), self._state.a0)
+ self._params.factor_c / 2 * np.dot(self._state.a0.transpose(), self._state.a0)
+ self._state.rho / 2 * np.eye(binary_size)
)
op1.objective.quadratic = quadratic_objective
Expand Down Expand Up @@ -726,9 +698,9 @@ def _create_step2_problem(self) -> QuadraticProgram:
# replacing Q0 objective and take of min/max sense, initially we consider minimization
op2.objective.quadratic[var_index, var_index] = self._state.rho / 2
# replacing linear objective
op2.objective.linear[var_index] = -1 * self._state.lambda_mult[
i
] - self._state.rho * (self._state.x0[i] - self._state.y[i])
op2.objective.linear[var_index] = -1 * self._state.lambda_mult[i] - self._state.rho * (
self._state.x0[i] - self._state.y[i]
)

# remove A0 x0 = b0 constraints
for constraint in self._state.binary_equality_constraints:
Expand All @@ -750,15 +722,13 @@ def _create_step3_problem(self) -> QuadraticProgram:
op3.continuous_var(lowerbound=-np.inf, upperbound=np.inf, name=name)

# set quadratic objective y
quadratic_y = self._params.beta / 2 * np.eye(
quadratic_y = self._params.beta / 2 * np.eye(binary_size) + self._state.rho / 2 * np.eye(
binary_size
) + self._state.rho / 2 * np.eye(binary_size)
)
op3.objective.quadratic = quadratic_y

# set linear objective for y
linear_y = -self._state.lambda_mult - self._state.rho * (
self._state.x0 - self._state.z
)
linear_y = -self._state.lambda_mult - self._state.rho * (self._state.x0 - self._state.z)
op3.objective.linear = linear_y

return op3
Expand Down Expand Up @@ -873,9 +843,7 @@ def _get_constraint_residual(self) -> float:
cr_ineq = 0.0
for constraint in self._state.inequality_constraints:
sense = -1.0 if constraint.sense == Constraint.Sense.GE else 1.0
cr_ineq += max(
sense * (constraint.evaluate(solution) - constraint.rhs), 0.0
)
cr_ineq += max(sense * (constraint.evaluate(solution) - constraint.rhs), 0.0)

return cr_eq + cr_ineq

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
cuts = self._generate_random_cuts(chi, len(adj_matrix))

numeric_solutions = [
(cuts[i, :], self.max_cut_value(cuts[i, :], adj_matrix))
for i in range(self._num_cuts)
(cuts[i, :], self.max_cut_value(cuts[i, :], adj_matrix)) for i in range(self._num_cuts)
]

if self._sort_cuts:
Expand Down Expand Up @@ -263,9 +262,7 @@ def _solve_max_cut_sdp(self, adj_matrix: np.ndarray) -> np.ndarray:
constraints.append(x[i, i] == 1)

# objective function
expr = cvx.sum(
cvx.multiply(adj_matrix, (np.ones((num_vertices, num_vertices)) - x))
)
expr = cvx.sum(cvx.multiply(adj_matrix, (np.ones((num_vertices, num_vertices)) - x)))

# solve
problem = cvx.Problem(cvx.Maximize(expr), constraints)
Expand Down
27 changes: 7 additions & 20 deletions qiskit_optimization/algorithms/grover_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@ def _get_a_operator(self, qr_key_value, problem):
def _get_oracle(self, qr_key_value):
# Build negative value oracle O.
if qr_key_value is None:
qr_key_value = QuantumRegister(
self._num_key_qubits + self._num_value_qubits
)
qr_key_value = QuantumRegister(self._num_key_qubits + self._num_value_qubits)

oracle_bit = QuantumRegister(1, "oracle")
oracle = QuantumCircuit(qr_key_value, oracle_bit)
Expand Down Expand Up @@ -227,9 +225,7 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
while not improvement_found:
# Determine the number of rotations.
loops_with_no_improvement += 1
rotation_count = int(
np.ceil(algorithm_globals.random.uniform(0, m - 1))
)
rotation_count = int(np.ceil(algorithm_globals.random.uniform(0, m - 1)))
rotations += rotation_count
# Apply Grover's Algorithm to find values below the threshold.
# TODO: Utilize Grover's incremental feature - requires changes to Grover.
Expand Down Expand Up @@ -272,12 +268,8 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
raw_samples = self._eigenvector_to_solutions(
self._circuit_results, problem_init
)
raw_samples.sort(
key=lambda x: problem_.objective.sense.value * x.fval
)
samples = self._interpret_samples(
problem, raw_samples, self._converters
)
raw_samples.sort(key=lambda x: problem_.objective.sense.value * x.fval)
samples = self._interpret_samples(problem, raw_samples, self._converters)
else:
# Using Durr and Hoyer method, increase m.
m = int(np.ceil(min(m * 8 / 7, 2 ** (n_key / 2))))
Expand Down Expand Up @@ -306,9 +298,7 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
if optimum_value >= 0 and orig_constant == 0:
optimum_key = 0

opt_x = np.array(
[1 if s == "1" else 0 for s in ("{0:%sb}" % n_key).format(optimum_key)]
)
opt_x = np.array([1 if s == "1" else 0 for s in ("{0:%sb}" % n_key).format(optimum_key)])
# Compute function value
fval = problem_init.objective.evaluate(opt_x)

Expand Down Expand Up @@ -346,8 +336,7 @@ def _get_probs(self, qc: QuantumCircuit) -> Dict[str, float]:
if self.quantum_instance.is_statevector:
state = result.get_statevector(qc)
keys = [
bin(i)[2::].rjust(int(np.log2(len(state))), "0")[::-1]
for i in range(0, len(state))
bin(i)[2::].rjust(int(np.log2(len(state))), "0")[::-1] for i in range(0, len(state))
]
probs = [abs(a) ** 2 for a in state]
total = math.fsum(probs)
Expand All @@ -358,9 +347,7 @@ def _get_probs(self, qc: QuantumCircuit) -> Dict[str, float]:
state = result.get_counts(qc)
shots = self.quantum_instance.run_config.shots
hist = {key[::-1]: val / shots for key, val in state.items() if val > 0}
self._circuit_results = {
b[::-1]: np.sqrt(v / shots) for (b, v) in state.items()
}
self._circuit_results = {b[::-1]: np.sqrt(v / shots) for (b, v) in state.items()}
return hist

@staticmethod
Expand Down
12 changes: 3 additions & 9 deletions qiskit_optimization/algorithms/minimum_eigen_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,15 @@ def _solve_internal(
raw_samples = self._eigenvector_to_solutions(
eigen_result.eigenstate, converted_problem
)
raw_samples.sort(
key=lambda x: converted_problem.objective.sense.value * x.fval
)
raw_samples.sort(key=lambda x: converted_problem.objective.sense.value * x.fval)
x = raw_samples[0].x
fval = raw_samples[0].fval

# if Hamiltonian is empty, then the objective function is constant to the offset
else:
x = np.zeros(converted_problem.get_num_binary_vars())
fval = offset
raw_samples = [
SolutionSample(x, fval, 1.0, OptimizationResultStatus.SUCCESS)
]
raw_samples = [SolutionSample(x, fval, 1.0, OptimizationResultStatus.SUCCESS)]

if fval is None or x is None:
# if not function value is given, then something went wrong, e.g., a
Expand All @@ -246,9 +242,7 @@ def _solve_internal(
min_eigen_solver_result=eigen_result,
)
# translate result back to integers
samples = self._interpret_samples(
original_problem, raw_samples, self._converters
)
samples = self._interpret_samples(original_problem, raw_samples, self._converters)
return cast(
MinimumEigenOptimizationResult,
self._interpret(
Expand Down
8 changes: 2 additions & 6 deletions qiskit_optimization/algorithms/multistart_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,8 @@ def multi_start_solve(
x_0 = np.zeros(problem.get_num_vars())
if trial > 0:
for i, var in enumerate(problem.variables):
lowerbound = (
var.lowerbound if var.lowerbound > -INFINITY else -self._clip
)
upperbound = (
var.upperbound if var.upperbound < INFINITY else self._clip
)
lowerbound = var.lowerbound if var.lowerbound > -INFINITY else -self._clip
upperbound = var.upperbound if var.upperbound < INFINITY else self._clip
x_0[i] = uniform.rvs(lowerbound, (upperbound - lowerbound))
# run optimization
t_0 = time.time()
Expand Down
Loading