@@ -291,3 +291,159 @@ def test_invalid_ops_with_mesh_patt():
291291 Av (MeshBasis (Perm ((0 , 1 )))).is_insertion_encodable ()
292292 with pytest .raises (NotImplementedError ):
293293 Av (MeshBasis (Perm ((0 , 1 )))).is_polynomial ()
294+
295+
296+ # Tests for right_juxtaposition
297+
298+
299+ def test_right_juxtaposition_basic ():
300+ """Test Av(21) | Av(12) = Av(213, 312)."""
301+ av_21 = Av (Basis (Perm ((1 , 0 ))))
302+ av_12 = Av (Basis (Perm ((0 , 1 ))))
303+ result = av_21 .right_juxtaposition (av_12 )
304+ expected_basis = {Perm ((1 , 0 , 2 )), Perm ((2 , 0 , 1 ))}
305+ assert set (result .basis ) == expected_basis
306+
307+
308+ def test_right_juxtaposition_same_class ():
309+ """Test Av(21) | Av(21) gives expected basis."""
310+ av_21 = Av (Basis (Perm ((1 , 0 ))))
311+ result = av_21 .right_juxtaposition (av_21 )
312+ # Basis should be {321, 2143, 2431} = {(2,1,0), (1,0,3,2), (1,3,2,0)}
313+ expected_basis = {Perm ((2 , 1 , 0 )), Perm ((1 , 0 , 3 , 2 )), Perm ((2 , 0 , 3 , 1 ))}
314+ assert set (result .basis ) == expected_basis
315+
316+
317+ def test_right_juxtaposition_enumeration ():
318+ """Test that juxtaposition class has correct enumeration."""
319+ av_21 = Av (Basis (Perm ((1 , 0 ))))
320+ av_12 = Av (Basis (Perm ((0 , 1 ))))
321+ result = av_21 .right_juxtaposition (av_12 )
322+ # [Av(21)|Av(12)] = permutations that can be split into decreasing|increasing
323+ # Enumeration: 1, 1, 2, 4, 8, 16, 32 (powers of 2 starting at n=2)
324+ assert result .enumeration (6 ) == [1 , 1 , 2 , 4 , 8 , 16 , 32 ]
325+
326+
327+ def test_right_juxtaposition_multiple_basis_elements ():
328+ """Test juxtaposition with multiple basis elements."""
329+ av_21_12 = Av (Basis (Perm ((1 , 0 )), Perm ((0 , 1 )))) # Only contains empty and singleton
330+ av_132 = Av (Basis (Perm ((0 , 2 , 1 ))))
331+ result = av_21_12 .right_juxtaposition (av_132 )
332+ # The result should be a valid Av object with a minimized basis
333+ assert isinstance (result .basis , Basis )
334+ assert len (result .basis ) > 0
335+
336+
337+ def test_right_juxtaposition_longer_patterns ():
338+ """Test juxtaposition with longer patterns."""
339+ av_132 = Av (Basis (Perm ((0 , 2 , 1 ))))
340+ av_231 = Av (Basis (Perm ((1 , 2 , 0 ))))
341+ result = av_132 .right_juxtaposition (av_231 )
342+ # Verify result is valid and has expected structure
343+ assert isinstance (result .basis , Basis )
344+ # All basis elements should have length between 3 and 6 (|b1|+|b2|-1 to |b1|+|b2|)
345+ for perm in result .basis :
346+ assert 5 <= len (perm ) <= 6
347+
348+
349+ def test_right_juxtaposition_mesh_basis_raises ():
350+ """Test that juxtaposition with MeshBasis raises NotImplementedError."""
351+ av_classical = Av (Basis (Perm ((1 , 0 ))))
352+ av_mesh = Av (MeshBasis (Perm ((0 , 1 ))))
353+ with pytest .raises (NotImplementedError ):
354+ av_classical .right_juxtaposition (av_mesh )
355+ with pytest .raises (NotImplementedError ):
356+ av_mesh .right_juxtaposition (av_classical )
357+
358+
359+ def test_right_juxtaposition_containment ():
360+ """Test that permutations in the juxtaposition class can be split correctly."""
361+ av_21 = Av (Basis (Perm ((1 , 0 ))))
362+ av_12 = Av (Basis (Perm ((0 , 1 ))))
363+ result = av_21 .right_juxtaposition (av_12 )
364+
365+ # Check some permutations that should be in the class
366+ # 21 can be split as (2)|(1) where (2) is decreasing and (1) is increasing
367+ assert Perm ((1 , 0 )) in result
368+ # 12 can be split as ()|(12) where () is trivially decreasing and (12) is increasing
369+ assert Perm ((0 , 1 )) in result
370+ # 1 is trivially in the class
371+ assert Perm ((0 ,)) in result
372+
373+ # Check some permutations that should NOT be in the class
374+ # 213 = (1,0,2) is a basis element, so not in the class
375+ assert Perm ((1 , 0 , 2 )) not in result
376+ # 312 = (2,0,1) is a basis element, so not in the class
377+ assert Perm ((2 , 0 , 1 )) not in result
378+
379+
380+ # Tests for above_juxtaposition
381+
382+
383+ def test_above_juxtaposition_basic ():
384+ """Test basic above juxtaposition with Av(21) below and Av(12) above."""
385+ av_21 = Av (Basis (Perm ((1 , 0 ))))
386+ av_12 = Av (Basis (Perm ((0 , 1 ))))
387+ result = av_21 .above_juxtaposition (av_12 )
388+ # Result should be valid Av with Basis
389+ assert isinstance (result .basis , Basis )
390+ assert len (result .basis ) > 0
391+
392+
393+ def test_above_juxtaposition_inverse_relationship ():
394+ """Test that above_juxtaposition relates to right_juxtaposition via inverses."""
395+ av_21 = Av (Basis (Perm ((1 , 0 ))))
396+ av_132 = Av (Basis (Perm ((0 , 2 , 1 ))))
397+
398+ # Compute above juxtaposition directly
399+ above_result = av_21 .above_juxtaposition (av_132 )
400+
401+ # Compute via inverses manually
402+ av_21_inv = Av (Basis (* [p .inverse () for p in av_21 .basis ]))
403+ av_132_inv = Av (Basis (* [p .inverse () for p in av_132 .basis ]))
404+ right_result = av_21_inv .right_juxtaposition (av_132_inv )
405+ manual_result = Av (Basis (* [p .inverse () for p in right_result .basis ]))
406+
407+ # The bases should be equivalent
408+ assert set (above_result .basis ) == set (manual_result .basis )
409+
410+
411+ def test_above_juxtaposition_enumeration ():
412+ """Test that above juxtaposition class has expected enumeration."""
413+ av_21 = Av (Basis (Perm ((1 , 0 ))))
414+ av_12 = Av (Basis (Perm ((0 , 1 ))))
415+ result = av_21 .above_juxtaposition (av_12 )
416+ # Permutations that can be split by value: lower values decreasing, upper increasing
417+ # This should give 2^(n-1) for n >= 1
418+ assert result .enumeration (6 ) == [1 , 1 , 2 , 4 , 8 , 16 , 32 ]
419+
420+
421+ def test_above_juxtaposition_same_class ():
422+ """Test above juxtaposition with the same class."""
423+ av_21 = Av (Basis (Perm ((1 , 0 ))))
424+ result = av_21 .above_juxtaposition (av_21 )
425+ # Should be valid and have a non-empty basis
426+ assert isinstance (result .basis , Basis )
427+ assert len (result .basis ) > 0
428+
429+
430+ def test_above_juxtaposition_longer_patterns ():
431+ """Test above juxtaposition with longer patterns."""
432+ av_132 = Av (Basis (Perm ((0 , 2 , 1 ))))
433+ av_231 = Av (Basis (Perm ((1 , 2 , 0 ))))
434+ result = av_132 .above_juxtaposition (av_231 )
435+ # Verify result is valid
436+ assert isinstance (result .basis , Basis )
437+ # All basis elements should have length between 5 and 6
438+ for perm in result .basis :
439+ assert 5 <= len (perm ) <= 6
440+
441+
442+ def test_above_juxtaposition_mesh_basis_raises ():
443+ """Test that above_juxtaposition with MeshBasis raises NotImplementedError."""
444+ av_classical = Av (Basis (Perm ((1 , 0 ))))
445+ av_mesh = Av (MeshBasis (Perm ((0 , 1 ))))
446+ with pytest .raises (NotImplementedError ):
447+ av_classical .above_juxtaposition (av_mesh )
448+ with pytest .raises (NotImplementedError ):
449+ av_mesh .above_juxtaposition (av_classical )
0 commit comments