search.py 40.7 KB
Newer Older
1
#   Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 3 4 5 6 7 8 9 10 11 12 13
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
14 15 16

# TODO: define searching & indexing functions of a tensor

17
import numpy as np
18

Z
zhiboniu 已提交
19
import paddle
20
from paddle import _C_ops
21 22
from paddle.common_ops_import import VarDesc, Variable

23
from ..fluid.data_feeder import check_dtype, check_variable_and_dtype
24 25 26 27 28 29
from ..framework import (
    LayerHelper,
    convert_np_dtype_to_dtype_,
    core,
    in_dygraph_mode,
)
30

31 32
# from ..fluid.layers import has_inf  #DEFINE_ALIAS
# from ..fluid.layers import has_nan  #DEFINE_ALIAS
33

34 35
__all__ = []

36

37 38
def argsort(x, axis=-1, descending=False, name=None):
    """
39
    Sorts the input along the given axis, and returns the corresponding index tensor for the sorted output values. The default sort algorithm is ascending, if you want the sort algorithm to be descending, you must set the :attr:`descending` as True.
40 41

    Args:
42
        x(Tensor): An input N-D Tensor with type float16, float32, float64, int16,
43 44 45
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is Rank(x). when axis<0, it works the same way
C
Chen Long 已提交
46
            as axis+R. Default is -1.
47 48 49
        descending(bool, optional) : Descending is a flag, if set to true,
            algorithm will sort by descending order, else sort by
            ascending order. Default is false.
50
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
51 52 53 54 55 56

    Returns:
        Tensor: sorted indices(with the same shape as ``x``
        and with data type int64).

    Examples:
李灿 已提交
57

58
        .. code-block:: python
李灿 已提交
59

60
            import paddle
61

62 63 64 65 66
            x = paddle.to_tensor([[[5,8,9,5],
                                   [0,0,1,7],
                                   [6,9,2,4]],
                                  [[5,2,4,2],
                                   [4,7,7,9],
67
                                   [1,7,0,6]]],
68
                                dtype='float32')
C
Chen Long 已提交
69 70 71
            out1 = paddle.argsort(x, axis=-1)
            out2 = paddle.argsort(x, axis=0)
            out3 = paddle.argsort(x, axis=1)
72

N
Noel 已提交
73
            print(out1)
W
wawltor 已提交
74 75 76
            #[[[0 3 1 2]
            #  [0 1 2 3]
            #  [2 3 0 1]]
77
            # [[1 3 2 0]
W
wawltor 已提交
78 79
            #  [0 1 2 3]
            #  [2 0 3 1]]]
80

N
Noel 已提交
81
            print(out2)
W
wawltor 已提交
82 83 84 85 86 87
            #[[[0 1 1 1]
            #  [0 0 0 0]
            #  [1 1 1 0]]
            # [[1 0 0 0]
            #  [1 1 1 1]
            #  [0 0 0 1]]]
88

N
Noel 已提交
89
            print(out3)
W
wawltor 已提交
90 91 92 93 94 95
            #[[[1 1 1 2]
            #  [0 0 2 0]
            #  [2 2 0 1]]
            # [[2 0 2 0]
            #  [1 1 0 2]
            #  [0 2 1 1]]]
96
    """
H
hong 已提交
97
    if in_dygraph_mode():
98
        _, ids = _C_ops.argsort(x, axis, descending)
H
hong 已提交
99
        return ids
100 101 102 103
    else:
        check_variable_and_dtype(
            x,
            'x',
104 105 106 107 108 109 110 111 112
            [
                'float16',
                'float32',
                'float64',
                'int16',
                'int32',
                'int64',
                'uint8',
            ],
113 114
            'argsort',
        )
H
hong 已提交
115

116 117 118 119 120 121 122 123 124 125 126 127
        helper = LayerHelper("argsort", **locals())
        out = helper.create_variable_for_type_inference(
            dtype=x.dtype, stop_gradient=True
        )
        ids = helper.create_variable_for_type_inference(
            VarDesc.VarType.INT64, stop_gradient=True
        )
        helper.append_op(
            type='argsort',
            inputs={'X': x},
            outputs={'Out': out, 'Indices': ids},
            attrs={'axis': axis, 'descending': descending},
128
        )
129 130 131
        return ids


132
def argmax(x, axis=None, keepdim=False, dtype="int64", name=None):
133
    """
134
    Computes the indices of the max elements of the input tensor's
135 136 137
    element along the provided axis.

    Args:
138
        x(Tensor): An input N-D Tensor with type float16, float32, float64, int16,
139 140
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
W
wawltor 已提交
141 142
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is None, the input `x` will be into the flatten tensor, and selecting the min value index.
143
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
144
        dtype(str|np.dtype, optional): Data type of the output tensor which can
145
                    be int32, int64. The default value is ``int64`` , and it will
146
                    return the int64 indices.
147
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
148 149

    Returns:
150
        Tensor, return the tensor of int32 if set :attr:`dtype` is int32, otherwise return the tensor of int64.
151 152 153 154

    Examples:
        .. code-block:: python

W
wawltor 已提交
155
            import paddle
156

157 158 159
            x = paddle.to_tensor([[5,8,9,5],
                                 [0,0,1,7],
                                 [6,9,2,4]])
W
wawltor 已提交
160
            out1 = paddle.argmax(x)
N
Noel 已提交
161
            print(out1) # 2
162
            out2 = paddle.argmax(x, axis=0)
163
            print(out2)
164
            # [2, 2, 0, 1]
W
wawltor 已提交
165
            out3 = paddle.argmax(x, axis=-1)
166
            print(out3)
167 168 169 170
            # [2, 3, 1]
            out4 = paddle.argmax(x, axis=0, keepdim=True)
            print(out4)
            # [[2, 2, 0, 1]]
171
    """
