def test_truncate(self): """Test truncate""" self.assertEqual(expr2str(123456789, truncate=5), "12345...") q_p = QuadraticProgram() q_p.binary_var_list(3, name="long_name") q_p.linear_constraint({0: 1, 1: 2, 2: 3}, "==", 0) self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, truncate=10), "long_name0...") self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, truncate=20), "long_name0 + 2*long_...", ) q_p.quadratic_constraint(quadratic={ (0, 0): 1, (1, 2): 2, (2, 0): -3 }, sense="==", rhs=0) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic, truncate=20), "long_name0^2 - 3*lon...", )
def test_wrap_and_indent(self): """Test wrap and indent""" q_p = QuadraticProgram() q_p.binary_var_list(3, name="x") q_p.linear_constraint({0: 1, 1: 2, 2: 3}, "==", 0) self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, wrap=0), "x0 + 2*x1 + 3*x2") self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, wrap=80), "x0 + 2*x1 + 3*x2") self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, wrap=8), "x0\n+ 2*x1\n+ 3*x2") self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, wrap=9), "x0 + 2*x1\n+ 3*x2") self.assertEqual( expr2str(linear=q_p.get_linear_constraint(0).linear, wrap=5, indent=2), " x0\n + 2*x1\n + 3*x2", ) q_p.quadratic_constraint(quadratic={ (0, 0): 1, (1, 2): 2, (2, 0): -3 }, sense="==", rhs=0) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic), "x0^2 - 3*x0*x2 + 2*x1*x2", ) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic, wrap=80), "x0^2 - 3*x0*x2 + 2*x1*x2", ) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic, wrap=13), "x0^2\n- 3*x0*x2\n+ 2*x1*x2", ) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic, wrap=14), "x0^2 - 3*x0*x2\n+ 2*x1*x2", ) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic, wrap=10, indent=2), " x0^2\n - 3*x0*x2\n + 2*x1*x2", )
def test_linear(self): """Test linear expression""" q_p = QuadraticProgram() q_p.binary_var_list(3) q_p.linear_constraint({0: 1, 1: 2, 2: 3}, "==", 0) self.assertEqual(expr2str(linear=q_p.get_linear_constraint(0).linear), "x0 + 2*x1 + 3*x2") self.assertEqual( expr2str(constant=-1, linear=q_p.get_linear_constraint(0).linear), "x0 + 2*x1 + 3*x2 - 1", )
def test_quadratic(self): """Test quadratic expression""" q_p = QuadraticProgram() q_p.binary_var_list(3) q_p.quadratic_constraint(quadratic={ (0, 0): 1, (1, 2): 2, (2, 0): -3 }, sense="==", rhs=0) self.assertEqual( expr2str(quadratic=q_p.get_quadratic_constraint(0).quadratic), "x0^2 - 3*x0*x2 + 2*x1*x2", ) self.assertEqual( expr2str(constant=1, quadratic=q_p.get_quadratic_constraint(0).quadratic), "x0^2 - 3*x0*x2 + 2*x1*x2 + 1", )
def test_str_repr(self): """Test str and repr""" with self.subTest("4 variables"): n = 4 q_p = QuadraticProgram() q_p.binary_var_list(n) # x0,...,x3 quad = {(i, i): float(i) for i in range(n)} lin = [float(i) for i in range(n)] q_p.maximize(quadratic=quad, linear=lin, constant=n) expected = "maximize x1^2 + 2*x2^2 + 3*x3^2 + x1 + 2*x2 + 3*x3 + 4" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.minimize(quadratic=quad, linear=lin, constant=n) expected = "minimize x1^2 + 2*x2^2 + 3*x3^2 + x1 + 2*x2 + 3*x3 + 4" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") quad = {(i, (i + 1) % n): i for i in range(n)} q_p.maximize(quadratic=quad, linear=lin, constant=0) expected = "maximize 3*x0*x3 + x1*x2 + 2*x2*x3 + x1 + 2*x2 + 3*x3" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.minimize(quadratic=quad, linear=lin, constant=0) expected = "minimize 3*x0*x3 + x1*x2 + 2*x2*x3 + x1 + 2*x2 + 3*x3" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") with self.subTest("50 variables"): # pylint: disable=cyclic-import from qiskit_optimization.translators.prettyprint import DEFAULT_TRUNCATE n = 50 q_p = QuadraticProgram() q_p.binary_var_list(n) quad = {(i, i): float(i) for i in range(n)} lin = [float(i) for i in range(n)] expected = " ".join( ["x1^2"] + sorted([f"+ {i}*x{i}^2" for i in range(2, n)], key=lambda e: e.split(" ")[1]) + ["+ x1"] + sorted([f"+ {i}*x{i}" for i in range(2, n)], key=lambda e: e.split(" ")[1]) + [f"+ {n}"] ) q_p.maximize(quadratic=quad, linear=lin, constant=n) self.assertEqual(str(q_p.objective), f"maximize {expected}") self.assertEqual( repr(q_p.objective), f"<QuadraticObjective: maximize {expected[:DEFAULT_TRUNCATE]}...>", ) q_p.minimize(quadratic=quad, linear=lin, constant=n) self.assertEqual(str(q_p.objective), f"minimize {expected}") self.assertEqual( repr(q_p.objective), f"<QuadraticObjective: minimize {expected[:DEFAULT_TRUNCATE]}...>", ) quad = {(i + 1, i): float(i + 1) for i in range(2)} lin = [float(i) for i in range(n)] expected = " ".join( ["x0*x1 + 2*x1*x2"] + ["+ x1"] + sorted([f"+ {i}*x{i}" for i in range(2, n)], key=lambda e: e.split(" ")[1]) + [f"+ {n}"] ) q_p.maximize(quadratic=quad, linear=lin, constant=n) self.assertEqual(str(q_p.objective), f"maximize {expected}") self.assertEqual( repr(q_p.objective), f"<QuadraticObjective: maximize {expected[:DEFAULT_TRUNCATE]}...>", ) q_p.minimize(quadratic=quad, linear=lin, constant=n) self.assertEqual(str(q_p.objective), f"minimize {expected}") self.assertEqual( repr(q_p.objective), f"<QuadraticObjective: minimize {expected[:DEFAULT_TRUNCATE]}...>", ) with self.subTest("only constant"): q_p = QuadraticProgram() q_p.maximize() expected = "maximize 0" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.minimize() expected = "minimize 0" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.maximize(constant=-1.23) expected = "maximize -1.23" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.minimize(constant=-1.23) expected = "minimize -1.23" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") with self.subTest("1 variable"): q_p = QuadraticProgram() q_p.binary_var("z") q_p.maximize(linear=[1], quadratic={("z", "z"): -1}, constant=1) expected = "maximize -z^2 + z + 1" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>") q_p.minimize(linear=[1], quadratic={("z", "z"): -1}, constant=1) expected = "minimize -z^2 + z + 1" self.assertEqual(str(q_p.objective), expected) self.assertEqual(repr(q_p.objective), f"<QuadraticObjective: {expected}>")
def test_prettyprint(self): """Test prettyprint""" with self.subTest("empty"): q_p = QuadraticProgram() expected = "\n".join([ "Problem name: ", "", "Minimize", " 0", "", "Subject to", " No constraints", "", " No variables", "", ]) self.assertEqual(prettyprint(q_p), expected) self.assertEqual(q_p.prettyprint(), expected) with self.subTest("minimize 1"): q_p = QuadraticProgram("test") q_p.binary_var(name="x") q_p.binary_var(name="y") q_p.minimize(linear={"x": 1}, quadratic={("x", "y"): 1}) expected = "\n".join([ "Problem name: test", "", "Minimize", " x*y + x", "", "Subject to", " No constraints", "", " Binary variables (2)", " x y", "", ]) self.assertEqual(prettyprint(q_p), expected) self.assertEqual(q_p.prettyprint(), expected) with self.subTest("maximize 1"): q_p = QuadraticProgram("test") q_p.integer_var(lowerbound=5, upperbound=10, name="x") q_p.continuous_var(lowerbound=-1, name="y") q_p.maximize(linear={"x": -1, "y": 2}, constant=3) q_p.quadratic_constraint({}, {("x", "y"): -1}, "<=", 4) expected = "\n".join([ "Problem name: test", "", "Maximize", " -x + 2*y + 3", "", "Subject to", " Quadratic constraints (1)", " -x*y <= 4 'q0'", "", " Integer variables (1)", " 5 <= x <= 10", "", " Continuous variables (1)", " -1 <= y", "", ]) self.assertEqual(prettyprint(q_p), expected) self.assertEqual(q_p.prettyprint(), expected) with self.subTest("minimize 2"): q_p = QuadraticProgram("my problem") q_p.binary_var("x") q_p.integer_var(-1, 5, "y") q_p.continuous_var(-1, 5, "z") q_p.minimize(1, { "x": 1, "y": -1, "z": 10 }, { ("x", "x"): 0.5, ("y", "z"): -1 }) q_p.linear_constraint({"x": 1, "y": 2}, "==", 1, "lin_eq") q_p.linear_constraint({"x": 1, "y": 2}, "<=", 1, "lin_leq") q_p.linear_constraint({"x": 1, "y": 2}, ">=", 1, "lin_geq") q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "==", 1, "quad_eq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "<=", 1, "quad_leq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, ">=", 1, "quad_geq", ) expected = "\n".join([ "Problem name: my problem", "", "Minimize", " 0.5*x^2 - y*z + x - y + 10*z + 1", "", "Subject to", " Linear constraints (3)", " x + 2*y == 1 'lin_eq'", " x + 2*y <= 1 'lin_leq'", " x + 2*y >= 1 'lin_geq'", "", " Quadratic constraints (3)", " x^2 - y*z + 2*z^2 + x + y == 1 'quad_eq'", " x^2 - y*z + 2*z^2 + x + y <= 1 'quad_leq'", " x^2 - y*z + 2*z^2 + x + y >= 1 'quad_geq'", "", " Integer variables (1)", " -1 <= y <= 5", "", " Continuous variables (1)", " -1 <= z <= 5", "", " Binary variables (1)", " x", "", ]) self.assertEqual(prettyprint(q_p), expected) self.assertEqual(q_p.prettyprint(), expected) with self.subTest("maximize 2"): q_p = QuadraticProgram("problem 1") q_p.integer_var(-1, 2, "x") q_p.integer_var(-1, 2, "y") q_p.continuous_var(-1, name="z") q_p.binary_var("u") q_p.binary_var("very_long_variable") q_p.binary_var_list(10) q_p.integer_var_list(3) q_p.continuous_var_list(3) q_p.minimize(constant=3, linear={ "x": 2, "y": 3 }, quadratic={("u", "x"): -1}) q_p.linear_constraint({"x": 1, "y": -2}, ">=", 2, name="lin_GE") q_p.linear_constraint({"x": 2, "y": -1}, "==", 1, name="lin_EQ") q_p.quadratic_constraint({ "x": 1, "u": 1 }, { (3, 4): 1, (5, 6): -1 }, "<=", 1, name="quad_LE") q_p.quadratic_constraint({ "x": 2, "y": -1 }, {("z", "z"): -1}, "<=", 1) expected = "\n".join([ "Problem name: problem 1", "", "Minimize", " -x*u + 2*x + 3*y + 3", "", "Subject to", " Linear constraints (2)", " x - 2*y >= 2 'lin_GE'", " 2*x - y == 1 'lin_EQ'", "", " Quadratic constraints (2)", " u*very_long_variable - x5*x6 + u + x <= 1 'quad_LE'", " -z^2 + 2*x - y <= 1 'q1'", "", " Integer variables (5)", " -1 <= x <= 2", " -1 <= y <= 2", " 0 <= x15", " 0 <= x16", " 0 <= x17", "", " Continuous variables (4)", " -1 <= z", " 0 <= x18", " 0 <= x19", " 0 <= x20", "", " Binary variables (12)", " u very_long_variable x5 x6 x7 x8 x9 x10 x11 x12 x13 x14", "", ]) self.assertEqual(prettyprint(q_p), expected) self.assertEqual(q_p.prettyprint(), expected)
def test_wrap(self): """Test wrap""" with self.subTest("minimize, wrap=15"): q_p = QuadraticProgram("my problem") q_p.binary_var("x") q_p.binary_var_list(10, "u") q_p.integer_var(-1, 5, "y") q_p.continuous_var(-1, 5, "z") q_p.minimize(1, { "x": 1, "y": -1, "z": 10 }, { ("x", "x"): 0.5, ("y", "z"): -1 }) q_p.linear_constraint({"x": 1, "y": 2}, "==", 1, "lin_eq") q_p.linear_constraint({"x": 1, "y": 2}, "<=", 1, "lin_leq") q_p.linear_constraint({"x": 1, "y": 2}, ">=", 1, "lin_geq") q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "==", 1, "quad_eq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "<=", 1, "quad_leq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, ">=", 1, "quad_geq", ) expected = "\n".join([ "Problem name: my problem", "", "Minimize", " 0.5*x^2 - y*z", " + x - y", " + 10*z + 1", "", "Subject to", " Linear constraints (3)", " x + 2*y", " == 1 'lin_eq'", " x + 2*y", " <= 1 'lin_leq'", " x + 2*y", " >= 1 'lin_geq'", "", " Quadratic constraints (3)", " x^2 - y*z", " + 2*z^2 + x", " + y", " == 1 'quad_eq'", " x^2 - y*z", " + 2*z^2 + x", " + y", " <= 1 'quad_leq'", " x^2 - y*z", " + 2*z^2 + x", " + y", " >= 1 'quad_geq'", "", " Integer variables (1)", " -1 <= y <= 5", "", " Continuous variables (1)", " -1 <= z <= 5", "", " Binary variables (11)", " x u1 u2 u3", " u4 u5 u6 u7", " u8 u9 u10", "", ]) wrap = 15 self.assertEqual(prettyprint(q_p, wrap), expected) self.assertEqual(q_p.prettyprint(wrap), expected) with self.subTest("minimize, wrap=22"): q_p = QuadraticProgram("my problem") q_p.binary_var("x") q_p.binary_var_list(10, "u") q_p.integer_var(-1, 5, "y") q_p.continuous_var(-1, 5, "z") q_p.minimize(1, { "x": 1, "y": -1, "z": 10 }, { ("x", "x"): 0.5, ("y", "z"): -1 }) q_p.linear_constraint({"x": 1, "y": 2}, "==", 1, "lin_eq") q_p.linear_constraint({"x": 1, "y": 2}, "<=", 1, "lin_leq") q_p.linear_constraint({"x": 1, "y": 2}, ">=", 1, "lin_geq") q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "==", 1, "quad_eq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "<=", 1, "quad_leq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, ">=", 1, "quad_geq", ) expected = "\n".join([ "Problem name: my problem", "", "Minimize", " 0.5*x^2 - y*z + x", " - y + 10*z + 1", "", "Subject to", " Linear constraints (3)", " x + 2*y", " == 1 'lin_eq'", " x + 2*y", " <= 1 'lin_leq'", " x + 2*y", " >= 1 'lin_geq'", "", " Quadratic constraints (3)", " x^2 - y*z + 2*z^2", " + x + y", " == 1 'quad_eq'", " x^2 - y*z + 2*z^2", " + x + y", " <= 1 'quad_leq'", " x^2 - y*z + 2*z^2", " + x + y", " >= 1 'quad_geq'", "", " Integer variables (1)", " -1 <= y <= 5", "", " Continuous variables (1)", " -1 <= z <= 5", "", " Binary variables (11)", " x u1 u2 u3 u4 u5", " u6 u7 u8 u9 u10", "", ]) wrap = 22 self.assertEqual(prettyprint(q_p, wrap), expected) self.assertEqual(q_p.prettyprint(wrap), expected) with self.subTest("minimize, wrap=23"): q_p = QuadraticProgram("my problem") q_p.binary_var("x") q_p.binary_var_list(10, "u") q_p.integer_var(-1, 5, "y") q_p.continuous_var(-1, 5, "z") q_p.minimize(1, { "x": 1, "y": -1, "z": 10 }, { ("x", "x"): 0.5, ("y", "z"): -1 }) q_p.linear_constraint({"x": 1, "y": 2}, "==", 1, "lin_eq") q_p.linear_constraint({"x": 1, "y": 2}, "<=", 1, "lin_leq") q_p.linear_constraint({"x": 1, "y": 2}, ">=", 1, "lin_geq") q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "==", 1, "quad_eq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, "<=", 1, "quad_leq", ) q_p.quadratic_constraint( { "x": 1, "y": 1 }, { ("x", "x"): 1, ("y", "z"): -1, ("z", "z"): 2 }, ">=", 1, "quad_geq", ) expected = "\n".join([ "Problem name: my problem", "", "Minimize", " 0.5*x^2 - y*z + x - y", " + 10*z + 1", "", "Subject to", " Linear constraints (3)", " x + 2*y", " == 1 'lin_eq'", " x + 2*y", " <= 1 'lin_leq'", " x + 2*y", " >= 1 'lin_geq'", "", " Quadratic constraints (3)", " x^2 - y*z + 2*z^2", " + x + y", " == 1 'quad_eq'", " x^2 - y*z + 2*z^2", " + x + y", " <= 1 'quad_leq'", " x^2 - y*z + 2*z^2", " + x + y", " >= 1 'quad_geq'", "", " Integer variables (1)", " -1 <= y <= 5", "", " Continuous variables (1)", " -1 <= z <= 5", "", " Binary variables (11)", " x u1 u2 u3 u4 u5 u6", " u7 u8 u9 u10", "", ]) wrap = 23 self.assertEqual(prettyprint(q_p, wrap), expected) self.assertEqual(q_p.prettyprint(wrap), expected)