| 216 | |
| 217 | By default, element are enumerated in a depth first search way. It is |
| 218 | possible to get a breadth first search iterator via the |
| 219 | ``breadth_first_search_iterator`` method:: |
| 220 | |
| 221 | sage: I = SearchForest([(0,0)], |
| 222 | ... lambda l: [(l[0]+1, l[1]), (l[0], 1)] |
| 223 | ... if l[1] == 0 else [(l[0], l[1]+1)]) |
| 224 | sage: depth_search = I.depth_first_search_iterator() |
| 225 | sage: [depth_search.next() for i in range(15)] |
| 226 | [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0), (10, 0), (11, 0), (12, 0), (13, 0), (14, 0)] |
| 227 | sage: breadth_search = I.breadth_first_search_iterator() |
| 228 | sage: [breadth_search.next() for i in range(15)] |
| 229 | [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), (0, 3), (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] |
| 230 | |
| 231 | Warning: A SearchForest instance is pickable if and only if it is |
| 232 | defined with pickable functions. If you want pickable object, don't |
| 233 | defined your argument function on the fly. |
| 234 | |
| 235 | sage: from sage.combinat.backtrack import pick_children |
| 236 | sage: I = SearchForest((1,), pick_children) |
| 237 | sage: TestSuite(I).run() |
| 238 | sage: I = SearchForest((1,), lambda x: [x+1]) |
| 239 | sage: TestSuite(I).run() |
| 240 | Failure in _test_pickling: |
| 241 | Traceback ... |
| 242 | ... |
| 243 | PicklingError: Can't pickle <type 'function'>: ... |
| 244 | ------------------------------------------------------------ |
| 245 | The following tests failed: _test_pickling |
| 246 | |
| 247 | TESTS:: |
| 248 | |
| 249 | sage: # The following test an empty set defined with no roots... |
| 250 | sage: father = lambda l : l[:-1] |
| 251 | sage: I = SearchForest([], lambda l: (l+[i] for i in range(l[-1])), father = father) |
| 252 | sage: I.first() |
| 253 | sage: list(I) |
| 254 | [] |
| 255 | sage: I.first_element_of_depth(0) |
| 256 | sage: I.first_element_of_depth(1) |
| 257 | sage: I.first_element_of_depth(2) |
| 258 | sage: list(I.element_of_depth_iterator(0)) |
| 259 | [] |
| 260 | sage: list(I.element_of_depth_iterator(1)) |
| 261 | [] |
| 262 | sage: list(I.element_of_depth_iterator(2)) |
| 263 | [] |
| 299 | def roots(self): |
| 300 | r""" |
| 301 | Returns an iterable over the roots of ``self``. |
| 302 | |
| 303 | EXAMPLES:: |
| 304 | |
| 305 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)]) |
| 306 | sage: [i for i in I.roots()] |
| 307 | [(0, 0)] |
| 308 | sage: I = SearchForest([(0,0),(1,1)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)]) |
| 309 | sage: [i for i in I.roots()] |
| 310 | [(0, 0), (1, 1)] |
| 311 | """ |
| 312 | return iter(self._roots) |
| 313 | |
| 314 | def children(self, x): |
| 315 | r""" |
| 316 | Returns an iterable over the children of the element ``x``. |
| 317 | |
| 318 | EXAMPLES:: |
| 319 | |
| 320 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)]) |
| 321 | sage: [i for i in I.children((0,0))] |
| 322 | [(1, 0), (0, 1)] |
| 323 | sage: [i for i in I.children((1,0))] |
| 324 | [(2, 0), (1, 1)] |
| 325 | sage: [i for i in I.children((1,1))] |
| 326 | [(1, 2)] |
| 327 | sage: [i for i in I.children((4,1))] |
| 328 | [(4, 2)] |
| 329 | sage: [i for i in I.children((4,0))] |
| 330 | [(5, 0), (4, 1)] |
| 331 | """ |
| 332 | return iter(self._children(x)) |
| 333 | |
| 334 | def father(self, x): |
| 335 | r""" |
| 336 | Returns the father of the element ``x`` if a fonction ``father`` |
| 337 | was given in argument. If not raise an ``AssertionError``. |
| 338 | |
| 339 | EXAMPLES:: |
| 340 | |
| 341 | sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1) |
| 342 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father) |
| 343 | sage: I.father((2,3)) |
| 344 | (2, 2) |
| 345 | sage: I.father(_) |
| 346 | (2, 1) |
| 347 | sage: I.father(_) |
| 348 | (2, 0) |
| 349 | sage: I.father(_) |
| 350 | (1, 0) |
| 351 | sage: I.father(_) |
| 352 | (0, 0) |
| 353 | """ |
| 354 | assert self._father != None, "No 'father' function given" |
| 355 | return self._father(x) |
| 356 | |
| 357 | def next_brother(self, x, father=None): |
| 358 | r""" |
| 359 | |
| 360 | Returns the next brother of the element ``x`` if it exist, returns |
| 361 | ``None`` otherwise. |
| 362 | |
| 363 | If a function ``_next_brother`` was given at the creation of ``self``, |
| 364 | the methods ``next_brother`` simply returns its results, otherwise it |
| 365 | returns the next children of the father of ``x``. |
| 366 | |
| 367 | EXAMPLES:: |
| 368 | |
| 369 | sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1) |
| 370 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father) |
| 371 | sage: I.next_brother((1,0)) |
| 372 | (0, 1) |
| 373 | sage: I.next_brother((0,1)) |
| 374 | sage: I.next_brother((3,0)) |
| 375 | (2, 1) |
| 376 | sage: I.next_brother((2,1)) |
| 377 | sage: brother = lambda t: (t[0]-1,1) if t[1] == 0 else None |
| 378 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], next_brother=brother) |
| 379 | sage: I.next_brother((1,0)) |
| 380 | (0, 1) |
| 381 | sage: I.next_brother((0,1)) |
| 382 | sage: I.next_brother((3,0)) |
| 383 | (2, 1) |
| 384 | sage: I.next_brother((2,1)) |
| 385 | """ |
| 386 | # If the function next_brother was given in argument of ``self.__init__``, |
| 387 | # we use it firstly. |
| 388 | if self._next_brother != None: |
| 389 | return self._next_brother(x) |
| 390 | else: |
| 391 | # If we have no next_brother method, we search for the father and |
| 392 | # mainly the father given in argument, otherwise the father method. |
| 393 | if father == None: |
| 394 | father = self.father(x) |
| 395 | children = self.children(father) |
| 396 | brother = children.next() |
| 397 | while brother != x: |
| 398 | brother = children.next() |
| 399 | try: |
| 400 | next = children.next() |
| 401 | except StopIteration: |
| 402 | next = None |
| 403 | return next |
| 404 | |
| 425 | def depth_first_search_iterator(self): |
| 426 | r""" |
| 427 | Returns an iterator on the elements of ``self`` exploring the tree by depth. |
| 428 | |
| 429 | EXAMPLES:: |
| 430 | |
| 431 | sage: f = SearchForest([[]], |
| 432 | ... lambda l: [l+[0], l+[1]] if len(l) < 3 else []) |
| 433 | sage: list(f.depth_first_search_iterator()) |
| 434 | [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1], [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]] |
| 435 | """ |
| 436 | return search_forest_iterator(self._roots, self._children, method="depth") |
| 437 | |
| 438 | def breadth_first_search_iterator(self): |
| 439 | r""" |
| 440 | Returns an iterator on the elements of ``self`` exploring the |
| 441 | tree by breadth first search. |
| 442 | |
| 443 | EXAMPLES:: |
| 444 | |
| 445 | sage: f = SearchForest([[]], |
| 446 | ... lambda l: [l+[0], l+[1]] if len(l) < 3 else []) |
| 447 | sage: list(f.breadth_first_search_iterator()) |
| 448 | [[], [0], [1], [0, 0], [0, 1], [1, 0], [1, 1], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] |
| 449 | """ |
| 450 | return search_forest_iterator(self._roots, self._children, method="breadth") |
| 451 | |
| 452 | def next_generation_iterator(self, fathers): |
| 453 | r""" |
| 454 | From an iterator ``it`` over some elements of ``self``, return an iterator |
| 455 | over all children of elements generated by ``it`. |
| 456 | |
| 457 | EXAMPLES:: |
| 458 | |
| 459 | sage: I = SearchForest([(0,0)], |
| 460 | ... lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 |
| 461 | ... else [(l[0], l[1]+1)]) |
| 462 | sage: list(I.next_generation_iterator(I.roots())) |
| 463 | [(1, 0), (0, 1)] |
| 464 | sage: I = SearchForest([[]], |
| 465 | ... lambda l: [l+[0], l+[1]] if len(l) < 3 else []) |
| 466 | sage: list(I.next_generation_iterator(I.roots())) |
| 467 | [[0], [1]] |
| 468 | """ |
| 469 | for father in fathers: |
| 470 | for child in self.children(father): |
| 471 | yield child |
| 472 | |
| 473 | def _next_element_by_father(self, x): |
| 474 | r""" |
| 475 | Returns the next element of ``self`` by breadth enumeration using |
| 476 | ``father`` and ``next_brother`` method. |
| 477 | |
| 478 | EXAMPLES:: |
| 479 | |
| 480 | sage: def children(t): |
| 481 | ... if t[2] == 0: |
| 482 | ... if t[1] == 0: |
| 483 | ... return [(t[0]+1,t[1],t[2]),(t[0],t[1]+1,t[2]),(t[0],t[1],t[2]+1)] |
| 484 | ... else: |
| 485 | ... return [(t[0],t[1]+1,t[2]),(t[0],t[1],t[2]+1)] |
| 486 | ... else: |
| 487 | ... return [(t[0],t[1],t[2]+1)] |
| 488 | sage: def father(t): |
| 489 | ... if t[2] == 0: |
| 490 | ... if t[1] == 0: |
| 491 | ... return (t[0]-1,0,0) |
| 492 | ... else: |
| 493 | ... return (t[0],t[1]-1,0) |
| 494 | ... else: |
| 495 | ... return (t[0],t[1],t[2]-1) |
| 496 | sage: I = SearchForest([(0,0,0)], children, father=father) |
| 497 | sage: I.first() |
| 498 | (0, 0, 0) |
| 499 | sage: I._next_element_by_father(_) |
| 500 | (1, 0, 0) |
| 501 | sage: I._next_element_by_father(_) |
| 502 | (0, 1, 0) |
| 503 | sage: I._next_element_by_father(_) |
| 504 | (0, 0, 1) |
| 505 | sage: I._next_element_by_father(_) |
| 506 | (2, 0, 0) |
| 507 | sage: I._next_element_by_father(_) |
| 508 | (1, 1, 0) |
| 509 | sage: I._next_element_by_father(_) |
| 510 | (1, 0, 1) |
| 511 | sage: I._next_element_by_father(_) |
| 512 | (0, 2, 0) |
| 513 | sage: I._next_element_by_father(_) |
| 514 | (0, 1, 1) |
| 515 | sage: I._next_element_by_father(_) |
| 516 | (0, 0, 2) |
| 517 | sage: I._next_element_by_father(_) |
| 518 | (3, 0, 0) |
| 519 | sage: I._next_element_by_father(_) |
| 520 | (2, 1, 0) |
| 521 | sage: I._next_element_by_father(_) |
| 522 | (2, 0, 1) |
| 523 | sage: I._next_element_by_father(_) |
| 524 | (1, 2, 0) |
| 525 | sage: I._next_element_by_father(_) |
| 526 | (1, 1, 1) |
| 527 | """ |
| 528 | roots = list(self.roots()) |
| 529 | for i in range(len(roots)): |
| 530 | if x == roots[i]: |
| 531 | if i < len(roots)-1: |
| 532 | return roots[i+1] |
| 533 | else: |
| 534 | return self.children(roots[0]).next() |
| 535 | brother = self.next_brother(x) |
| 536 | if brother != None: |
| 537 | return brother |
| 538 | else: |
| 539 | next_father = self._next_element_by_father(self.father(x)) |
| 540 | while x != next_father: |
| 541 | try: |
| 542 | return self.children(next_father).next() |
| 543 | except StopIteration: |
| 544 | next_father = self._next_element_by_father(next_father) |
| 545 | continue |
| 546 | try: |
| 547 | return self.children(next_father).next() |
| 548 | except StopIteration: |
| 549 | return None |
| 550 | |
| 551 | def _iter_from_to(self, start, end): |
| 552 | r""" |
| 553 | Returns an iterator starting with the element ``start`` and stopping |
| 554 | just before the element ``end``. |
| 555 | |
| 556 | EXAMPLES:: |
| 557 | |
| 558 | sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1) |
| 559 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father) |
| 560 | sage: [i for i in I._iter_from_to((3,0),(5,0))] |
| 561 | [(3, 0), (2, 1), (1, 2), (0, 3), (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)] |
| 562 | sage: [i for i in I._iter_from_to((6,0),(6,1))] |
| 563 | [(6, 0), (5, 1), (4, 2), (3, 3), (2, 4), (1, 5), (0, 6), (7, 0)] |
| 564 | """ |
| 565 | node = start |
| 566 | while node != end: |
| 567 | yield node |
| 568 | node = self._next_element_by_father(node) |
| 569 | |
| 570 | def first_element_of_depth(self, depth, father_with_depth=None): |
| 571 | r""" |
| 572 | Returns the first element of given ``depth``. |
| 573 | |
| 574 | EXAMPLES:: |
| 575 | |
| 576 | sage: father = lambda l : l[:-1] |
| 577 | sage: I = SearchForest([[3]], lambda l: (l+[i] for i in range(l[-1])), father = father) |
| 578 | sage: I.first_element_of_depth(0) |
| 579 | [3] |
| 580 | sage: I.first_element_of_depth(1) |
| 581 | [3, 0] |
| 582 | sage: I.first_element_of_depth(2) |
| 583 | [3, 1, 0] |
| 584 | sage: I.first_element_of_depth(3) |
| 585 | [3, 2, 1, 0] |
| 586 | sage: I.first_element_of_depth(4) |
| 587 | sage: I.first_element_of_depth(5) |
| 588 | """ |
| 589 | if depth == 0: |
| 590 | try: |
| 591 | return self.roots().next() |
| 592 | except StopIteration: |
| 593 | return None |
| 594 | else: |
| 595 | if father_with_depth == None: |
| 596 | try: |
| 597 | next_father = self.roots().next() |
| 598 | return self.first_element_of_depth(depth, father_with_depth=(next_father,0)) |
| 599 | except StopIteration: |
| 600 | return None |
| 601 | else: |
| 602 | father = father_with_depth[0] |
| 603 | depth_father = father_with_depth[1] |
| 604 | try: |
| 605 | next_father = self.children(father).next() |
| 606 | if depth == depth_father+1: |
| 607 | return next_father |
| 608 | else: |
| 609 | return self.first_element_of_depth(depth, father_with_depth=(next_father,depth_father+1)) |
| 610 | except StopIteration: |
| 611 | next_father = self._next_element_by_father(father) |
| 612 | if next_father == None: |
| 613 | return None |
| 614 | else: |
| 615 | return self.first_element_of_depth(depth, father_with_depth=(next_father,depth_father)) |
| 616 | |
| 617 | def element_of_depth_iterator(self, depth=0, method="full_generation"): |
| 618 | r""" |
| 619 | Returns an iterator on the elements of ``self`` of given depth. |
| 620 | An element of depth `n` can be obtained applying `n` times the |
| 621 | children function from a root. |
| 622 | |
| 623 | INPUT: |
| 624 | |
| 625 | - ``depth``: a non negative integer |
| 626 | - ``method``: optional string. |
| 627 | |
| 628 | |
| 629 | By default ``method`` is ``"full_generation"``. This means the |
| 630 | algorithm start from the roots and generate all elements until the |
| 631 | given depth is reached. |
| 632 | |
| 633 | If ``method`` is different of ``"full_generation"``, the algorithm |
| 634 | makes use of ``father`` and ``next_brother`` methods. This reduces the |
| 635 | number of calls to the ``children`` method. |
| 636 | |
| 637 | EXAMPLES:: |
| 638 | |
| 639 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)]) |
| 640 | sage: list(I.element_of_depth_iterator(8)) |
| 641 | [(8, 0), (7, 1), (6, 2), (5, 3), (4, 4), (3, 5), (2, 6), (1, 7), (0, 8)] |
| 642 | sage: I = SearchForest([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else []) |
| 643 | sage: list(I.element_of_depth_iterator(0)) |
| 644 | [[]] |
| 645 | sage: list(I.element_of_depth_iterator(1)) |
| 646 | [[0], [1]] |
| 647 | sage: list(I.element_of_depth_iterator(2)) |
| 648 | [[0, 0], [0, 1], [1, 0], [1, 1]] |
| 649 | sage: list(I.element_of_depth_iterator(3)) |
| 650 | [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] |
| 651 | sage: list(I.element_of_depth_iterator(4)) |
| 652 | [] |
| 653 | sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1) |
| 654 | sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father) |
| 655 | sage: list(I.element_of_depth_iterator(10, method="father")) |
| 656 | [(10, 0), (9, 1), (8, 2), (7, 3), (6, 4), (5, 5), (4, 6), (3, 7), (2, 8), (1, 9), (0, 10)] |
| 657 | sage: father = lambda l : l[:-1] |
| 658 | sage: I = SearchForest([[3]], lambda l: (l+[i] for i in range(l[-1])), father = father) |
| 659 | sage: list(I.element_of_depth_iterator(0, method="father")) |
| 660 | [[3]] |
| 661 | sage: list(I.element_of_depth_iterator(1, method="father")) |
| 662 | [[3, 0], [3, 1], [3, 2]] |
| 663 | sage: for i in range(8): |
| 664 | ... assert list(I.element_of_depth_iterator(i)) == list(I.element_of_depth_iterator(i, method="father")) |
| 665 | """ |
| 666 | if method == "full_generation": |
| 667 | iter = self.roots() |
| 668 | for i in range(depth): |
| 669 | iter = self.next_generation_iterator(iter) |
| 670 | return iter |
| 671 | else: |
| 672 | # Another way to enumerate all children of given depth is to |
| 673 | # use father and next_brother method... |
| 674 | node = self.first_element_of_depth(depth) |
| 675 | # node is now the starting point for the enumeration |
| 676 | if node == None: |
| 677 | return [].__iter__() |
| 678 | else: |
| 679 | end_node = self.first_element_of_depth(depth+1, father_with_depth=(node,depth)) |
| 680 | return self._iter_from_to(node, end_node) |
| 681 | |
| 682 | |