11import pyoptinterface as poi
22from pytest import approx
33
4+ import numpy as np
5+
46
57def test_simple_qp (model_interface ):
68 model = model_interface
@@ -21,3 +23,46 @@ def test_simple_qp(model_interface):
2123
2224 obj_val = model .get_model_attribute (poi .ModelAttribute .ObjectiveValue )
2325 assert obj_val == approx (N ** 2 )
26+
27+
28+ # reported by https://github.com/metab0t/PyOptInterface/issues/59
29+ def test_shuffle_qp_objective (model_interface ):
30+ model = model_interface
31+
32+ N = 3
33+ weights = model .add_m_variables (N , lb = 0 )
34+
35+ expected_returns = [0.05 , 0.07 , 0.12 ]
36+ min_return = 0.06
37+ cov = [
38+ (0 , 0 , 0.1 ),
39+ (0 , 1 , 0.1 ),
40+ (0 , 2 , 0.04 ),
41+ (1 , 1 , 0.4 ),
42+ (1 , 2 , 0.2 ),
43+ (2 , 2 , 0.9 ),
44+ ]
45+ cov_objs = [weights [i ] * weights [j ] * v for i , j , v in cov ]
46+
47+ model .add_linear_constraint (poi .quicksum (weights ) == 1 )
48+ model .add_linear_constraint (
49+ poi .quicksum (expected_returns [i ] * weights [i ] for i in range (N )) >= min_return
50+ )
51+
52+ trial = 120
53+ obj_values = []
54+ for _ in range (trial ):
55+ import random
56+
57+ random .shuffle (cov_objs )
58+ obj = poi .quicksum (cov_objs )
59+ model .set_objective (obj , poi .ObjectiveSense .Minimize )
60+
61+ model .optimize ()
62+
63+ obj_value = model .get_model_attribute (poi .ModelAttribute .ObjectiveValue )
64+ obj_values .append (obj_value )
65+
66+ obj_values = np .array (obj_values )
67+ # test all values are the same
68+ assert np .all (np .abs (obj_values - obj_values [0 ]) < 1e-8 )
0 commit comments