172
    if axis is not None and not isinstance(axis, (int, Variable)):
173
        raise TypeError(
174
            "The type of 'axis'  must be int or Tensor or None in argmax, but received %s."
175 176
            % (type(axis))
        )
177

178 179 180 181
    if dtype is None:
        raise ValueError(
            "the value of 'dtype' in argmax could not be None, but received None"
        )
182

183
    var_dtype = convert_np_dtype_to_dtype_(dtype)
W
wawltor 已提交
184 185 186 187 188
    flatten = False
    if axis is None:
        flatten = True
        axis = 0

H
hong 已提交
189
    if in_dygraph_mode():
190
        return _C_ops.argmax(x, axis, keepdim, flatten, var_dtype)
191 192 193
    else:
        helper = LayerHelper("argmax", **locals())
        check_variable_and_dtype(
194
            x,
195
            'x',
196
            [
197
                'uint16',
198 199 200 201 202 203 204 205
                'float16',
                'float32',
                'float64',
                'int16',
                'int32',
                'int64',
                'uint8',
            ],
206
            'paddle.argmax',
207
        )
208 209 210 211 212 213 214 215 216 217 218
        check_dtype(var_dtype, 'dtype', ['int32', 'int64'], 'argmin')
        attrs = {}
        out = helper.create_variable_for_type_inference(var_dtype)
        attrs['keepdims'] = keepdim
        attrs['axis'] = axis
        attrs['flatten'] = flatten
        attrs['dtype'] = var_dtype
        helper.append_op(
            type='arg_max', inputs={'X': x}, outputs={'Out': [out]}, attrs=attrs
        )
        out.stop_gradient = True
W
wawltor 已提交
219 220 221
        return out


222
def argmin(x, axis=None, keepdim=False, dtype="int64", name=None):
W
wawltor 已提交
223
    """
224
    Computes the indices of the min elements of the input tensor's
W
wawltor 已提交
225 226 227
    element along the provided axis.

    Args:
228
        x(Tensor): An input N-D Tensor with type float16, float32, float64, int16,
W
wawltor 已提交
229 230 231 232
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is None, the input `x` will be into the flatten tensor, and selecting the min value index.
233
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
234
        dtype(str, optional): Data type of the output tensor which can
235
                    be int32, int64. The default value is 'int64', and it will
W
wawltor 已提交
236
                    return the int64 indices.
237
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
238

W
wawltor 已提交
239
    Returns:
240
        Tensor, return the tensor of `int32` if set :attr:`dtype` is `int32`, otherwise return the tensor of `int64`.
W
wawltor 已提交
241 242 243

    Examples:
        .. code-block:: python
244

W
wawltor 已提交
245 246
            import paddle

247 248 249
            x =  paddle.to_tensor([[5,8,9,5],
                                     [0,0,1,7],
                                     [6,9,2,4]])
W
wawltor 已提交
250
            out1 = paddle.argmin(x)
N
Noel 已提交
251
            print(out1) # 4
252
            out2 = paddle.argmin(x, axis=0)
253
            print(out2)
254
            # [1, 1, 1, 2]
W
wawltor 已提交
255
            out3 = paddle.argmin(x, axis=-1)
256
            print(out3)
257 258 259 260
            # [0, 0, 2]
            out4 = paddle.argmin(x, axis=0, keepdim=True)
            print(out4)
            # [[1, 1, 1, 2]]
W
wawltor 已提交
261
    """
262
    if axis is not None and not isinstance(axis, (int, Variable)):
263
        raise TypeError(
264
            "The type of 'axis'  must be int or Tensor or None in argmin, but received %s."
265 266
            % (type(axis))
        )
267

268 269 270 271
    if dtype is None:
        raise ValueError(
            "the value of 'dtype' in argmin could not be None, but received None"
        )
272

273
    var_dtype = convert_np_dtype_to_dtype_(dtype)
W
wawltor 已提交
274
    flatten = False
275
    if axis is None:
W
wawltor 已提交
276 277 278
        flatten = True
        axis = 0

H
hong 已提交
279
    if in_dygraph_mode():
280
        return _C_ops.argmin(x, axis, keepdim, flatten, var_dtype)
281 282 283
    else:
        helper = LayerHelper("argmin", **locals())
        check_variable_and_dtype(
284
            x,
285
            'x',
286
            [
287
                'uint16',
288 289 290 291 292 293 294 295
                'float16',
                'float32',
                'float64',
                'int16',
                'int32',
                'int64',
                'uint8',
            ],
296
            'paddle.argmin',
297
        )
298 299 300 301 302 303 304 305 306 307 308
        check_dtype(var_dtype, 'dtype', ['int32', 'int64'], 'argmin')
        out = helper.create_variable_for_type_inference(var_dtype)
        attrs = {}
        attrs['keepdims'] = keepdim
        attrs['axis'] = axis
        attrs['flatten'] = flatten
        attrs['dtype'] = var_dtype
        helper.append_op(
            type='arg_min', inputs={'X': x}, outputs={'Out': [out]}, attrs=attrs
        )
        out.stop_gradient = True
W
wawltor 已提交
309 310
        return out

311

