Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev logical_and/or modules #5636

Merged
merged 9 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/oneflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ oneflow
gather,
gather_nd,
in_top_k,
logical_and,
logical_or,
load,
masked_fill,
matmul,
Expand Down
2 changes: 2 additions & 0 deletions docs/source/tensor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ OneFlow Tensor Class
le,
log,
log1p,
logical_and,
logical_or,
long,
lt,
masked_fill,
Expand Down
8 changes: 8 additions & 0 deletions oneflow/core/functional/functional_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@
signature: "Tensor BroadcastGreaterEqual(Tensor x, Tensor y)"
bind_python: True

- name: "broadcast_logical_and"
signature: "Tensor BroadcastLogicalAnd(Tensor x, Tensor y)"
bind_python: True

- name: "broadcast_logical_or"
signature: "Tensor BroadcastLogicalOr(Tensor x, Tensor y)"
bind_python: True

- name: "broadcast_less"
signature: "Tensor BroadcastLess(Tensor x, Tensor y)"
bind_python: True
Expand Down
18 changes: 18 additions & 0 deletions oneflow/core/functional/impl/binary_functor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,22 @@ class BroadcastGreaterEqualFunctor : public BinaryFunctor {
}
};

class BroadcastLogicalAndFunctor : public BinaryFunctor {
public:
BroadcastLogicalAndFunctor() {
op_ = CHECK_JUST(
one::OpBuilder("broadcast_logical_and").Input("x").Input("y").Output("z").Build());
}
};

class BroadcastLogicalOrFunctor : public BinaryFunctor {
public:
BroadcastLogicalOrFunctor() {
op_ = CHECK_JUST(
one::OpBuilder("broadcast_logical_or").Input("x").Input("y").Output("z").Build());
}
};

