arm_compute v18.08
diff --git a/utils/GraphUtils.h b/utils/GraphUtils.h
index 5977083..3b09c6b 100644
--- a/utils/GraphUtils.h
+++ b/utils/GraphUtils.h
@@ -25,12 +25,15 @@
 #define __ARM_COMPUTE_GRAPH_UTILS_H__
 
 #include "arm_compute/core/PixelValue.h"
+#include "arm_compute/core/Utils.h"
 #include "arm_compute/core/utils/misc/Utility.h"
 #include "arm_compute/graph/Graph.h"
 #include "arm_compute/graph/ITensorAccessor.h"
 #include "arm_compute/graph/Types.h"
 #include "arm_compute/runtime/Tensor.h"
 
+#include "utils/CommonGraphOptions.h"
+
 #include <array>
 #include <random>
 #include <string>
@@ -150,29 +153,122 @@
     std::ostream     &_output_stream;
 };
 
-/** PPM accessor class */
-class PPMAccessor final : public graph::ITensorAccessor
+/** Image accessor class */
+class ImageAccessor final : public graph::ITensorAccessor
 {
 public:
     /** Constructor
      *
-     * @param[in] ppm_path     Path to PPM file
-     * @param[in] bgr          (Optional) Fill the first plane with blue channel (default = false)
-     * @param[in] preprocessor (Optional) PPM pre-processing object
+     * @param[in] filename     Image file
+     * @param[in] bgr          (Optional) Fill the first plane with blue channel (default = false - RGB format)
+     * @param[in] preprocessor (Optional) Image pre-processing object
      */
-    PPMAccessor(std::string ppm_path, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr);
+    ImageAccessor(std::string filename, bool bgr = true, std::unique_ptr<IPreprocessor> preprocessor = nullptr);
     /** Allow instances of this class to be move constructed */
-    PPMAccessor(PPMAccessor &&) = default;
+    ImageAccessor(ImageAccessor &&) = default;
 
     // Inherited methods overriden:
     bool access_tensor(ITensor &tensor) override;
 
 private:
-    const std::string              _ppm_path;
+    bool                           _already_loaded;
+    const std::string              _filename;
     const bool                     _bgr;
     std::unique_ptr<IPreprocessor> _preprocessor;
 };
 
+/** Input Accessor used for network validation */
+class ValidationInputAccessor final : public graph::ITensorAccessor
+{
+public:
+    /** Constructor
+     *
+     * @param[in]  image_list    File containing all the images to validate
+     * @param[in]  images_path   Path to images.
+     * @param[in]  bgr           (Optional) Fill the first plane with blue channel (default = false - RGB format)
+     * @param[in]  preprocessor  (Optional) Image pre-processing object  (default = nullptr)
+     * @param[in]  start         (Optional) Start range
+     * @param[in]  end           (Optional) End range
+     * @param[out] output_stream (Optional) Output stream
+     *
+     * @note Range is defined as [start, end]
+     */
+    ValidationInputAccessor(const std::string             &image_list,
+                            std::string                    images_path,
+                            std::unique_ptr<IPreprocessor> preprocessor  = nullptr,
+                            bool                           bgr           = true,
+                            unsigned int                   start         = 0,
+                            unsigned int                   end           = 0,
+                            std::ostream                  &output_stream = std::cout);
+
+    // Inherited methods overriden:
+    bool access_tensor(ITensor &tensor) override;
+
+private:
+    std::string                    _path;
+    std::vector<std::string>       _images;
+    std::unique_ptr<IPreprocessor> _preprocessor;
+    bool                           _bgr;
+    size_t                         _offset;
+    std::ostream                  &_output_stream;
+};
+
+/** Output Accessor used for network validation */
+class ValidationOutputAccessor final : public graph::ITensorAccessor
+{
+public:
+    /** Default Constructor
+     *
+     * @param[in]  image_list    File containing all the images and labels results
+     * @param[out] output_stream (Optional) Output stream (Defaults to the standard output stream)
+     * @param[in]  start         (Optional) Start range
+     * @param[in]  end           (Optional) End range
+     *
+     * @note Range is defined as [start, end]
+     */
+    ValidationOutputAccessor(const std::string &image_list,
+                             std::ostream      &output_stream = std::cout,
+                             unsigned int       start         = 0,
+                             unsigned int       end           = 0);
+    /** Reset accessor state */
+    void reset();
+
+    // Inherited methods overriden:
+    bool access_tensor(ITensor &tensor) override;
+
+private:
+    /** Access predictions of the tensor
+     *
+     * @tparam T Tensor elements type
+     *
+     * @param[in] tensor Tensor to read the predictions from
+     */
+    template <typename T>
+    std::vector<size_t> access_predictions_tensor(ITensor &tensor);
+    /** Aggregates the results of a sample
+     *
+     * @param[in]     res              Vector containing the results of a graph
+     * @param[in,out] positive_samples Positive samples to be updated
+     * @param[in]     top_n            Top n accuracy to measure
+     * @param[in]     correct_label    Correct label of the current sample
+     */
+    void aggregate_sample(const std::vector<size_t> &res, size_t &positive_samples, size_t top_n, size_t correct_label);
+    /** Reports top N accuracy
+     *
+     * @param[in] top_n            Top N accuracy that is being reported
+     * @param[in] total_samples    Total number of samples
+     * @param[in] positive_samples Positive samples
+     */
+    void report_top_n(size_t top_n, size_t total_samples, size_t positive_samples);
+
+private:
+    std::vector<int> _results;
+    std::ostream    &_output_stream;
+    size_t           _offset;
+    size_t           _positive_samples_top1;
+    size_t           _positive_samples_top5;
+};
+
 /** Result accessor class */
 class TopNPredictionsAccessor final : public graph::ITensorAccessor
 {
@@ -245,6 +341,7 @@
     bool access_tensor(ITensor &tensor) override;
 
 private:
+    bool              _already_loaded;
     const std::string _filename;
     const DataLayout  _file_layout;
 };
