Returns the value of an available element of `inputs`. This op tests each of the tensors in `inputs` in turn to determine if any of them is available. If it finds an available tensor, it returns it and its index in `inputs`. It is an error if more than one tensor in `inputs` is available.
(inputs, name=None)
| 363 | |
| 364 | |
| 365 | def merge(inputs, name=None): |
| 366 | """Returns the value of an available element of `inputs`. |
| 367 | |
| 368 | This op tests each of the tensors in `inputs` in turn to determine if any of |
| 369 | them is available. If it finds an available tensor, it returns it and its |
| 370 | index in `inputs`. |
| 371 | |
| 372 | It is an error if more than one tensor in `inputs` is available. If no tensor |
| 373 | in `inputs` is available, the returned tensor and index are not set. |
| 374 | |
| 375 | This op handles both `Tensor`s and `IndexedSlices`. If inputs has a mix of |
| 376 | `Tensor`s and `IndexedSlices`, all inputs are converted to IndexedSlices |
| 377 | before merging. |
| 378 | |
| 379 | Args: |
| 380 | inputs: The input tensors, at most one of which is available. |
| 381 | name: A name for this operation (optional). |
| 382 | |
| 383 | Returns: |
| 384 | A tuple containing the chosen input tensor and its index in `inputs`. |
| 385 | |
| 386 | Raises: |
| 387 | ValueError: If any of the inputs is None, or inputs are IndexedSlices and |
| 388 | some but not all have a dense_shape property. |
| 389 | """ |
| 390 | if any(inp is None for inp in inputs): |
| 391 | raise ValueError("At least one of the merge inputs is None: %s" % inputs) |
| 392 | with ops.name_scope(name, "Merge", inputs) as name: |
| 393 | inputs = [ |
| 394 | ops.internal_convert_to_tensor_or_composite(inp, as_ref=True) |
| 395 | for inp in inputs |
| 396 | ] |
| 397 | if all(isinstance(v, ops.Tensor) for v in inputs): |
| 398 | if all(v.dtype._is_ref_dtype for v in inputs): # pylint: disable=protected-access |
| 399 | return gen_control_flow_ops.ref_merge(inputs, name) |
| 400 | else: |
| 401 | return gen_control_flow_ops.merge(inputs, name) |
| 402 | else: |
| 403 | # If there is a mix of tensors and indexed slices, then convert the |
| 404 | # tensors to indexed slices. |
| 405 | if all(isinstance(v, (ops.IndexedSlices, ops.Tensor)) for v in inputs): |
| 406 | inputs = math_ops._as_indexed_slices_list(inputs, optimize=False) |
| 407 | |
| 408 | for v in inputs: |
| 409 | if not isinstance(v, composite_tensor.CompositeTensor): |
| 410 | raise TypeError("Type %s not supported" % type(v)) |
| 411 | |
| 412 | for v in inputs[1:]: |
| 413 | nest.assert_same_structure(inputs[0], v, expand_composites=True) |
| 414 | |
| 415 | flat_inputs = [nest.flatten(v, expand_composites=True) for v in inputs] |
| 416 | merged_results = [ |
| 417 | gen_control_flow_ops.merge(component) |
| 418 | for component in zip(*flat_inputs) |
| 419 | ] |
| 420 | flat_merged = [tensor for (tensor, _) in merged_results] |
| 421 | chosen_index = merged_results[0][1] |
| 422 | merged_inputs = nest.pack_sequence_as( |
no test coverage detected