Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / tests / unit / inference_engine_tests / util_const_infer_test.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <gtest/gtest.h>
6
7 #include <initializer_list>
8 #include <string>
9 #include <utility>
10 #include <unordered_set>
11 #include <unordered_map>
12
13 #include <ie_util_internal.hpp>
14 #include <tests_common.hpp>
15 #include <graph_transformer.h>
16 #include "ie_utils.hpp"
17 #include "blob_factory.hpp"
18 #include "debug.h"
19 #include "util_test.hpp"
20 #include "util_const_infer_test.hpp"
21 #include <details/ie_cnn_network_tools.h>
22
23 namespace IE = InferenceEngine;
24
25 void RemoveLayerTests::SetUp() {
26     net = getNetwork();
27     originalLayersNum = net->allLayers().size();
28     testTransformator.reset(new ConstTransformatorTest(net.get()));
29 }
30
31 //
32 // I1-d1-L1-d4              I4
33 //       / \  \              \
34 //      |  d7  \            d10
35 //      |  |    \            /
36 //  I2-d2-L2-d5-L4-d6-L5-d9-L10
37 //        /           /
38 //       /  ____d8___/
39 //      /  /
40 // I3-d3-L3
41 //
42 IE::details::CNNNetworkImplPtr RemoveLayerTests::getNetwork() {
43     return netBuilder
44             .data("data1", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
45             .data("data2", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
46             .data("data3", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
47             .data("data4", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
48             .data("data5", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
49             .data("data6", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
50             .data("data7", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
51             .data("data8", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
52             .data("data9", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
53             .data("data10", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
54             .data("data11", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
55             .layer<IE::CNNLayer>(IE::LayerParams{"input1", "input", IE::Precision::FP32})
56             .layer<IE::CNNLayer>(IE::LayerParams{"input2", "Input", IE::Precision::FP32})
57             .layer<IE::CNNLayer>(IE::LayerParams{"input3", "input", IE::Precision::FP32})
58             .layer<IE::CNNLayer>(IE::LayerParams{"input4", "input", IE::Precision::FP32})
59             .layer<IE::CNNLayer>(IE::LayerParams{"layer1", "dummy", IE::Precision::FP32})
60             .layer<IE::CNNLayer>(IE::LayerParams{"layer2", "dummy", IE::Precision::FP32})
61             .layer<IE::CNNLayer>(IE::LayerParams{"layer3", "dummy", IE::Precision::FP32})
62             .layer<IE::CNNLayer>(IE::LayerParams{"layer4", "dummy", IE::Precision::FP32})
63             .layer<IE::CNNLayer>(IE::LayerParams{"layer5", "dummy", IE::Precision::FP32})
64             .layer<IE::CNNLayer>(IE::LayerParams{"layer6", "dummy", IE::Precision::FP32})
65             .linkToData("input1", "data1")
66             .linkToData("input2", "data2")
67             .linkToData("input3", "data3")
68             .linkToData("input4", "data10")
69
70             .linkDataTo("data1", "layer1")
71             .linkDataTo("data2", "layer2")
72             .linkDataTo("data2", "layer1")
73             .linkDataTo("data3", "layer3")
74             .linkDataTo("data3", "layer2")
75             .linkDataTo("data10", "layer6")
76
77             .linkToData("layer1", "data4")
78             .linkToData("layer1", "data7")
79             .linkToData("layer2", "data5")
80             .linkToData("layer3", "data8")
81
82             .linkDataTo("data4", "layer4")
83             .linkDataTo("data5", "layer4")
84             .linkDataTo("data8", "layer5")
85             .linkDataTo("data7", "layer2")
86
87             .linkToData("layer4", "data6")
88
89             .linkDataTo("data6", "layer5")
90
91             .linkToData("layer5", "data9")
92
93             .linkDataTo("data9", "layer6")
94
95             .linkToData("layer6", "data11")
96
97             .addInput("data1")
98             .addInput("data2")
99             .addInput("data3")
100             .finalize();
101 }
102
103 IE::CNNLayerPtr RemoveLayerTests::getLayer(const std::string& name) {
104     const auto& layers = netBuilder.getLayersMap();
105     auto it = layers.find(name);
106     if (it == layers.end()) throw std::logic_error("Failed to find layer: " + name);
107     return it->second;
108 }
109
110 IE::DataPtr RemoveLayerTests::getData(const std::string& name) {
111     const auto& datas = netBuilder.getDataMap();
112     auto it = datas.find(name);
113     if (it == datas.end()) throw std::logic_error("Failed to find data: " + name);
114     return it->second;
115 }
116
117 IE::BlobMap RemoveLayerTests::fillConstData(const std::vector<std::string>& constLayers) {
118     IE::BlobMap constData;
119     for (const auto& name:constLayers) {
120         auto layer = getLayer(name);
121         for (const auto& outData:layer->outData) {
122             IE::TensorDesc desc = outData->getTensorDesc();
123             IE::Blob::Ptr blob = make_blob_with_precision(desc);
124             blob->allocate();
125             auto* buffer = blob->buffer().as<float*>();
126             for (int i = 0; i < blob->size(); i++) {
127                 buffer[i] = i + 1;
128             }
129             constData[outData->name] = blob;
130         }
131     }
132     return constData;
133 }
134
135 IE::BlobMap RemoveLayerTests::initConstLayers(const std::vector<std::string>& constLayers) {
136     for (const auto& name : constLayers) {
137         getLayer(name)->type = "Const";
138     }
139     IE::BlobMap customBlobs = fillConstData(constLayers);
140     for (const auto& layerName: constLayers) {
141         auto layer = getLayer(layerName);
142         layer->type = "Const";
143         layer->blobs["custom"] = customBlobs[layer->outData[0]->name];
144     }
145     return customBlobs;
146 }
147
148 TEST_F(RemoveLayerTests, canTrimL2) {
149     auto layer1 = getLayer("layer1");
150     auto layer4 = getLayer("layer4");
151     auto data2 = getData("data2");
152     auto data3 = getData("data3");
153     auto data7 = getData("data7");
154     auto data5 = getData("data5");
155     std::vector<std::string> constLayers = {"layer2"};
156     std::vector<std::string> refNewLayers = {constLayers[0] + "__data5__Const"};
157     auto constData = fillConstData(constLayers);
158     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
159
160     auto newLayers = testTransformator->foldConstSubgraphsInternal({{constLayers[0], false}}, constData, sortedLayers);
161
162     ASSERT_EQ(newLayers, refNewLayers);
163     IE::CNNNetwork cnnNetwork(net);
164     ASSERT_THROW(cnnNetwork.getLayerByName("layer2"), IE::NotFound);
165     auto newLayer = cnnNetwork.getLayerByName(refNewLayers[0].c_str());
166     ASSERT_EQ(newLayer->type, "Const");
167     ASSERT_EQ(constData["data5"], newLayer->blobs.at("custom"));
168     ASSERT_EQ(nullptr, net->getData("data7"));
169     net->removeData("data7");
170     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
171     ASSERT_EQ(data2->inputTo.size(), 1);
172     ASSERT_EQ(data2->inputTo.find("layer1")->second, layer1);
173     ASSERT_EQ(data5->creatorLayer.lock(), newLayer);
174     ASSERT_EQ(layer4->insData.size(), 2);
175     ASSERT_EQ(layer4->insData[1].lock(), data5);
176     ASSERT_EQ(layer1->insData.size(), 2);
177     ASSERT_EQ(layer1->insData[0].lock(), getData("data1"));
178     ASSERT_EQ(layer1->insData[1].lock(), data2);
179     ASSERT_EQ(layer1->outData.size(), 1);
180     ASSERT_EQ(layer1->outData[0], getData("data4"));
181     ASSERT_EQ(newLayer->outData.size(), 1);
182     ASSERT_EQ(newLayer->outData[0], data5);
183     ASSERT_EQ(data3->inputTo.size(), 1);
184     ASSERT_EQ(data3->inputTo.find("layer3")->second, getLayer("layer3"));
185 }
186
187 TEST_F(RemoveLayerTests, canTrimI1andL1) {
188     auto layer4 = getLayer("layer4");
189     auto layer2 = getLayer("layer2");
190     auto data2 = getData("data2");
191     std::vector<std::string> constLayers = {"input1", "layer1"};
192     std::map<std::string, bool> mapConstLayers;
193     for (const auto& it : constLayers) {
194         mapConstLayers[it] = false;
195     }
196     std::vector<std::string> refNewLayers = {(constLayers[1] + "__data4__Const"), (constLayers[1] + "__data7__Const")};
197
198     auto constData = fillConstData(constLayers);
199     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
200     auto newLayers = testTransformator->foldConstSubgraphsInternal(mapConstLayers, constData, sortedLayers);
201
202     ASSERT_EQ(newLayers, refNewLayers);
203     IE::CNNNetwork cnnNetwork(net);
204     ASSERT_THROW(cnnNetwork.getLayerByName("input1"), IE::NotFound);
205     ASSERT_THROW(cnnNetwork.getLayerByName("layer1"), IE::NotFound);
206     auto newLayerD4 = cnnNetwork.getLayerByName(refNewLayers[0].c_str());
207     auto newLayerD7 = cnnNetwork.getLayerByName(refNewLayers[1].c_str());
208     auto newData4 = net->getData("data4__layer4");
209     auto newData7 = net->getData("data7__layer2");
210     ASSERT_EQ(newLayerD4->type, "Const");
211     ASSERT_EQ(newLayerD7->type, "Const");
212     ASSERT_EQ(constData["data4"], newLayerD4->blobs.at("custom"));
213     ASSERT_EQ(constData["data7"], newLayerD7->blobs.at("custom"));
214     ASSERT_EQ(nullptr, net->getData("data1"));
215     net->removeData("data1");
216     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
217     ASSERT_EQ(data2->inputTo.size(), 1);
218     ASSERT_EQ(data2->inputTo.find("layer2")->second, layer2);
219     ASSERT_EQ(newData4->creatorLayer.lock(), newLayerD4);
220     ASSERT_EQ(newData7->creatorLayer.lock(), newLayerD7);
221     ASSERT_EQ(newLayerD4->outData.size(), 1);
222     ASSERT_EQ(newLayerD7->outData.size(), 1);
223     ASSERT_EQ(newLayerD4->outData[0], newData4);
224     ASSERT_EQ(newLayerD7->outData[0], newData7);
225     ASSERT_EQ(layer4->insData.size(), 2);
226     ASSERT_EQ(layer4->insData[0].lock(), newData4);
227     ASSERT_EQ(layer4->insData[1].lock(), getData("data5"));
228     ASSERT_EQ(layer2->insData.size(), 3);
229     ASSERT_EQ(layer2->insData[0].lock(), data2);
230     ASSERT_EQ(layer2->insData[1].lock(), getData("data3"));
231     ASSERT_EQ(layer2->insData[2].lock(), newData7);
232 }
233
234 TEST_F(RemoveLayerTests, canFindConstLayers) {
235     getLayer("input1")->type = "Const";
236     getLayer("layer2")->type = "Shape";
237
238     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
239     auto constLayers = testTransformator->getConstLayers(sortedLayers);
240
241     ASSERT_EQ(constLayers.size(), 2);
242     auto begin = constLayers.begin();
243     auto end = constLayers.end();
244     ASSERT_FALSE(constLayers.at("input1"));
245     ASSERT_FALSE(constLayers.at("layer2"));
246 }
247
248 TEST_F(RemoveLayerTests, canFindConstLayers2) {
249     getLayer("input3")->type = "Const";
250     getLayer("input2")->type = "Const";
251     getLayer("layer2")->type = "Shape";
252
253     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
254     auto constLayers = testTransformator->getConstLayers(sortedLayers);
255
256     ASSERT_EQ(constLayers.size(), 4);
257     ASSERT_FALSE(constLayers.at("input3"));
258     ASSERT_FALSE(constLayers.at("layer2"));
259     ASSERT_FALSE(constLayers.at("layer3"));
260     ASSERT_FALSE(constLayers.at("input2"));
261 }
262
263 TEST_F(RemoveLayerTests, canFindConstLayers3) {
264     getLayer("input3")->type = "Const";
265     getLayer("layer2")->type = "Shape";
266     getLayer("layer1")->type = "Shape";
267     getLayer("layer4")->type = "Reshape";
268
269     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
270     auto constLayers = testTransformator->getConstLayers(sortedLayers);
271
272     ASSERT_EQ(constLayers.size(), 6);
273     ASSERT_FALSE(constLayers.at("input3"));
274     ASSERT_FALSE(constLayers.at("layer1"));
275     ASSERT_TRUE(constLayers.at("layer2"));
276     ASSERT_FALSE(constLayers.at("layer3"));
277     ASSERT_FALSE(constLayers.at("layer4"));
278     ASSERT_FALSE(constLayers.at("layer5"));
279 }
280
281 TEST_F(RemoveLayerTests, canFindShapeConstLayers) {
282     getLayer("input3")->type = "Const";
283     getLayer("layer2")->type = "Shape";
284     getLayer("layer1")->type = "Shape";
285     getLayer("layer6")->type = "Interp";
286
287     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
288     auto constLayers = testTransformator->getConstLayers(sortedLayers);
289
290     ASSERT_EQ(constLayers.size(), 6);
291     ASSERT_TRUE(constLayers.at("input3"));
292     ASSERT_TRUE(constLayers.at("layer1"));
293     ASSERT_TRUE(constLayers.at("layer2"));
294     ASSERT_TRUE(constLayers.at("layer3"));
295     ASSERT_TRUE(constLayers.at("layer4"));
296     ASSERT_TRUE(constLayers.at("layer5"));
297 }
298
299 TEST_F(RemoveLayerTests, canFindShapeConstLayers2) {
300     getLayer("input3")->type = "Const";
301     getLayer("input2")->type = "Const";
302     getLayer("layer2")->type = "Shape";
303     getLayer("layer1")->type = "Resample";
304
305     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
306     auto constLayers = testTransformator->getConstLayers(sortedLayers);
307
308     ASSERT_EQ(constLayers.size(), 4);
309     ASSERT_FALSE(constLayers.at("input3"));
310     ASSERT_FALSE(constLayers.at("layer2"));
311     ASSERT_FALSE(constLayers.at("layer3"));
312     ASSERT_FALSE(constLayers.at("input2"));
313 }
314
315 TEST_F(RemoveLayerTests, canTrimShapeInput) {
316     std::vector<std::string> constLayers = {"input3", "layer3", "input2"};
317     for (const auto& name : constLayers) {
318         getLayer(name)->type = "Const";
319     }
320     getLayer("layer2")->type = "Shape";
321     getLayer("layer1")->type = "Interp";
322     getLayer("layer4")->type = "Reshape";
323     getLayer("layer5")->type = "Reshape";
324     auto layer1 = getLayer("layer1");
325     auto layer4 = getLayer("layer4");
326     auto layer5 = getLayer("layer5");
327
328     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
329     auto mapConstLayers = testTransformator->getConstLayers(sortedLayers);
330     auto newLayers = testTransformator->foldConstSubgraphsInternal(mapConstLayers, {}, sortedLayers);
331     testTransformator->trimShapeInputs(newLayers);
332
333     ASSERT_EQ(nullptr, net->getData("data5"));
334     ASSERT_EQ(nullptr, net->getData("data2"));
335     net->removeData("data5");
336     net->removeData("data2");
337     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 3);
338     ASSERT_EQ(layer1->insData.size(), 1);
339     ASSERT_EQ(layer1->insData[0].lock(), getData("data1"));
340     ASSERT_EQ(layer4->insData.size(), 1);
341     ASSERT_EQ(layer4->insData[0].lock(), getData("data4"));
342     ASSERT_EQ(layer5->insData.size(), 2);
343     ASSERT_EQ(layer5->insData[0].lock(), getData("data8"));
344     ASSERT_EQ(layer5->insData[1].lock(), getData("data6"));
345 }
346
347 TEST_F(RemoveLayerTests, canTrimShapeInput2) {
348     std::vector<std::string> constLayers = {"input3", "input2"};
349     for (const auto& name : constLayers) {
350         getLayer(name)->type = "Const";
351     }
352     auto layer1 = getLayer("layer1");
353     auto layer2 = getLayer("layer2");
354     layer1->type = "Resample";
355     layer2->type = "StridedSlice";
356
357     testTransformator->trimShapeInputs(constLayers);
358
359     auto data6 = net->getData("data6");
360     auto data2 = net->getData("data2");
361     ASSERT_EQ(data2->inputTo.size(), 1);
362     ASSERT_EQ(data2->inputTo.at(layer2->name), layer2);
363     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
364     ASSERT_EQ(layer1->insData.size(), 1);
365     ASSERT_EQ(layer1->insData[0].lock(), getData("data1"));
366     ASSERT_EQ(layer2->insData.size(), 3);
367     ASSERT_EQ(layer2->insData[0].lock(), getData("data2"));
368     ASSERT_EQ(layer2->insData[1].lock(), getData("data3"));
369     ASSERT_EQ(layer2->insData[2].lock(), getData("data7"));
370 }
371
372 TEST_F(RemoveLayerTests, notTrimFirstConstInput) {
373     std::vector<std::string> testLayers = {"Interp", "Reshape", "Pad", "Gather", "Resample"};
374     std::string constLayer = "input4";
375     getLayer(constLayer)->type = "Const";
376     auto layer6 = getLayer("layer6");
377     auto data10 = getData("data10");
378     for (const auto& name: testLayers) {
379         layer6->type = name;
380
381         testTransformator->trimShapeInputs({constLayer});
382
383         ASSERT_EQ(net->allLayers().size(), originalLayersNum);
384         IE::CNNNetwork cnnNetwork(net);
385         auto input4 = cnnNetwork.getLayerByName(constLayer.c_str());
386         ASSERT_EQ(data10->inputTo.size(), 1);
387         ASSERT_EQ(data10->creatorLayer.lock(), input4);
388         ASSERT_EQ(layer6->insData.size(), 2);
389         ASSERT_EQ(layer6->insData[0].lock(), data10);
390         ASSERT_EQ(layer6->insData[1].lock(), getData("data9"));
391     }
392 }
393
394 TEST_F(RemoveLayerTests, canSaveConstForEltWise) {
395     auto input2 = getLayer("input2");
396     auto layer1 = getLayer("layer1");
397     auto data2 = getData("data2");
398     input2->type = "Const";
399     layer1->type = "Eltwise";
400
401     testTransformator->trimShapeInputs({input2->name});
402
403     IE::CNNNetwork cnnNetwork(net);
404     ASSERT_NO_THROW(input2 = cnnNetwork.getLayerByName(input2->name.c_str()));
405     ASSERT_EQ(net->allLayers().size(), 10);
406     ASSERT_EQ(layer1->insData.size(), 2);
407     ASSERT_EQ(layer1->insData[1].lock(), data2);
408     ASSERT_EQ(data2->inputTo.size(), 2);
409     ASSERT_EQ(data2->inputTo.at(layer1->name), layer1);
410     ASSERT_EQ(data2->creatorLayer.lock(), input2);
411 }
412
413 TEST_F(RemoveLayerTests, canSaveDataWithMultipleInputTo) {
414     auto input3 = getLayer("input3");
415     auto layer2 = getLayer("layer2");
416     auto layer3 = getLayer("layer3");
417     auto data3 = getData("data3");
418     input3->type = "Const";
419     layer2->type = "Reshape";
420
421     testTransformator->trimShapeInputs({input3->name});
422
423     IE::CNNNetwork cnnNetwork(net);
424     ASSERT_NO_THROW(input3 = cnnNetwork.getLayerByName(input3->name.c_str()));
425     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
426     ASSERT_EQ(layer2->insData.size(), 2);
427     ASSERT_EQ(layer2->insData[0].lock(), getData("data2"));
428     ASSERT_EQ(layer2->insData[1].lock(), getData("data7"));
429     ASSERT_EQ(data3->inputTo.size(), 1);
430     ASSERT_EQ(data3->inputTo.at(layer3->name), layer3);
431     ASSERT_EQ(data3->creatorLayer.lock(), input3);
432     ASSERT_EQ(layer3->insData.size(), 1);
433     ASSERT_EQ(layer3->insData[0].lock(), data3);
434 }
435
436 TEST_F(RemoveLayerTests, canFoldConstSubgraphToConst) {
437     std::vector<std::string> constLayers = {"input1", "input2", "input3"};
438     std::vector<std::string> refNewLayers = {"layer5__data9__Const"};
439     for (const auto& name : constLayers) {
440         getLayer(name)->type = "Const";
441     }
442     getLayer("layer2")->type = "Shape";
443
444     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
445     auto mapConstLayers = testTransformator->getConstLayers(sortedLayers);
446     auto newLayers = testTransformator->foldConstSubgraphsInternal(mapConstLayers, {}, sortedLayers);
447
448     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 7);
449     ASSERT_EQ(newLayers, refNewLayers);
450     IE::CNNNetwork cnnNetwork(net);
451     auto newLayer = cnnNetwork.getLayerByName(refNewLayers[0].c_str());
452     ASSERT_EQ(newLayer->type, "Const");
453     ASSERT_EQ(newLayer->outData[0], getData("data9"));
454 }
455
456 TEST_F(RemoveLayerTests, canGetConstData) {
457     std::vector<std::string> constLayers = {"input2", "input3", "layer3"};
458     IE::BlobMap refBlobs = initConstLayers(constLayers);
459     std::map<std::string, bool> mapConstLayers;
460     for (const auto& it : constLayers) {
461         mapConstLayers[it] = false;
462     }
463     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
464
465     auto actBlobs = testTransformator->getConstData(mapConstLayers, sortedLayers);
466
467     ASSERT_EQ(actBlobs.size(), refBlobs.size());
468     for (const auto& it: refBlobs) {
469         ASSERT_EQ(it.second, actBlobs[it.first]);
470     }
471 }
472
473 TEST_F(RemoveLayerTests, canGetConstDataForUnknownImpl) {
474     initConstLayers({"input1", "input2", "input3"});
475     {
476         getLayer("layer1")->type = "UNKNOWN";
477         getLayer("layer2")->type = "UNKNOWN";
478         getLayer("layer3")->type = "Shape";
479         getLayer("layer4")->type = "UNKNOWN";
480         getLayer("layer5")->type = "Mul";
481         getLayer("layer6")->type = "Reshape";
482     }
483     auto sortedLayers = IE::details::CNNNetSortTopologically(*net);
484     IE::SizeVector refShape = {1, 1, 3};
485
486     auto mapConstLayers = testTransformator->getConstLayers(sortedLayers);
487     auto actBlobs = testTransformator->getConstData(mapConstLayers, sortedLayers);
488
489     ASSERT_EQ(getData("data9")->getTensorDesc().getDims(), refShape);
490 }
491
492 TEST_F(RemoveLayerTests, canFoldConstSubgraphs) {
493     IE::BlobMap refBlobs = initConstLayers({"input1", "input2", "input3"});
494     std::vector<std::string> refNewLayers = {"layer5__data9__Const"};
495     {   // TODO: method for marking layers
496         getLayer("layer1")->type = "Mul";
497         getLayer("layer2")->type = "Shape";
498         getLayer("layer3")->type = "Power";
499         getLayer("layer3")->params = {{"power", "1"},
500                                       {"scale", "2"},
501                                       {"shift", "-4"}};
502         getLayer("layer4")->type = "Mul";
503         getLayer("layer5")->type = "Mul";
504     }
505     float arr[] = {-2.f, 0.f, 54.f};
506     auto ref5 = make_blob_with_precision(getData("data9")->getTensorDesc(), arr);
507
508     IE::ConstTransformer transformator(net.get());
509     transformator.foldConstSubgraphs();
510
511     IE::CNNNetwork cnnNetwork(net);
512     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 7);
513     auto newLayer = cnnNetwork.getLayerByName(refNewLayers[0].c_str());
514     auto actualBlob = newLayer->blobs["custom"];
515     ASSERT_NE(actualBlob, nullptr);
516     ASSERT_FALSE(actualBlob->buffer() == nullptr);
517     TestsCommon::compare(*actualBlob, *ref5);
518     ASSERT_EQ(newLayer->type, "Const");
519 }
520
521 TEST_F(RemoveLayerTests, canSkipConstCalculation) {
522     IE::BlobMap refBlobs = initConstLayers({"input1", "input2", "input3"});
523     getLayer("layer6")->type = "Reshape";
524
525     IE::ConstTransformer transformator(net.get());
526     transformator.foldConstSubgraphs();
527
528     IE::CNNNetwork cnnNetwork(net);
529     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 8);
530 }
531
532 TEST_F(RemoveLayerTests, canFoldConstWithUnknownImplForShapeDefiningLayers) {
533     IE::BlobMap refBlobs = initConstLayers({"input1", "input2", "input3"});
534     {
535         getLayer("layer1")->type = "UNKNOWN";
536         getLayer("layer2")->type = "UNKNOWN";
537         getLayer("layer3")->type = "Shape";
538         getLayer("layer4")->type = "Reshape";
539         getLayer("layer5")->type = "Mul";
540         getLayer("layer6")->type = "Reshape";
541     }
542
543     IE::ConstTransformer transformator(net.get());
544     transformator.foldConstSubgraphs();
545
546     IE::CNNNetwork cnnNetwork(net);
547     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 8);
548     ASSERT_EQ(getLayer("layer6")->insData.size(), 1);
549 }
550
551 TEST_F(RemoveLayerTests, throwErrorOnFoldWithUnknownImplForNotShapeDefiningLayers) {
552     IE::BlobMap refBlobs = initConstLayers({"input1", "input2", "input3"});
553     {
554         getLayer("layer1")->type = "UNKNOWN";
555         getLayer("layer2")->type = "Shape";
556         getLayer("layer3")->type = "Shape";
557         getLayer("layer4")->type = "Mul";
558         getLayer("layer5")->type = "Mul";
559         getLayer("layer6")->type = "Gather";
560     }
561
562     IE::ConstTransformer transformator(net.get());
563     ASSERT_THROW(transformator.foldConstSubgraphs(), IE::details::InferenceEngineException);
564 }
565
566 TEST_F(RemoveLayerTests, canFullTrim) {
567     IE::BlobMap refBlobs = initConstLayers({"input1", "input2", "input3"});
568     auto layer6 = getLayer("layer6");
569     {   // TODO: method for marking layers
570         getLayer("layer1")->type = "Mul";
571         getLayer("layer2")->type = "Shape";
572         getLayer("layer3")->type = "Power";
573         getLayer("layer3")->params = {{"power", "1"},
574                                       {"scale", "2"},
575                                       {"shift", "-4"}};
576         getLayer("layer4")->type = "Mul";
577         getLayer("layer5")->type = "Mul";
578         layer6->type = "Reshape";
579     }
580
581     IE::ConstTransformer transformator(net.get());
582     transformator.fullTrim();
583
584     IE::CNNNetwork cnnNetwork(net);
585     std::string newName = "layer5__data9__Const";
586     ASSERT_THROW(cnnNetwork.getLayerByName(newName.c_str()), IE::NotFound);
587     ASSERT_EQ(net->allLayers().size(), 2);
588     ASSERT_EQ(layer6->insData.size(), 1);
589     ASSERT_EQ(layer6->insData[0].lock(), getData("data10"));
590 }
591
592 TEST_F(RemoveLayerTests, canFullTrimConstToReshape) {
593     IE::BlobMap refBlobs = initConstLayers({"input2"});
594     auto layer1 = getLayer("layer1");
595     layer1->type = "Reshape";
596
597     IE::ConstTransformer transformator(net.get());
598     transformator.fullTrim();
599
600     IE::CNNNetwork cnnNetwork(net);
601     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
602     ASSERT_EQ(layer1->insData.size(), 1);
603     ASSERT_EQ(layer1->insData[0].lock(), getData("data1"));
604 }
605
606 TEST_F(AdvancedShapeInferTests, canReshape) {
607     //
608     // I2-d2-Shape
609     //         \
610     //         d3
611     //          \
612     //  I1-d1-Reshape-d4
613     //
614     net = netBuilder
615             .data("data1", IE::SizeVector{1, 1, 3}, IE::Precision::FP32, IE::Layout::CHW)
616             .data("data2", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
617             .data("data3", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
618             .data("data4", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
619             .layer<IE::CNNLayer>(IE::LayerParams{"input1", "input", IE::Precision::FP32})
620             .layer<IE::CNNLayer>(IE::LayerParams{"input2", "Input", IE::Precision::FP32})
621             .layer<IE::CNNLayer>(IE::LayerParams{"layer1", "Reshape", IE::Precision::FP32})
622             .layer<IE::CNNLayer>(IE::LayerParams{"layer2", "Shape", IE::Precision::FP32})
623             .linkToData("input1", "data1")
624             .linkToData("input2", "data2")
625             .linkDataTo("data1", "layer1")
626             .linkDataTo("data2", "layer2")
627             .linkToData("layer2", "data3")
628             .linkDataTo("data3", "layer1")
629             .linkToData("layer1", "data4")
630             .addInput("data1")
631             .addInput("data2")
632             .finalize();
633     originalLayersNum = net->allLayers().size();
634     IE::CNNNetwork cnnNetwork(net);
635     IE::SizeVector newShape = {1, 3, 1};
636     std::map<std::string, IE::SizeVector> inputShapes = {{"data2", newShape}};
637     cnnNetwork.reshape(inputShapes);
638
639     ASSERT_NO_THROW(cnnNetwork.getLayerByName("layer2"));
640     ASSERT_EQ(getData("data3")->getTensorDesc().getDims(), IE::SizeVector{3});
641     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
642
643     IE::ConstTransformer transformator(net.get());
644     transformator.fullTrim();
645
646     ASSERT_THROW(cnnNetwork.getLayerByName("layer2"), IE::NotFound);
647     ASSERT_EQ(getData("data4")->getTensorDesc().getDims(), newShape);
648     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 1);
649 }
650
651 TEST_F(AdvancedShapeInferTests, canReshape2) {
652     //
653     //                 I3-d3-Shape(L3)-d5
654     //                                  \
655     // I2-d2-Shape(L2)-d4-Power(L4)-d6-Mul(L5)-d7
656     //                                          \
657     //                                   I1-d1-Reshape(L1)-d8
658     //
659     net = netBuilder
660             .data("data1", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
661             .data("data2", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
662             .data("data3", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
663             .data("data4", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
664             .data("data5", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
665             .data("data6", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
666             .data("data7", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
667             .data("data8", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
668             .layer<IE::CNNLayer>(IE::LayerParams{"input1", "input", IE::Precision::FP32})
669             .layer<IE::CNNLayer>(IE::LayerParams{"input2", "Input", IE::Precision::FP32})
670             .layer<IE::CNNLayer>(IE::LayerParams{"input3", "Input", IE::Precision::FP32})
671             .layer<IE::CNNLayer>(IE::LayerParams{"layer1", "Reshape", IE::Precision::FP32})
672             .layer<IE::CNNLayer>(IE::LayerParams{"layer2", "Shape", IE::Precision::FP32})
673             .layer<IE::CNNLayer>(IE::LayerParams{"layer3", "Shape", IE::Precision::FP32})
674             .layer<IE::CNNLayer>(IE::LayerParams{"layer4", "Power", IE::Precision::FP32})
675             .layer<IE::CNNLayer>(IE::LayerParams{"layer5", "Mul", IE::Precision::FP32})
676             .linkToData("input1", "data1")
677             .linkToData("input2", "data2")
678             .linkToData("input3", "data3")
679
680             .linkDataTo("data1", "layer1")
681             .linkDataTo("data2", "layer2")
682             .linkDataTo("data3", "layer3")
683
684             .linkToData("layer2", "data4")
685             .linkToData("layer3", "data5")
686
687             .linkDataTo("data4", "layer4")
688
689             .linkToData("layer4", "data6")
690
691             .linkDataTo("data5", "layer5")
692             .linkDataTo("data6", "layer5")
693
694             .linkToData("layer5", "data7")
695
696             .linkDataTo("data7", "layer1")
697
698             .linkToData("layer1", "data8")
699
700             .addInput("data1")
701             .addInput("data2")
702             .addInput("data3")
703             .finalize();
704     originalLayersNum = net->allLayers().size();
705     IE::CNNNetwork cnnNetwork(net);
706     IE::SizeVector newShape = {5, 9, 3};
707     std::map<std::string, IE::SizeVector> inputShapes = {{"data1", {135}},
708                                                          {"data2", {2, 1, 1}},
709                                                          {"data3", {1, 3, 1}}};
710     getLayer("layer4")->params = {{"power", "1"},
711                                   {"scale", "2"},
712                                   {"shift", "1"}};
713
714     cnnNetwork.reshape(inputShapes);
715
716     ASSERT_EQ(getData("data7")->getTensorDesc().getDims(), IE::SizeVector{3});
717     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
718
719     IE::ConstTransformer transformator(net.get());
720     transformator.fullTrim();
721
722     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 4);
723     ASSERT_EQ(getData("data8")->getTensorDesc().getDims(), newShape);
724 }
725
726 TEST_F(AdvancedShapeInferTests, canReshapeConst) {
727     //
728     //    Const-d2
729     //           \
730     // I1-d1-Reshape(L1)-d3
731     //
732     net = netBuilder
733             .data("data1", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
734             .data("data2", IE::SizeVector{3}, IE::Precision::FP32, IE::Layout::C)
735             .data("data3", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
736             .layer<IE::CNNLayer>(IE::LayerParams{"input1", "input", IE::Precision::FP32})
737             .layer<IE::CNNLayer>(IE::LayerParams{"const1", "dummy", IE::Precision::FP32})
738             .layer<IE::CNNLayer>(IE::LayerParams{"layer1", "Reshape", IE::Precision::FP32})
739             .linkToData("input1", "data1")
740             .linkToData("const1", "data2")
741             .linkDataTo("data1", "layer1")
742             .linkDataTo("data2", "layer1")
743             .linkToData("layer1", "data3")
744             .addInput("data1")
745             .finalize();
746     originalLayersNum = net->allLayers().size();
747     IE::CNNNetwork cnnNetwork(net);
748     initConstLayers({"const1"});
749     IE::SizeVector newOutShape = {1, 2, 3};
750     IE::SizeVector newInShape = {IE::details::product(newOutShape)};
751
752     std::map<std::string, IE::SizeVector> inputShapes = {{"data1", newInShape}};
753
754     cnnNetwork.reshape(inputShapes);
755
756     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
757
758     IE::ConstTransformer transformator(net.get());
759     transformator.fullTrim();
760
761     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 1);
762     ASSERT_EQ(getData("data1")->getTensorDesc().getDims(), newInShape);
763     ASSERT_EQ(getData("data3")->getTensorDesc().getDims(), newOutShape);
764 }
765
766 TEST_F(AdvancedShapeInferTests, canReshapeCHWConst) {
767     //
768     //    Const-d1-Tile-d2
769     //
770     net = netBuilder
771             .data("data1", IE::SizeVector{3, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
772             .data("data2", IE::SizeVector{1, 1, 1}, IE::Precision::FP32, IE::Layout::CHW)
773             .layer<IE::CNNLayer>(IE::LayerParams{"const", "dummy", IE::Precision::FP32})
774             .layer<IE::CNNLayer>(IE::LayerParams{"tile", "Tile", IE::Precision::FP32})
775             .linkToData("const", "data1")
776             .linkDataTo("data1", "tile")
777             .linkToData("tile", "data2")
778             .addInput("data1")
779             .finalize();
780     getLayer("tile")->params = {{"axis",  "0"},
781                                 {"tiles", "2"}};
782     originalLayersNum = net->allLayers().size();
783     IE::CNNNetwork cnnNetwork(net);
784     initConstLayers({"const"});
785
786     cnnNetwork.reshape({});
787
788     IE::SizeVector expectedDims = {2, 1, 3};
789     ASSERT_EQ(getData("data2")->getTensorDesc().getDims(), expectedDims);
790 }
791
792 TEST_F(AdvancedShapeInferTests, canReshapeWithScalar) {
793     //
794     //   Scalar-d2
795     //           \
796     // I1-d1-Reshape(L1)-d3
797     //
798     net = netBuilder
799             .data("data1", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
800             .data("data2", IE::SizeVector{}, IE::Precision::FP32, IE::Layout::SCALAR)
801             .data("data3", IE::SizeVector{1}, IE::Precision::FP32, IE::Layout::C)
802             .layer<IE::CNNLayer>(IE::LayerParams{"input1", "input", IE::Precision::FP32})
803             .layer<IE::CNNLayer>(IE::LayerParams{"scalar", "dummy", IE::Precision::FP32})
804             .layer<IE::CNNLayer>(IE::LayerParams{"layer1", "Reshape", IE::Precision::FP32})
805             .linkToData("input1", "data1")
806             .linkToData("scalar", "data2")
807             .linkDataTo("data1", "layer1")
808             .linkDataTo("data2", "layer1")
809             .linkToData("layer1", "data3")
810             .addInput("data1")
811             .finalize();
812     originalLayersNum = net->allLayers().size();
813     IE::CNNNetwork cnnNetwork(net);
814     initConstLayers({"scalar"});
815     IE::SizeVector newOutShape = {1};
816     IE::SizeVector newInShape = {IE::details::product(newOutShape)};
817
818     std::map<std::string, IE::SizeVector> inputShapes = {{"data1", newInShape}};
819
820     cnnNetwork.reshape(inputShapes);
821
822     ASSERT_EQ(net->allLayers().size(), originalLayersNum);
823
824     IE::ConstTransformer transformator(net.get());
825     transformator.fullTrim();
826
827     ASSERT_EQ(net->allLayers().size(), originalLayersNum - 1);
828     ASSERT_EQ(getData("data1")->getTensorDesc().getDims(), newInShape);
829     ASSERT_EQ(getData("data3")->getTensorDesc().getDims(), newOutShape);
830 }