Skip to content

Commit 015fe97

Browse files
authoredFeb 20, 2025··
[core] Util to set (auto) names on model's input, output tensors (openvinotoolkit#28975)
### Details: - Add utils to core to set names on model input/output tensors - Define default tensor names and port separator - Use auto naming in model created by python API. Model outputs will have got names also. - The auto naming can be part of Model API but requires to add validation tools to find and resolve names collision - Auto naming cannot be added to Model creation in C++ as it can have impact on (de)serialization, requires more investigation ### Tickets: - CVS-159997 --------- Signed-off-by: Raasz, Pawel <pawel.raasz@intel.com>
1 parent d9c2aee commit 015fe97

File tree

10 files changed

+440
-51
lines changed

10 files changed

+440
-51
lines changed
 

‎src/bindings/python/src/pyopenvino/graph/model.cpp

+21-38
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "openvino/core/except.hpp"
1414
#include "openvino/core/graph_util.hpp"
1515
#include "openvino/core/model.hpp" // ov::Model
16+
#include "openvino/core/model_util.hpp"
1617
#include "openvino/core/partial_shape.hpp"
1718
#include "openvino/op/assign.hpp"
1819
#include "openvino/op/parameter.hpp" // ov::op::v0::Parameter
@@ -30,15 +31,14 @@ using PyRTMap = ov::RTMap;
3031

3132
PYBIND11_MAKE_OPAQUE(PyRTMap);
3233

