def test_auto_penalty(self): """Test auto penalty function""" op = QuadraticProgram() op.binary_var("x") op.binary_var("y") op.binary_var("z") op.minimize(constant=3, linear={"x": 1}, quadratic={("x", "y"): 2}) op.linear_constraint(linear={ "x": 1, "y": 1, "z": 1 }, sense="EQ", rhs=2, name="xyz_eq") lineq2penalty = LinearEqualityToPenalty(penalty=1e5) lineq2penalty_auto = LinearEqualityToPenalty() qubo = lineq2penalty.convert(op) qubo_auto = lineq2penalty_auto.convert(op) exact_mes = NumPyMinimumEigensolver() exact = MinimumEigenOptimizer(exact_mes) result = exact.solve(qubo) result_auto = exact.solve(qubo_auto) self.assertEqual(result.fval, result_auto.fval) np.testing.assert_array_almost_equal(result.x, result_auto.x)
def test_linear_equality_to_penalty_decode(self): """Test decode func of LinearEqualityToPenalty""" qprog = QuadraticProgram() qprog.binary_var("x") qprog.binary_var("y") qprog.binary_var("z") qprog.maximize(linear={"x": 3, "y": 1, "z": 1}) qprog.linear_constraint(linear={ "x": 1, "y": 1, "z": 1 }, sense="EQ", rhs=2, name="xyz_eq") lineq2penalty = LinearEqualityToPenalty() qubo = lineq2penalty.convert(qprog) exact_mes = NumPyMinimumEigensolver() exact = MinimumEigenOptimizer(exact_mes) result = exact.solve(qubo) new_x = lineq2penalty.interpret(result.x) np.testing.assert_array_almost_equal(new_x, [1, 1, 0]) infeasible_x = lineq2penalty.interpret([1, 1, 1]) np.testing.assert_array_almost_equal(infeasible_x, [1, 1, 1])
def test_penalty_recalculation_when_reusing(self): """Test the penalty retrieval and recalculation of LinearEqualityToPenalty""" op = QuadraticProgram() op.binary_var("x") op.binary_var("y") op.binary_var("z") op.minimize(constant=3, linear={"x": 1}, quadratic={("x", "y"): 2}) op.linear_constraint(linear={ "x": 1, "y": 1, "z": 1 }, sense="EQ", rhs=2, name="xyz_eq") # First, create a converter with no penalty lineq2penalty = LinearEqualityToPenalty() self.assertIsNone(lineq2penalty.penalty) # Then converter must calculate the penalty for the problem (should be 4.0) lineq2penalty.convert(op) self.assertEqual(4, lineq2penalty.penalty) # Re-use the converter with a newly defined penalty lineq2penalty.penalty = 3 lineq2penalty.convert(op) self.assertEqual(3, lineq2penalty.penalty) # Re-use the converter letting the penalty be calculated again lineq2penalty.penalty = None lineq2penalty.convert(op) self.assertEqual(4, lineq2penalty.penalty)
def test_converter_list(self): """Test converter list""" op = QuadraticProgram() op.integer_var(0, 3, "x") op.binary_var('y') op.maximize(linear={'x': 1, 'y': 2}) op.linear_constraint(linear={'x': 1, 'y': 1}, sense='LE', rhs=3, name='xy_leq') min_eigen_solver = NumPyMinimumEigensolver() # a single converter qp2qubo = QuadraticProgramToQubo() min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver, converters=qp2qubo) result = min_eigen_optimizer.solve(op) self.assertEqual(result.fval, 4) # a list of converters ineq2eq = InequalityToEquality() int2bin = IntegerToBinary() penalize = LinearEqualityToPenalty() converters = [ineq2eq, int2bin, penalize] min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver, converters=converters) result = min_eigen_optimizer.solve(op) self.assertEqual(result.fval, 4) with self.assertRaises(TypeError): invalid = [qp2qubo, "invalid converter"] MinimumEigenOptimizer(min_eigen_solver, converters=invalid)
def test_converter_list(self): """Test converters list""" # Input. model = Model() x_0 = model.binary_var(name='x0') x_1 = model.binary_var(name='x1') model.maximize(-x_0+2*x_1) op = QuadraticProgram() op.from_docplex(model) # Get the optimum key and value. n_iter = 8 # a single converter. qp2qubo = QuadraticProgramToQubo() gmf = GroverOptimizer(4, num_iterations=n_iter, quantum_instance=self.sv_simulator, converters=qp2qubo) results = gmf.solve(op) self.validate_results(op, results) # a list of converters ineq2eq = InequalityToEquality() int2bin = IntegerToBinary() penalize = LinearEqualityToPenalty() converters = [ineq2eq, int2bin, penalize] gmf = GroverOptimizer(4, num_iterations=n_iter, quantum_instance=self.sv_simulator, converters=converters) results = gmf.solve(op) self.validate_results(op, results) # invalid converters with self.assertRaises(TypeError): invalid = [qp2qubo, "invalid converter"] GroverOptimizer(4, num_iterations=n_iter, quantum_instance=self.sv_simulator, converters=invalid)
def test_empty_problem(self): """ Test empty problem """ op = QuadraticProgram() conv = InequalityToEquality() op = conv.convert(op) conv = IntegerToBinary() op = conv.convert(op) conv = LinearEqualityToPenalty() op = conv.convert(op) _, shift = op.to_ising() self.assertEqual(shift, 0.0)
def test_penalize_sense(self): """Test PenalizeLinearEqualityConstraints with senses""" op = QuadraticProgram() for i in range(3): op.binary_var(name="x{}".format(i)) # Linear constraints linear_constraint = {"x0": 1, "x1": 1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 1, "x0x1") linear_constraint = {"x1": 1, "x2": -1} op.linear_constraint(linear_constraint, Constraint.Sense.LE, 2, "x1x2") linear_constraint = {"x0": 1, "x2": 3} op.linear_constraint(linear_constraint, Constraint.Sense.GE, 2, "x0x2") self.assertEqual(op.get_num_linear_constraints(), 3) conv = LinearEqualityToPenalty() with self.assertRaises(QiskitOptimizationError): conv.convert(op)
def test_optimizationproblem_to_ising(self): """Test optimization problem to operators""" op = QuadraticProgram() for i in range(4): op.binary_var(name="x{}".format(i)) linear = {} for x in op.variables: linear[x.name] = 1 op.maximize(0, linear, {}) linear = {} for i, x in enumerate(op.variables): linear[x.name] = i + 1 op.linear_constraint(linear, Constraint.Sense.EQ, 3, "sum1") penalize = LinearEqualityToPenalty(penalty=1e5) op2 = penalize.convert(op) qubitop, offset = op2.to_ising() self.assertEqual(qubitop, QUBIT_OP_MAXIMIZE_SAMPLE) self.assertEqual(offset, OFFSET_MAXIMIZE_SAMPLE)
def test_auto_penalty_warning(self): """ Test warnings of auto penalty function""" op = QuadraticProgram() op.binary_var('x') op.binary_var('y') op.binary_var('z') op.minimize(linear={'x': 1, 'y': 2}) op.linear_constraint(linear={'x': 0.5, 'y': 0.5, 'z': 0.5}, sense='EQ', rhs=1, name='xyz') with self.assertLogs('qiskit_optimization', level='WARNING') as log: lineq2penalty = LinearEqualityToPenalty() _ = lineq2penalty.convert(op) warning = ( 'WARNING:qiskit_optimization.converters.linear_equality_to_penalty:' 'Warning: Using 100000.000000 for the penalty coefficient because a float ' 'coefficient exists in constraints. \nThe value could be too small. If so, ' 'set the penalty coefficient manually.' ) self.assertIn(warning, log.output)
def test_penalize_binary(self): """Test PenalizeLinearEqualityConstraints with binary variables""" op = QuadraticProgram() for i in range(3): op.binary_var(name="x{}".format(i)) # Linear constraints linear_constraint = {"x0": 1, "x1": 1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 1, "x0x1") linear_constraint = {"x1": 1, "x2": -1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 2, "x1x2") linear_constraint = {"x0": 1, "x2": 3} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 2, "x0x2") self.assertEqual(op.get_num_linear_constraints(), 3) conv = LinearEqualityToPenalty() op2 = conv.convert(op) self.assertEqual(op2.get_num_linear_constraints(), 0) new_x = conv.interpret(np.arange(3)) np.testing.assert_array_almost_equal(new_x, np.arange(3))
def test_penalize_integer(self): """Test PenalizeLinearEqualityConstraints with integer variables""" op = QuadraticProgram() for i in range(3): op.integer_var(name="x{}".format(i), lowerbound=-3, upperbound=3) # Linear constraints linear_constraint = {"x0": 1, "x1": 1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 1, "x0x1") linear_constraint = {"x1": 1, "x2": -1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 2, "x1x2") linear_constraint = {"x0": 1, "x2": -1} op.linear_constraint(linear_constraint, Constraint.Sense.EQ, 1, "x0x2") op.minimize(constant=3, linear={"x0": 1}, quadratic={("x1", "x2"): 2}) self.assertEqual(op.get_num_linear_constraints(), 3) conv = LinearEqualityToPenalty() op2 = conv.convert(op) self.assertEqual(op2.get_num_linear_constraints(), 0) new_x = conv.interpret([0, 1, -1]) np.testing.assert_array_almost_equal(new_x, [0, 1, -1])
def test_converter_list(self): """Test converter list""" op = QuadraticProgram() op.integer_var(0, 3, "x") op.binary_var("y") op.maximize(linear={"x": 1, "y": 2}) op.linear_constraint(linear={ "y": 1, "x": 1 }, sense="LE", rhs=3, name="xy_leq") # construct minimum eigen optimizer min_eigen_solver = NumPyMinimumEigensolver() min_eigen_optimizer = MinimumEigenOptimizer(min_eigen_solver) # a single converter qp2qubo = QuadraticProgramToQubo() recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( min_eigen_optimizer, min_num_vars=2, converters=qp2qubo) result = recursive_min_eigen_optimizer.solve(op) self.assertEqual(result.fval, 4) # a list of converters ineq2eq = InequalityToEquality() int2bin = IntegerToBinary() penalize = LinearEqualityToPenalty() converters = [ineq2eq, int2bin, penalize] recursive_min_eigen_optimizer = RecursiveMinimumEigenOptimizer( min_eigen_optimizer, min_num_vars=2, converters=converters) result = recursive_min_eigen_optimizer.solve(op) self.assertEqual(result.fval, 4) # invalid converters with self.assertRaises(TypeError): invalid = [qp2qubo, "invalid converter"] RecursiveMinimumEigenOptimizer(min_eigen_optimizer, min_num_vars=2, converters=invalid)
def test_auto_penalty_warning(self): """Test warnings of auto penalty function""" op = QuadraticProgram() op.binary_var("x") op.binary_var("y") op.binary_var("z") op.minimize(linear={"x": 1, "y": 2}) op.linear_constraint(linear={ "x": 0.5, "y": 0.5, "z": 0.5 }, sense="EQ", rhs=1, name="xyz") with self.assertLogs("qiskit_optimization", level="WARNING") as log: lineq2penalty = LinearEqualityToPenalty() _ = lineq2penalty.convert(op) warning = ( "WARNING:qiskit_optimization.converters.linear_equality_to_penalty:" "Warning: Using 100000.000000 for the penalty coefficient because a float " "coefficient exists in constraints. \nThe value could be too small. If so, " "set the penalty coefficient manually.") self.assertIn(warning, log.output)