312
def index_select(x, index, axis=0, name=None):
313
    """
S
swtkiwi 已提交
314

315 316 317 318
    Returns a new tensor which indexes the ``input`` tensor along dimension ``axis`` using
    the entries in ``index`` which is a Tensor. The returned tensor has the same number
    of dimensions as the original ``x`` tensor. The dim-th dimension has the same
    size as the length of ``index``; other dimensions have the same size as in the ``x`` tensor.
C
Chengmo 已提交
319

320
    Args:
321
        x (Tensor): The input Tensor to be operated. The data of ``x`` can be one of float16, float32, float64, int32, int64.
322 323
        index (Tensor): The 1-D Tensor containing the indices to index. The data type of ``index`` must be int32 or int64.
        axis (int, optional): The dimension in which we index. Default: if None, the ``axis`` is 0.
324
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
325 326

    Returns:
327
        Tensor: A Tensor with same data type as ``x``.
328

329 330
    Examples:
        .. code-block:: python
331

332 333
            import paddle

334 335 336 337
            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]])
            index = paddle.to_tensor([0, 1, 1], dtype='int32')
338 339 340 341 342 343 344 345
            out_z1 = paddle.index_select(x=x, index=index)
            #[[1. 2. 3. 4.]
            # [5. 6. 7. 8.]
            # [5. 6. 7. 8.]]
            out_z2 = paddle.index_select(x=x, index=index, axis=1)
            #[[ 1.  2.  2.]
            # [ 5.  6.  6.]
            # [ 9. 10. 10.]]
346
    """
347

F
From00 已提交
348
    if in_dygraph_mode():
349
        return _C_ops.index_select(x, index, axis)
350 351 352 353 354
    else:
        helper = LayerHelper("index_select", **locals())
        check_variable_and_dtype(
            x,
            'x',
W
wangxiaoning 已提交
355
            ['uint16', 'float16', 'float32', 'float64', 'int32', 'int64'],
356 357 358 359 360 361 362 363
            'paddle.tensor.search.index_select',
        )
        check_variable_and_dtype(
            index,
            'index',
            ['int32', 'int64'],
            'paddle.tensor.search.index_select',
        )
F
From00 已提交
364

365
        out = helper.create_variable_for_type_inference(x.dtype)
366

367 368 369 370 371 372 373
        helper.append_op(
            type='index_select',
            inputs={'X': x, 'Index': index},
            outputs={'Out': out},
            attrs={'dim': axis},
        )
        return out
374 375


376
def nonzero(x, as_tuple=False):
377
    """
378 379 380 381 382 383
    Return a tensor containing the indices of all non-zero elements of the `input`
    tensor. If as_tuple is True, return a tuple of 1-D tensors, one for each dimension
    in `input`, each containing the indices (in that dimension) of all non-zero elements
    of `input`. Given a n-Dimensional `input` tensor with shape [x_1, x_2, ..., x_n], If
    as_tuple is False, we can get a output tensor with shape [z, n], where `z` is the
    number of all non-zero elements in the `input` tensor. If as_tuple is True, we can get
384
    a 1-D tensor tuple of length `n`, and the shape of each 1-D tensor is [z, 1].
C
Chengmo 已提交
385

386
    Args:
387
        x (Tensor): The input tensor variable.
388
        as_tuple (bool, optional): Return type, Tensor or tuple of Tensor.
389 390

    Returns:
391
        Tensor. The data type is int64.
392 393

    Examples:
394

N
Noel 已提交
395
        .. code-block:: python
李灿 已提交
396

397
            import paddle
398 399

            x1 = paddle.to_tensor([[1.0, 0.0, 0.0],
N
Noel 已提交
400 401
                                   [0.0, 2.0, 0.0],
                                   [0.0, 0.0, 3.0]])
402 403
            x2 = paddle.to_tensor([0.0, 1.0, 0.0, 3.0])
            out_z1 = paddle.nonzero(x1)
N
Noel 已提交
404
            print(out_z1)
405 406 407 408 409
            #[[0 0]
            # [1 1]
            # [2 2]]
            out_z1_tuple = paddle.nonzero(x1, as_tuple=True)
            for out in out_z1_tuple:
N
Noel 已提交
410
                print(out)
411 412 413 414 415 416 417
            #[[0]
            # [1]
            # [2]]
            #[[0]
            # [1]
            # [2]]
            out_z2 = paddle.nonzero(x2)
N
Noel 已提交
418
            print(out_z2)
419 420 421 422
            #[[1]
            # [3]]
            out_z2_tuple = paddle.nonzero(x2, as_tuple=True)
            for out in out_z2_tuple:
N
Noel 已提交
423
                print(out)
424 425
            #[[1]
            # [3]]
N
Noel 已提交
426

427 428
    """
    list_out = []
429
    shape = x.shape
430 431
    rank = len(shape)

432
    if in_dygraph_mode():
433
        outs = _C_ops.nonzero(x)
434
    else:
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
        check_variable_and_dtype(
            x,
            'x',
            [
                'int16',
                'int32',
                'int64',
                'uint16',
                'float16',
                'float32',
                'float64',
                'bool',
            ],
            'where_index',
        )

451 452 453
        helper = LayerHelper("where_index", **locals())

        outs = helper.create_variable_for_type_inference(
454 455
            dtype=core.VarDesc.VarType.INT64
        )
456

457 458 459
        helper.append_op(
            type='where_index', inputs={'Condition': x}, outputs={'Out': [outs]}
        )