class BroadcastLessFunctor : public BinaryFunctor {
public:
BroadcastLessFunctor() {
Expand Down Expand Up @@ -232,6 +248,8 @@ ONEFLOW_FUNCTION_LIBRARY(m) {
m.add_functor<impl::BroadcastNotEqualFunctor>("BroadcastNotEqual");
m.add_functor<impl::BroadcastGreaterFunctor>("BroadcastGreater");
m.add_functor<impl::BroadcastGreaterEqualFunctor>("BroadcastGreaterEqual");
m.add_functor<impl::BroadcastLogicalAndFunctor>("BroadcastLogicalAnd");
m.add_functor<impl::BroadcastLogicalOrFunctor>("BroadcastLogicalOr");
m.add_functor<impl::BroadcastLessFunctor>("BroadcastLess");
m.add_functor<impl::BroadcastLessEqualFunctor>("BroadcastLessEqual");
m.add_functor<impl::ScalarAddByTensorFunctor>("ScalarAddByTensor");
Expand Down
12 changes: 10 additions & 2 deletions oneflow/core/ndarray/binary_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ limitations under the License.
namespace oneflow {

#define ARITHMETIC_BINARY_FUNC_NAME_SEQ (Add)(Sub)(Mul)(Div)(Min)(Max)(FloorMod)(FMod)
#define LOGICAL_BINARY_FUNC_NAME_SEQ (EQ)(NE)(GT)(GE)(LT)(LE)(AND)
#define LOGICAL_BINARY_FUNC_NAME_SEQ (EQ)(NE)(GT)(GE)(LT)(LE)(AND)(OR)

#define PREPEND_PREFIX_BINARY_FUNC(name) OF_PP_CAT(BinaryFunc, name)
#define ARITHMETIC_BINARY_FUNC_SEQ \
Expand Down Expand Up @@ -172,6 +172,12 @@ template<typename T>
struct BinaryFuncAND final {
static OF_DEVICE_FUNC const int8_t Invoke(const T x, const T y) { return x && y; }
};

template<typename T>
struct BinaryFuncOR final {
static OF_DEVICE_FUNC const int8_t Invoke(const T x, const T y) { return x || y; }
};

template<typename T>
struct BinaryFuncAll final {
static OF_DEVICE_FUNC const int8_t Invoke(const T x, const T y) {
Expand All @@ -182,7 +188,9 @@ SPECIALIZE_CONST_TYPE_BINARY_FUNC(BinaryFuncAND);

template<typename T>
struct BinaryFuncAny final {
static OF_DEVICE_FUNC const int8_t Invoke(const T x, const T y) { return x || y; }
static OF_DEVICE_FUNC const int8_t Invoke(const T x, const T y) {
return BinaryFuncOR<T>::Invoke(x, y);
}
};
SPECIALIZE_CONST_TYPE_BINARY_FUNC(BinaryFuncAny);

Expand Down
3 changes: 2 additions & 1 deletion oneflow/user/ops/math_binary_broadcast_seq.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ namespace oneflow {
OF_PP_MAKE_TUPLE_SEQ("broadcast_greater_equal", GE) \
OF_PP_MAKE_TUPLE_SEQ("broadcast_less", LT) \
OF_PP_MAKE_TUPLE_SEQ("broadcast_less_equal", LE) \
OF_PP_MAKE_TUPLE_SEQ("broadcast_logical_and", AND)
OF_PP_MAKE_TUPLE_SEQ("broadcast_logical_and", AND) \
OF_PP_MAKE_TUPLE_SEQ("broadcast_logical_or", OR)

} // namespace oneflow

Expand Down
4 changes: 4 additions & 0 deletions python/oneflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ def Sync():
import oneflow.nn.modules.floor
import oneflow.nn.modules.greater
import oneflow.nn.modules.greater_equal
import oneflow.nn.modules.logical_and
import oneflow.nn.modules.logical_or
import oneflow.nn.modules.in_top_k
import oneflow.nn.modules.masked_select
import oneflow.nn.modules.math_ops
Expand Down Expand Up @@ -258,6 +260,8 @@ def Sync():
from oneflow.nn.modules.gather_nd import gather_nd_op as gather_nd
from oneflow.nn.modules.greater import greater_op as gt
from oneflow.nn.modules.greater_equal import greater_equal_op as ge
from oneflow.nn.modules.logical_and import logical_and_op as logical_and
from oneflow.nn.modules.logical_or import logical_or_op as logical_or
from oneflow.nn.modules.in_top_k import in_top_k_op as in_top_k
from oneflow.nn.modules.less import less_op as lt
from oneflow.nn.modules.less_equal import less_equal_op as le
Expand Down
2 changes: 2 additions & 0 deletions python/oneflow/compatible/single_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ def custom_exit(returncode):
import oneflow.compatible.single_client.nn.modules.floor
import oneflow.compatible.single_client.nn.modules.greater
import oneflow.compatible.single_client.nn.modules.greater_equal
import oneflow.compatible.single_client.nn.modules.logical_and
import oneflow.compatible.single_client.nn.modules.logical_or
import oneflow.compatible.single_client.nn.modules.masked_select
import oneflow.compatible.single_client.nn.modules.math_ops
import oneflow.compatible.single_client.nn.modules.norm
Expand Down
77 changes: 77 additions & 0 deletions python/oneflow/compatible/single_client/nn/modules/logical_and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Copyright 2020 The OneFlow Authors. All rights reserved.

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.
"""
from oneflow.compatible import single_client as flow
from oneflow.compatible.single_client.framework.tensor import register_tensor_op
from oneflow.compatible.single_client.nn.module import Module


class LogicalAnd(Module):
def __init__(self) -> None:
super().__init__()

def forward(self, input, other):
if other.dtype != input.dtype:
other = flow.cast(other, input.dtype)
return flow.F.broadcast_logical_and(input, other)


def logical_and_op(input, other):
"""
Computes the element-wise logical AND of the given input tensors.
Zeros are treated as False and nonzeros are treated as True.

Args:
input (oneflow.Tensor): The input Tensor
other (oneflow.Tensor): The Tensor to compute AND with

Returns:
oneflow.Tensor: The output Tensor

For example:

.. code-block:: python

>>> import oneflow.compatible.single_client.experimental as flow
>>> import numpy as np
>>> flow.enable_eager_execution()

>>> input1 = flow.Tensor(np.array([1, 0, 1]).astype(np.float32), dtype=flow.float32)
>>> input2 = flow.Tensor(np.array([1, 1, 0]).astype(np.float32), dtype=flow.float32)

>>> out = flow.logical_and(input1, input2)
>>> out
tensor([1, 0, 0], dtype=oneflow.int8)

"""
return LogicalAnd()(input, other)


@register_tensor_op("logical_and")
def logical_and_op_tensor(input, other):
"""

logical_and() -> Tensor

See :func:`oneflow.logical_and`

"""
return LogicalAnd()(input, other)


if __name__ == "__main__":
import doctest

doctest.testmod(raise_on_error=True)
77 changes: 77 additions & 0 deletions python/oneflow/compatible/single_client/nn/modules/logical_or.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Copyright 2020 The OneFlow Authors. All rights reserved.

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.
"""
from oneflow.compatible import single_client as flow
from oneflow.compatible.single_client.framework.tensor import register_tensor_op
from oneflow.compatible.single_client.nn.module import Module


class LogicalOr(Module):
def __init__(self) -> None:
super().__init__()

def forward(self, input, other):
if other.dtype != input.dtype:
other = flow.cast(other, input.dtype)
return flow.F.broadcast_logical_or(input, other)


def logical_or_op(input, other):
"""
Computes the element-wise logical OR of the given input tensors.
Zeros are treated as False and nonzeros are treated as True.

Args:
input (oneflow.Tensor): The input Tensor
other (oneflow.Tensor): The Tensor to compute OR with

Returns:
oneflow.Tensor: The output Tensor

For example:

.. code-block:: python

>>> import oneflow.compatible.single_client.experimental as flow
>>> import numpy as np
>>> flow.enable_eager_execution()

>>> input1 = flow.Tensor(np.array([1, 0, 1]).astype(np.float32), dtype=flow.float32)
>>> input2 = flow.Tensor(np.array([1, 0, 0]).astype(np.float32), dtype=flow.float32)

>>> out = flow.logical_or(input1, input2)
>>> out
tensor([1, 0, 1], dtype=oneflow.int8)

"""
return LogicalOr()(input, other)


@register_tensor_op("logical_or")
def logical_or_op_tensor(input, other):
"""

logical_or() -> Tensor

See :func:`oneflow.logical_or`

"""
return LogicalOr()(input, other)


if __name__ == "__main__":
import doctest

doctest.testmod(raise_on_error=True)
76 changes: 76 additions & 0 deletions python/oneflow/nn/modules/logical_and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Copyright 2020 The OneFlow Authors. All rights reserved.

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.
"""
import oneflow as flow
from oneflow.framework.tensor import register_tensor_op
from oneflow.nn.module import Module


class LogicalAnd(Module):
def __init__(self) -> None:
super().__init__()

def forward(self, input, other):
if other.dtype != input.dtype:
other = flow.cast(other, input.dtype)
return flow.F.broadcast_logical_and(input, other)


def logical_and_op(input, other):
"""
Computes the element-wise logical AND of the given input tensors.
Zeros are treated as False and nonzeros are treated as True.

Args:
input (oneflow.Tensor): The input Tensor
other (oneflow.Tensor): The Tensor to compute AND with

Returns:
oneflow.Tensor: The output Tensor

For example:

.. code-block:: python

>>> import numpy as np
>>> import oneflow as flow

>>> input1 = flow.Tensor(np.array([1, 0, 1]).astype(np.float32), dtype=flow.float32)
>>> input2 = flow.Tensor(np.array([1, 1, 0]).astype(np.float32), dtype=flow.float32)

>>> out = flow.logical_and(input1, input2)
>>> out
tensor([1, 0, 0], dtype=oneflow.int8)

"""
return LogicalAnd()(input, other)


@register_tensor_op("logical_and")
def logical_and_op_tensor(input, other):
"""

logical_and() -> Tensor

See :func:`oneflow.logical_and`

"""
return LogicalAnd()(input, other)


if __name__ == "__main__":
import doctest

doctest.testmod(raise_on_error=True)
Loading