bd89cef43f98ff9ee0cf81569f9f3fe870965d04
[platform/upstream/dldt.git] / inference-engine / tests / ngraph_functions / src / low_precision_transformations / add_function.cpp
1 // Copyright (C) 2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "ngraph_functions/low_precision_transformations/add_function.hpp"
6 #include "low_precision/network_helper.hpp"
7
8 #include <ngraph/opsets/opset1.hpp>
9 #include "ngraph_functions/builders.hpp"
10 #include "ngraph_functions/subgraph_builders.hpp"
11
12 using namespace ngraph::pass::low_precision;
13
14 namespace ngraph {
15 namespace builder {
16 namespace subgraph {
17
18 std::shared_ptr<ngraph::Function> AddFunction::getOriginal(
19     const ngraph::element::Type precision,
20     const ngraph::Shape& inputShape,
21     const bool broadcast,
22     const ngraph::pass::low_precision::LayerTransformation::Params& params,
23     const ngraph::element::Type& precision1,
24     const ngraph::builder::subgraph::DequantizationOperations& dequantization1,
25     const ngraph::element::Type& precision2,
26     const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
27     const int constInput,
28     const std::vector<float>& constValues,
29     const std::string& additionalLayer) {
30     std::shared_ptr<ngraph::Node> input1;
31     if (constInput == 0) {
32         input1 = std::make_shared<ngraph::opset1::Constant>(
33             precision,
34             inputShape,
35             constValues);
36     } else {
37         input1 = std::make_shared<ngraph::opset1::Parameter>(
38             precision1,
39             broadcast ? ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 }) : ngraph::Shape(inputShape));
40     }
41
42     const auto dequantizationOp1 = is_type<ngraph::opset1::Constant>(input1) ? input1 : makeDequantization(input1, dequantization1);
43
44     std::shared_ptr<ngraph::Node> input2;
45     if (constInput == 1) {
46         input2 = std::make_shared<ngraph::opset1::Constant>(
47             precision,
48             inputShape,
49             constValues);
50     } else {
51         input2 = std::make_shared<ngraph::opset1::Parameter>(
52             precision2, ngraph::Shape(inputShape));
53     }
54     auto parent = input2;
55     if (additionalLayer == "convolution") {
56         parent = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Convolution>>(
57             std::vector<element::Type>{ element::f32, element::f32 },
58             std::vector<element::Type>{ element::f32 },
59             ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
60             ngraph::op::TemporaryReplaceOutputType(
61                 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 1, 4, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
62                 element::f32).get(),
63             ngraph::Strides{ 1, 1 },
64             ngraph::CoordinateDiff{ 0, 0 },
65             ngraph::CoordinateDiff{ 0, 0 },
66             ngraph::Strides{ 1, 1 });
67     }
68     if (additionalLayer == "group_convolution") {
69         parent = std::make_shared< ngraph::op::TypeRelaxed<ngraph::opset1::GroupConvolution>>(
70             std::vector<element::Type>{ element::f32, element::f32 },
71             std::vector<element::Type>{ element::f32 },
72             ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
73             ngraph::op::TemporaryReplaceOutputType(
74                 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 4, 1, 1, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
75                 element::f32).get(),
76             ngraph::Strides{ 1, 1 },
77             ngraph::CoordinateDiff{ 0, 0 },
78             ngraph::CoordinateDiff{ 0, 0 },
79             ngraph::Strides{ 1, 1 });
80     }
81     if (additionalLayer != "") {
82         parent = std::make_shared<ngraph::opset1::Add>(
83             parent,
84             std::make_shared<ngraph::opset1::Constant>(element::f32, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
85         parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
86                 parent,
87                 ngraph::element::f32,
88                 {256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
89     }
90     const auto dequantizationOp2 = is_type<ngraph::opset1::Constant>(parent) ? parent : makeDequantization(parent, dequantization2);
91
92     const auto add = std::make_shared<ngraph::opset1::Add>(dequantizationOp1, dequantizationOp2);
93
94     add->set_friendly_name("output");
95
96     ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(add) };
97     ngraph::ParameterVector parameters;
98     if (constInput == -1) {
99         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1), as_type_ptr<ngraph::opset1::Parameter>(input2) };
100     } else if (constInput == 0) {
101         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input2) };
102     } else if (constInput == 1) {
103         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1) };
104     } else {
105         THROW_IE_EXCEPTION << "Unexpected constant input index";
106     }
107     return std::make_shared<ngraph::Function>(results, parameters, "AddTransformation");
108 }
109
110 std::shared_ptr<ngraph::Function> AddFunction::getReference(
111     const ngraph::element::Type precision,
112     const ngraph::Shape& inputShape,
113     const bool broadcast,
114     const ngraph::pass::low_precision::LayerTransformation::Params& params,
115     const ngraph::element::Type& precision1,
116     const ngraph::builder::subgraph::DequantizationOperations& dequantization1,
117     const ngraph::element::Type& precision2,
118     const ngraph::builder::subgraph::DequantizationOperations& dequantization2,
119     const ngraph::builder::subgraph::DequantizationOperations& dequantizationAfter,
120     const int constInputIndex,
121     const std::vector<float>& constValues,
122     const std::string& additionalLayer,
123     const std::string& operationType) {
124     std::shared_ptr<ngraph::Node> input1;
125     if (constInputIndex == 0) {
126         input1 = std::make_shared<ngraph::opset1::Constant>(
127             precision,
128             inputShape,
129             constValues);
130     } else {
131         input1 = std::make_shared<ngraph::opset1::Parameter>(
132             precision1,
133             broadcast ? ngraph::Shape({ inputShape[0], inputShape[1], 1, 1 }) : ngraph::Shape(inputShape));
134     }
135
136     const auto dequantizationOp1 = is_type<ngraph::opset1::Constant>(input1) ? input1 : makeDequantization(input1, dequantization1);
137
138     std::shared_ptr<ngraph::Node> input2;
139     if (constInputIndex == 1) {
140         input2 = std::make_shared<ngraph::opset1::Constant>(
141             precision,
142             inputShape,
143             constValues);
144     } else {
145         input2 = std::make_shared<ngraph::opset1::Parameter>(
146             precision2, ngraph::Shape(inputShape));
147     }
148     auto parent = input2;
149     if (additionalLayer == "convolution") {
150         parent = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Convolution>>(
151             std::vector<element::Type>{ element::f32, element::f32 },
152             std::vector<element::Type>{ element::f32 },
153             ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
154             ngraph::op::TemporaryReplaceOutputType(
155                 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 1, 4, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
156                 element::f32).get(),
157             ngraph::Strides{ 1, 1 },
158             ngraph::CoordinateDiff{ 0, 0 },
159             ngraph::CoordinateDiff{ 0, 0 },
160             ngraph::Strides{ 1, 1 });
161     }
162     if (additionalLayer == "group_convolution") {
163         parent = std::make_shared< ngraph::op::TypeRelaxed<ngraph::opset1::GroupConvolution>>(
164             std::vector<element::Type>{ element::f32, element::f32 },
165             std::vector<element::Type>{ element::f32 },
166             ngraph::op::TemporaryReplaceOutputType(parent, element::f32).get(),
167             ngraph::op::TemporaryReplaceOutputType(
168                 std::make_shared<ngraph::opset1::Constant>(element::i8, Shape{ 4, 1, 1, 1, 1 }, std::vector<float>{0.8f, 0.8f, 0.8f, 0.8f}),
169                 element::f32).get(),
170             ngraph::Strides{ 1, 1 },
171             ngraph::CoordinateDiff{ 0, 0 },
172             ngraph::CoordinateDiff{ 0, 0 },
173             ngraph::Strides{ 1, 1 });
174     }
175     if (additionalLayer != "") {
176         parent = std::make_shared<ngraph::opset1::Add>(
177             parent,
178             std::make_shared<ngraph::opset1::Constant>(element::f32, Shape{ 1, 1, 1, 1 }, std::vector<float>{1.f}));
179         parent = ngraph::builder::subgraph::makeFakeQuantizeTypeRelaxed(
180                 parent,
181                 ngraph::element::f32,
182                 {256, Shape{}, { 0 }, { 255 }, { 0 }, { 255 }, element::u8});
183     }
184     const auto dequantizationOp2 = is_type<ngraph::opset1::Constant>(parent) ? parent : makeDequantization(parent, dequantization2);
185
186     const std::shared_ptr<Node> add = operationType == "Add" ?
187         std::dynamic_pointer_cast<Node>(std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Add>>(
188             std::vector<element::Type>{ element::f32, element::f32 },
189             std::vector<element::Type>{},
190             ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(),
191             ngraph::op::TemporaryReplaceOutputType(dequantizationOp2, element::f32).get())) :
192         std::make_shared<ngraph::op::TypeRelaxed<DequantizationSubtract>>(
193             std::vector<element::Type>{ element::f32, element::f32 },
194             std::vector<element::Type>{},
195             ngraph::op::TemporaryReplaceOutputType(dequantizationOp1, element::f32).get(),
196             ngraph::op::TemporaryReplaceOutputType(dequantizationOp2, element::f32).get());
197
198     NetworkHelper::setOutDataPrecisionForTypeRelaxed(add, precision);
199
200     const auto dequantizationOpAfter = makeDequantization(add, dequantizationAfter);
201
202     dequantizationOpAfter->set_friendly_name("output");
203
204     ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(dequantizationOpAfter) };
205     ngraph::ParameterVector parameters;
206     if (constInputIndex == -1) {
207         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1), as_type_ptr<ngraph::opset1::Parameter>(input2) };
208     } else if (constInputIndex == 0) {
209         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input2) };
210     } else if (constInputIndex == 1) {
211         parameters = { as_type_ptr<ngraph::opset1::Parameter>(input1) };
212     } else {
213         THROW_IE_EXCEPTION << "Unexpected constant input index";
214     }
215     return std::make_shared<ngraph::Function>(results, parameters, "AddTransformation");
216 }
217
218 }  // namespace subgraph
219 }  // namespace builder
220 }  // namespace ngraph