460 461 462 463

    if not as_tuple:
        return outs
    elif rank == 1:
464
        return (outs,)
465 466 467
    else:
        for i in range(rank):
            list_out.append(
468 469
                paddle.slice(outs, axes=[1], starts=[i], ends=[i + 1])
            )
470 471 472
        return tuple(list_out)


473
def sort(x, axis=-1, descending=False, name=None):
474
    """
S
swtkiwi 已提交
475

476
    Sorts the input along the given axis, and returns the sorted output tensor. The default sort algorithm is ascending, if you want the sort algorithm to be descending, you must set the :attr:`descending` as True.
C
Chengmo 已提交
477

478
    Args:
479
        x(Tensor): An input N-D Tensor with type float32, float64, int16,
480 481 482
            int32, int64, uint8.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is Rank(x). when axis<0, it works the same way
483
            as axis+R. Default is -1.
484 485 486
        descending(bool, optional) : Descending is a flag, if set to true,
            algorithm will sort by descending order, else sort by
            ascending order. Default is false.
487
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
488

489
    Returns:
W
wawltor 已提交
490
        Tensor: sorted tensor(with the same shape and data type as ``x``).
491
    Examples:
N
Noel 已提交
492

493
        .. code-block:: python
N
Noel 已提交
494

495
            import paddle
N
Noel 已提交
496

497 498 499 500 501
            x = paddle.to_tensor([[[5,8,9,5],
                                   [0,0,1,7],
                                   [6,9,2,4]],
                                  [[5,2,4,2],
                                   [4,7,7,9],
502
                                   [1,7,0,6]]],
503
                                 dtype='float32')
504 505 506
            out1 = paddle.sort(x=x, axis=-1)
            out2 = paddle.sort(x=x, axis=0)
            out3 = paddle.sort(x=x, axis=1)
N
Noel 已提交
507
            print(out1)
W
wawltor 已提交
508 509 510 511 512 513
            #[[[5. 5. 8. 9.]
            #  [0. 0. 1. 7.]
            #  [2. 4. 6. 9.]]
            # [[2. 2. 4. 5.]
            #  [4. 7. 7. 9.]
            #  [0. 1. 6. 7.]]]
N
Noel 已提交
514
            print(out2)
515
            #[[[5. 2. 4. 2.]
W
wawltor 已提交
516 517 518 519 520
            #  [0. 0. 1. 7.]
            #  [1. 7. 0. 4.]]
            # [[5. 8. 9. 5.]
            #  [4. 7. 7. 9.]
            #  [6. 9. 2. 6.]]]
N
Noel 已提交
521
            print(out3)
522
            #[[[0. 0. 1. 4.]
W
wawltor 已提交
523 524 525 526 527
            #  [5. 8. 2. 5.]
            #  [6. 9. 9. 7.]]
            # [[1. 2. 0. 2.]
            #  [4. 7. 4. 6.]
            #  [5. 7. 7. 9.]]]
528
    """
529
    if in_dygraph_mode():
530
        outs, _ = _C_ops.argsort(x, axis, descending)
531
        return outs
532 533 534 535
    else:
        helper = LayerHelper("sort", **locals())
        out = helper.create_variable_for_type_inference(
            dtype=x.dtype, stop_gradient=False
536
        )
537 538 539 540 541 542 543 544 545 546
        ids = helper.create_variable_for_type_inference(
            VarDesc.VarType.INT64, stop_gradient=True
        )
        helper.append_op(
            type='argsort',
            inputs={'X': x},
            outputs={'Out': out, 'Indices': ids},
            attrs={'axis': axis, 'descending': descending},
        )
        return out
C
Chengmo 已提交
547 548


549 550
def mode(x, axis=-1, keepdim=False, name=None):
    """
551
    Used to find values and indices of the modes at the optional axis.
552 553 554 555 556 557 558

    Args:
        x(Tensor): Tensor, an input N-D Tensor with type float32, float64, int32, int64.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is -1.
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
559
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
560 561 562 563 564 565 566 567 568

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.

    Examples:

        .. code-block:: python

           import paddle
569

570 571 572 573 574 575 576 577
           tensor = paddle.to_tensor([[[1,2,2],[2,3,3]],[[0,5,5],[9,9,0]]], dtype=paddle.float32)
           res = paddle.mode(tensor, 2)
           print(res)
           # (Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
           #   [[2., 3.],
           #    [5., 9.]]), Tensor(shape=[2, 2], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
           #   [[1, 1],
           #    [1, 0]]))
578

579
    """
580
    if in_dygraph_mode():
581
        return _C_ops.mode(x, axis, keepdim)
582 583 584 585 586 587
    else:
        helper = LayerHelper("mode", **locals())
        inputs = {"X": [x]}
        attrs = {}
        attrs['axis'] = axis
        attrs['keepdim'] = keepdim
588

589 590
        values = helper.create_variable_for_type_inference(dtype=x.dtype)
        indices = helper.create_variable_for_type_inference(dtype="int64")
591

592 593 594 595 596 597 598 599
        helper.append_op(
            type="mode",
            inputs=inputs,
            outputs={"Out": [values], "Indices": [indices]},
            attrs=attrs,
        )
        indices.stop_gradient = True
        return values, indices
600 601


