Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into reuse-openvino-co…
Browse files Browse the repository at this point in the history
…nfig
  • Loading branch information
ilya-lavrenov committed Sep 10, 2021
2 parents 4ba3c74 + 754ee2e commit 9ef4387
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//

#include <legacy/ngraph_ops/power.hpp>
#include <ngraph/opsets/opset6.hpp>
#include "shared_test_classes/subgraph/softsign.hpp"
#include "ngraph_functions/builders.hpp"

Expand Down Expand Up @@ -37,8 +37,13 @@ void SoftsignTest::SetUp() {
auto params = ngraph::builder::makeParams(ngPrc, { inputShape });

auto abs = std::make_shared<ngraph::op::Abs>(params[0]);
auto add = std::make_shared<ngraph::op::PowerIE>(abs, 1, 1, 1);
auto power = std::make_shared<ngraph::op::PowerIE>(add, -1, 1, 0);

auto const_1 = ngraph::opset1::Constant::create(ngPrc, ngraph::Shape{}, {1});
auto const_neg_1 = ngraph::opset1::Constant::create(ngPrc, ngraph::Shape{}, {-1});

auto add = std::make_shared<ngraph::opset6::Add>(abs, const_1);
auto power = std::make_shared<ngraph::opset6::Power>(add, const_neg_1);

auto mul = std::make_shared<ngraph::op::v1::Multiply>(power, params[0]);
ngraph::ResultVector results{ std::make_shared<ngraph::op::Result>(mul) };
function = std::make_shared<ngraph::Function>(results, params, "SoftSignTest");
Expand Down
18 changes: 18 additions & 0 deletions ngraph/frontend/onnx/frontend/src/edge_mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,24 @@ bool onnx_editor::EdgeMapper::is_correct_tensor_name(const std::string& name) co
return false;
}

std::vector<std::string> onnx_editor::EdgeMapper::get_input_ports(const EditorNode& node) const {
NGRAPH_CHECK(is_correct_and_unambiguous_node(node),
"The node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) +
", output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) +
" is ambiguous");
const auto node_index = find_node_indexes(node.m_node_name, node.m_output_name)[0];
return m_node_inputs[node_index];
}

std::vector<std::string> onnx_editor::EdgeMapper::get_output_ports(const EditorNode& node) const {
NGRAPH_CHECK(is_correct_and_unambiguous_node(node),
"The node with name: " + (node.m_node_name.empty() ? "not_given" : node.m_node_name) +
", output_name: " + (node.m_output_name.empty() ? "not_given" : node.m_output_name) +
" is ambiguous");
const auto node_index = find_node_indexes(node.m_node_name, node.m_output_name)[0];
return m_node_outputs[node_index];
}