@@ -286,56 +383,79 @@
     }
 }
 
-/** Generates appropriate input accessor according to the specified ppm_path
+/** Generates appropriate input accessor according to the specified graph parameters
  *
- * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor
- *
- * @param[in] ppm_path     Path to PPM file
- * @param[in] preprocessor Preproccessor object
- * @param[in] bgr          (Optional) Fill the first plane with blue channel (default = true)
+ * @param[in] graph_parameters Graph parameters
+ * @param[in] preprocessor     (Optional) Preproccessor object
+ * @param[in] bgr              (Optional) Fill the first plane with blue channel (default = true)
  *
  * @return An appropriate tensor accessor
  */
-inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const std::string             &ppm_path,
-                                                                  std::unique_ptr<IPreprocessor> preprocessor = nullptr,
-                                                                  bool                           bgr          = true)
+inline std::unique_ptr<graph::ITensorAccessor> get_input_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
+                                                                  std::unique_ptr<IPreprocessor>               preprocessor = nullptr,
+                                                                  bool                                         bgr          = true)
 {
-    if(ppm_path.empty())
+    if(!graph_parameters.validation_file.empty())
     {
-        return arm_compute::support::cpp14::make_unique<DummyAccessor>();
+        return arm_compute::support::cpp14::make_unique<ValidationInputAccessor>(graph_parameters.validation_file,
+                                                                                 graph_parameters.validation_path,
+                                                                                 std::move(preprocessor),
+                                                                                 bgr,
+                                                                                 graph_parameters.validation_range_start,
+                                                                                 graph_parameters.validation_range_end);
     }
     else
     {
-        if(arm_compute::utility::endswith(ppm_path, ".npy"))
+        const std::string &image_file       = graph_parameters.image;
+        const std::string &image_file_lower = lower_string(image_file);
+        if(arm_compute::utility::endswith(image_file_lower, ".npy"))
         {
-            return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(ppm_path);
+            return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(image_file);
+        }
+        else if(arm_compute::utility::endswith(image_file_lower, ".jpeg")
+                || arm_compute::utility::endswith(image_file_lower, ".jpg")
+                || arm_compute::utility::endswith(image_file_lower, ".ppm"))
+        {
+            return arm_compute::support::cpp14::make_unique<ImageAccessor>(image_file, bgr, std::move(preprocessor));
         }
         else
         {
-            return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, bgr, std::move(preprocessor));
+            return arm_compute::support::cpp14::make_unique<DummyAccessor>();
         }
     }
 }
 
-/** Generates appropriate output accessor according to the specified labels_path
+/** Generates appropriate output accessor according to the specified graph parameters
  *
- * @note If labels_path is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
+ * @note If the output accessor is requested to validate the graph then ValidationOutputAccessor is generated
+ *       else if output_accessor_file is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
  *
- * @param[in]  labels_path   Path to labels text file
- * @param[in]  top_n         (Optional) Number of output classes to print
- * @param[out] output_stream (Optional) Output stream
+ * @param[in]  graph_parameters Graph parameters
+ * @param[in]  top_n            (Optional) Number of output classes to print (default = 5)
+ * @param[in]  is_validation    (Optional) Validation flag (default = false)
+ * @param[out] output_stream    (Optional) Output stream (default = std::cout)
  *
  * @return An appropriate tensor accessor
  */
-inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout)
+inline std::unique_ptr<graph::ITensorAccessor> get_output_accessor(const arm_compute::utils::CommonGraphParams &graph_parameters,
+                                                                   size_t                                       top_n         = 5,
+                                                                   bool                                         is_validation = false,
+                                                                   std::ostream                                &output_stream = std::cout)
 {
-    if(labels_path.empty())
+    if(!graph_parameters.validation_file.empty())
+    {
+        return arm_compute::support::cpp14::make_unique<ValidationOutputAccessor>(graph_parameters.validation_file,
+                                                                                  output_stream,
+                                                                                  graph_parameters.validation_range_start,
+                                                                                  graph_parameters.validation_range_end);
+    }
+    else if(graph_parameters.labels.empty())
     {
         return arm_compute::support::cpp14::make_unique<DummyAccessor>(0);
     }
     else
     {
-        return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
+        return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(graph_parameters.labels, top_n, output_stream);
     }
 }
 /** Generates appropriate npy output accessor according to the specified npy_path
@@ -361,6 +481,24 @@
     }
 }
 
+/** Permutes a given tensor shape given the input and output data layout
+ *
+ * @param[in] tensor_shape    Tensor shape to permute
+ * @param[in] in_data_layout  Input tensor shape data layout
+ * @param[in] out_data_layout Output tensor shape data layout
+ *
+ * @return Permuted tensor shape
+ */
+inline TensorShape permute_shape(TensorShape tensor_shape, DataLayout in_data_layout, DataLayout out_data_layout)
+{
+    if(in_data_layout != out_data_layout)
+    {
+        arm_compute::PermutationVector perm_vec = (in_data_layout == DataLayout::NCHW) ? arm_compute::PermutationVector(2U, 0U, 1U) : arm_compute::PermutationVector(1U, 2U, 0U);
+        arm_compute::permute(tensor_shape, perm_vec);
+    }
+    return tensor_shape;
+}
+
 /** Utility function to return the TargetHint
  *
  * @param[in] target Integer value which expresses the selected target. Must be 0 for NEON or 1 for OpenCL or 2 (OpenCL with Tuner)