- Notifications
You must be signed in to change notification settings - Fork15
AddA.setdiag(x, k)#493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
3f31627ffc0421f9c95c5457cd03da98a68acb00677665530bd37af50f62bbd7c2f0ae5a365119e51b87File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2805,6 +2805,119 @@ def power(self, n, op=semiring.plus_times): | ||
| dtype=self.dtype, | ||
| ) | ||
| def setdiag(self, values, k=0, *, mask=None, accum=None, **opts): | ||
| """Set k'th diagonal with a Scalar, Vector, or array. | ||
| This is not a built-in GraphBLAS operation. It is implemented as a recipe. | ||
| Parameters | ||
| ---------- | ||
| values : Vector or list or np.ndarray or scalar | ||
| New values to assign to the diagonal. The length of Vector and array | ||
| values must match the size of the diagonal being assigned to. | ||
| k : int, default=0 | ||
| Which diagonal or off-diagonal to set. For example, set the elements | ||
| ``A[i, i+k] = values[i]``. The default, k=0, is the main diagonal. | ||
| mask : Mask, optional | ||
| Vector or Matrix Mask to control which diagonal elements to set. | ||
| If it is Matrix Mask, then only the diagonal is used as the mask. | ||
jim22k marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| accum : Monoid or BinaryOp, optional | ||
| Operator to use to combine existing diagonal values and new values. | ||
| """ | ||
| if (K := maybe_integral(k)) is None: | ||
| raise TypeError(f"k must be an integer; got bad type: {type(k)}") | ||
| k = K | ||
| if k < 0: | ||
| if (size := min(self._nrows + k, self._ncols)) <= 0 and k <= -self._nrows: | ||
| raise IndexError( | ||
| f"k={k} is too small; the k'th diagonal is out of range. " | ||
| f"Valid k for Matrix with shape {self._nrows}x{self._ncols}: " | ||
| f"{-self._nrows} {'<' if self._nrows else '<='} k " | ||
| f"{'<' if self._ncols else '<='} {self._ncols}" | ||
| ) | ||
| elif (size := min(self._ncols - k, self._nrows)) <= 0 and k > 0 and k >= self._ncols: | ||
| raise IndexError( | ||
| f"k={k} is too large; the k'th diagonal is out of range. " | ||
| f"Valid k for Matrix with shape {self._nrows}x{self._ncols}: " | ||
| f"{-self._nrows} {'<' if self._nrows else '<='} k " | ||
| f"{'<' if self._ncols else '<='} {self._ncols}" | ||
| ) | ||
| # Convert `values` to Vector if necessary (i.e., it's scalar or array) | ||
| is_scalar = clear_diag = False | ||
| if output_type(values) is Vector: | ||
| v = values | ||
| clear_diag = accum is None and v._nvals != v._size | ||
| elif type(values) is Scalar: | ||
| is_scalar = True | ||
| else: | ||
| dtype = self.dtype if self.dtype._is_udt else None | ||
| try: | ||
| # Try to make it a Scalar | ||
| values = Scalar.from_value(values, dtype, is_cscalar=None, name="") | ||
| is_scalar = True | ||
| except (TypeError, ValueError): | ||
| try: | ||
| # Else try to make it a numpy array | ||
| values, dtype = values_to_numpy_buffer(values, dtype) | ||
| except Exception: | ||
| self._expect_type( | ||
| values, | ||
| (Scalar, Vector, np.ndarray), | ||
| within="setdiag", | ||
| argname="values", | ||
| extra_message="Literal scalars also accepted.", | ||
| ) | ||
| else: | ||
| v = Vector.from_dense(values, dtype=dtype, **opts) | ||
| if is_scalar: | ||
| v = Vector.from_scalar(values, size, **opts) | ||
| elif v._size != size: | ||
| raise DimensionMismatch( | ||
| f"Dimensions not compatible for assigning length {v._size} Vector " | ||
| f"to {k}'th diagonal of Matrix with shape {self._nrows}x{self._ncols}." | ||
| f"The Vector should be size {size}." | ||
| ) | ||
| if mask is not None: | ||
| mask = _check_mask(mask) | ||
| if mask.parent.ndim == 2: | ||
| if mask.parent.shape != self.shape: | ||
| raise DimensionMismatch( | ||
| "Matrix mask in setdiag is the wrong shape; " | ||
| f"expected shape {self._nrows}x{self._ncols}, " | ||
| f"got {mask.parent._nrows}x{mask.parent._ncols}" | ||
| ) | ||
| if mask.complement: | ||
| mval = type(mask)(mask.parent.diag(k)).new(**opts) | ||
| mask = mval.S | ||
| M = mval.diag() | ||
| else: | ||
| M = select.diag(mask.parent, k).new(**opts) | ||
| elif mask.parent._size != size: | ||
| raise DimensionMismatch( | ||
| "Vector mask in setdiag is the wrong length; " | ||
| f"expected size {size}, got size {mask.parent._size}." | ||
| ) | ||
| else: | ||
| if mask.complement: | ||
| mask = mask.new(**opts).S | ||
| M = mask.parent.diag() | ||
| if M.shape != self.shape: | ||
| M.resize(self._nrows, self._ncols) | ||
| mask = type(mask)(M) | ||
| if clear_diag: | ||
| self(mask=mask, **opts) << select.offdiag(self, k) | ||
| Diag = v.diag(k) | ||
| if Diag.shape != self.shape: | ||
| Diag.resize(self._nrows, self._ncols) | ||
| if mask is None: | ||
| mask = Diag.S | ||
| self(accum=accum, mask=mask, **opts) << Diag | ||
Comment on lines +2914 to +2919 MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. For posterity and those who browse this PR, these lines are the main recipe for setting the diagonal of a Matrix with a Vector. The rest of the function mostly deals with handing different input types and giving good error messages when necessary. | ||
| ################################## | ||
| # Extract and Assign index methods | ||
| ################################## | ||
Uh oh!
There was an error while loading.Please reload this page.