33-
static void set_tensor_names(const ov::ParameterVector& parameters) {
34-
for (const auto& param : parameters) {
35-
ov::Output<ov::Node> p = param;
36-
if (p.get_node()->output(0).get_names().empty()) {
37-
std::unordered_set<std::string> p_names({p.get_node()->get_friendly_name()});
38-
p.get_node()->output(0).set_names(p_names);
39-
}
40-
}
34+
namespace {
35+
template <class... Args>
36+
std::shared_ptr<ov::Model> make_model_with_tensor_names(Args&&... args) {
37+
auto model = std::make_shared<ov::Model>(std::forward<Args>(args)...);
38+
ov::util::set_tensors_names(ov::AUTO, *model);
39+
return model;
4140
}
41+
} // namespace
4242

4343
static std::shared_ptr<ov::Node> get_node_ptr(std::shared_ptr<ov::Node> node) {
4444
return node;
@@ -163,9 +163,8 @@ void regclass_graph_Model(py::module m) {
163163
const std::vector<std::shared_ptr<ov::Node>>& nodes,
164164
const ov::ParameterVector& params,
165165
const std::string& name) {
166-
set_tensor_names(params);
167166
const auto sinks = cast_to_sink_vector(nodes);
168-
auto model = std::make_shared<ov::Model>(res, sinks, params, name);
167+
auto model = make_model_with_tensor_names(res, sinks, params, name);
169168
set_correct_variables_for_assign_ops(model, sinks);
170169
return model;
171170
}),
@@ -189,8 +188,7 @@ void regclass_graph_Model(py::module m) {
189188
model.def(py::init([](const std::vector<std::shared_ptr<ov::Node>>& results,
190189
const ov::ParameterVector& parameters,
191190
const std::string& name) {
192-
set_tensor_names(parameters);
193-
return std::make_shared<ov::Model>(results, parameters, name);
191+
return make_model_with_tensor_names(results, parameters, name);
194192
}),
195193
py::arg("results"),
196194
py::arg("parameters"),
@@ -209,8 +207,7 @@ void regclass_graph_Model(py::module m) {
209207
model.def(py::init([](const std::shared_ptr<ov::Node>& result,
210208
const ov::ParameterVector& parameters,
211209
const std::string& name) {
212-
set_tensor_names(parameters);
213-
return std::make_shared<ov::Model>(result, parameters, name);
210+
return make_model_with_tensor_names(result, parameters, name);
214211
}),
215212
py::arg("result"),
216213
py::arg("parameters"),
@@ -228,8 +225,7 @@ void regclass_graph_Model(py::module m) {
228225

229226
model.def(
230227
py::init([](const ov::OutputVector& results, const ov::ParameterVector& parameters, const std::string& name) {
231-
set_tensor_names(parameters);
232-
return std::make_shared<ov::Model>(results, parameters, name);
228+
return make_model_with_tensor_names(results, parameters, name);
233229
}),
234230
py::arg("results"),
235231
py::arg("parameters"),
@@ -249,9 +245,8 @@ void regclass_graph_Model(py::module m) {
249245
const std::vector<std::shared_ptr<ov::Node>>& nodes,
250246
const ov::ParameterVector& parameters,
251247
const std::string& name) {
252-
set_tensor_names(parameters);
253248
const auto sinks = cast_to_sink_vector(nodes);
254-
auto model = std::make_shared<ov::Model>(results, sinks, parameters, name);
249+
auto model = make_model_with_tensor_names(results, sinks, parameters, name);
255250
set_correct_variables_for_assign_ops(model, sinks);
256251
return model;
257252
}),
@@ -276,9 +271,8 @@ void regclass_graph_Model(py::module m) {
276271
const ov::OutputVector& nodes,
277272
const ov::ParameterVector& parameters,
278273
const std::string& name) {
279-
set_tensor_names(parameters);
280274
const auto sinks = cast_to_sink_vector(nodes);
281-
auto model = std::make_shared<ov::Model>(results, sinks, parameters, name);
275+
auto model = make_model_with_tensor_names(results, sinks, parameters, name);
282276
set_correct_variables_for_assign_ops(model, sinks);
283277
return model;
284278
}),
@@ -304,9 +298,7 @@ void regclass_graph_Model(py::module m) {
304298
const ov::ParameterVector& parameters,
305299
const ov::op::util::VariableVector& variables,
306300
const std::string& name) {
307-
set_tensor_names(parameters);
308-
const auto sinks = cast_to_sink_vector(nodes);
309-
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
301+
return make_model_with_tensor_names(results, cast_to_sink_vector(nodes), parameters, variables, name);
310302
}),
311303
py::arg("results"),
312304
py::arg("sinks"),
@@ -332,9 +324,8 @@ void regclass_graph_Model(py::module m) {
332324
const ov::OutputVector& nodes,
333325
const ov::ParameterVector& parameters,
334326
const std::string& name) {
335-
set_tensor_names(parameters);
336327
const auto sinks = cast_to_sink_vector(nodes);
337-
auto model = std::make_shared<ov::Model>(results, sinks, parameters, name);
328+
auto model = make_model_with_tensor_names(results, sinks, parameters, name);
338329
set_correct_variables_for_assign_ops(model, sinks);
339330
return model;
340331
}),
@@ -360,9 +351,7 @@ void regclass_graph_Model(py::module m) {
360351
const ov::ParameterVector& parameters,
361352
const ov::op::util::VariableVector& variables,
362353
const std::string& name) {
363-
set_tensor_names(parameters);
364-
const auto sinks = cast_to_sink_vector(nodes);
365-
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
354+
return make_model_with_tensor_names(results, cast_to_sink_vector(nodes), parameters, variables, name);
366355
}),
367356
py::arg("results"),
368357
py::arg("sinks"),
@@ -389,9 +378,7 @@ void regclass_graph_Model(py::module m) {
389378
const ov::ParameterVector& parameters,
390379
const ov::op::util::VariableVector& variables,
391380
const std::string& name) {
392-
set_tensor_names(parameters);
393-
const auto sinks = cast_to_sink_vector(nodes);
394-
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
381+
return make_model_with_tensor_names(results, cast_to_sink_vector(nodes), parameters, variables, name);
395382
}),
396383
py::arg("results"),
397384
py::arg("sinks"),
@@ -418,9 +405,7 @@ void regclass_graph_Model(py::module m) {
418405
const ov::ParameterVector& parameters,
419406
const ov::op::util::VariableVector& variables,
420407
const std::string& name) {
421-
set_tensor_names(parameters);
422-
const auto sinks = cast_to_sink_vector(nodes);
423-
return std::make_shared<ov::Model>(results, sinks, parameters, variables, name);
408+
return make_model_with_tensor_names(results, cast_to_sink_vector(nodes), parameters, variables, name);
424409
}),
425410
py::arg("results"),
426411
py::arg("sinks"),
@@ -444,8 +429,7 @@ void regclass_graph_Model(py::module m) {
444429
const ov::ParameterVector& parameters,
445430
const ov::op::util::VariableVector& variables,
446431
const std::string& name) {
447-
set_tensor_names(parameters);
448-
return std::make_shared<ov::Model>(results, parameters, variables, name);
432+
return make_model_with_tensor_names(results, parameters, variables, name);
449433
}),
450434
py::arg("results"),
451435
py::arg("parameters"),
@@ -468,8 +452,7 @@ void regclass_graph_Model(py::module m) {
468452
const ov::ParameterVector& parameters,
469453
const ov::op::util::VariableVector& variables,
470454
const std::string& name) {
471-
set_tensor_names(parameters);
472-
return std::make_shared<ov::Model>(results, parameters, variables, name);
455+
return make_model_with_tensor_names(results, parameters, variables, name);
473456
}),
474457
py::arg("results"),
475458
py::arg("parameters"),

