diff --git a/src/core/src/op/broadcast.cpp b/src/core/src/op/broadcast.cpp index 0a6fbd96a20..9a8d5a6fdff 100644 --- a/src/core/src/op/broadcast.cpp +++ b/src/core/src/op/broadcast.cpp @@ -68,17 +68,16 @@ std::pair op::v3::Broadcast::get_broadcast_axes() const { namespace { ov::PartialShape get_result_shape_bidirectional(const Node* this_ptr, - const ov::PartialShape& arg_shape, - ov::Shape& target_shape) { - if (arg_shape.rank().is_dynamic()) { + ov::PartialShape arg_shape, + ov::PartialShape target_shape) { + if (arg_shape.rank().is_dynamic() || target_shape.rank().is_dynamic()) { return ov::PartialShape::dynamic(); } - auto arg_shape_vec = static_cast>(arg_shape); ov::PartialShape result_shape; // Add left padding to shorter target or argument shape - const auto target_padded_rank = std::max(arg_shape_vec.size(), target_shape.size()); - while (arg_shape_vec.size() < target_padded_rank) { - arg_shape_vec.insert(arg_shape_vec.begin(), 1); + const auto target_padded_rank = std::max(arg_shape.size(), target_shape.size()); + while (arg_shape.size() < target_padded_rank) { + arg_shape.insert(arg_shape.begin(), 1); } while (target_shape.size() < target_padded_rank) { target_shape.insert(target_shape.begin(), 1); @@ -86,23 +85,30 @@ ov::PartialShape get_result_shape_bidirectional(const Node* this_ptr, result_shape = target_shape; for (size_t i = 0; i < target_shape.size(); ++i) { - if (arg_shape_vec[i].is_dynamic()) { - if (target_shape[i] == 1) { - result_shape[i] = Dimension::dynamic(); + const auto& arg_dim = arg_shape[i]; + const auto& target_dim = target_shape[i]; + + if (arg_dim.is_dynamic() || target_dim.is_dynamic()) { + if (target_dim == 1 || (arg_dim.is_static() && arg_dim != 1)) { + result_shape[i] = arg_dim; + } else if (arg_dim == 1 || (target_dim.is_static() && target_dim != 1)) { + result_shape[i] = target_dim; } else { - result_shape[i] = target_shape[i]; + result_shape[i] = Dimension(std::min(arg_dim.get_min_length(), target_dim.get_min_length()), + std::max(arg_dim.get_max_length(), target_dim.get_max_length())); } continue; } - const size_t arg_shape_dim = arg_shape_vec[i].get_length(); + + const auto& arg_shape_dim = arg_shape[i].get_length(); + const auto& target_shape_dim = target_shape[i].get_length(); NODE_VALIDATION_CHECK(this_ptr, - arg_shape_dim == 1 || target_shape[i] == 1 || arg_shape_dim == target_shape[i], + arg_shape_dim == 1 || target_shape[i] == 1 || arg_shape_dim == target_shape_dim, "Broadcast incorrect target shape. Expecting either 1 or ", arg_shape_dim, ". Got ", target_shape[i]); - - result_shape[i] = std::max(arg_shape_dim, target_shape[i]); + result_shape[i] = std::max(arg_shape_dim, target_shape_dim); } return result_shape; } @@ -112,7 +118,8 @@ bool op::v3::Broadcast::broadcast_evaluate(const HostTensorVector& outputs, cons if (get_broadcast_spec().m_type == op::BroadcastType::BIDIRECTIONAL) { auto arg_shape = inputs[0]->get_shape(); ov::Shape target_shape = op::util::BroadcastBase::get_target_shape(inputs[1]); - ov::PartialShape result_shape = get_result_shape_bidirectional(this, ov::PartialShape{arg_shape}, target_shape); + ov::PartialShape result_shape = + get_result_shape_bidirectional(this, ov::PartialShape{arg_shape}, ov::PartialShape{target_shape}); auto pair_broadcast_axes = get_broadcast_axes_bidirectional(arg_shape, result_shape.to_shape()); return op::util::BroadcastBase::evaluate_broadcast(inputs[0], outputs[0], @@ -141,9 +148,8 @@ void op::v3::Broadcast::validate_and_infer_types() { if (get_input_partial_shape(0).rank().is_static() && get_input_partial_shape(1).is_static()) { auto arg_shape = get_input_partial_shape(0); - const auto shape_constant = get_constant_from_source(input_value(1)); - if (shape_constant) { - auto target_shape = shape_constant->get_shape_val(); + PartialShape target_shape; + if (evaluate_as_partial_shape(input_value(1), target_shape)) { result_shape = get_result_shape_bidirectional(this, arg_shape, target_shape); } } diff --git a/src/core/src/validation_util.cpp b/src/core/src/validation_util.cpp index cb62ec2fc44..300d9f6842b 100644 --- a/src/core/src/validation_util.cpp +++ b/src/core/src/validation_util.cpp @@ -1287,13 +1287,20 @@ bool ov::evaluate_as_partial_shape(const Output& output, PartialShape& psh std::tie(lb, ub) = evaluate_both_bounds(output); bool shape_defined = false; if (lb && ub) { - const auto lower_bound = std::make_shared(lb)->cast_vector(); - const auto upper_bound = std::make_shared(ub)->cast_vector(); + auto lower_bound = std::make_shared(lb)->cast_vector(); + auto upper_bound = std::make_shared(ub)->cast_vector(); NGRAPH_CHECK(lower_bound.size() == upper_bound.size()); vector resulting_pshape(lower_bound.size()); for (size_t i = 0; i < lower_bound.size(); ++i) { - NGRAPH_CHECK(lower_bound[i] >= 0 && upper_bound[i] >= 0); - resulting_pshape[i] = {lower_bound[i], upper_bound[i]}; + auto low = lower_bound[i], up = upper_bound[i]; + NGRAPH_CHECK(low >= 0 && up >= 0); + if (output.get_element_type() == element::i32 && low != up) { + if (up == std::numeric_limits::max()) + up = std::numeric_limits::max(); + if (low == std::numeric_limits::max()) + low = std::numeric_limits::max(); + } + resulting_pshape[i] = {low, up}; } pshape = PartialShape(resulting_pshape); shape_defined = true; diff --git a/src/core/tests/type_prop/broadcast.cpp b/src/core/tests/type_prop/broadcast.cpp index 094377bb5e2..51f2d855ef1 100644 --- a/src/core/tests/type_prop/broadcast.cpp +++ b/src/core/tests/type_prop/broadcast.cpp @@ -51,9 +51,9 @@ TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_constants) { auto axes_mapping = op::Constant::create(element::i64, Shape{1}, {1}); auto bc = make_shared(param, target_shape, axes_mapping, "NONE"); ASSERT_TRUE(bc->get_output_partial_shape(0).rank().is_static()); - ASSERT_TRUE(bc->get_output_partial_shape(0).rank().same_scheme(Rank{4})); + ASSERT_EQ(bc->get_output_partial_shape(0).rank(), (Rank{4})); ASSERT_TRUE(bc->get_output_partial_shape(0).is_static()); - ASSERT_TRUE(bc->get_output_partial_shape(0).same_scheme(PartialShape{1, 16, 50, 50})); + ASSERT_EQ(bc->get_output_partial_shape(0), (PartialShape{1, 16, 50, 50})); } TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_node) { @@ -71,7 +71,7 @@ TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_node) { auto axes_mapping = op::Constant::create(element::i64, Shape{1}, {1}); auto bc = make_shared(param, target_shape, axes_mapping, "NONE"); ASSERT_TRUE(bc->get_output_partial_shape(0).rank().is_static()); - ASSERT_TRUE(bc->get_output_partial_shape(0).rank().same_scheme(Rank{4})); + ASSERT_EQ(bc->get_output_partial_shape(0).rank(), (Rank{4})); ASSERT_TRUE(bc->get_output_partial_shape(0).is_dynamic()); ASSERT_EQ(bc->get_output_partial_shape(0), PartialShape({Dimension::dynamic(), 16, 50, 50})); } @@ -738,7 +738,7 @@ TEST(type_prop, broadcast_v3_output_rank_not_deduced) { const auto broadcast_v3 = make_shared(arg, shape, broadcast_spec); - ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme(PartialShape::dynamic())); + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), (PartialShape::dynamic())); } TEST(type_prop, broadcast_v3_output_rank_deduced_from_arg) { @@ -747,7 +747,7 @@ TEST(type_prop, broadcast_v3_output_rank_deduced_from_arg) { const auto broadcast_spec = op::BroadcastType::BIDIRECTIONAL; const auto broadcast_v3 = make_shared(arg, shape, broadcast_spec); - ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 8, 6, 4})); + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), (PartialShape{Dimension::dynamic(), 8, 6, 4})); } TEST(type_prop, broadcast_v3_output_rank_deduced_from_new_shape_input) { @@ -758,8 +758,8 @@ TEST(type_prop, broadcast_v3_output_rank_deduced_from_new_shape_input) { const auto broadcast_v3 = make_shared(arg, shape, broadcast_spec); ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).rank().is_static()); ASSERT_EQ(broadcast_v3->get_output_partial_shape(0).rank().get_length(), 5); - ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme( - PartialShape{8, 6, Dimension::dynamic(), 5, Dimension::dynamic()})); + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), + (PartialShape{8, 6, Dimension::dynamic(), 5, Dimension::dynamic()})); } TEST(type_prop, broadcast_v3_bidirectional_dynamic_input) { @@ -859,3 +859,29 @@ TEST(type_prop, broadcast_v3_bidirectional_partially_dynamic_input) { ASSERT_EQ(bc->get_output_partial_shape(0).rank().get_length(), 4); ASSERT_EQ(bc->get_output_partial_shape(0), (PartialShape{1, Dimension::dynamic(), 50, 50})); } + +TEST(type_prop, broadcast_i32_shape_value) { + const auto arg = make_shared(element::f32, PartialShape({5, -1})); + const auto shape = make_shared(arg, element::i64); + const auto broadcast_spec = op::BroadcastType::BIDIRECTIONAL; + + const auto broadcast_v3 = make_shared(arg, shape, broadcast_spec); + + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1})); + + // shape type resetting + shape->set_output_type(element::i32); + arg->revalidate_and_infer_types(); + shape->revalidate_and_infer_types(); + broadcast_v3->revalidate_and_infer_types(); + + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1})); + + // broadcast type resetting + broadcast_v3->set_broadcast_spec(op::BroadcastType::NUMPY); + arg->revalidate_and_infer_types(); + shape->revalidate_and_infer_types(); + broadcast_v3->revalidate_and_infer_types(); + + ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1})); +} \ No newline at end of file diff --git a/src/tests/functional/plugin/myriad/subgraph_tests/nonzero_broadcast.cpp b/src/tests/functional/plugin/myriad/subgraph_tests/nonzero_broadcast.cpp index 70d4a2fcd57..dab8937352d 100644 --- a/src/tests/functional/plugin/myriad/subgraph_tests/nonzero_broadcast.cpp +++ b/src/tests/functional/plugin/myriad/subgraph_tests/nonzero_broadcast.cpp @@ -125,11 +125,7 @@ TEST_P(NonZero_Broadcast, CompareWithReference) { std::vector broadcastTestParams = { { DataShapeWithUpperBound{ {1, 1, 4}, {} }, DataShapeWithUpperBound{ {200, 2, 4}, {300, 2, 4} }, {} }, - { DataShapeWithUpperBound{ {15, 14}, {} }, DataShapeWithUpperBound{ {2, 16, 1, 14}, {2, 16, 15, 14} }, {} }, { DataShapeWithUpperBound{ {15, 1}, {} }, DataShapeWithUpperBound{ {1, 16, 15, 14}, {2, 16, 15, 14} }, {} }, - { DataShapeWithUpperBound{ {2, 16, 15, 14}, {} }, DataShapeWithUpperBound{ {1, 15, 14}, {16, 15, 14} }, {} }, - { DataShapeWithUpperBound{ {2, 16, 15, 14}, {} }, DataShapeWithUpperBound{ {16, 1, 1}, {16, 1, 14}}, {} }, - { DataShapeWithUpperBound{ {16, 15, 1}, {} }, DataShapeWithUpperBound{ {2, 1, 15, 14}, {2, 16, 15, 14} }, {} }, { DataShapeWithUpperBound{ {142, 1, 1, 64}, {300, 1, 1, 64} }, DataShapeWithUpperBound { {142, 3, 64, 64}, {300, 3, 64, 64} }, {} }, { DataShapeWithUpperBound{ {1}, {} }, DataShapeWithUpperBound{ {1, 800}, {1, 1000} }, {0} }, { DataShapeWithUpperBound{ {4}, {} }, DataShapeWithUpperBound{ {100, 4}, {1000, 4} }, {1} },