From 3a3f55b7b3fbd66bd85d35b2bce9301b3dbd1fef Mon Sep 17 00:00:00 2001 From: hub-bla Date: Fri, 30 Aug 2024 20:02:53 +0200 Subject: [PATCH 1/2] Support complex tensors for Sub operation --- src/frontends/tensorflow/src/op_table.cpp | 2 +- .../include/common_op_table.hpp | 1 + .../tensorflow_common/src/op/binary_op.cpp | 27 ++++++++ .../tensorflow_tests/test_tf_Sub.py | 67 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/frontends/tensorflow/src/op_table.cpp b/src/frontends/tensorflow/src/op_table.cpp index aa188d81808614..e8c3ee40b62e3e 100644 --- a/src/frontends/tensorflow/src/op_table.cpp +++ b/src/frontends/tensorflow/src/op_table.cpp @@ -195,7 +195,6 @@ const std::map get_supported_ops() { {"Pow", CreatorFunction(translate_binary_op)}, {"RealDiv", CreatorFunction(translate_binary_op)}, {"SquaredDifference", CreatorFunction(translate_binary_op)}, - {"Sub", CreatorFunction(translate_binary_op)}, // note: ReduceOp translator declaration for each op must to be added in reduce.cpp file {"Any", CreatorFunction(translate_direct_reduce_op)}, @@ -396,6 +395,7 @@ const std::map get_supported_ops() { {"StatelessIf", CreatorFunction(translate_if_op)}, {"StatelessWhile", CreatorFunction(translate_while_op)}, {"StridedSlice", CreatorFunction(translate_strided_slice_op)}, + {"Sub", CreatorFunction(translate_sub_op)}, {"Switch", CreatorFunction(translate_switch_op)}, {"TensorArrayCloseV3", CreatorFunction(translate_tensor_array_close_v3_op)}, {"TensorArrayConcatV3", CreatorFunction(translate_tensor_array_concat_v3_op)}, diff --git a/src/frontends/tensorflow_common/include/common_op_table.hpp b/src/frontends/tensorflow_common/include/common_op_table.hpp index e01d2dcc6f789a..c262a826e67727 100644 --- a/src/frontends/tensorflow_common/include/common_op_table.hpp +++ b/src/frontends/tensorflow_common/include/common_op_table.hpp @@ -162,6 +162,7 @@ OP_CONVERTER(translate_split_v_op); OP_CONVERTER(translate_square_op); OP_CONVERTER(translate_squeeze_op); OP_CONVERTER(translate_strided_slice_op); +OP_CONVERTER(translate_sub_op); OP_CONVERTER(translate_sqrt_op); OP_CONVERTER(translate_empty_tensor_list_op); OP_CONVERTER(translate_tensor_list_from_tensor_op); diff --git a/src/frontends/tensorflow_common/src/op/binary_op.cpp b/src/frontends/tensorflow_common/src/op/binary_op.cpp index c3e390e9435b3a..c420ec8c7b0f8f 100644 --- a/src/frontends/tensorflow_common/src/op/binary_op.cpp +++ b/src/frontends/tensorflow_common/src/op/binary_op.cpp @@ -171,6 +171,33 @@ OutputVector translate_addv2_op(const NodeContext& node) { return {result}; } +OutputVector translate_sub_op(const NodeContext& node) { + default_op_checks(node, 2, {"Sub"}, true); + auto lhs = node.get_input(0); + auto rhs = node.get_input(1); + + auto complex_type_mark_lhs = as_type_ptr(lhs.get_node_shared_ptr()); + auto complex_type_mark_rhs = as_type_ptr(rhs.get_node_shared_ptr()); + auto complex_type_inputs = (complex_type_mark_lhs && complex_type_mark_rhs); + + if (complex_type_inputs) { + lhs = complex_type_mark_lhs->input_value(0); + rhs = complex_type_mark_rhs->input_value(0); + } + + // performing an actual operation + auto result = make_shared(lhs, rhs); + + if (complex_type_inputs) { + auto complex_result = make_shared(result, complex_type_mark_lhs->get_complex_part_type()); + set_node_name(node.get_name(), result); + + return {complex_result}; + } + set_node_name(node.get_name(), result); + return {result}; +} + template OutputVector translate_binary_op(const NodeContext& node); template OutputVector translate_binary_op(const NodeContext& node); template OutputVector translate_binary_op(const NodeContext& node); diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py index 9c127d1a3ccebe..c8ad4d512fe8ef 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py @@ -216,3 +216,70 @@ def test_sub_placeholder_const_broadcast_5D(self, params, ie_device, precision, use_legacy_frontend=use_legacy_frontend), ie_device, precision, ir_version, temp_dir=temp_dir, use_legacy_frontend=use_legacy_frontend) + + +class TestComplexSub(CommonTFLayerTest): + def _prepare_input(self, inputs_info): + rng = np.random.default_rng(84821) + + assert 'param_real_x:0' in inputs_info + assert 'param_imag_x:0' in inputs_info + + assert 'param_real_y:0' in inputs_info + assert 'param_imag_y:0' in inputs_info + + param_real_shape_x = inputs_info['param_real_x:0'] + param_imag_shape_x = inputs_info['param_imag_x:0'] + + param_real_shape_y = inputs_info['param_real_y:0'] + param_imag_shape_y = inputs_info['param_imag_y:0'] + + inputs_data = {} + inputs_data['param_real_x:0'] = rng.uniform(-10.0, 10.0, param_real_shape_x).astype(np.float32) + inputs_data['param_imag_x:0'] = rng.uniform(-10.0, 10.0, param_imag_shape_x).astype(np.float32) + + inputs_data['param_real_y:0'] = rng.uniform(-10.0, 10.0, param_real_shape_y).astype(np.float32) + inputs_data['param_imag_y:0'] = rng.uniform(-10.0, 10.0, param_imag_shape_y).astype(np.float32) + + return inputs_data + + def create_complex_sub_net(self, x_shape, y_shape, ir_version, use_legacy_frontend): + import tensorflow as tf + + tf.compat.v1.reset_default_graph() + with tf.compat.v1.Session() as sess: + param_real_x = tf.compat.v1.placeholder(np.float32, x_shape, 'param_real_x') + param_imag_x = tf.compat.v1.placeholder(np.float32, x_shape, 'param_imag_x') + + param_real_y = tf.compat.v1.placeholder(np.float32, y_shape, 'param_real_y') + param_imag_y = tf.compat.v1.placeholder(np.float32, y_shape, 'param_imag_y') + + x = tf.raw_ops.Complex(real=param_real_x, imag=param_imag_x) + y = tf.raw_ops.Complex(real=param_real_y, imag=param_imag_y) + + result = tf.subtract(x, y, name="Operation") + + tf.raw_ops.Real(input=result) + tf.raw_ops.Imag(input=result) + + tf.compat.v1.global_variables_initializer() + tf_net = sess.graph_def + + ref_net = None + + return tf_net, ref_net + + @pytest.mark.parametrize('x_shape, y_shape', [ + [[5, 5], [5]], + [[4, 10], [4, 1]], + [[1, 3, 50, 224], [1]], + [[10, 10, 10], [10, 10, 10]], + ]) + @pytest.mark.precommit + @pytest.mark.nightly + def test_complex_sub(self, x_shape, y_shape, + ie_device, precision, ir_version, temp_dir, use_legacy_frontend): + self._test(*self.create_complex_sub_net(x_shape, y_shape, ir_version=ir_version, + use_legacy_frontend=use_legacy_frontend), + ie_device, precision, ir_version, temp_dir=temp_dir, + use_legacy_frontend=use_legacy_frontend) From 22e2a3fc72ac99b352714e66a6c4067dabda4a83 Mon Sep 17 00:00:00 2001 From: hub-bla Date: Sun, 1 Sep 2024 13:00:14 +0200 Subject: [PATCH 2/2] change to tf.raw_ops.Sub and remove unused Sub include --- src/frontends/tensorflow/src/op_table.cpp | 1 - tests/layer_tests/tensorflow_tests/test_tf_Sub.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/frontends/tensorflow/src/op_table.cpp b/src/frontends/tensorflow/src/op_table.cpp index e8c3ee40b62e3e..db9cf02cedfaf9 100644 --- a/src/frontends/tensorflow/src/op_table.cpp +++ b/src/frontends/tensorflow/src/op_table.cpp @@ -64,7 +64,6 @@ #include "openvino/op/softplus.hpp" #include "openvino/op/softsign.hpp" #include "openvino/op/squared_difference.hpp" -#include "openvino/op/subtract.hpp" #include "openvino/op/swish.hpp" #include "openvino/op/tan.hpp" #include "openvino/op/tanh.hpp" diff --git a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py index c8ad4d512fe8ef..211e5f979d52a4 100644 --- a/tests/layer_tests/tensorflow_tests/test_tf_Sub.py +++ b/tests/layer_tests/tensorflow_tests/test_tf_Sub.py @@ -257,7 +257,7 @@ def create_complex_sub_net(self, x_shape, y_shape, ir_version, use_legacy_fronte x = tf.raw_ops.Complex(real=param_real_x, imag=param_imag_x) y = tf.raw_ops.Complex(real=param_real_y, imag=param_imag_y) - result = tf.subtract(x, y, name="Operation") + result = tf.raw_ops.Sub(x=x, y=y, name='Sub') tf.raw_ops.Real(input=result) tf.raw_ops.Imag(input=result)