‎src/bindings/python/tests/test_graph/test_core.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from openvino import Dimension, Model, PartialShape, Shape
1111

12-
import openvino.opset8 as ov
12+
import openvino.opset13 as ov
1313

1414

1515
def test_dimension():
@@ -408,14 +408,16 @@ def test_repr_dynamic_shape():
408408
parameter_a = ov.parameter(shape, dtype=np.float32, name="A")
409409
parameter_b = ov.parameter(shape, dtype=np.float32, name="B")
410410
param_sum = parameter_a + parameter_b
411+
# set tensor name to have deterministic output name of model (default use unique node name)
412+
param_sum.output(0).set_names({"sum"})
411413
model = Model(param_sum, [parameter_a, parameter_b], "simple_dyn_shapes_graph")
412414

413415
assert (
414416
repr(model)
415417
== "<Model: 'simple_dyn_shapes_graph'\ninputs["
416418
+ "\n<ConstOutput: names[A] shape[?,2] type: f32>,"
417419
+ "\n<ConstOutput: names[B] shape[?,2] type: f32>\n]"
418-
+ "\noutputs[\n<ConstOutput: names[] shape[?,2] type: f32>\n]>"
420+
+ "\noutputs[\n<ConstOutput: names[sum] shape[?,2] type: f32>\n]>"
419421
)
420422

421423
ops = model.get_ordered_ops()

‎src/bindings/python/tests/test_runtime/test_ovdict.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ def test_ovdict_single_output_noname(device, is_direct):
154154
_ = result["some_name"]
155155
assert "some_name" in str(e0.value)
156156

157-
# Check if returned names are tuple with one empty set
157+
# Check if returned names are tuple with one default name set
158158
assert len(result.names()) == 1
159-
assert result.names()[0] == set()
159+
assert result.names()[0] != set()
160160

161161

162162
@pytest.mark.parametrize("is_direct", [True, False])