R
ronnywang 已提交
602
def where(condition, x=None, y=None, name=None):
603
    r"""
604
    Return a Tensor of elements selected from either :attr:`x` or :attr:`y` according to corresponding elements of :attr:`condition`. Concretely,
R
ronnywang 已提交
605

606
    .. math::
C
Chengmo 已提交
607

608 609 610 611 612
        out_i =
        \begin{cases}
        x_i, & \text{if}  \ condition_i \  \text{is} \ True \\
        y_i, & \text{if}  \ condition_i \  \text{is} \ False \\
        \end{cases}.
C
Chengmo 已提交
613

614
    Notes:
张春乔 已提交
615
        ``numpy.where(condition)`` is identical to ``paddle.nonzero(condition, as_tuple=True)``, please refer to :ref:`api_paddle_nonzero`.
616

617
    Args:
618
        condition (Tensor): The condition to choose x or y. When True (nonzero), yield x, otherwise yield y.
619 620
        x (Tensor|scalar, optional): A Tensor or scalar to choose when the condition is True with data type of float16, float32, float64, int32 or int64. Either both or neither of x and y should be given.
        y (Tensor|scalar, optional): A Tensor or scalar to choose when the condition is False with data type of float16, float32, float64, int32 or int64. Either both or neither of x and y should be given.
621
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
622

623
    Returns:
624
        Tensor: A Tensor with the same shape as :attr:`condition` and same data type as :attr:`x` and :attr:`y`.
625

626
    Examples:
627

628 629
        .. code-block:: python

630
            import paddle
631

632 633
            x = paddle.to_tensor([0.9383, 0.1983, 3.2, 1.2])
            y = paddle.to_tensor([1.0, 1.0, 1.0, 1.0])
634

635 636 637
            out = paddle.where(x>1, x, y)
            print(out)
            #out: [1.0, 1.0, 3.2, 1.2]
638

639 640 641 642 643
            out = paddle.where(x>1)
            print(out)
            #out: (Tensor(shape=[2, 1], dtype=int64, place=CPUPlace, stop_gradient=True,
            #            [[2],
            #             [3]]),)
644
    """
R
ronnywang 已提交
645
    if np.isscalar(x):
646
        x = paddle.full([1], x, np.array([x]).dtype.name)
R
ronnywang 已提交
647 648

    if np.isscalar(y):
649
        y = paddle.full([1], y, np.array([y]).dtype.name)
R
ronnywang 已提交
650

R
ronnywang 已提交
651 652 653 654 655 656
    if x is None and y is None:
        return nonzero(condition, as_tuple=True)

    if x is None or y is None:
        raise ValueError("either both or neither of x and y should be given")

657
    condition_shape = list(condition.shape)
658 659
    x_shape = list(x.shape)
    y_shape = list(y.shape)
660

661
    if x_shape == y_shape and condition_shape == x_shape:
662 663 664 665
        broadcast_condition = condition
        broadcast_x = x
        broadcast_y = y
    else:
Z
zhiboniu 已提交
666 667 668 669 670 671 672 673 674 675 676 677 678
        zeros_like_x = paddle.zeros_like(x)
        zeros_like_y = paddle.zeros_like(y)
        zeros_like_condition = paddle.zeros_like(condition)
        zeros_like_condition = paddle.cast(zeros_like_condition, x.dtype)
        cast_cond = paddle.cast(condition, x.dtype)

        broadcast_zeros = paddle.add(zeros_like_x, zeros_like_y)
        broadcast_zeros = paddle.add(broadcast_zeros, zeros_like_condition)
        broadcast_x = paddle.add(x, broadcast_zeros)
        broadcast_y = paddle.add(y, broadcast_zeros)
        broadcast_condition = paddle.add(cast_cond, broadcast_zeros)
        broadcast_condition = paddle.cast(broadcast_condition, 'bool')

J
Jiabin Yang 已提交
679
    if in_dygraph_mode():
680
        return _C_ops.where(broadcast_condition, broadcast_x, broadcast_y)
681
    else:
682 683
        check_variable_and_dtype(condition, 'condition', ['bool'], 'where')
        check_variable_and_dtype(
684
            x, 'x', ['float16', 'float32', 'float64', 'int32', 'int64'], 'where'
685 686
        )
        check_variable_and_dtype(
687
            y, 'y', ['float16', 'float32', 'float64', 'int32', 'int64'], 'where'
688
        )
689 690
        helper = LayerHelper("where", **locals())
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
691

692 693 694 695 696 697 698 699 700 701 702
        helper.append_op(
            type='where',
            inputs={
                'Condition': broadcast_condition,
                'X': broadcast_x,
                'Y': broadcast_y,
            },
            outputs={'Out': [out]},
        )

        return out
703 704


