55Test random lists.
66'''
77
8- from random import Random
8+ from enum import auto , IntEnum
9+ from typing import Any , Dict , List
910
1011from constrainedrandom import RandObj
1112from constrainedrandom .utils import unique
@@ -339,6 +340,26 @@ def not_7(x):
339340 r .add_rand_var ('listvar' , bits = 5 , constraints = [not_7 ], rand_length = 'length' )
340341 return r
341342
343+ def get_tmp_constraints (self ):
344+ tmp_constrs = []
345+ def not_6 (x ):
346+ return x != 6
347+ tmp_constrs .append ((not_6 , ('listvar' ,)))
348+ tmp_constrs .append ((not_6 , ('length' ,)))
349+ def mul_3 (x ):
350+ return x % 3 == 0
351+ tmp_constrs .append ((mul_3 , ('length' ,)))
352+ return tmp_constrs
353+
354+ def tmp_check (self , results ):
355+ self .check (results )
356+ for result in results :
357+ length = result ['length' ]
358+ listvar = result ['listvar' ]
359+ self .assertNotEqual (length , 6 , "Temp constraint not respected" )
360+ self .assertNotEqual (listvar , 6 , "Temp constraint not respected" )
361+ self .assertEqual (length % 3 , 0 , "Temp constraint not respected" )
362+
342363 def check (self , results ):
343364 nonzero_seen = False
344365 for result in results :
@@ -355,13 +376,22 @@ def check(self, results):
355376 self .assertTrue (nonzero_seen , "All values were zero" )
356377
357378
379+ class RandSizeListValue (RandSizeList ):
380+ '''
381+ Test a random sized list with temporary values.
382+ '''
383+
384+ def get_tmp_values (self ):
385+ return {'length' : 12 }
386+
387+
358388class RandSizeListConstrained (RandSizeList ):
359389 '''
360390 Test a randomized list, with a random size.
361391 Add constriants between the length and another variable.
362392 '''
363393
364- ITERATIONS = 1000
394+ ITERATIONS = 500
365395
366396 def get_randobj (self , * args ):
367397 r = super ().get_randobj (* args )
@@ -385,6 +415,12 @@ def check(self, results):
385415 self .assertEqual (length % 2 , 1 , "Length was even, should be odd" )
386416
387417
418+ class RandSizeListConstrainedValue (RandSizeListValue , RandSizeListConstrained ):
419+ '''
420+ Test a random sized list, with constraints, and with temporary values.
421+ '''
422+
423+
388424class RandSizeListConstrainedMore (RandSizeListConstrained ):
389425 '''
390426 Test a randomized list, with a random size.
@@ -407,3 +443,234 @@ def check(self, results):
407443 length = result ['length' ]
408444 listvar = result ['listvar' ]
409445 self .assertNotIn (length , listvar , "Length should not appear in list" )
446+
447+
448+ class RandSizeListConstrainedMoreValue (RandSizeListValue , RandSizeListConstrained ):
449+ '''
450+ Test a randomized list, with a random size.
451+ Add constriants between the length and other variables,
452+ and the length and the list.
453+ Test with temporary values.
454+ '''
455+
456+
457+ class RandSizeListConstrainedSparse (RandSizeListConstrained ):
458+ '''
459+ Test a constrained randomized list with a random length,
460+ exercising the sparse solver.
461+ '''
462+
463+ def get_randobj (self , * args ):
464+ r = super ().get_randobj (* args )
465+ r .set_solver_mode (naive = False , sparse = True , thorough = False )
466+ return r
467+
468+
469+ class RandSizeListConstrainedSparseValue (RandSizeListValue , RandSizeListConstrainedSparse ):
470+ '''
471+ Test a constrained randomized list with a random length,
472+ exercising the sparse solver, with temporary values.
473+ '''
474+
475+
476+ class RandSizeListConstrainedMoreSparse (RandSizeListConstrainedMore ):
477+ '''
478+ Test a further constrained randomized list with a random length,
479+ exercising the sparse solver.
480+ '''
481+
482+ def get_randobj (self , * args ):
483+ r = super ().get_randobj (* args )
484+ r .set_solver_mode (naive = False , sparse = True , thorough = False )
485+ return r
486+
487+
488+ class RandSizeListConstrainedMoreSparseValue (RandSizeListValue , RandSizeListConstrainedMoreSparse ):
489+ '''
490+ Test a further constrained randomized list with a random length,
491+ exercising the sparse solver, with temporary values.
492+ '''
493+
494+
495+ class RandSizeListConstrainedThorough (RandSizeListConstrained ):
496+ '''
497+ Test a constrained randomized list with a random length,
498+ exercising the thorough solver.
499+ '''
500+
501+ ITERATIONS = 5
502+
503+ def get_randobj (self , * args ):
504+ r = super ().get_randobj (* args )
505+ r .set_solver_mode (naive = False , sparse = False , thorough = True )
506+ return r
507+
508+
509+ class RandSizeListConstrainedThoroughValue (RandSizeListValue , RandSizeListConstrainedThorough ):
510+ '''
511+ Test a constrained randomized list with a random length,
512+ exercising the thorough solver, with temporary values.
513+ '''
514+
515+
516+ class RandSizeListConstrainedMoreThorough (RandSizeListConstrainedMore ):
517+ '''
518+ Test a constrained randomized list with a random length,
519+ exercising the thorough solver.
520+ '''
521+
522+ ITERATIONS = 2
523+
524+ def get_randobj (self , * args ):
525+ r = super ().get_randobj (* args )
526+ r .set_solver_mode (naive = False , sparse = False , thorough = True )
527+ return r
528+
529+
530+ class RandSizeListConstrainedMoreThoroughValue (RandSizeListValue , RandSizeListConstrainedMoreThorough ):
531+ '''
532+ Test a constrained randomized list with a random length,
533+ exercising the thorough solver.
534+ '''
535+
536+
537+ class RandSizeListHard (testutils .RandObjTestBase ):
538+ '''
539+ Test a much more difficult problem with randomized-length lists.
540+ '''
541+
542+ ITERATIONS = 100
543+
544+ class RegEnum (IntEnum ):
545+
546+ REG0 = 0
547+ REG1 = auto ()
548+ REG2 = auto ()
549+ REG3 = auto ()
550+ REG4 = auto ()
551+ REG5 = auto ()
552+ REG6 = auto ()
553+ REG7 = auto ()
554+
555+ def get_randobj (self , * args ):
556+ r = RandObj (* args )
557+ r .add_rand_var ('shared_length' , domain = range (8 ))
558+ def not_reg0 (x ):
559+ return x != self .RegEnum .REG0
560+ r .add_rand_var (
561+ 'list1' ,
562+ domain = self .RegEnum ,
563+ rand_length = 'shared_length' ,
564+ constraints = [not_reg0 ],
565+ list_constraints = [unique ],
566+ )
567+ r .add_rand_var ('list2' , domain = range (32 ), rand_length = 'shared_length' )
568+ def lists_dont_intersect (list1 , list2 ):
569+ for x in list1 :
570+ if x in list2 :
571+ return False
572+ return True
573+ r .add_constraint (lists_dont_intersect , ('list1' , 'list2' ))
574+ return r
575+
576+ def get_tmp_constraints (self ):
577+ return super ().get_tmp_constraints ()
578+
579+ def check (self , results ):
580+ for idx , result in enumerate (results ):
581+ list1 = result ['list1' ]
582+ list2 = result ['list2' ]
583+ shared_length = result ['shared_length' ]
584+ self .assertIn (shared_length , range (8 ))
585+ self .assertEqual (len (list1 ), shared_length , f"{ idx } List length was wrong" )
586+ self .assertEqual (len (list2 ), shared_length , "List length was wrong" )
587+ for idx , item in enumerate (list1 ):
588+ self .assertIn (item , self .RegEnum )
589+ other_elems = list1 [0 :idx ] + list1 [idx + 1 :]
590+ self .assertNotIn (item , other_elems , "List had repeated elements" )
591+ for item in list2 :
592+ self .assertNotIn (item , list1 , "Lists were not disjoint" )
593+
594+
595+ class RandSizeListVeryHard (RandSizeListHard ):
596+ '''
597+ Test an extremely difficult problem with randomized-length lists.
598+ '''
599+
600+ ITERATIONS = 2
601+
602+ def get_randobj (self , * args ):
603+ r = super ().get_randobj (* args )
604+ def double_length (length , length2 ):
605+ return length2 == length * 2
606+ r .add_rand_var ('other_length' , domain = range (16 ))
607+ r .add_constraint (double_length , ('shared_length' , 'other_length' ))
608+ r .add_rand_var ('list3' , domain = range (32 ), rand_length = 'other_length' , order = 2 )
609+ def composed_from_others (list1 , list2 , list3 ):
610+ for x in list3 :
611+ if x not in list1 and x not in list2 :
612+ return False
613+ return True
614+ r .add_constraint (composed_from_others , ('list1' , 'list2' , 'list3' ))
615+ return r
616+
617+ def check (self , results ):
618+ super ().check (results )
619+ for result in results :
620+ list1 = result ['list1' ]
621+ list2 = result ['list2' ]
622+ list3 = result ['list3' ]
623+ shared_length = result ['shared_length' ]
624+ other_length = result ['other_length' ]
625+ self .assertEqual (len (list3 ), shared_length * 2 , "List length was wrong" )
626+ self .assertEqual (other_length , shared_length * 2 , "List length was wrong" )
627+ for item in list3 :
628+ self .assertIn (item , list1 + list2 , "Item was not in other lists" )
629+
630+
631+ class RandSizeListShort (testutils .RandObjTestBase ):
632+ '''
633+ Test random lists and lengths with small domains, to
634+ use CSP.
635+ '''
636+
637+ def get_randobj (self , * args ):
638+ r = RandObj (* args )
639+ r .add_rand_var ('length1' , domain = range (1 , 4 ))
640+ r .add_rand_var ('list1' , domain = range (1 , 4 ), rand_length = 'length1' )
641+ def in_list (x , y ):
642+ return x in y
643+ r .add_rand_var ('length2' , domain = range (1 , 4 ))
644+ r .add_constraint (in_list , ('length2' , 'list1' ))
645+ r .add_rand_var ('list2' , domain = range (1 , 4 ), rand_length = 'length2' )
646+ return r
647+
648+ def check (self , results ):
649+ for result in results :
650+ length1 = result ['length1' ]
651+ list1 = result ['list1' ]
652+ length2 = result ['length2' ]
653+ list2 = result ['list2' ]
654+ self .assertEqual (len (list1 ), length1 , "List length was wrong" )
655+ self .assertIn (length2 , list1 , "Length 2 must be in list 1" )
656+ self .assertEqual (len (list2 ), length2 , "List length was wrong" )
657+
658+
659+ class RandSizeListShortSparse (RandSizeListShort ):
660+
661+ ITERATIONS = 200
662+
663+ def get_randobj (self , * args ):
664+ r = super ().get_randobj (* args )
665+ r .set_solver_mode (naive = False , sparse = True , thorough = False )
666+ return r
667+
668+
669+ class RandSizeListShortThorough (RandSizeListShort ):
670+
671+ ITERATIONS = 50
672+
673+ def get_randobj (self , * args ):
674+ r = super ().get_randobj (* args )
675+ r .set_solver_mode (naive = False , sparse = False , thorough = True )
676+ return r
0 commit comments