@@ -97,39 +97,36 @@ def update(self):
9797
9898
9999class _MutableQuadraticCoefficient :
100- def __init__ (self , expr , row_idx , col_idx ):
100+ def __init__ (self , expr , v1_id , v2_id ):
101101 self .expr = expr
102- self .row_idx = row_idx
103- self .col_idx = col_idx
102+ self .v1_id = v1_id
103+ self .v2_id = v2_id
104104
105105
106106class _MutableObjective :
107- def __init__ (self , highs , constant , linear_coefs , quadratic_coefs ):
107+ def __init__ (
108+ self ,
109+ highs ,
110+ constant ,
111+ linear_coefs ,
112+ quadratic_coefs ,
113+ pyomo_var_to_solver_var_map ,
114+ ):
108115 self .highs = highs
109116 self .constant = constant
110117 self .linear_coefs = linear_coefs
111118 self .quadratic_coefs = quadratic_coefs
112- self .last_quadratic_coef_values = [ value ( i . expr ) for i in self . quadratic_coefs ]
119+ self ._pyomo_var_to_solver_var_map = pyomo_var_to_solver_var_map
113120 # Store the quadratic coefficients in dictionary format
114- self .quad_coef_dict = {}
115- self ._initialize_quad_coef_dict ()
121+ self ._initialize_quad_coef_dicts ()
116122 # Flag to force first update of quadratic coefficients
117123 self ._first_update = True
118124
119- def _initialize_quad_coef_dict (self ):
125+ def _initialize_quad_coef_dicts (self ):
126+ self .quad_coef_dict = {}
120127 for coef in self .quadratic_coefs :
121- v1_ndx = coef .row_idx
122- v2_ndx = coef .col_idx
123- # Ensure we're storing the lower triangular part
124- row = max (v1_ndx , v2_ndx )
125- col = min (v1_ndx , v2_ndx )
126-
127- coef_val = value (coef .expr )
128- # Adjust for diagonal elements
129- if v1_ndx == v2_ndx :
130- coef_val *= 2.0
131-
132- self .quad_coef_dict [(row , col )] = coef_val
128+ self .quad_coef_dict [(coef .v1_id , coef .v2_id )] = value (coef .expr )
129+ self .previous_quad_coef_dict = self .quad_coef_dict .copy ()
133130
134131 def update (self ):
135132 """
@@ -141,23 +138,13 @@ def update(self):
141138 for coef in self .linear_coefs :
142139 coef .update ()
143140
144- for ndx , coef in enumerate ( self .quadratic_coefs ) :
141+ for coef in self .quadratic_coefs :
145142 current_val = value (coef .expr )
146- if current_val != self .last_quadratic_coef_values [ndx ]:
143+ previous_val = self .previous_quad_coef_dict .get ((coef .v1_id , coef .v2_id ))
144+ if previous_val is not None and current_val != previous_val :
147145 needs_quadratic_update = True
148-
149- v1_ndx = coef .row_idx
150- v2_ndx = coef .col_idx
151- row = max (v1_ndx , v2_ndx )
152- col = min (v1_ndx , v2_ndx )
153-
154- # Adjust the diagonal to match Highs' expected format
155- if v1_ndx == v2_ndx :
156- current_val *= 2.0
157-
158- self .quad_coef_dict [(row , col )] = current_val
159-
160- self .last_quadratic_coef_values [ndx ] = current_val
146+ self .quad_coef_dict [(coef .v1_id , coef .v2_id )] = current_val
147+ self .previous_quad_coef_dict [(coef .v1_id , coef .v2_id )] = current_val
161148
162149 # If anything changed, rebuild and pass the Hessian
163150 if needs_quadratic_update :
@@ -176,8 +163,20 @@ def _build_and_pass_hessian(self):
176163 hessian_index = []
177164 hessian_start = [0 ] * dim
178165
166+ quad_coef_idx_dict = {}
167+ for (v1_id , v2_id ), coef in self .quad_coef_dict .items ():
168+ v1_ndx = self ._pyomo_var_to_solver_var_map [v1_id ]
169+ v2_ndx = self ._pyomo_var_to_solver_var_map [v2_id ]
170+ # Ensure we're storing the lower triangular part
171+ row = max (v1_ndx , v2_ndx )
172+ col = min (v1_ndx , v2_ndx )
173+ # Adjust the diagonal to match Highs' expected format
174+ if v1_ndx == v2_ndx :
175+ coef *= 2.0
176+ quad_coef_idx_dict [(row , col )] = coef
177+
179178 sorted_entries = sorted (
180- self . quad_coef_dict .items (), key = lambda x : (x [0 ][1 ], x [0 ][0 ])
179+ quad_coef_idx_dict .items (), key = lambda x : (x [0 ][1 ], x [0 ][0 ])
181180 )
182181
183182 last_col = - 1
@@ -645,16 +644,11 @@ def _set_objective(self, obj):
645644
646645 if repn .quadratic_vars and len (repn .quadratic_vars ) > 0 :
647646 for ndx , (v1 , v2 ) in enumerate (repn .quadratic_vars ):
648- v1_id = id (v1 )
649- v2_id = id (v2 )
650- v1_ndx = self ._pyomo_var_to_solver_var_map [v1_id ]
651- v2_ndx = self ._pyomo_var_to_solver_var_map [v2_id ]
652-
653647 coef = repn .quadratic_coefs [ndx ]
654648
655649 mutable_quadratic_coefficients .append (
656650 _MutableQuadraticCoefficient (
657- expr = coef , row_idx = v1_ndx , col_idx = v2_ndx
651+ expr = coef , v1_id = id ( v1 ), v2_id = id ( v2 )
658652 )
659653 )
660654
@@ -665,6 +659,7 @@ def _set_objective(self, obj):
665659 mutable_constant ,
666660 mutable_linear_coefficients ,
667661 mutable_quadratic_coefficients ,
662+ self ._pyomo_var_to_solver_var_map ,
668663 )
669664 self ._mutable_objective .update ()
670665
0 commit comments