@@ -2404,42 +2404,74 @@ def test_local_blockwise_advanced_inc_subtensor(set_instead_of_inc):
2404
2404
np .testing .assert_allclose (fn (test_x , test_y ), expected_out )
2405
2405
2406
2406
2407
- def test_slice_canonicalize () :
2408
- rng = np . random . default_rng ( 43 )
2409
- x = tensor ( shape = ( 3 , 5 , None , 9 ))
2410
- test_x = rng . normal ( size = (3 , 5 , 8 , 9 ))
2411
- # Test case 1
2412
- y = x [ 0 : None , 0 : 5 , 0 : 7 , 0 : 9 : 1 ]
2413
- f = pytensor . function ([ x ], y , allow_input_downcast = True )
2414
-
2415
- # Get the DeepCopy input and assert that the Op is a DeepCopy
2416
- test_y = f . maker . fgraph . outputs [ 0 ]. owner . inputs [ 0 ]
2417
- assert isinstance ( f .maker .fgraph .outputs [0 ].owner . op , DeepCopyOp )
2418
-
2419
- expected_y = x [ None : None : None , None : None : None , None : 7 : None ]
2420
-
2421
- assert equal_computations ([ test_y ], [ expected_y ])
2422
-
2423
- np . testing . assert_allclose (
2424
- f ( test_x ),
2425
- test_x [
2426
- 0 : None , 0 : 5 , 0 : 7 , 0 : 9 : 1
2427
- ], # Use the unoptimized slice to make sure our rewrite logic is correct
2428
- )
2407
+ class TestUselessSlice :
2408
+ def test_positive_step ( self ):
2409
+ # When steps are positive, default start and end are `0` and `len(dim)`
2410
+ x = tensor ( shape = (3 , 5 , None , 9 ), dtype = "float64" )
2411
+ test_x = np . random . normal ( size = ( 3 , 5 , 8 , 9 ))
2412
+
2413
+ y = x [ 0 : 3 : 1 , 1 : 5 : 2 , 0 : 7 : 1 , 0 : 9 : 1 ]
2414
+ f = pytensor . function ([ x ], y )
2415
+
2416
+ # Get the DeepCopy input and assert that the Op is a DeepCopy
2417
+ deep_copy_node = f .maker .fgraph .outputs [0 ].owner
2418
+ assert isinstance ( deep_copy_node . op , DeepCopyOp )
2419
+
2420
+ rewritten_y = deep_copy_node . inputs [ 0 ]
2421
+ expected_y = x [ None : None : None , 1 : None : 2 , None : 7 : None ]
2422
+ assert equal_computations ([ rewritten_y ], [ expected_y ])
2423
+
2424
+ np . testing . assert_allclose (
2425
+ f ( test_x ),
2426
+ # Use the unoptimized slice to make sure our rewrite logic is correct
2427
+ test_x [ 0 : 3 : 1 , 1 : 5 : 2 , 0 : 7 : 1 , 0 : 9 : 1 ],
2428
+ )
2429
2429
2430
- # Test case 2
2431
- y1 = x [0 :- 1 , 0 :5 , 0 :7 , 0 :- 1 :- 1 ]
2432
- f1 = pytensor .function ([x ], y1 , allow_input_downcast = True )
2430
+ def test_negative_step (self ):
2431
+ # When steps are negative, default start and end are `-1` and `-len(dim) - 1`
2432
+ x = tensor (shape = (3 , 5 , None , 9 ), dtype = "float64" )
2433
+ test_x = np .random .normal (size = (3 , 5 , 8 , 9 ))
2433
2434
2434
- # Get the DeepCopy input and assert that the Op is a DeepCopy
2435
- test_y1 = f1 .maker .fgraph .outputs [0 ].owner .inputs [0 ]
2436
- assert isinstance (f1 .maker .fgraph .outputs [0 ].owner .op , DeepCopyOp )
2435
+ y = x [- 1 :- 4 :- 1 , 0 :5 :- 2 , - 1 :- 9 :- 1 , 0 :9 :None ]
2436
+ f = pytensor .function ([x ], y )
2437
2437
2438
- expected_y1 = x [None :- 1 :None , None :None :None , None :7 :None , None :- 1 :- 1 ]
2438
+ # Get the DeepCopy input and assert that the Op is a DeepCopy
2439
+ deep_copy_node = f .maker .fgraph .outputs [0 ].owner
2440
+ assert isinstance (deep_copy_node .op , DeepCopyOp )
2439
2441
2440
- assert equal_computations ([test_y1 ], [expected_y1 ])
2442
+ rewritten_y = deep_copy_node .inputs [0 ]
2443
+ expected_y = x [None :None :- 1 , 0 :5 :- 2 , None :- 9 :- 1 ]
2444
+ assert equal_computations ([rewritten_y ], [expected_y ])
2441
2445
2442
- np .testing .assert_allclose (
2443
- f1 (test_x ),
2444
- test_x [0 :- 1 , 0 :5 , 0 :7 , 0 :- 1 :- 1 ],
2445
- )
2446
+ np .testing .assert_allclose (
2447
+ f (test_x ),
2448
+ test_x [- 1 :- 4 :- 1 , 0 :5 :- 2 , - 1 :- 9 :- 1 , 0 :9 :None ],
2449
+ )
2450
+
2451
+ def test_unknown_step (self ):
2452
+ # If step isn't known, we can't canonicalize start and stop points
2453
+ step = pt .scalar ("step" , dtype = int )
2454
+ x = tensor (shape = (3 , 5 , None ), dtype = "float64" )
2455
+ test_x = np .random .normal (size = (3 , 5 , 7 ))
2456
+
2457
+ y = x [0 :3 :step , - 1 :- 6 :- step , ::]
2458
+ # Need this rewrite when `FAST_COMPILE` otherwise step = -1 * step instead of neg(step)
2459
+ mode = get_default_mode ().including ("local_mul_specialize" )
2460
+ f = pytensor .function ([x , step ], y , mode = mode )
2461
+
2462
+ # Get the DeepCopy input and assert that the Op is a DeepCopy
2463
+ deep_copy_node = f .maker .fgraph .outputs [0 ].owner
2464
+ assert isinstance (deep_copy_node .op , DeepCopyOp )
2465
+
2466
+ rewritten_y = deep_copy_node .inputs [0 ]
2467
+ expected_y = x [0 :3 :step , - 1 :- 6 :- step ]
2468
+ assert equal_computations ([rewritten_y ], [expected_y ])
2469
+
2470
+ np .testing .assert_allclose (
2471
+ f (test_x , 1 ),
2472
+ test_x [0 :3 :1 , - 1 :- 6 :- 1 , ::],
2473
+ )
2474
+ np .testing .assert_allclose (
2475
+ f (test_x , - 2 ),
2476
+ test_x [0 :3 :- 2 , - 1 :- 6 :2 , ::],
2477
+ )
0 commit comments