C
Chengmo 已提交
705 706 707 708
def index_sample(x, index):
    """
    **IndexSample Layer**

709 710
    IndexSample OP returns the element of the specified location of X,
    and the location is specified by Index.
C
Chengmo 已提交
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

    .. code-block:: text


                Given:

                X = [[1, 2, 3, 4, 5],
                     [6, 7, 8, 9, 10]]

                Index = [[0, 1, 3],
                         [0, 2, 4]]

                Then:

                Out = [[1, 2, 4],
                       [6, 8, 10]]

    Args:
729
        x (Tensor): The source input tensor with 2-D shape. Supported data type is
730
            int32, int64, float16, float32, float64.
731
        index (Tensor): The index input tensor with 2-D shape, first dimension should be same with X.
C
Chengmo 已提交
732 733 734
            Data type is int32 or int64.

    Returns:
C
Chengmo 已提交
735
        output (Tensor): The output is a tensor with the same shape as index.
C
Chengmo 已提交
736 737 738 739 740 741

    Examples:

        .. code-block:: python

            import paddle
742 743 744 745 746 747 748 749 750 751 752

            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]], dtype='float32')
            index = paddle.to_tensor([[0, 1, 2],
                                      [1, 2, 3],
                                      [0, 0, 0]], dtype='int32')
            target = paddle.to_tensor([[100, 200, 300, 400],
                                       [500, 600, 700, 800],
                                       [900, 1000, 1100, 1200]], dtype='int32')
            out_z1 = paddle.index_sample(x, index)
N
Noel 已提交
753
            print(out_z1)
754 755 756 757 758 759 760 761
            #[[1. 2. 3.]
            # [6. 7. 8.]
            # [9. 9. 9.]]

            # Use the index of the maximum value by topk op
            # get the value of the element of the corresponding index in other tensors
            top_value, top_index = paddle.topk(x, k=2)
            out_z2 = paddle.index_sample(target, top_index)
N
Noel 已提交
762
            print(top_value)
763 764 765 766
            #[[ 4.  3.]
            # [ 8.  7.]
            # [12. 11.]]

N
Noel 已提交
767
            print(top_index)
768 769 770 771
            #[[3 2]
            # [3 2]
            # [3 2]]

N
Noel 已提交
772
            print(out_z2)
773 774 775
            #[[ 400  300]
            # [ 800  700]
            # [1200 1100]]
C
Chengmo 已提交
776

C
Chengmo 已提交
777
    """
J
Jiabin Yang 已提交
778
    if in_dygraph_mode():
779
        return _C_ops.index_sample(x, index)
J
Jiabin Yang 已提交
780
    else:
781 782 783 784 785 786 787 788 789 790 791 792 793 794
        helper = LayerHelper("index_sample", **locals())
        check_variable_and_dtype(
            x,
            'x',
            ['float16', 'float32', 'float64', 'int32', 'int64'],
            'paddle.tensor.search.index_sample',
        )
        check_variable_and_dtype(
            index,
            'index',
            ['int32', 'int64'],
            'paddle.tensor.search.index_sample',
        )
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
J
Jiabin Yang 已提交
795

796 797 798 799 800 801
        helper.append_op(
            type='index_sample',
            inputs={'X': x, 'Index': index},
            outputs={'Out': out},
        )
        return out
802 803 804 805


def masked_select(x, mask, name=None):
    """
C
Chen Long 已提交
806
    Returns a new 1-D tensor which indexes the input tensor according to the ``mask``
807 808 809
    which is a tensor with data type of bool.

    Args:
810
        x (Tensor): The input Tensor, the data type can be int32, int64, uint16, float16, float32, float64.
811
        mask (Tensor): The Tensor containing the binary mask to index with, it's data type is bool.
812
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
813

814
    Returns:
815
        A 1-D Tensor which is the same data type  as ``x``.
816

817 818 819 820 821
    Examples:

        .. code-block:: python

            import paddle
822 823 824 825 826 827 828

            x = paddle.to_tensor([[1.0, 2.0, 3.0, 4.0],
                                  [5.0, 6.0, 7.0, 8.0],
                                  [9.0, 10.0, 11.0, 12.0]])
            mask = paddle.to_tensor([[True, False, False, False],
                                     [True, True, False, False],
                                     [True, False, False, False]])
829 830 831 832
            out = paddle.masked_select(x, mask)
            #[1.0 5.0 6.0 9.0]
    """

H
hong 已提交
833
    if in_dygraph_mode():
834
        return _C_ops.masked_select(x, mask)
H
hong 已提交
835

836 837 838 839 840
    else:
        helper = LayerHelper("masked_select", **locals())
        check_variable_and_dtype(
            x,
            'x',
841
            ['float16', 'float32', 'float64', 'int32', 'int64', 'uint16'],
842 843 844 845 846 847 848 849 850 851 852 853
            'paddle.tensor.search.mask_select',
        )
        check_variable_and_dtype(
            mask, 'mask', ['bool'], 'paddle.tensor.search.masked_select'
        )
        out = helper.create_variable_for_type_inference(dtype=x.dtype)
        helper.append_op(
            type='masked_select',
            inputs={'X': x, 'Mask': mask},
            outputs={'Y': out},
        )
        return out
W
wawltor 已提交
854 855 856 857


def topk(x, k, axis=None, largest=True, sorted=True, name=None):
    """
858
    Return values and indices of the k largest or smallest at the optional axis.
W
wawltor 已提交
859 860 861 862 863 864 865 866 867 868 869 870
    If the input is a 1-D Tensor, finds the k largest or smallest values and indices.
    If the input is a Tensor with higher rank, this operator computes the top k values and indices along the :attr:`axis`.

    Args:
        x(Tensor): Tensor, an input N-D Tensor with type float32, float64, int32, int64.
        k(int, Tensor): The number of top elements to look for along the axis.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. Default is -1.
        largest(bool, optional) : largest is a flag, if set to true,
            algorithm will sort by descending order, otherwise sort by
            ascending order. Default is True.
871
        sorted(bool, optional): controls whether to return the elements in sorted order, default value is True. In gpu device, it always return the sorted value.
W
wawltor 已提交
872 873 874 875 876 877 878 879
        name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.

    Examples:

        .. code-block:: python
880

881
            import paddle
W
wawltor 已提交
882

883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
            data_1 = paddle.to_tensor([1, 4, 5, 7])
            value_1, indices_1 = paddle.topk(data_1, k=1)
            print(value_1) # [7]
            print(indices_1) # [3]

            data_2 = paddle.to_tensor([[1, 4, 5, 7], [2, 6, 2, 5]])
            value_2, indices_2 = paddle.topk(data_2, k=1)
            print(value_2) # [[7], [6]]
            print(indices_2) # [[3], [1]]

            value_3, indices_3 = paddle.topk(data_2, k=1, axis=-1)
            print(value_3) # [[7], [6]]
            print(indices_3) # [[3], [1]]

            value_4, indices_4 = paddle.topk(data_2, k=1, axis=0)
            print(value_4) # [[2, 6, 5, 7]]
            print(indices_4) # [[1, 1, 0, 0]]
W
wawltor 已提交
900 901 902


    """