‎src/core/dev_api/openvino/core/descriptor_tensor.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
namespace ov {
1313
namespace descriptor {
1414

15+
/// @brief Defines tensor name port separator.
16+
inline constexpr auto port_separator = ':';
17+
1518
class Tensor;
1619
class Input;
1720
class Output;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#pragma once
6+
7+
#include <unordered_map>
8+
9+
#include "openvino/core/core_visibility.hpp"
10+
#include "openvino/core/descriptor/tensor.hpp"
11+
#include "openvino/core/model.hpp"
12+
13+
namespace ov {
14+
15+
/** @brief Generic atg suggests automated functionality.
16+
*
17+
* Can be use for template specialization or function overloading
18+
*/
19+
struct AutoTag {};
20+
inline constexpr AutoTag AUTO{};
21+
22+
/** @brief Alias to map of port number and tensor names */
23+
using TensorNamesMap = std::unordered_map<size_t, TensorNames>;
24+
} // namespace ov
25+
26+
namespace ov::util {
27+
28+
/** @brief Set input tensors names for the model
29+
*
30+
* Sets only tensors defined in the input map.
31+
* The tensors defined in map but not existing in the model will be ignored.
32+
*
33+
* @param model Model to set its input tensors names.
34+
* @param inputs_names Map of input tensor names.
35+
*/
36+
OPENVINO_API void set_input_tensors_names(Model& model, const TensorNamesMap& inputs_names);
37+
38+
/** @brief Set input tensors names for the model
39+
*
40+
* Sets tensors defined in the input map.
41+
* Tensors not defined in the map are set to default names if the tensor hasn't got names.
42+
* The tensors defined in the map but not existing in the model will be ignored.
43+
*
44+
* @param model Model to set its input tensors names.
45+
* @param inputs_names Map of input tensor names. Default empty.
46+
*/
47+
OPENVINO_API void set_input_tensors_names(const AutoTag&, Model& model, const TensorNamesMap& inputs_names = {});
48+
49+
/** @brief Set output tensors names for the model
50+
*
51+
* Sets only tensors defined in the output map.
52+
* The tensors defined in map but not existing in the model will be ignored.
53+
*
54+
* @param model Model to set its output tensors names.
55+
* @param outputs_names Map of output tensor names.AnyMap
56+
*/
57+
OPENVINO_API void set_output_tensor_names(Model& model, const TensorNamesMap& outputs_names);
58+
59+
/** @brief Set output tensors names for the model.
60+
*
61+
* Sets tensors defined in the output map.
62+
* Tensors not defined in the map are set to default names if the tensor hasn't got names.
63+
* The tensors defined in the map but not existing in the model will be ignored.
64+
*
65+
* @param model Model to set its output tensors names.
66+
* @param outputs_names Map of output tensor names. Default empty.
67+
*/
68+
OPENVINO_API void set_output_tensor_names(const AutoTag&, Model& model, const TensorNamesMap& outputs_names = {});
69+
70+
/** @brief Set input and output tensors names for the model
71+
*
72+
* Sets only tensors defined in the input and output maps.
73+
* The tensors defined in maps but not existing in the model will be ignored.
74+
*
75+
* @param model Model to set its input and output tensors names.
76+
* @param inputs_names Map of input tensor names.
77+
* @param outputs_names Map of output tensor names.
78+
*/
79+
OPENVINO_API void set_tensors_names(Model& model,
80+
const TensorNamesMap& inputs_names,
81+
const TensorNamesMap& outputs_names);
82+
83+
/** @brief Set input and output tensors names for the model.
84+
*
85+
* Sets tensors defined in the input and output maps.
86+
* Tensors not defined in the maps are set to default names if the tensor hasn't got names.
87+
* The tensors defined in the maps but not existing in the model will be ignored.
88+
*
89+
* @param model Model to set its input and output tensors names.
90+
* @param inputs_names Map of input tensor names. Default empty.
91+
* @param outputs_names Map of output tensor names. Default empty.
92+
*/
93+
OPENVINO_API void set_tensors_names(const AutoTag&,
94+
Model& model,
95+
const TensorNamesMap& inputs_names = {},
96+
const TensorNamesMap& outputs_names = {});
97+
98+
} // namespace ov::util

‎src/core/dev_api/openvino/op/util/node_util.hpp

+14-3
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,29 @@
44

55
#pragma once
66

7+
#include <string>
8+
79
#include "openvino/core/node.hpp"
810

911
namespace ov {
10-
namespace op {
1112
namespace util {
13+
/**
14+
* @brief Creates default tensor name for given Node's output.
15+
* The name format is "node_name:output_port".
16+
*
17+
* @param output - Node's output to create name for tensor.
18+
* @return Default tensor name.
19+
*/
20+
OPENVINO_API std::string make_default_tensor_name(const Output<const Node>& output);
21+
} // namespace util
22+
23+
namespace op::util {
1224
/**
1325
* @brief Set name for both node and output tensor. Any other names will be overriden by a given single name
1426
* @param node - node to rename
1527
* @param name - new name
1628
* @param output_port - output port to rename
1729
*/
1830
void OPENVINO_API set_name(ov::Node& node, const std::string& name, size_t output_port = 0);
19-
} // namespace util
20-
} // namespace op
31+
} // namespace op::util
2132
} // namespace ov

‎src/core/include/openvino/core/descriptor/tensor.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ using TensorSymbol = std::vector<std::shared_ptr<Symbol>>;
2626
/// \brief Alias for vector of symbol tensors.
2727
using TensorSymbolVector = std::vector<TensorSymbol>;
2828

29+
/// \brief Alias for set of tensor names.
30+
using TensorNames = std::unordered_set<std::string>;
2931
namespace descriptor {
3032
class ITensorDescriptor;
3133

‎src/core/src/op/util/model_util.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include "openvino/core/model_util.hpp"
6+
7+
#include "openvino/core/model.hpp"
8+
#include "openvino/op/util/node_util.hpp"
9+
10+
namespace ov::util {
11+
namespace {
12+
13+
void set_default_tensor_names(OutputVector&& outputs) {
14+
for (auto& output : outputs) {
15+
if (output.get_tensor().get_names().empty()) {
16+
output.get_tensor().set_names({make_default_tensor_name(output)});
17+
}
18+
}
19+
}
20+
21+
void set_tensor_names(OutputVector&& outputs, const TensorNamesMap& tensor_names) {
22+
for (const auto& [port, names] : tensor_names) {
23+
if (port < outputs.size()) {
24+
outputs[port].get_tensor().set_names(names);
25+
}
26+
}
27+
}
28+
} // namespace
29+
30+
void set_input_tensors_names(Model& model, const TensorNamesMap& inputs_names) {
31+
set_tensor_names(model.inputs(), inputs_names);
32+
}
33+
34+
void set_input_tensors_names(const AutoTag&, Model& model, const TensorNamesMap& inputs_names) {
35+
set_input_tensors_names(model, inputs_names);
36+
set_default_tensor_names(model.inputs());
37+
}
38+
39+
void set_output_tensor_names(Model& model, const TensorNamesMap& outputs_names) {
40+
set_tensor_names(model.outputs(), outputs_names);
41+
}
42+
43+
void set_output_tensor_names(const AutoTag&, Model& model, const TensorNamesMap& outputs_names) {
44+
set_output_tensor_names(model, outputs_names);
45+
set_default_tensor_names(model.outputs());
46+
}
47+
48+
void set_tensors_names(Model& model, const TensorNamesMap& inputs_names, const TensorNamesMap& outputs_names) {
49+
set_input_tensors_names(model, inputs_names);
50+
set_output_tensor_names(model, outputs_names);
51+
}
52+
53+
void set_tensors_names(const AutoTag&,
54+
Model& model,
55+
const TensorNamesMap& inputs_names,
56+
const TensorNamesMap& outputs_names) {
57+
set_input_tensors_names(AUTO, model, inputs_names);
58+
set_output_tensor_names(AUTO, model, outputs_names);
59+
}
60+
61+
} // namespace ov::util

‎src/core/src/op/util/node_util.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,23 @@
44

55
#include "openvino/op/util/node_util.hpp"
66

7-
namespace ov {
8-
namespace op {
9-
namespace util {
7+
#include "openvino/core/descriptor_tensor.hpp"
8+
9+
namespace ov::op::util {
10+
1011
void set_name(ov::Node& node, const std::string& name, size_t output_port) {
1112
node.set_friendly_name(name);
1213
node.get_output_tensor(output_port).set_names({name});
1314
}
14-
} // namespace util
15-
} // namespace op
16-
} // namespace ov
15+
} // namespace ov::op::util
16+
17+
namespace ov::util {
18+
19+
std::string make_default_tensor_name(const Output<const Node>& output) {
20+
auto default_name = output.get_node()->get_friendly_name();
21+
if (output.get_node()->get_output_size() > 1) {
22+
default_name += descriptor::port_separator + std::to_string(output.get_index());
23+
}
24+
return default_name;
25+
}
26+
} // namespace ov::util

‎src/core/tests/model_util_tests.cpp

+219
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// Copyright (C) 2018-2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
//
4+
5+
#include <gmock/gmock.h>
6+
7+
#include <optional>
8+
9+
#include "openvino/core/model.hpp"
10+
#include "openvino/core/model_util.hpp"
11+
#include "openvino/op/add.hpp"
12+
#include "openvino/op/multiply.hpp"
13+
14+
namespace ov::test {
15+
16+
using op::v0::Parameter, op::v1::Add, op::v1::Multiply, op::v0::Result;
17+
18+
class ModelUtilTest : public testing::Test {
19+
protected:
20+
static auto make_model_without_tensor_names() {
21+
auto input_1 = std::make_shared<Parameter>(element::f32, Shape{1, 3});
22+
auto input_2 = std::make_shared<Parameter>(element::f32, Shape{3, 3});
23+
auto input_3 = std::make_shared<Parameter>(element::f32, Shape{3, 1});
24+
25+
auto add = std::make_shared<Add>(input_1, input_2);
26+
auto mul = std::make_shared<Multiply>(add, input_3);
27+
auto add_final = std::make_shared<Add>(mul, add);
28+
29+
auto add_result = std::make_shared<Result>(add);
30+
auto mul_result = std::make_shared<Result>(mul);
31+
auto final_result = std::make_shared<Result>(add_final);
32+
33+
auto model = std::make_shared<Model>(ResultVector{add_result, mul_result, final_result},
34+
ParameterVector{input_1, input_2, input_3},
35+
"ModelWithoutTensorNames");
36+
return model;
37+
}
38+
39+
static auto make_model_with_named_nodes() {
40+
auto model = make_model_without_tensor_names();
41+
42+
const auto& inputs = model->inputs();
43+
for (size_t i = 0; i < inputs.size(); ++i) {
44+
inputs[i].get_node()->set_friendly_name("input_" + std::to_string(i + 1));
45+
}
46+
47+
auto results = model->get_results();
48+
results[0]->set_friendly_name("add_result");
49+
results[1]->set_friendly_name("mul_result");
50+
results[2]->set_friendly_name("final_result");
51+
model->set_friendly_name("ModelWithNamedNodes");
52+
return model;
53+
}
54+
55+
static auto compare_tensor_names(const OutputVector& outputs, const TensorNamesMap& expected) {
56+
std::optional<std::string> mismatch_err;
57+
58+
for (const auto& [port, expected_names] : expected) {
59+
if (const auto& names = outputs[port].get_names(); expected_names != names) {
60+
using testing::PrintToString;
61+
mismatch_err.emplace("Tensor names mismatch on port " + PrintToString(port) + "\n Expected: " +
62+
PrintToString(expected_names) + "\n Actual: " + PrintToString(names));
63+
}
64+
}
65+
return mismatch_err;
66+
}
67+
};
68+
69+
TEST_F(ModelUtilTest, manual_set_all_input_tensors_names) {
70+
const auto inputs_names = TensorNamesMap{{0, {"input_1"}}, {1, {"input_2"}}, {2, {"input_3"}}};
71+
72+
auto model = make_model_without_tensor_names();
73+
util::set_input_tensors_names(*model, inputs_names);
74+
75+
ASSERT_EQ(model->inputs().size(), inputs_names.size());
76+
for (const auto& [port, names] : inputs_names) {
77+
EXPECT_EQ(model->input(port).get_names(), names) << "Names not match for input port " << port;
78+
}
79+
}
80+
TEST_F(ModelUtilTest, manual_set_some_input_tensors_names) {
81+
const auto inputs_names = TensorNamesMap{{2, {"input_2", "mul_input"}}, {0, {"add_input"}}};
82+
auto expected_names = inputs_names;
83+
expected_names.emplace(1, TensorNames{});
84+
85+
auto model = make_model_without_tensor_names();
86+
util::set_input_tensors_names(*model, inputs_names);
87+
88+
ASSERT_EQ(model->inputs().size(), expected_names.size());
89+
const auto mismatch_error = compare_tensor_names(model->inputs(), expected_names);
90+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
91+
}
92+
93+
TEST_F(ModelUtilTest, auto_set_all_input_tensors_names) {
94+
const auto expected_names = TensorNamesMap{{0, {"input_1"}}, {1, {"input_2"}}, {2, {"input_3"}}};
95+
96+
auto model = make_model_with_named_nodes();
97+
util::set_input_tensors_names(AUTO, *model);
98+
99+
ASSERT_EQ(model->inputs().size(), expected_names.size());
100+
const auto mismatch_error = compare_tensor_names(model->inputs(), expected_names);
101+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
102+
}
103+
104+
TEST_F(ModelUtilTest, auto_set_missing_input_tensors_names) {
105+
const auto inputs_names = TensorNamesMap{{2, {"input_2", "mul_input"}}, {0, {"add_input"}}};
106+
auto expected_names = inputs_names;
107+
expected_names.emplace(1, TensorNames{"input_2"});
108+
109+
auto model = make_model_with_named_nodes();
110+
util::set_input_tensors_names(AUTO, *model, inputs_names);
111+
112+
ASSERT_EQ(model->inputs().size(), expected_names.size());
113+
const auto mismatch_error = compare_tensor_names(model->inputs(), expected_names);
114+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
115+
}
116+
117+
TEST_F(ModelUtilTest, auto_set_all_io_tensors_names) {
118+
const auto exp_inputs_names = TensorNamesMap{{2, {"input_3"}}, {0, {"input_1"}}, {1, {"input_2"}}};
119+
const auto exp_outputs_names = TensorNamesMap{{0, {"add_result"}}, {1, {"mul_result"}}, {2, {"final_result"}}};
120+
121+
auto model = make_model_with_named_nodes();
122+
util::set_tensors_names(AUTO, *model);
123+
124+
ASSERT_EQ(model->inputs().size(), exp_inputs_names.size());
125+
auto mismatch_error = compare_tensor_names(model->inputs(), exp_inputs_names);
126+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
127+
128+
ASSERT_EQ(model->outputs().size(), exp_outputs_names.size());
129+
mismatch_error = compare_tensor_names(model->outputs(), exp_outputs_names);
130+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
131+
}
132+
133+
TEST_F(ModelUtilTest, manual_set_all_io_tensors_names) {
134+
const auto inputs_names = TensorNamesMap{{0, {"input_1"}}, {1, {"input_2"}}, {2, {"input_3"}}};
135+
const auto outputs_names = TensorNamesMap{{0, {"add_result"}}, {1, {"mul_result"}}, {2, {"final_result"}}};
136+
137+
auto model = make_model_without_tensor_names();
138+
util::set_tensors_names(*model, inputs_names, outputs_names);
139+
140+
ASSERT_EQ(model->inputs().size(), inputs_names.size());
141+
auto mismatch_error = compare_tensor_names(model->inputs(), inputs_names);
142+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
143+
144+
ASSERT_EQ(model->outputs().size(), outputs_names.size());
145+
mismatch_error = compare_tensor_names(model->outputs(), outputs_names);
146+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
147+
}
148+
149+
TEST_F(ModelUtilTest, manual_set_some_io_tensors_names) {
150+
const auto inputs_names = TensorNamesMap{{0, {"input_1"}}, {2, {"input_3"}}};
151+
auto expected_input_names = inputs_names;
152+
expected_input_names.emplace(1, TensorNames{});
153+
154+
const auto outputs_names = TensorNamesMap{{1, {"mul_result"}}};
155+
auto expected_output_names = outputs_names;
156+
expected_output_names.emplace(0, TensorNames{});
157+
expected_output_names.emplace(2, TensorNames{});
158+
159+
auto model = make_model_without_tensor_names();
160+
util::set_tensors_names(*model, inputs_names, outputs_names);
161+
162+
ASSERT_EQ(model->inputs().size(), expected_input_names.size());
163+
auto mismatch_error = compare_tensor_names(model->inputs(), expected_input_names);
164+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
165+
166+
ASSERT_EQ(model->outputs().size(), expected_output_names.size());
167+
mismatch_error = compare_tensor_names(model->outputs(), expected_output_names);
168+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
169+
}
170+
171+
TEST_F(ModelUtilTest, manual_set_all_output_tensors_names) {
172+
const auto outputs_names = TensorNamesMap{{0, {"add_result"}}, {1, {"mul_result"}}, {2, {"final_result"}}};
173+
174+
auto model = make_model_with_named_nodes();
175+
util::set_output_tensor_names(*model, outputs_names);
176+
177+
ASSERT_EQ(model->outputs().size(), outputs_names.size());
178+
const auto mismatch_error = compare_tensor_names(model->outputs(), outputs_names);
179+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
180+
}
181+
182+
TEST_F(ModelUtilTest, manual_set_some_output_tensors_names) {
183+
const auto outputs_names = TensorNamesMap{{1, {"mul_result"}}, {2, {"final_result"}}};
184+
auto expected_names = outputs_names;
185+
expected_names.emplace(0, TensorNames{});
186+
187+
auto model = make_model_with_named_nodes();
188+
util::set_output_tensor_names(*model, outputs_names);
189+
190+
ASSERT_EQ(model->outputs().size(), expected_names.size());
191+
const auto mismatch_error = compare_tensor_names(model->outputs(), expected_names);
192+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
193+
}
194+
195+
TEST_F(ModelUtilTest, auto_set_all_output_tensors_names) {
196+
const auto expected_names = TensorNamesMap{{0, {"add_result"}}, {1, {"mul_result"}}, {2, {"final_result"}}};
197+
198+
auto model = make_model_with_named_nodes();
199+
util::set_output_tensor_names(AUTO, *model);
200+
201+
ASSERT_EQ(model->outputs().size(), expected_names.size());
202+
const auto mismatch_error = compare_tensor_names(model->outputs(), expected_names);
203+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
204+
}
205+
206+
TEST_F(ModelUtilTest, auto_set_missing_output_tensors_names) {
207+
const auto outputs_names = TensorNamesMap{{1, {"mul_result"}}, {2, {"final_result"}}};
208+
auto expected_names = outputs_names;
209+
expected_names.emplace(0, TensorNames{"add_result"});
210+
211+
auto model = make_model_with_named_nodes();
212+
util::set_output_tensor_names(AUTO, *model, outputs_names);
213+
214+
ASSERT_EQ(model->outputs().size(), expected_names.size());
215+
const auto mismatch_error = compare_tensor_names(model->outputs(), expected_names);
216+
EXPECT_FALSE(mismatch_error) << *mismatch_error;
217+
}
218+
219+
} // namespace ov::test

0 commit comments

Comments
 (0)
Please sign in to comment.