Ticket #10537: trac_10537_dictionary_vector_input.patch
File trac_10537_dictionary_vector_input.patch, 7.9 KB (added by , 11 years ago) 


sage/modules/free_module_element.pyx
# HG changeset patch # User Rob Beezer <beezer@ups.edu> # Date 1293791147 28800 # Node ID b849f0558252b6778b0e45f6163a7cd09886d027 # Parent a4f56eba9ffe0a81b82dfb89475a3ab197ba4d23 10537: fix dictionary input to vector constructor diff r a4f56eba9ffe r b849f0558252 sage/modules/free_module_element.pyx
a b 268 268 sage: vector({1:1.1, 3:3.14}) 269 269 (0.000000000000000, 1.10000000000000, 0.000000000000000, 3.14000000000000) 270 270 271 It is very unlikely that giving a degree and a dictionary will succeed. :: 272 273 sage: v = vector(QQ, 8, {0:1/2, 4:6}); v 274 Traceback (most recent call last): 275 ... 276 TypeError: cannot specify the degree of a vector while entries are given by a dictionary 277 278 Instead, provide a "terminal" element (likely a zero) to fill out 279 the vector to the desired number of entries. :: 271 With no degree given, a dictionary of entries implicitly declares a 272 degree by the largest index (key) present. So you can provide a 273 terminal element (perhaps a zero?) to set the degree. But it is probably safer 274 to just include a degree in your construction. :: 280 275 281 276 sage: v = vector(QQ, {0:1/2, 4:6, 7:0}); v 282 277 (1/2, 0, 0, 0, 6, 0, 0, 0) … … 284 279 8 285 280 sage: v.is_sparse() 286 281 True 282 sage: w = vector(QQ, 8, {0:1/2, 4:6}) 283 sage: w == v 284 True 287 285 288 286 It is an error to specify a negative degree. :: 289 287 … … 292 290 ... 293 291 ValueError: cannot specify the degree of a vector as a negative integer (4) 294 292 293 And it is an error to specify an index in a dictionary 294 that is greater than or equal to a requested degree. :: 295 296 sage: vector(ZZ, 10, {3:4, 7:2, 10:637}) 297 Traceback (most recent call last): 298 ... 299 ValueError: dictionary of entries has a key (index) exceeding the requested degree 300 295 301 Any 1 dimensional numpy array of type float or complex may be 296 302 passed to vector. The result will be a vector in the appropriate 297 303 dimensional vector space over the real double field or the complex … … 347 353 if hasattr(arg1, '_vector_'): 348 354 return arg1._vector_(arg0) 349 355 356 # consider a possible degree specified in second argument 357 degree = None 358 maxindex = None 350 359 if sage.rings.integer.is_Integer(arg1) or isinstance(arg1,(int,long)): 351 360 if arg1 < 0: 352 361 raise ValueError("cannot specify the degree of a vector as a negative integer (%s)" % arg1) 353 362 if isinstance(arg2, dict): 354 raise TypeError("cannot specify the degree of a vector while entries are given by a dictionary") 363 maxindex = max([1]+[index for index in arg2]) 364 if not maxindex < arg1: 365 raise ValueError("dictionary of entries has a key (index) exceeding the requested degree") 366 # arg1 is now a legitimate degree 367 # replace it with a zero list or a dictionary, or a sizechecked iterable 368 # so then down to just two arguments 369 degree = arg1 355 370 if arg2 is None: 356 arg1 = [0]* arg1371 arg1 = [0]*degree 357 372 else: 358 if len(arg2) != arg1:373 if not isinstance(arg2, dict) and len(arg2) != degree: 359 374 raise ValueError, "incompatible degrees in vector constructor" 360 375 arg1 = arg2 361 376 377 # Analyze arg0 and arg1 to create a ring (R) and entries (v) 362 378 if is_Ring(arg0): 363 379 R = arg0 364 380 v = arg1 … … 385 401 return _v 386 402 387 403 if isinstance(v, dict): 404 if degree is None: 405 degree = max([1]+[index for index in v])+1 388 406 if sparse is None: 389 407 sparse = True 390 v, R = prepare_dict(v, R)391 408 else: 409 degree = None 392 410 if sparse is None: 393 411 sparse = False 394 v, R = prepare(v, R) 412 413 v, R = prepare(v, R, degree) 395 414 396 415 if sparse: 397 416 import free_module # slow  can we improve … … 401 420 402 421 free_module_element = vector 403 422 404 def prepare(v, R): 405 """ 406 Find a common ring (using R as universe) that contains every 407 element of v, and replace v with the sequence of elements in v 408 coerced to this ring. For more details, see the 409 sage.structure.sequence.Sequence object. 423 def prepare(v, R, degree=None): 424 r""" 425 Converts an object describing elements of a vector into a list of entries in a common ring. 410 426 411 427 INPUT: 412 428 413  v  list or tuple 414  R  ring or None 429  ``v``  a dictionary with nonnegative integers as keys, 430 or a list or other object that can be converted to Sequence 431  ``R``  a ring containing all the entries, possibly given as ``None`` 432  ``degree``  a requested size for the list when the input is a dictionary, 433 otherwise ignored 434 435 OUTPUT: 436 437 A pair. 438 439 The first item is a list of the values specified in the object ``v``. 440 If the object is a dictionary , entries are placed in the list 441 according to the indices that were their keys in the dictionary, 442 and the remainder of the entries are zero. The value of 443 ``degree`` is assumed to be larger than any index provided 444 in the dictionary and will be used as the number of entries 445 in the returned list. 446 447 The second item returned is a ring that contains all of 448 the entries in the list. If ``R`` is given, the entries 449 are coerced in. Otherwise a common ring is found. For 450 more details, see the 451 :class:`~sage.structure.sequence.Sequence` object. 452 415 453 416 454 EXAMPLES:: 417 455 418 sage: sage.modules.free_module_element.prepare([1,2/3,5],None) 456 sage: from sage.modules.free_module_element import prepare 457 sage: prepare([1,2/3,5],None) 419 458 ([1, 2/3, 5], Rational Field) 420 sage: sage.modules.free_module_element.prepare([1,2/3,5],RR) 459 460 sage: prepare([1,2/3,5],RR) 421 461 ([1.00000000000000, 0.666666666666667, 5.00000000000000], Real Field with 53 bits of precision) 422 sage: sage.modules.free_module_element.prepare([1,2/3,'10',5],None) 462 463 sage: prepare({1:4, 3:2}, ZZ, 6) 464 ([0, 4, 0, 2, 0, 0], Integer Ring) 465 466 sage: prepare({3:1, 5:3}, QQ, 6) 467 ([0, 0, 0, 1, 0, 3], Rational Field) 468 469 sage: prepare([1,2/3,'10',5],RR) 470 ([1.00000000000000, 0.666666666666667, 10.0000000000000, 5.00000000000000], Real Field with 53 bits of precision) 471 472 sage: prepare({},QQ, 0) 473 ([], Rational Field) 474 475 sage: prepare([1,2/3,'10',5],None) 423 476 Traceback (most recent call last): 424 477 ... 425 478 TypeError: unable to find a common ring for all elements 426 sage: sage.modules.free_module_element.prepare([1,2/3,'10',5],RR) 427 ([1.00000000000000, 0.666666666666667, 10.0000000000000, 5.00000000000000], Real Field with 53 bits of precision) 479 428 480 """ 481 if isinstance(v, dict): 482 # convert to a list 483 X = [0]*degree 484 for key, value in v.iteritems(): 485 X[key] = value 486 v = X 487 # convert to a Sequence over common ring 429 488 v = Sequence(v, universe=R, use_sage_types=True) 430 489 ring = v.universe() 431 490 if not is_Ring(ring): 432 491 raise TypeError, "unable to find a common ring for all elements" 433 492 return v, ring 434 493 435 def prepare_dict(w, R):436 """437 EXAMPLES::438 439 sage: from sage.modules.free_module_element import prepare_dict440 sage: prepare_dict({3:1 , 5:3}, QQ)441 ([0, 0, 0, 1, 0, 3], Rational Field)442 sage: prepare_dict({},QQ)443 ([], Rational Field)444 """445 Z = w.items()446 cdef Py_ssize_t n447 n = max([1]+[key for key,value in Z])+1448 X = [0]*n449 for key, value in Z:450 X[key] = value451 return prepare(X, R)452 453 494 def zero_vector(arg0, arg1=None): 454 495 r""" 455 496 Returns a vector or free module element with a specified number of zeros.