H
hong 已提交
903

H
hong 已提交
904
    if in_dygraph_mode():
905
        if axis is None:
H
hong 已提交
906
            axis = -1
907
        out, indices = _C_ops.topk(x, k, axis, largest, sorted)
H
hong 已提交
908
        return out, indices
W
wawltor 已提交
909
    else:
910 911 912 913 914 915 916 917 918 919 920
        helper = LayerHelper("top_k_v2", **locals())
        inputs = {"X": [x]}
        attrs = {}
        if isinstance(k, Variable):
            inputs['K'] = [k]
        else:
            attrs = {'k': k}
        attrs['largest'] = largest
        attrs['sorted'] = sorted
        if axis is not None:
            attrs['axis'] = axis
W
wawltor 已提交
921

922 923
        values = helper.create_variable_for_type_inference(dtype=x.dtype)
        indices = helper.create_variable_for_type_inference(dtype="int64")
W
wawltor 已提交
924

925 926 927 928 929 930 931 932
        helper.append_op(
            type="top_k_v2",
            inputs=inputs,
            outputs={"Out": [values], "Indices": [indices]},
            attrs=attrs,
        )
        indices.stop_gradient = True
        return values, indices
Y
Yanxing Shi 已提交
933 934


935 936 937 938 939 940
def bucketize(x, sorted_sequence, out_int32=False, right=False, name=None):
    """
    This API is used to find the index of the corresponding 1D tensor `sorted_sequence` in the innermost dimension based on the given `x`.

    Args:
        x(Tensor): An input N-D tensor value with type int32, int64, float32, float64.
941
        sorted_sequence(Tensor): An input 1-D tensor with type int32, int64, float32, float64. The value of the tensor monotonically increases in the innermost dimension.
942 943
        out_int32(bool, optional): Data type of the output tensor which can be int32, int64. The default value is False, and it indicates that the output data type is int64.
        right(bool, optional): Find the upper or lower bounds of the sorted_sequence range in the innermost dimension based on the given `x`. If the value of the sorted_sequence is nan or inf, return the size of the innermost dimension.
944
                               The default value is False and it shows the lower bounds.
945
        name(str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`.
946

947
    Returns:
948 949
        Tensor(the same sizes of the `x`), return the tensor of int32 if set :attr:`out_int32` is True, otherwise return the tensor of int64.

950 951 952
    Examples:

        .. code-block:: python
953

954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
            import paddle

            sorted_sequence = paddle.to_tensor([2, 4, 8, 16], dtype='int32')
            x = paddle.to_tensor([[0, 8, 4, 16], [-1, 2, 8, 4]], dtype='int32')
            out1 = paddle.bucketize(x, sorted_sequence)
            print(out1)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 2, 1, 3],
            #         [0, 0, 2, 1]])
            out2 = paddle.bucketize(x, sorted_sequence, right=True)
            print(out2)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 3, 2, 4],
            #         [0, 1, 3, 2]])
            out3 = x.bucketize(sorted_sequence)
            print(out3)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 2, 1, 3],
            #         [0, 0, 2, 1]])
            out4 = x.bucketize(sorted_sequence, right=True)
            print(out4)
            # Tensor(shape=[2, 4], dtype=int64, place=CPUPlace, stop_gradient=True,
            #        [[0, 3, 2, 4],
            #         [0, 1, 3, 2]])
978

979
    """
980 981 982 983 984 985
    check_variable_and_dtype(
        sorted_sequence,
        'SortedSequence',
        ['float32', 'float64', 'int32', 'int64'],
        'paddle.searchsorted',
    )
986 987 988 989 990 991 992
    if sorted_sequence.dim() != 1:
        raise ValueError(
            f"sorted_sequence tensor must be 1 dimension, but got dim {sorted_sequence.dim()}"
        )
    return searchsorted(sorted_sequence, x, out_int32, right, name)


