1212 sampled_from , shared , builds )
1313
1414from . import _array_module as xp , api_version
15+ from . import array_helpers as ah
1516from . import dtype_helpers as dh
1617from . import shape_helpers as sh
1718from . import xps
@@ -211,6 +212,7 @@ def tuples(elements, *, min_size=0, max_size=None, unique_by=None, unique=False)
211212
212213# Use this to avoid memory errors with NumPy.
213214# See https://github.com/numpy/numpy/issues/15753
215+ # Note, the hypothesis default for max_dims is min_dims + 2 (i.e., 0 + 2)
214216def shapes (** kw ):
215217 kw .setdefault ('min_dims' , 0 )
216218 kw .setdefault ('min_side' , 0 )
@@ -280,25 +282,29 @@ def mutually_broadcastable_shapes(
280282
281283# Note: This should become hermitian_matrices when complex dtypes are added
282284@composite
283- def symmetric_matrices (draw , dtypes = xps .floating_dtypes (), finite = True ):
285+ def symmetric_matrices (draw , dtypes = xps .floating_dtypes (), finite = True , bound = 10. ):
284286 shape = draw (square_matrix_shapes )
285287 dtype = draw (dtypes )
286288 if not isinstance (finite , bool ):
287289 finite = draw (finite )
288290 elements = {'allow_nan' : False , 'allow_infinity' : False } if finite else None
289291 a = draw (arrays (dtype = dtype , shape = shape , elements = elements ))
290- upper = xp .triu (a )
291- lower = xp .triu (a , k = 1 ).mT
292- return upper + lower
292+ at = ah ._matrix_transpose (a )
293+ H = (a + at )* 0.5
294+ if finite :
295+ assume (not xp .any (xp .isinf (H )))
296+ assume (xp .all ((H == 0. ) | ((1 / bound <= xp .abs (H )) & (xp .abs (H ) <= bound ))))
297+ return H
293298
294299@composite
295300def positive_definite_matrices (draw , dtypes = xps .floating_dtypes ()):
296301 # For now just generate stacks of identity matrices
297302 # TODO: Generate arbitrary positive definite matrices, for instance, by
298303 # using something like
299304 # https://github.com/scikit-learn/scikit-learn/blob/844b4be24/sklearn/datasets/_samples_generator.py#L1351.
300- n = draw (integers (0 ))
301- shape = draw (shapes ()) + (n , n )
305+ base_shape = draw (shapes ())
306+ n = draw (integers (0 , 8 )) # 8 is an arbitrary small but interesting-enough value
307+ shape = base_shape + (n , n )
302308 assume (prod (i for i in shape if i ) < MAX_ARRAY_SIZE )
303309 dtype = draw (dtypes )
304310 return broadcast_to (eye (n , dtype = dtype ), shape )
@@ -308,12 +314,18 @@ def invertible_matrices(draw, dtypes=xps.floating_dtypes(), stack_shapes=shapes(
308314 # For now, just generate stacks of diagonal matrices.
309315 n = draw (integers (0 , SQRT_MAX_ARRAY_SIZE ),)
310316 stack_shape = draw (stack_shapes )
311- d = draw (arrays (dtypes , shape = (* stack_shape , 1 , n ),
312- elements = dict (allow_nan = False , allow_infinity = False )))
317+ dtype = draw (dtypes )
318+ elements = one_of (
319+ from_dtype (dtype , min_value = 0.5 , allow_nan = False , allow_infinity = False ),
320+ from_dtype (dtype , max_value = - 0.5 , allow_nan = False , allow_infinity = False ),
321+ )
322+ d = draw (arrays (dtype , shape = (* stack_shape , 1 , n ), elements = elements ))
323+
313324 # Functions that require invertible matrices may do anything when it is
314325 # singular, including raising an exception, so we make sure the diagonals
315326 # are sufficiently nonzero to avoid any numerical issues.
316- assume (xp .all (xp .abs (d ) > 0.5 ))
327+ assert xp .all (xp .abs (d ) >= 0.5 )
328+
317329 diag_mask = xp .arange (n ) == xp .reshape (xp .arange (n ), (n , 1 ))
318330 return xp .where (diag_mask , d , xp .zeros_like (d ))
319331
0 commit comments