std::string onnx_editor::EdgeMapper::get_source_tensor_name(const InputEdge& edge) const {
if (edge.m_node_idx >= 0 && edge.m_node_idx < static_cast<int>(m_node_inputs.size()) && edge.m_port_idx >= 0 &&
edge.m_port_idx < static_cast<int>(m_node_inputs[edge.m_node_idx].size())) {
Expand Down
14 changes: 14 additions & 0 deletions ngraph/frontend/onnx/frontend/src/edge_mapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,20 @@ class EdgeMapper {
///
bool is_correct_tensor_name(const std::string& name) const;

/// \brief Get names of input ports of given node.
///
/// \param node An EditorNode helper structure created based on a node name
/// or a node output name.
///
std::vector<std::string> get_input_ports(const EditorNode& node) const;

/// \brief Get names of output ports of given node.
///
/// \param node An EditorNode helper structure created based on a node name
/// or a node output name.
///
std::vector<std::string> get_output_ports(const EditorNode& node) const;

/// \brief Get name of the tensor which is the source of the input edge.
///
/// \note Empty string is returned if the tensor name is not found.
Expand Down
10 changes: 10 additions & 0 deletions ngraph/frontend/onnx/frontend/src/editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,16 @@ bool onnx_editor::ONNXModelEditor::is_correct_tensor_name(const std::string& nam
return m_pimpl->m_edge_mapper.is_correct_tensor_name(name);
}

std::vector<std::string> onnx_editor::ONNXModelEditor::get_input_ports(const EditorNode& node) const {
update_mapper_if_needed();
return m_pimpl->m_edge_mapper.get_input_ports(node);
}

std::vector<std::string> onnx_editor::ONNXModelEditor::get_output_ports(const EditorNode& node) const {
update_mapper_if_needed();
return m_pimpl->m_edge_mapper.get_output_ports(node);
}

std::shared_ptr<Function> onnx_editor::ONNXModelEditor::decode() {
return onnx_import::detail::decode_to_framework_nodes(m_pimpl->m_model_proto, m_model_path);
}
14 changes: 14 additions & 0 deletions ngraph/frontend/onnx/frontend/src/editor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,20 @@ class ONNX_IMPORTER_API ONNXModelEditor final {
///
bool is_correct_tensor_name(const std::string& name) const;

/// \brief Get names of input ports of given node.
///
/// \param node An EditorNode helper structure created based on a node name
/// or a node output name.
///
std::vector<std::string> get_input_ports(const EditorNode& node) const;

/// \brief Get names of output ports of given node.
///
/// \param node An EditorNode helper structure created based on a node name
/// or a node output name.
///
std::vector<std::string> get_output_ports(const EditorNode& node) const;

/// \brief Returns a nGraph function based on edited model
/// decoded to framework nodes
///
Expand Down
14 changes: 11 additions & 3 deletions ngraph/frontend/onnx/frontend/src/input_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,17 @@ std::vector<Place::Ptr> InputModelONNX::get_outputs() const {
}

Place::Ptr InputModelONNX::get_place_by_tensor_name(const std::string& tensor_name) const {
NGRAPH_CHECK(m_editor->is_correct_tensor_name(tensor_name),
"The tensor with name: " + tensor_name + " does not exist in the graph");
return std::make_shared<PlaceTensorONNX>(tensor_name, m_editor);
if (m_editor->is_correct_tensor_name(tensor_name)) {
return std::make_shared<PlaceTensorONNX>(tensor_name, m_editor);
}
return nullptr;
}

Place::Ptr InputModelONNX::get_place_by_operation_name(const std::string& operation_name) const {
if (m_editor->is_correct_and_unambiguous_node(operation_name)) {
return std::make_shared<PlaceOpONNX>(onnx_editor::EditorNode{operation_name}, m_editor);
}
return nullptr;
}

Place::Ptr InputModelONNX::get_place_by_operation_name_and_input_port(const std::string& operation_name,
Expand Down
1 change: 1 addition & 0 deletions ngraph/frontend/onnx/frontend/src/input_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class InputModelONNX : public InputModel {
std::vector<Place::Ptr> get_inputs() const override;
std::vector<Place::Ptr> get_outputs() const override;
Place::Ptr get_place_by_tensor_name(const std::string& tensor_name) const override;
Place::Ptr get_place_by_operation_name(const std::string& operation_name) const override;
Place::Ptr get_place_by_operation_name_and_input_port(const std::string& operation_name,
int input_port_index) override;
void set_partial_shape(Place::Ptr place, const ngraph::PartialShape& shape) override;
Expand Down
56 changes: 56 additions & 0 deletions ngraph/frontend/onnx/frontend/src/place.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,59 @@ bool PlaceTensorONNX::is_equal_data(Place::Ptr another) const {
return is_equal(another) || (is_input() ? false : get_producing_port()->is_equal(another)) ||
eq_to_consuming_port(another);
}

PlaceOpONNX::PlaceOpONNX(const onnx_editor::EditorNode& node, std::shared_ptr<onnx_editor::ONNXModelEditor> editor)
: m_node{node},
m_editor{editor} {}

std::vector<std::string> PlaceOpONNX::get_names() const {
return {m_node.m_node_name};
}

Place::Ptr PlaceOpONNX::get_output_port() const {
if (m_editor->get_output_ports(m_node).size() == 1) {
return get_output_port(0);
}
return nullptr;
}

Place::Ptr PlaceOpONNX::get_output_port(int output_port_index) const {
if (output_port_index < m_editor->get_output_ports(m_node).size()) {
const auto output_edge = m_editor->find_output_edge(m_node, onnx_editor::EditorOutput{output_port_index});
return std::make_shared<PlaceOutputEdgeONNX>(output_edge, m_editor);
}
return nullptr;
}

Place::Ptr PlaceOpONNX::get_output_port(const std::string& output_port_name) const {
const auto output_ports = m_editor->get_output_ports(m_node);
if (std::count(std::begin(output_ports), std::end(output_ports), output_port_name) == 1) {
const auto output_edge = m_editor->find_output_edge(m_node, onnx_editor::EditorOutput{output_port_name});
return std::make_shared<PlaceOutputEdgeONNX>(output_edge, m_editor);
}
return nullptr;
}

Place::Ptr PlaceOpONNX::get_input_port() const {
if (m_editor->get_input_ports(m_node).size() == 1) {
return get_input_port(0);
}
return nullptr;
}

Place::Ptr PlaceOpONNX::get_input_port(int input_port_index) const {
if (input_port_index < m_editor->get_input_ports(m_node).size()) {
const auto input_edge = m_editor->find_input_edge(m_node, onnx_editor::EditorInput{input_port_index});
return std::make_shared<PlaceInputEdgeONNX>(input_edge, m_editor);
}
return nullptr;
}

Place::Ptr PlaceOpONNX::get_input_port(const std::string& input_name) const {
const auto input_ports = m_editor->get_input_ports(m_node);
if (std::count(std::begin(input_ports), std::end(input_ports), input_name) == 1) {
const auto input_edge = m_editor->find_input_edge(m_node, onnx_editor::EditorInput{input_name});
return std::make_shared<PlaceInputEdgeONNX>(input_edge, m_editor);
}
return nullptr;
}
18 changes: 18 additions & 0 deletions ngraph/frontend/onnx/frontend/src/place.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ class PlaceTensorONNX : public Place {
std::string m_name;
std::shared_ptr<onnx_editor::ONNXModelEditor> m_editor;
};

class PlaceOpONNX : public Place {
public:
PlaceOpONNX(const onnx_editor::EditorNode& node, std::shared_ptr<onnx_editor::ONNXModelEditor> editor);
std::vector<std::string> get_names() const override;

Place::Ptr get_output_port() const override;
Place::Ptr get_output_port(int output_port_index) const override;
Place::Ptr get_output_port(const std::string& output_port_name) const override;

Place::Ptr get_input_port() const override;
Place::Ptr get_input_port(int input_port_index) const override;
Place::Ptr get_input_port(const std::string& input_name) const override;

private:
onnx_editor::EditorNode m_node;
std::shared_ptr<onnx_editor::ONNXModelEditor> m_editor;
};
} // namespace frontend

} // namespace ngraph
57 changes: 57 additions & 0 deletions ngraph/test/onnx/onnx_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,3 +1347,60 @@ NGRAPH_TEST(onnx_editor, is_correct_tensor_name) {
EXPECT_FALSE(editor.is_correct_tensor_name("not_existed"));
EXPECT_FALSE(editor.is_correct_tensor_name(""));
}

NGRAPH_TEST(onnx_editor, get_input_ports) {
ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")};

const auto ports_1 = editor.get_input_ports(EditorNode{"relu1_name"});
EXPECT_EQ(ports_1.size(), 1);
EXPECT_EQ(ports_1[0], "in1");
const auto ports_2 = editor.get_input_ports(EditorNode{"split_name"});
EXPECT_EQ(ports_2.size(), 1);
EXPECT_EQ(ports_2[0], "add2");
const auto ports_3 = editor.get_input_ports(EditorNode{EditorOutput{"add2"}});
EXPECT_EQ(ports_3.size(), 2);
EXPECT_EQ(ports_3[0], "relu1");
EXPECT_EQ(ports_3[1], "add1");
try {
editor.get_input_ports(EditorNode{"add_ambiguous_name"});
} catch (const std::exception& e) {
std::string msg{e.what()};
EXPECT_TRUE(msg.find("The node with name: add_ambiguous_name, output_name: not_given is ambiguous") !=
std::string::npos);
}
try {
editor.get_input_ports(EditorNode{""});
} catch (const std::exception& e) {
std::string msg{e.what()};
EXPECT_TRUE(msg.find("The node with name: not_given, output_name: not_given is ambiguous") !=
std::string::npos);
}
}
NGRAPH_TEST(onnx_editor, get_output_ports) {
ONNXModelEditor editor{file_util::path_join(SERIALIZED_ZOO, "onnx/model_editor/subgraph_extraction_tests.onnx")};

const auto ports_1 = editor.get_output_ports(EditorNode{"relu1_name"});
EXPECT_EQ(ports_1.size(), 1);
EXPECT_EQ(ports_1[0], "relu1");
const auto ports_2 = editor.get_output_ports(EditorNode{"split_name"});
EXPECT_EQ(ports_2.size(), 2);
EXPECT_EQ(ports_2[0], "split1");
EXPECT_EQ(ports_2[1], "split2");
const auto ports_3 = editor.get_output_ports(EditorNode{EditorOutput{"add2"}});
EXPECT_EQ(ports_3.size(), 1);
EXPECT_EQ(ports_3[0], "add2");
try {
editor.get_output_ports(EditorNode{"add_ambiguous_name"});
} catch (const std::exception& e) {
std::string msg{e.what()};
EXPECT_TRUE(msg.find("The node with name: add_ambiguous_name, output_name: not_given is ambiguous") !=
std::string::npos);
}
try {
editor.get_output_ports(EditorNode{""});
} catch (const std::exception& e) {
std::string msg{e.what()};
EXPECT_TRUE(msg.find("The node with name: not_given, output_name: not_given is ambiguous") !=
std::string::npos);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,56 @@ def test_get_place_by_tensor_name():
place3 = model.get_place_by_tensor_name(tensorName="in1")
assert place3

with pytest.raises(Exception) as e:
model.get_place_by_tensor_name(tensorName="0:add_out")
assert "The tensor with name: 0:add_out does not exist in the graph" in str(e)
assert not model.get_place_by_tensor_name(tensorName="0:add_out")


def test_get_place_by_operation_name():
skip_if_onnx_frontend_is_disabled()
fe = fem.load_by_framework(framework=ONNX_FRONTEND_NAME)
assert fe

model = fe.load("input_model.onnx")
assert model

place1 = model.get_place_by_operation_name(operationName="split1")
assert place1

place2 = model.get_place_by_operation_name(operationName="not_existed")
assert not place2


def test_get_output_port():
skip_if_onnx_frontend_is_disabled()
fe = fem.load_by_framework(framework=ONNX_FRONTEND_NAME)
assert fe
model = fe.load("input_model.onnx")
assert model

split_op = model.get_place_by_operation_name(operationName="split1")
place1 = split_op.get_output_port(outputPortIndex=0)
place2 = split_op.get_output_port(outputName="out2")

assert place1.get_target_tensor().get_names()[0] == "out1"
assert place2.get_target_tensor().get_names()[0] == "out2"

assert not split_op.get_output_port()
assert not split_op.get_output_port(outputPortIndex=3)
assert not split_op.get_output_port(outputName="not_existed")


def test_get_input_port():
skip_if_onnx_frontend_is_disabled()
fe = fem.load_by_framework(framework=ONNX_FRONTEND_NAME)
assert fe
model = fe.load("input_model.onnx")
assert model

split_op = model.get_place_by_operation_name(operationName="split1")
place1 = split_op.get_input_port(inputPortIndex=0)
assert place1.get_source_tensor().get_names()[0] == "add_out"

place2 = split_op.get_input_port()
assert place1.is_equal(place2)

assert not split_op.get_input_port(inputPortIndex=1)
assert not split_op.get_input_port(inputName="not_existed")

0 comments on commit 9ef4387

Please sign in to comment.