993 994 995
def searchsorted(
    sorted_sequence, values, out_int32=False, right=False, name=None
):
Y
Yanxing Shi 已提交
996
    """
997
    Find the index of the corresponding `sorted_sequence` in the innermost dimension based on the given `values`.
Y
Yanxing Shi 已提交
998 999

    Args:
1000
        sorted_sequence(Tensor): An input N-D or 1-D tensor with type int32, int64, float32, float64. The value of the tensor monotonically increases in the innermost dimension.
Y
Yanxing Shi 已提交
1001 1002 1003
        values(Tensor): An input N-D tensor value with type int32, int64, float32, float64.
        out_int32(bool, optional): Data type of the output tensor which can be int32, int64. The default value is False, and it indicates that the output data type is int64.
        right(bool, optional): Find the upper or lower bounds of the sorted_sequence range in the innermost dimension based on the given `values`. If the value of the sorted_sequence is nan or inf, return the size of the innermost dimension.
1004
                               The default value is False and it shows the lower bounds.
1005
        name(str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
1006

Y
Yanxing Shi 已提交
1007
    Returns:
1008 1009
        Tensor(the same sizes of the `values`), return the tensor of int32 if set :attr:`out_int32` is True, otherwise return the tensor of int64.

Y
Yanxing Shi 已提交
1010 1011 1012
    Examples:

        .. code-block:: python
1013

Y
Yanxing Shi 已提交
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
            import paddle

            sorted_sequence = paddle.to_tensor([[1, 3, 5, 7, 9, 11],
                                                [2, 4, 6, 8, 10, 12]], dtype='int32')
            values = paddle.to_tensor([[3, 6, 9, 10], [3, 6, 9, 10]], dtype='int32')
            out1 = paddle.searchsorted(sorted_sequence, values)
            print(out1)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[1, 3, 4, 5],
            #         [1, 2, 4, 4]])
            out2 = paddle.searchsorted(sorted_sequence, values, right=True)
            print(out2)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[2, 3, 5, 5],
            #         [1, 3, 4, 5]])
            sorted_sequence_1d = paddle.to_tensor([1, 3, 5, 7, 9, 11, 13])
1030
            out3 = paddle.searchsorted(sorted_sequence_1d, values)
Y
Yanxing Shi 已提交
1031 1032 1033 1034
            print(out3)
            # Tensor(shape=[2, 4], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #        [[1, 3, 4, 5],
            #         [1, 3, 4, 5]])
1035

Y
Yanxing Shi 已提交
1036
    """
F
From00 已提交
1037
    if in_dygraph_mode():
1038
        return _C_ops.searchsorted(sorted_sequence, values, out_int32, right)
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
    else:
        check_variable_and_dtype(
            sorted_sequence,
            'SortedSequence',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.searchsorted',
        )
        check_variable_and_dtype(
            values,
            'Values',
            ['float32', 'float64', 'int32', 'int64'],
            'paddle.searchsorted',
1051
        )
Y
Yanxing Shi 已提交
1052

1053 1054 1055 1056 1057 1058 1059 1060 1061
        helper = LayerHelper('searchsorted', **locals())
        out_type = 'int32' if out_int32 else 'int64'
        out = helper.create_variable_for_type_inference(dtype=out_type)
        helper.append_op(
            type='searchsorted',
            inputs={'SortedSequence': sorted_sequence, "Values": values},
            outputs={'Out': out},
            attrs={"out_int32": out_int32, "right": right},
        )
Y
Yanxing Shi 已提交
1062

1063
        return out
1064 1065 1066 1067


def kthvalue(x, k, axis=None, keepdim=False, name=None):
    """
1068
    Find values and indices of the k-th smallest at the axis.
1069 1070 1071 1072 1073 1074 1075 1076

    Args:
        x(Tensor): A N-D Tensor with type float32, float64, int32, int64.
        k(int): The k for the k-th smallest number to look for along the axis.
        axis(int, optional): Axis to compute indices along. The effective range
            is [-R, R), where R is x.ndim. when axis < 0, it works the same way
            as axis + R. The default is None. And if the axis is None, it will computed as -1 by default.
        keepdim(bool, optional): Whether to keep the given axis in output. If it is True, the dimensions will be same as input x and with size one in the axis. Otherwise the output dimentions is one fewer than x since the axis is squeezed. Default is False.
1077
        name (str, optional): For details, please refer to :ref:`api_guide_Name`. Generally, no setting is required. Default: None.
1078 1079 1080

    Returns:
        tuple(Tensor), return the values and indices. The value data type is the same as the input `x`. The indices data type is int64.
1081

1082 1083 1084
    Examples:

        .. code-block:: python
1085

1086
            import paddle
1087

1088 1089 1090 1091 1092 1093 1094 1095
            x = paddle.randn((2,3,2))
            # Tensor(shape=[2, 3, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
            #       [[[ 0.22954939, -0.01296274],
            #         [ 1.17135799, -0.34493217],
            #         [-0.19550551, -0.17573971]],
            #
            #        [[ 0.15104349, -0.93965352],
            #         [ 0.14745511,  0.98209465],
1096 1097
            #         [ 0.10732264, -0.55859774]]])
            y = paddle.kthvalue(x, 2, 1)
1098 1099 1100 1101 1102 1103
            # (Tensor(shape=[2, 2], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
            # [[ 0.22954939, -0.17573971],
            #  [ 0.14745511, -0.55859774]]), Tensor(shape=[2, 2], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
            #  [[0, 2],
            #  [1, 2]]))
    """
1104
    if in_dygraph_mode():
1105
        if axis is not None:
1106
            return _C_ops.kthvalue(x, k, axis, keepdim)
1107
        else:
1108
            return _C_ops.kthvalue(x, k, -1, keepdim)
1109 1110 1111 1112 1113 1114 1115 1116 1117

    helper = LayerHelper("kthvalue", **locals())
    inputs = {"X": [x]}
    attrs = {'k': k}
    if axis is not None:
        attrs['axis'] = axis
    values = helper.create_variable_for_type_inference(dtype=x.dtype)
    indices = helper.create_variable_for_type_inference(dtype="int64")

1118 1119 1120 1121 1122 1123
    helper.append_op(
        type="kthvalue",
        inputs=inputs,
        outputs={"Out": [values], "Indices": [indices]},
        attrs=attrs,
    )
1124 1125
    indices.stop_gradient = True
    return values, indices