@@ -613,16 +613,19 @@ def nterm(self) -> int:
613613 def coord_names (self ) -> list [str ]:
614614 return [str (c .name ) for c in self ._coords ]
615615
616+ def _active_to_dataarray (
617+ self , active_values : np .ndarray , fill : float | int = - 1
618+ ) -> DataArray :
619+ full = np .full (self .full_size , fill , dtype = active_values .dtype )
620+ full [self .active_positions ] = active_values
621+ return DataArray (full .reshape (self .shape ), coords = self ._coords )
622+
616623 @property
617624 def labels (self ) -> DataArray :
618625 """Get labels DataArray, shape (*coord_dims)."""
619626 if self ._cindex is None :
620627 return DataArray ([])
621- shape = self .shape
622- full_size = self .full_size
623- labels_flat = np .full (full_size , - 1 , dtype = np .int64 )
624- labels_flat [self .active_positions ] = self ._con_labels
625- return DataArray (labels_flat .reshape (shape ), coords = self ._coords )
628+ return self ._active_to_dataarray (self ._con_labels , fill = - 1 )
626629
627630 @property
628631 def coeffs (self ) -> DataArray :
@@ -654,10 +657,7 @@ def sign(self) -> DataArray:
654657 @property
655658 def rhs (self ) -> DataArray :
656659 """Get RHS DataArray, shape (*coord_dims)."""
657- shape = self .shape
658- rhs_full = np .full (self .full_size , np .nan )
659- rhs_full [self .active_positions ] = self ._rhs
660- return DataArray (rhs_full .reshape (shape ), coords = self ._coords )
660+ return self ._active_to_dataarray (self ._rhs , fill = np .nan )
661661
662662 @property
663663 @has_optimized_model
@@ -667,9 +667,7 @@ def dual(self) -> DataArray:
667667 raise AttributeError (
668668 "Underlying is optimized but does not have dual values stored."
669669 )
670- dual_full = np .full (self .full_size , np .nan )
671- dual_full [self .active_positions ] = self ._dual
672- return DataArray (dual_full .reshape (self .shape ), coords = self ._coords )
670+ return self ._active_to_dataarray (self ._dual , fill = np .nan )
673671
674672 @dual .setter
675673 def dual (self , value : DataArray ) -> None :
@@ -731,24 +729,10 @@ def _to_dataset(self, nterm: int) -> Dataset:
731729 def data (self ) -> Dataset :
732730 """Reconstruct the xarray Dataset from the CSR representation."""
733731 ds = self ._to_dataset (self .nterm )
734- shape = self .shape
735- active_pos = self .active_positions
736- rhs_full = np .full (self .full_size , np .nan )
737- rhs_full [active_pos ] = self ._rhs
738- ds = ds .assign (
739- sign = DataArray (np .full (shape , self ._sign ), coords = self ._coords ),
740- rhs = DataArray (rhs_full .reshape (shape ), coords = self ._coords ),
741- )
732+ ds = ds .assign (sign = self .sign , rhs = self .rhs )
742733 if self ._dual is not None :
743- dual_full = np .full (self .full_size , np .nan )
744- dual_full [active_pos ] = self ._dual
745- ds = ds .assign (
746- dual = DataArray (dual_full .reshape (shape ), coords = self ._coords )
747- )
748- attrs : dict [str , Any ] = {"name" : self ._name }
749- if self ._cindex is not None :
750- attrs ["label_range" ] = (self ._cindex , self ._cindex + self .full_size )
751- return ds .assign_attrs (attrs )
734+ ds = ds .assign (dual = self ._active_to_dataarray (self ._dual , fill = np .nan ))
735+ return ds .assign_attrs (self .attrs )
752736
753737 def __repr__ (self ) -> str :
754738 """Print the constraint without reconstructing the full Dataset."""
@@ -771,11 +755,13 @@ def __repr__(self) -> str:
771755 header_string = f"{ self .type } `{ self ._name } `" if self ._name else f"{ self .type } "
772756 lines = []
773757
758+ vlabels = self ._model .variables .label_index .vlabels
759+
774760 def row_expr (row : int ) -> str :
775761 start , end = int (csr .indptr [row ]), int (csr .indptr [row + 1 ])
776762 vars_row = np .full (nterm , - 1 , dtype = np .int64 )
777763 coeffs_row = np .zeros (nterm , dtype = csr .dtype )
778- vars_row [: end - start ] = csr .indices [start :end ]
764+ vars_row [: end - start ] = vlabels [ csr .indices [start :end ] ]
779765 coeffs_row [: end - start ] = csr .data [start :end ]
780766 return f"{ print_single_expression (coeffs_row , vars_row , 0 , self ._model )} { SIGNS_pretty [self ._sign ]} { self ._rhs [row ]} "
781767
@@ -1630,7 +1616,12 @@ def set_blocks(self, block_map: np.ndarray) -> None:
16301616
16311617 res = res .where (not_missing .any (constraint .term_dim ), - 1 )
16321618 res = res .where (not_zero .any (constraint .term_dim ), 0 )
1633- constraint ._data = assign_multiindex_safe (constraint .data , blocks = res )
1619+ if isinstance (constraint , MutableConstraint ):
1620+ constraint ._data = assign_multiindex_safe (constraint .data , blocks = res )
1621+ else :
1622+ mc = constraint .mutable ()
1623+ mc ._data = assign_multiindex_safe (mc .data , blocks = res )
1624+ self .data [name ] = Constraint .from_mutable (mc , constraint ._cindex )
16341625
16351626 @property
16361627 def flat (self ) -> pd .DataFrame :
@@ -1687,18 +1678,7 @@ def reset_dual(self) -> None:
16871678 """
16881679 for k , c in self .items ():
16891680 if isinstance (c , Constraint ):
1690- if c ._dual is not None :
1691- self .data [k ] = Constraint (
1692- c ._csr ,
1693- c ._con_labels ,
1694- c ._rhs ,
1695- c ._sign ,
1696- c ._coords ,
1697- c ._model ,
1698- c ._name ,
1699- cindex = c ._cindex ,
1700- dual = None ,
1701- )
1681+ c ._dual = None
17021682 elif isinstance (c , MutableConstraint ):
17031683 if "dual" in c .data :
17041684 c ._data = c .data .drop_vars ("dual" )
0 commit comments