diff --git a/src/report/DataSyncReport.java b/src/report/DataSyncReport.java
index 1fde09e235c5cd31357d5c38070d1d8490017744..573f23aa2b7dab651a046d364021d23515a29053 100644
--- a/src/report/DataSyncReport.java
+++ b/src/report/DataSyncReport.java
@@ -127,6 +127,7 @@ public class DataSyncReport extends SamplingReport{
         //Write out statistics gathered over all hosts with database
         write("sim_time: " + format(getSimTime()) +", "+
                 "avg_used_mem: " + getAverage(usedDataBasePercentage) +"%, "+
+                "min_used_mem: " + getMinimum(usedDataBasePercentage) +"%, "+
                 "max_used_mem: " + getMaximum(usedDataBasePercentage) +"%, "+
                 "med_avg_data_util: " + getMedian(averageDataUtility)+ ", "+
                 "avg_data_util: " + getAverage(averageDataUtility) + ", "+
diff --git a/src/report/Report.java b/src/report/Report.java
index 1b9be30127baa6e46572ce35c341d9fe89fbe604..479e69888737a25cf797301b667ef0028886e107 100644
--- a/src/report/Report.java
+++ b/src/report/Report.java
@@ -414,6 +414,21 @@ public abstract class Report {
         return format(max);
     }
 
+    /**
+     * Returns the minimum of the values in the list
+     * as a formatted string with the given numerical precision.
+     * Return "NaN" for empty lists.
+     *
+     * @param values the list to search the minimum in
+     * @return a formatted string of the minimum in the list
+     */
+    public String getMinimum(List<Double> values){
+        if (values.isEmpty()){
+            return NAN;
+        }
+        double min = Collections.min(values);
+        return format(min);
+    }
 	/**
 	 * Returns the variance of the values in the List.
 	 *
diff --git a/src/test/DataSyncReportTest.java b/src/test/DataSyncReportTest.java
index b22a8df6fbac739724569938e1ebf375a7be0ad0..eda30cb19aa13b3ef7e58fa0900fd86a10108159 100644
--- a/src/test/DataSyncReportTest.java
+++ b/src/test/DataSyncReportTest.java
@@ -35,30 +35,30 @@ public class DataSyncReportTest extends AbstractReportTest{
     private static final long SMALLEST_DB_SIZE = 200L;
 
     /* String arrays containing all the expected metrics and ratios to check whether everything necessary is contained*/
-    private static final String[] EXPECTED_METRICS = new String[]{"avg_used_mem", "max_used_mem", "med_avg_data_util",
-            "avg_data_util", "med_avg_data_age", "avg_data_age", "med_max_data_age", "med_avg_data_dist",
-            "avg_data_dist", "med_max_data_dist"};
+    private static final String[] EXPECTED_METRICS = new String[]{"avg_used_mem", "min_used_mem", "max_used_mem",
+            "med_avg_data_util", "avg_data_util", "med_avg_data_age", "avg_data_age", "med_max_data_age",
+            "med_avg_data_dist", "avg_data_dist", "med_max_data_dist"};
     private static final String[] EXPECTED_RATIOS= new String[]{"avg_ratio_map", "avg_ratio_marker",
             "avg_ratio_skill", "avg_ratio_res"};
 
     /* Expected lines */
     private static final String EXPECTED_FIRST_LINE="Data sync stats for scenario TEST-Scenario";
     private static final String[] EXPECTED_OUTPUTS= new String []{
-            "sim_time: 51.0, avg_used_mem: 0.0%, max_used_mem: 0.0%, med_avg_data_util: NaN, avg_data_util: NaN, " +
-                    "med_avg_data_age: NaN, avg_data_age: NaN, med_max_data_age: NaN, med_avg_data_dist: NaN, " +
-                    "avg_data_dist: NaN, med_max_data_dist: NaN",
+            "sim_time: 51.0, avg_used_mem: 0.0%, min_used_mem: 0.0%, max_used_mem: 0.0%, med_avg_data_util: NaN, " +
+                    "avg_data_util: NaN, med_avg_data_age: NaN, avg_data_age: NaN, med_max_data_age: NaN, " +
+                    "med_avg_data_dist: NaN, avg_data_dist: NaN, med_max_data_dist: NaN",
             "avg_ratio_map: NaN%, avg_ratio_marker: NaN%, avg_ratio_skill: NaN%, avg_ratio_res: NaN%",
-            "sim_time: 81.0, avg_used_mem: 3.7%, max_used_mem: 7.3%, med_avg_data_util: 1.0, avg_data_util: 1.0, " +
-                    "med_avg_data_age: NaN, avg_data_age: NaN, med_max_data_age: NaN, med_avg_data_dist: 0.0, " +
-                    "avg_data_dist: 0.0, med_max_data_dist: 0.0",
+            "sim_time: 81.0, avg_used_mem: 3.7%, min_used_mem: 0.0%, max_used_mem: 7.3%, med_avg_data_util: 1.0, " +
+                    "avg_data_util: 1.0, med_avg_data_age: NaN, avg_data_age: NaN, med_max_data_age: NaN, " +
+                    "med_avg_data_dist: 0.0, avg_data_dist: 0.0, med_max_data_dist: 0.0",
             "avg_ratio_map: 100.0%, avg_ratio_marker: 0.0%, avg_ratio_skill: 0.0%, avg_ratio_res: 0.0%",
-            "sim_time: 111.0, avg_used_mem: 8.1%, max_used_mem: 8.8%, med_avg_data_util: 1.0, avg_data_util: 1.0, " +
-                    "med_avg_data_age: 91.0, avg_data_age: 91.0, med_max_data_age: 91.0, med_avg_data_dist: 565.7, " +
-                    "avg_data_dist: 282.8, med_max_data_dist: 565.7",
+            "sim_time: 111.0, avg_used_mem: 8.1%, min_used_mem: 7.3%, max_used_mem: 8.8%, med_avg_data_util: 1.0, " +
+                    "avg_data_util: 1.0, med_avg_data_age: 91.0, avg_data_age: 91.0, med_max_data_age: 91.0, " +
+                    "med_avg_data_dist: 565.7, avg_data_dist: 282.8, med_max_data_dist: 565.7",
             "avg_ratio_map: 50.0%, avg_ratio_marker: 0.0%, avg_ratio_skill: 50.0%, avg_ratio_res: 0.0%",
-            "sim_time: 141.0, avg_used_mem: 22.7%, max_used_mem: 30.8%, med_avg_data_util: 1.0, avg_data_util: 0.9, " +
-                    "med_avg_data_age: 121.0, avg_data_age: 90.8, med_max_data_age: 121.0, med_avg_data_dist: 848.5, " +
-                    "avg_data_dist: 565.7, med_max_data_dist: 1131.4",
+            "sim_time: 141.0, avg_used_mem: 22.7%, min_used_mem: 14.7%, max_used_mem: 30.8%, med_avg_data_util: 1.0, " +
+                    "avg_data_util: 0.9, med_avg_data_age: 121.0, avg_data_age: 90.8, med_max_data_age: 121.0, " +
+                    "med_avg_data_dist: 848.5, avg_data_dist: 565.7, med_max_data_dist: 1131.4",
             "avg_ratio_map: 25.0%, avg_ratio_marker: 25.0%, avg_ratio_skill: 50.0%, avg_ratio_res: 0.0%"
     };
 
diff --git a/src/test/ReportTest.java b/src/test/ReportTest.java
index a041c5d8bd232c52acebceb19a9f8b54dde5bc22..05693714ce714d71cfd1df6e5fd9c769df4ef6b8 100644
--- a/src/test/ReportTest.java
+++ b/src/test/ReportTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.*;
 public class ReportTest {
 
     private static final String WRONG_MAXIMUM = "The maximum was computed or formatted incorrectly.";
+    private static final String WRONG_MINIMUM = "The minimum was computed or formatted incorrectly.";
 
     private File outputFile;
     private Report report;
@@ -73,6 +74,24 @@ public class ReportTest {
         assertEquals(WRONG_MAXIMUM, "100.3000", report.getMaximum(valuesWithMaxTwice));
     }
 
+    @Test
+    public void testGetMinimumReturnsNaNForEmptyList(){
+        List<Double> values = new ArrayList<>();
+        assertEquals("For empty lists, NaN should be returned", "NaN", report.getMinimum(values));
+    }
+
+    @Test
+    public void testGetMinimumReturnsMinimum(){
+        final List<Double> values = Arrays.asList(3.0, -1.2, 100.0, 100.3, 0.07);
+        assertEquals(WRONG_MINIMUM, "-1.2000", report.getMinimum(values));
+        final List<Double> valuesWithNegativeMin = Arrays.asList(-3.0, -1.2, -100.0, -100.3, -0.07);
+        assertEquals(WRONG_MINIMUM, "-100.3000", report.getMinimum(valuesWithNegativeMin));
+        final List<Double> valuesWithSameNumberTwice = Arrays.asList(30.0, -1.2, 100.0, 100.3, -0.07, 100.0);
+        assertEquals(WRONG_MINIMUM, "-1.2000", report.getMinimum(valuesWithSameNumberTwice));
+        final  List<Double> valuesWithMinTwice = Arrays.asList(30.0, 1.2, 100.0, 100.3, 0.07, 100.3, 0.07);
+        assertEquals(WRONG_MINIMUM, "0.0700", report.getMinimum(valuesWithMinTwice));
+    }
+
     @After
     public void cleanUp() {
         SimScenario.reset();
diff --git a/toolkit/reportSummary/dataSyncAnalysis.py b/toolkit/reportSummary/dataSyncAnalysis.py
index 0cae787ac5343627fd55376813926164e1bd32f8..f714e522849e5dda85b6ee434f5538392a8aa1d2 100644
--- a/toolkit/reportSummary/dataSyncAnalysis.py
+++ b/toolkit/reportSummary/dataSyncAnalysis.py
@@ -15,10 +15,10 @@ import matplotlib.ticker as ticker
 # (2) a path to save the resulting graphic to.
 #
 # Data sync stats for scenario realisticScenario
-# sim_time: 60.00, avg_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.99, med_avg_data_age: 21.15, avg_data_age: 24.56, med_max_data_age: 21.15, med_avg_data_dist: 97.41, avg_data_dist: 90.05, med_max_data_dist: 97.41
+# sim_time: 60.00, avg_used_mem: 0.00%, min_used_mem: 0.00%,  max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.99, med_avg_data_age: 21.15, avg_data_age: 24.56, med_max_data_age: 21.15, med_avg_data_dist: 97.41, avg_data_dist: 90.05, med_max_data_dist: 97.41
 # avg_ratio_map: 0.00%, avg_ratio_marker: 29.41%, avg_ratio_skill: 47.06%, avg_ratio_res: 23.53%
 #
-# sim_time: 120.10, avg_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.98, med_avg_data_age: 42.55, avg_data_age: 54.16, med_max_data_age: 42.55, med_avg_data_dist: 117.17, avg_data_dist: 146.08, med_max_data_dist: 117.17
+# sim_time: 120.10, avg_used_mem: 0.00%, min_used_mem: 0.00%, max_used_mem: 0.00%, med_avg_data_util: 0.99, avg_data_util: 0.98, med_avg_data_age: 42.55, avg_data_age: 54.16, med_max_data_age: 42.55, med_avg_data_dist: 117.17, avg_data_dist: 146.08, med_max_data_dist: 117.17
 # avg_ratio_map: 0.00%, avg_ratio_marker: 23.64%, avg_ratio_skill: 32.73%, avg_ratio_res: 43.64%
 # ...
 
@@ -30,6 +30,7 @@ def main(analysisFileName, graphicFileName):
     # Interpret lines to find memory consumption, data utility, data distance and data age metrics over time
     timePoints = []
     averageMemoryConsumption = []
+    minimumMemoryConsumption = []
     maximumMemoryConsumption = []
     medianAverageDataUtility = []
     averageAverageDataUtility = []
@@ -42,7 +43,7 @@ def main(analysisFileName, graphicFileName):
     nextTimePoint = 0
     for line in report:
         match = re.match("sim_time: (\d+.\d+), "
-                         "avg_used_mem: (\d+.\d+)%, ""max_used_mem: (\d+.\d+)%, "
+                         "avg_used_mem: (\d+.\d+)%, min_used_mem: (\d+.\d+)%, max_used_mem: (\d+.\d+)%, "
                          "med_avg_data_util: (\d+.\d+), avg_data_util: (\d+.\d+), "
                          "med_avg_data_age: (\d+.\d+), avg_data_age: (\d+.\d+), med_max_data_age: (\d+.\d+), "
                          "med_avg_data_dist: (\d+.\d+), avg_data_dist: (\d+.\d+), med_max_data_dist: (\d+.\d+)", line)
@@ -57,15 +58,16 @@ def main(analysisFileName, graphicFileName):
         # Make sure to use correct unit (minutes, kilometres)
         timePoints.append(timePoint)
         averageMemoryConsumption.append(float(match.group(2)))
-        maximumMemoryConsumption.append(float(match.group(3)))
-        medianAverageDataUtility.append(float(match.group(4)))
-        averageAverageDataUtility.append(float(match.group(5)))
-        medianAverageDataAge.append(float(match.group(6)) / 60)
-        averageAverageDataAge.append(float(match.group(7)) / 60)
-        medianMaximumDataAge.append(float(match.group(8)) / 60)
-        medianAverageDataDistance.append(float(match.group(9)) / 1000)
-        averageAverageDataDistance.append(float(match.group(10)) / 1000)
-        medianMaximumDataDistance.append(float(match.group(11)) / 1000)
+        minimumMemoryConsumption.append(float(match.group(3)))
+        maximumMemoryConsumption.append(float(match.group(4)))
+        medianAverageDataUtility.append(float(match.group(5)))
+        averageAverageDataUtility.append(float(match.group(6)))
+        medianAverageDataAge.append(float(match.group(7)) / 60)
+        averageAverageDataAge.append(float(match.group(8)) / 60)
+        medianMaximumDataAge.append(float(match.group(9)) / 60)
+        medianAverageDataDistance.append(float(match.group(10)) / 1000)
+        averageAverageDataDistance.append(float(match.group(11)) / 1000)
+        medianMaximumDataDistance.append(float(match.group(12)) / 1000)
 
     # Create four graphics over time: one each for memory consumption, data utility, data distance and data age
     fig = plt.figure(figsize=(12,12))
@@ -88,7 +90,9 @@ def main(analysisFileName, graphicFileName):
 
     addSubplot(3, title='Memory Consumption',
                ylabel='Used memory',
-               plots=[(averageMemoryConsumption, 'Average'), (maximumMemoryConsumption, 'Maximum')])
+               plots=[(averageMemoryConsumption, 'Average'),
+                      (maximumMemoryConsumption, 'Maximum'),
+                      (minimumMemoryConsumption, 'Minimum')])
     addSubplot(2, title='Average Data Utility in Local Database',
                ylabel='Average data utility',
                plots=[(medianAverageDataUtility, 'Median'), (averageAverageDataUtility, 'Average')])