Converter for the while_loop. The conversion of a while_loop is another while_loop. The arguments to this converted while_loop are as follows: not_all_done: Boolean scalar Tensor indicating if all the pfor iterations are done. indices: int32 1-D Tensor storing the id of the i
(self, pfor_input)
| 547 | return new_outputs |
| 548 | |
| 549 | def __call__(self, pfor_input): |
| 550 | """Converter for the while_loop. |
| 551 | |
| 552 | The conversion of a while_loop is another while_loop. |
| 553 | |
| 554 | The arguments to this converted while_loop are as follows: |
| 555 | not_all_done: Boolean scalar Tensor indicating if all the pfor iterations |
| 556 | are done. |
| 557 | indices: int32 1-D Tensor storing the id of the iterations that are not |
| 558 | done. |
| 559 | args: Remaining arguments. These can be divided into 3 categories: |
| 560 | - First set of arguments are the tensors that correspond to the initial |
| 561 | elements of self._enters. The elements that appear in original while |
| 562 | loop's `loop_vars`. |
| 563 | - The second set of arguments are the tensors that correspond to the |
| 564 | remaining elements of self._enters. These are the tensors that directly |
| 565 | enter the original while loop body. |
| 566 | - Finally, the last set of arguments are TensorArrays. These TensorArrays |
| 567 | correspond to the outputs of the original while_loop, i.e. to the |
| 568 | elements in self._outputs. Each TensorArray has `PFor.loop_len` |
| 569 | elements, i.e. the number of pfor iterations. At the end, the i'th |
| 570 | element of each TensorArray will contain the output computed by the |
| 571 | i'th iteration of pfor. Note that elements can be written into these |
| 572 | tensors arrays in any order, depending on when the corresponding pfor |
| 573 | iteration is done. |
| 574 | If the original while_loop had `k` tensors in its `loop_vars` and its body |
| 575 | directly captured `m` tensors, the `args` will contain `2 * k + m` values. |
| 576 | |
| 577 | In each iteration, the while_loop body recomputes the condition for all |
| 578 | active pfor iterations to see which of them are now done. It then partitions |
| 579 | all the inputs and passes them along to the converted body. Values for all |
| 580 | the iterations that are done are written to TensorArrays indexed by the pfor |
| 581 | iteration number. When all iterations are done, the TensorArrays are stacked |
| 582 | to get the final value. |
| 583 | |
| 584 | Args: |
| 585 | pfor_input: A PForInput object corresponding to the output of any Exit |
| 586 | node from this while loop. |
| 587 | |
| 588 | Returns: |
| 589 | List of converted outputs. |
| 590 | """ |
| 591 | # Create init_values that will be passed to the while_loop. |
| 592 | init_values, inputs_stacked, shape_invariants = self._create_init_values( |
| 593 | pfor_input) |
| 594 | # Note that we use a list as a hack since we need the nested function body |
| 595 | # to set the value of cond_is_stacked. python2.x doesn't support nonlocal |
| 596 | # variables. |
| 597 | cond_is_stacked = [None] |
| 598 | |
| 599 | def cond(not_all_done, *_): |
| 600 | return not_all_done |
| 601 | |
| 602 | def body(not_all_done, indices, *args): |
| 603 | # See documentatin for __call__ for the structure of *args. |
| 604 | num_enters = len(self._enters) |
| 605 | inputs = args[:num_enters] |
| 606 | output_tas = args[num_enters:] |
no test coverage detected