Deprecate nGraph v0 ops and builders (#1856)
[platform/upstream/dldt.git] / ngraph / test / specialize_function.cpp
1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16
17 #include "gtest/gtest.h"
18
19 #include "ngraph/ngraph.hpp"
20 #include "ngraph/specialize_function.hpp"
21
22 NGRAPH_SUPPRESS_DEPRECATED_START
23
24 using namespace ngraph;
25
26 // Simple case: create a function with static parameter shapes and "specialize" them to the same
27 // shapes.
28 TEST(specialize_function, et_shape_static)
29 {
30     auto p0 = std::make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
31     auto p1 = std::make_shared<op::Parameter>(element::i32, Shape{1, 2, 3});
32
33     auto k = std::make_shared<op::Convert>(p1, element::f32);
34     auto a = p0 + k;
35
36     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
37
38     std::vector<void*> param_vals{nullptr, nullptr};
39
40     auto g = specialize_function(f,
41                                  {element::f32, element::i32},
42                                  {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
43                                  param_vals);
44
45     ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
46     ASSERT_EQ(g->get_output_element_type(0), element::f32);
47 }
48
49 // Test specialization of dynamic element types.
50 TEST(specialize_function, et_dynamic_shape_static)
51 {
52     auto p0 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
53     auto p1 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
54
55     auto k = std::make_shared<op::Convert>(p1, element::f32);
56     auto a = p0 + k;
57
58     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
59
60     std::vector<void*> param_vals{nullptr, nullptr};
61
62     auto g = specialize_function(f,
63                                  {element::f32, element::i32},
64                                  {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
65                                  param_vals);
66
67     ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
68     ASSERT_EQ(g->get_output_element_type(0), element::f32);
69 }
70
71 // Test specialization of rank-dynamic shapes.
72 TEST(specialize_function, et_static_shape_rank_dynamic)
73 {
74     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
75     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic());
76
77     auto k = std::make_shared<op::Convert>(p1, element::f32);
78     auto a = p0 + k;
79
80     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
81
82     std::vector<void*> param_vals{nullptr, nullptr};
83
84     auto g = specialize_function(f,
85                                  {element::f32, element::i32},
86                                  {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
87                                  param_vals);
88
89     ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
90     ASSERT_EQ(g->get_output_element_type(0), element::f32);
91 }
92
93 // Test specialization of rank-static dynamic shapes.
94 TEST(specialize_function, et_static_shape_rank_static_dynamic)
95 {
96     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
97     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
98
99     auto k = std::make_shared<op::Convert>(p1, element::f32);
100     auto a = p0 + k;
101
102     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
103
104     std::vector<void*> param_vals{nullptr, nullptr};
105
106     auto g = specialize_function(f,
107                                  {element::f32, element::i32},
108                                  {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
109                                  param_vals);
110
111     ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
112     ASSERT_EQ(g->get_output_element_type(0), element::f32);
113 }
114
115 // Test specialization of values to a shape-dynamic parameters.
116 TEST(specialize_function, et_static_shape_rank_static_dynamic_subst_val)
117 {
118     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
119     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
120
121     auto k = std::make_shared<op::Convert>(p1, element::f32);
122     auto a = p0 + k;
123
124     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
125
126     std::vector<int32_t> p1_subst_vals{5, 0, 3, 8, 5, 8};
127
128     std::vector<void*> param_vals{nullptr, p1_subst_vals.data()};
129
130     auto g = specialize_function(f,
131                                  {element::f32, element::i32},
132                                  {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
133                                  param_vals);
134
135     ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
136     ASSERT_EQ(g->get_output_element_type(0), element::f32);
137
138     auto plus_node =
139         as_type_ptr<op::Add>(g->get_results().at(0)->input_value(0).get_node_shared_ptr());
140     ASSERT_TRUE(plus_node);
141     auto convert_node = as_type_ptr<op::Convert>(plus_node->input_value(1).get_node_shared_ptr());
142     ASSERT_TRUE(convert_node);
143     auto const_node = as_type_ptr<op::Constant>(convert_node->input_value(0).get_node_shared_ptr());
144     ASSERT_TRUE(const_node);
145
146     ASSERT_EQ(const_node->get_output_element_type(0), element::i32);
147     ASSERT_EQ(const_node->get_output_shape(0), (Shape{1, 2, 3}));
148     ASSERT_EQ(const_node->get_vector<int32_t>(), p1_subst_vals);
149 }
150
151 // Test specialization of rank-dynamic shapes to a case where validation will fail.
152 //
153 // (The input shapes we provide at specialization time are inconsistent.)
154 TEST(specialize_function, et_static_shape_rank_dynamic_validation_fails)
155 {
156     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
157     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic());
158
159     auto k = std::make_shared<op::Convert>(p1, element::f32);
160     auto a = p0 + k;
161
162     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
163
164     std::vector<void*> param_vals{nullptr, nullptr};
165
166     ASSERT_THROW(
167         {
168             specialize_function(f,
169                                 {element::f32, element::i32},
170                                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3, 4}},
171                                 param_vals);
172         },
173         NodeValidationFailure);
174 }
175
176 // Test specialization of dynamic element types to a case where validation will fail.
177 //
178 // (The input element types we provide at specialization time are inconsistent.)
179 TEST(specialize_function, et_dynamic_shape_static_validation_fails)
180 {
181     auto p0 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
182     auto p1 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
183
184     auto k = std::make_shared<op::Convert>(p1, element::f32);
185     auto a = p0 + k;
186
187     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
188
189     std::vector<void*> param_vals{nullptr, nullptr};
190
191     ASSERT_THROW(
192         {
193             specialize_function(f,
194                                 {element::u32, element::i32},
195                                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
196                                 param_vals);
197         },
198         NodeValidationFailure);
199 }
200
201 // Test specialization of rank-static dynamic shapes, where the replacement shapes have the wrong
202 // rank.
203 //
204 // (Note that we are testing for a different exception class here because the failure is in
205 // specialize_shape's pre-checks, which use NGRAPH_CHECK, rather than inside validation as we
206 // reconstruct the graph.)
207 TEST(specialize_function, et_static_shape_rank_static_dynamic_rank_mismatch)
208 {
209     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
210     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
211
212     auto k = std::make_shared<op::Convert>(p1, element::f32);
213     auto a = p0 + k;
214
215     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
216
217     std::vector<void*> param_vals{nullptr, nullptr};
218
219     ASSERT_THROW(
220         {
221             specialize_function(f,
222                                 {element::f32, element::i32},
223                                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3, 4}},
224                                 param_vals);
225         },
226         CheckFailure);
227 }
228
229 // Test specialization of rank-static dynamic shapes, where the replacement shapes have wrong
230 // dimensions.
231 //
232 // (Note that we are testing for a different exception class here because the failure is in
233 // specialize_shape's pre-checks, which use NGRAPH_CHECK, rather than inside validation as we
234 // reconstruct the graph.)
235 TEST(specialize_function, et_static_shape_rank_static_dynamic_dim_mismatch)
236 {
237     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
238     auto p1 =
239         std::make_shared<op::Parameter>(element::i32, PartialShape{1, Dimension::dynamic(), 3});
240
241     auto k = std::make_shared<op::Convert>(p1, element::f32);
242     auto a = p0 + k;
243
244     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
245
246     std::vector<void*> param_vals{nullptr, nullptr};
247
248     ASSERT_THROW(
249         {
250             specialize_function(f,
251                                 {element::f32, element::i32},
252                                 {PartialShape{1, 2, 3}, PartialShape{1, 9, 4}},
253                                 param_vals);
254         },
255         CheckFailure);
256 }
257
258 // Test for failure when we supply the wrong number of replacement element types.
259 TEST(specialize_function, et_count_wrong)
260 {
261     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
262     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
263
264     auto k = std::make_shared<op::Convert>(p1, element::f32);
265     auto a = p0 + k;
266
267     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
268
269     std::vector<void*> param_vals{nullptr, nullptr};
270
271     ASSERT_THROW(
272         {
273             specialize_function(f,
274                                 {element::f32, element::i32, element::u32},
275                                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
276                                 param_vals);
277         },
278         CheckFailure);
279 }
280
281 // Test for failure when we supply the wrong number of replacement shapes.
282 TEST(specialize_function, shape_count_wrong)
283 {
284     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
285     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
286
287     auto k = std::make_shared<op::Convert>(p1, element::f32);
288     auto a = p0 + k;
289
290     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
291
292     std::vector<void*> param_vals{nullptr, nullptr};
293
294     ASSERT_THROW(
295         {
296             specialize_function(
297                 f,
298                 {element::f32, element::i32},
299                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}, PartialShape{4, 5, 6}},
300                 param_vals);
301         },
302         CheckFailure);
303 }
304
305 // Test for failure when we supply the wrong number of replacement parameter values.
306 TEST(specialize_function, value_count_wrong)
307 {
308     auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
309     auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
310
311     auto k = std::make_shared<op::Convert>(p1, element::f32);
312     auto a = p0 + k;
313
314     auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
315
316     std::vector<void*> param_vals{nullptr, nullptr, nullptr};
317
318     ASSERT_THROW(
319         {
320             specialize_function(f,
321                                 {element::f32, element::i32},
322                                 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
323                                 param_vals);
324         },
325         CheckFailure);
326 }