diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e69de29
diff --git a/Data/Global_Datasets/Christofides/CMT01.xml b/Data/Global_Datasets/Christofides/CMT01.xml
new file mode 100644
index 0000000..3e4ee13
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT01.xml
@@ -0,0 +1,376 @@
+
+
+
+ Christofides et al. 1979
+ CMT01
+
+
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 30.0
+ 40.0
+
+
+
+ 0
+
+
+
+ 51
+ 51
+ 160.0
+
+
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT02.xml b/Data/Global_Datasets/Christofides/CMT02.xml
new file mode 100644
index 0000000..5312508
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT02.xml
@@ -0,0 +1,551 @@
+
+
+
+ Christofides et al. 1979
+ CMT02
+
+
+
+
+ 22.0
+ 22.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 45.0
+
+
+ 45.0
+ 35.0
+
+
+ 55.0
+ 20.0
+
+
+ 33.0
+ 34.0
+
+
+ 50.0
+ 50.0
+
+
+ 55.0
+ 45.0
+
+
+ 26.0
+ 59.0
+
+
+ 40.0
+ 66.0
+
+
+ 55.0
+ 65.0
+
+
+ 35.0
+ 51.0
+
+
+ 62.0
+ 35.0
+
+
+ 62.0
+ 57.0
+
+
+ 62.0
+ 24.0
+
+
+ 21.0
+ 36.0
+
+
+ 33.0
+ 44.0
+
+
+ 9.0
+ 56.0
+
+
+ 62.0
+ 48.0
+
+
+ 66.0
+ 14.0
+
+
+ 44.0
+ 13.0
+
+
+ 26.0
+ 13.0
+
+
+ 11.0
+ 28.0
+
+
+ 7.0
+ 43.0
+
+
+ 17.0
+ 64.0
+
+
+ 41.0
+ 46.0
+
+
+ 55.0
+ 34.0
+
+
+ 35.0
+ 16.0
+
+
+ 52.0
+ 26.0
+
+
+ 43.0
+ 26.0
+
+
+ 31.0
+ 76.0
+
+
+ 22.0
+ 53.0
+
+
+ 26.0
+ 29.0
+
+
+ 50.0
+ 40.0
+
+
+ 55.0
+ 50.0
+
+
+ 54.0
+ 10.0
+
+
+ 60.0
+ 15.0
+
+
+ 47.0
+ 66.0
+
+
+ 30.0
+ 60.0
+
+
+ 30.0
+ 50.0
+
+
+ 12.0
+ 17.0
+
+
+ 15.0
+ 14.0
+
+
+ 16.0
+ 19.0
+
+
+ 21.0
+ 48.0
+
+
+ 50.0
+ 30.0
+
+
+ 51.0
+ 42.0
+
+
+ 50.0
+ 15.0
+
+
+ 48.0
+ 21.0
+
+
+ 12.0
+ 38.0
+
+
+ 15.0
+ 56.0
+
+
+ 29.0
+ 39.0
+
+
+ 54.0
+ 38.0
+
+
+ 55.0
+ 57.0
+
+
+ 67.0
+ 41.0
+
+
+ 10.0
+ 70.0
+
+
+ 6.0
+ 25.0
+
+
+ 65.0
+ 27.0
+
+
+ 40.0
+ 60.0
+
+
+ 70.0
+ 64.0
+
+
+ 64.0
+ 4.0
+
+
+ 36.0
+ 6.0
+
+
+ 30.0
+ 20.0
+
+
+ 20.0
+ 30.0
+
+
+ 15.0
+ 5.0
+
+
+ 50.0
+ 70.0
+
+
+ 57.0
+ 72.0
+
+
+ 45.0
+ 42.0
+
+
+ 38.0
+ 33.0
+
+
+ 50.0
+ 4.0
+
+
+ 66.0
+ 8.0
+
+
+ 59.0
+ 5.0
+
+
+ 35.0
+ 60.0
+
+
+ 27.0
+ 24.0
+
+
+ 40.0
+ 20.0
+
+
+ 40.0
+ 37.0
+
+
+ 40.0
+ 40.0
+
+
+
+ 0
+
+
+
+ 76
+ 76
+ 140.0
+
+
+
+
+ 18.0
+
+
+ 26.0
+
+
+ 11.0
+
+
+ 30.0
+
+
+ 21.0
+
+
+ 19.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 29.0
+
+
+ 26.0
+
+
+ 37.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 31.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 22.0
+
+
+ 28.0
+
+
+ 12.0
+
+
+ 6.0
+
+
+ 27.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 29.0
+
+
+ 13.0
+
+
+ 22.0
+
+
+ 25.0
+
+
+ 28.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 24.0
+
+
+ 16.0
+
+
+ 33.0
+
+
+ 15.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 5.0
+
+
+ 22.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 22.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 26.0
+
+
+ 14.0
+
+
+ 21.0
+
+
+ 24.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 18.0
+
+
+ 11.0
+
+
+ 28.0
+
+
+ 9.0
+
+
+ 37.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 6.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT03.xml b/Data/Global_Datasets/Christofides/CMT03.xml
new file mode 100644
index 0000000..dfc35b2
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT03.xml
@@ -0,0 +1,726 @@
+
+
+
+ Christofides et al. 1979
+ CMT03
+
+
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 101
+ 101
+ 200.0
+
+
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT04.xml b/Data/Global_Datasets/Christofides/CMT04.xml
new file mode 100644
index 0000000..fe5fd57
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT04.xml
@@ -0,0 +1,1076 @@
+
+
+
+ Christofides et al. 1979
+ CMT04
+
+
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 151
+ 151
+ 200.0
+
+
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT05.xml b/Data/Global_Datasets/Christofides/CMT05.xml
new file mode 100644
index 0000000..2784466
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT05.xml
@@ -0,0 +1,1419 @@
+
+
+
+ Christofides et al. 1979
+ CMT05
+
+
+
+
+ 22.0
+ 22.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 45.0
+
+
+ 45.0
+ 35.0
+
+
+ 55.0
+ 20.0
+
+
+ 33.0
+ 34.0
+
+
+ 50.0
+ 50.0
+
+
+ 55.0
+ 45.0
+
+
+ 26.0
+ 59.0
+
+
+ 40.0
+ 66.0
+
+
+ 55.0
+ 65.0
+
+
+ 35.0
+ 51.0
+
+
+ 62.0
+ 35.0
+
+
+ 62.0
+ 57.0
+
+
+ 62.0
+ 24.0
+
+
+ 21.0
+ 36.0
+
+
+ 33.0
+ 44.0
+
+
+ 9.0
+ 56.0
+
+
+ 62.0
+ 48.0
+
+
+ 66.0
+ 14.0
+
+
+ 44.0
+ 13.0
+
+
+ 26.0
+ 13.0
+
+
+ 11.0
+ 28.0
+
+
+ 7.0
+ 43.0
+
+
+ 17.0
+ 64.0
+
+
+ 41.0
+ 46.0
+
+
+ 55.0
+ 34.0
+
+
+ 35.0
+ 16.0
+
+
+ 52.0
+ 26.0
+
+
+ 43.0
+ 26.0
+
+
+ 31.0
+ 76.0
+
+
+ 22.0
+ 53.0
+
+
+ 26.0
+ 29.0
+
+
+ 50.0
+ 40.0
+
+
+ 55.0
+ 50.0
+
+
+ 54.0
+ 10.0
+
+
+ 60.0
+ 15.0
+
+
+ 47.0
+ 66.0
+
+
+ 30.0
+ 60.0
+
+
+ 30.0
+ 50.0
+
+
+ 12.0
+ 17.0
+
+
+ 15.0
+ 14.0
+
+
+ 16.0
+ 19.0
+
+
+ 21.0
+ 48.0
+
+
+ 50.0
+ 30.0
+
+
+ 51.0
+ 42.0
+
+
+ 50.0
+ 15.0
+
+
+ 48.0
+ 21.0
+
+
+ 12.0
+ 38.0
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 200
+ 200
+ 200.0
+
+
+
+
+ 18.0
+
+
+ 26.0
+
+
+ 11.0
+
+
+ 30.0
+
+
+ 21.0
+
+
+ 19.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 29.0
+
+
+ 26.0
+
+
+ 37.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 31.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 22.0
+
+
+ 28.0
+
+
+ 12.0
+
+
+ 6.0
+
+
+ 27.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 29.0
+
+
+ 13.0
+
+
+ 22.0
+
+
+ 25.0
+
+
+ 28.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 24.0
+
+
+ 16.0
+
+
+ 33.0
+
+
+ 15.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT06.xml b/Data/Global_Datasets/Christofides/CMT06.xml
new file mode 100644
index 0000000..632ccbe
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT06.xml
@@ -0,0 +1,376 @@
+
+
+
+ Christofides et al. 1979
+ CMT06
+
+
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 30.0
+ 40.0
+
+
+
+ 0
+
+
+
+ 51
+ 51
+ 160.0
+
+
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT07.xml b/Data/Global_Datasets/Christofides/CMT07.xml
new file mode 100644
index 0000000..f86475f
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT07.xml
@@ -0,0 +1,551 @@
+
+
+
+ Christofides et al. 1979
+ CMT07
+
+
+
+
+ 22.0
+ 22.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 45.0
+
+
+ 45.0
+ 35.0
+
+
+ 55.0
+ 20.0
+
+
+ 33.0
+ 34.0
+
+
+ 50.0
+ 50.0
+
+
+ 55.0
+ 45.0
+
+
+ 26.0
+ 59.0
+
+
+ 40.0
+ 66.0
+
+
+ 55.0
+ 65.0
+
+
+ 35.0
+ 51.0
+
+
+ 62.0
+ 35.0
+
+
+ 62.0
+ 57.0
+
+
+ 62.0
+ 24.0
+
+
+ 21.0
+ 36.0
+
+
+ 33.0
+ 44.0
+
+
+ 9.0
+ 56.0
+
+
+ 62.0
+ 48.0
+
+
+ 66.0
+ 14.0
+
+
+ 44.0
+ 13.0
+
+
+ 26.0
+ 13.0
+
+
+ 11.0
+ 28.0
+
+
+ 7.0
+ 43.0
+
+
+ 17.0
+ 64.0
+
+
+ 41.0
+ 46.0
+
+
+ 55.0
+ 34.0
+
+
+ 35.0
+ 16.0
+
+
+ 52.0
+ 26.0
+
+
+ 43.0
+ 26.0
+
+
+ 31.0
+ 76.0
+
+
+ 22.0
+ 53.0
+
+
+ 26.0
+ 29.0
+
+
+ 50.0
+ 40.0
+
+
+ 55.0
+ 50.0
+
+
+ 54.0
+ 10.0
+
+
+ 60.0
+ 15.0
+
+
+ 47.0
+ 66.0
+
+
+ 30.0
+ 60.0
+
+
+ 30.0
+ 50.0
+
+
+ 12.0
+ 17.0
+
+
+ 15.0
+ 14.0
+
+
+ 16.0
+ 19.0
+
+
+ 21.0
+ 48.0
+
+
+ 50.0
+ 30.0
+
+
+ 51.0
+ 42.0
+
+
+ 50.0
+ 15.0
+
+
+ 48.0
+ 21.0
+
+
+ 12.0
+ 38.0
+
+
+ 15.0
+ 56.0
+
+
+ 29.0
+ 39.0
+
+
+ 54.0
+ 38.0
+
+
+ 55.0
+ 57.0
+
+
+ 67.0
+ 41.0
+
+
+ 10.0
+ 70.0
+
+
+ 6.0
+ 25.0
+
+
+ 65.0
+ 27.0
+
+
+ 40.0
+ 60.0
+
+
+ 70.0
+ 64.0
+
+
+ 64.0
+ 4.0
+
+
+ 36.0
+ 6.0
+
+
+ 30.0
+ 20.0
+
+
+ 20.0
+ 30.0
+
+
+ 15.0
+ 5.0
+
+
+ 50.0
+ 70.0
+
+
+ 57.0
+ 72.0
+
+
+ 45.0
+ 42.0
+
+
+ 38.0
+ 33.0
+
+
+ 50.0
+ 4.0
+
+
+ 66.0
+ 8.0
+
+
+ 59.0
+ 5.0
+
+
+ 35.0
+ 60.0
+
+
+ 27.0
+ 24.0
+
+
+ 40.0
+ 20.0
+
+
+ 40.0
+ 37.0
+
+
+ 40.0
+ 40.0
+
+
+
+ 0
+
+
+
+ 76
+ 76
+ 140.0
+
+
+
+
+ 18.0
+
+
+ 26.0
+
+
+ 11.0
+
+
+ 30.0
+
+
+ 21.0
+
+
+ 19.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 29.0
+
+
+ 26.0
+
+
+ 37.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 31.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 22.0
+
+
+ 28.0
+
+
+ 12.0
+
+
+ 6.0
+
+
+ 27.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 29.0
+
+
+ 13.0
+
+
+ 22.0
+
+
+ 25.0
+
+
+ 28.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 24.0
+
+
+ 16.0
+
+
+ 33.0
+
+
+ 15.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 5.0
+
+
+ 22.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 22.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 26.0
+
+
+ 14.0
+
+
+ 21.0
+
+
+ 24.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 18.0
+
+
+ 11.0
+
+
+ 28.0
+
+
+ 9.0
+
+
+ 37.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 6.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT08.xml b/Data/Global_Datasets/Christofides/CMT08.xml
new file mode 100644
index 0000000..c6f4a90
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT08.xml
@@ -0,0 +1,726 @@
+
+
+
+ Christofides et al. 1979
+ CMT08
+
+
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 101
+ 101
+ 200.0
+
+
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT09.xml b/Data/Global_Datasets/Christofides/CMT09.xml
new file mode 100644
index 0000000..5b9ab97
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT09.xml
@@ -0,0 +1,1076 @@
+
+
+
+ Christofides et al. 1979
+ CMT09
+
+
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 151
+ 151
+ 200.0
+
+
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT10.xml b/Data/Global_Datasets/Christofides/CMT10.xml
new file mode 100644
index 0000000..520cd1d
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT10.xml
@@ -0,0 +1,1419 @@
+
+
+
+ Christofides et al. 1979
+ CMT10
+
+
+
+
+ 22.0
+ 22.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 45.0
+
+
+ 45.0
+ 35.0
+
+
+ 55.0
+ 20.0
+
+
+ 33.0
+ 34.0
+
+
+ 50.0
+ 50.0
+
+
+ 55.0
+ 45.0
+
+
+ 26.0
+ 59.0
+
+
+ 40.0
+ 66.0
+
+
+ 55.0
+ 65.0
+
+
+ 35.0
+ 51.0
+
+
+ 62.0
+ 35.0
+
+
+ 62.0
+ 57.0
+
+
+ 62.0
+ 24.0
+
+
+ 21.0
+ 36.0
+
+
+ 33.0
+ 44.0
+
+
+ 9.0
+ 56.0
+
+
+ 62.0
+ 48.0
+
+
+ 66.0
+ 14.0
+
+
+ 44.0
+ 13.0
+
+
+ 26.0
+ 13.0
+
+
+ 11.0
+ 28.0
+
+
+ 7.0
+ 43.0
+
+
+ 17.0
+ 64.0
+
+
+ 41.0
+ 46.0
+
+
+ 55.0
+ 34.0
+
+
+ 35.0
+ 16.0
+
+
+ 52.0
+ 26.0
+
+
+ 43.0
+ 26.0
+
+
+ 31.0
+ 76.0
+
+
+ 22.0
+ 53.0
+
+
+ 26.0
+ 29.0
+
+
+ 50.0
+ 40.0
+
+
+ 55.0
+ 50.0
+
+
+ 54.0
+ 10.0
+
+
+ 60.0
+ 15.0
+
+
+ 47.0
+ 66.0
+
+
+ 30.0
+ 60.0
+
+
+ 30.0
+ 50.0
+
+
+ 12.0
+ 17.0
+
+
+ 15.0
+ 14.0
+
+
+ 16.0
+ 19.0
+
+
+ 21.0
+ 48.0
+
+
+ 50.0
+ 30.0
+
+
+ 51.0
+ 42.0
+
+
+ 50.0
+ 15.0
+
+
+ 48.0
+ 21.0
+
+
+ 12.0
+ 38.0
+
+
+ 37.0
+ 52.0
+
+
+ 49.0
+ 49.0
+
+
+ 52.0
+ 64.0
+
+
+ 20.0
+ 26.0
+
+
+ 40.0
+ 30.0
+
+
+ 21.0
+ 47.0
+
+
+ 17.0
+ 63.0
+
+
+ 31.0
+ 62.0
+
+
+ 52.0
+ 33.0
+
+
+ 51.0
+ 21.0
+
+
+ 42.0
+ 41.0
+
+
+ 31.0
+ 32.0
+
+
+ 5.0
+ 25.0
+
+
+ 12.0
+ 42.0
+
+
+ 36.0
+ 16.0
+
+
+ 52.0
+ 41.0
+
+
+ 27.0
+ 23.0
+
+
+ 17.0
+ 33.0
+
+
+ 13.0
+ 13.0
+
+
+ 57.0
+ 58.0
+
+
+ 62.0
+ 42.0
+
+
+ 42.0
+ 57.0
+
+
+ 16.0
+ 57.0
+
+
+ 8.0
+ 52.0
+
+
+ 7.0
+ 38.0
+
+
+ 27.0
+ 68.0
+
+
+ 30.0
+ 48.0
+
+
+ 43.0
+ 67.0
+
+
+ 58.0
+ 48.0
+
+
+ 58.0
+ 27.0
+
+
+ 37.0
+ 69.0
+
+
+ 38.0
+ 46.0
+
+
+ 46.0
+ 10.0
+
+
+ 61.0
+ 33.0
+
+
+ 62.0
+ 63.0
+
+
+ 63.0
+ 69.0
+
+
+ 32.0
+ 22.0
+
+
+ 45.0
+ 35.0
+
+
+ 59.0
+ 15.0
+
+
+ 5.0
+ 6.0
+
+
+ 10.0
+ 17.0
+
+
+ 21.0
+ 10.0
+
+
+ 5.0
+ 64.0
+
+
+ 30.0
+ 15.0
+
+
+ 39.0
+ 10.0
+
+
+ 32.0
+ 39.0
+
+
+ 25.0
+ 32.0
+
+
+ 25.0
+ 55.0
+
+
+ 48.0
+ 28.0
+
+
+ 56.0
+ 37.0
+
+
+ 41.0
+ 49.0
+
+
+ 35.0
+ 17.0
+
+
+ 55.0
+ 45.0
+
+
+ 55.0
+ 20.0
+
+
+ 15.0
+ 30.0
+
+
+ 25.0
+ 30.0
+
+
+ 20.0
+ 50.0
+
+
+ 10.0
+ 43.0
+
+
+ 55.0
+ 60.0
+
+
+ 30.0
+ 60.0
+
+
+ 20.0
+ 65.0
+
+
+ 50.0
+ 35.0
+
+
+ 30.0
+ 25.0
+
+
+ 15.0
+ 10.0
+
+
+ 30.0
+ 5.0
+
+
+ 10.0
+ 20.0
+
+
+ 5.0
+ 30.0
+
+
+ 20.0
+ 40.0
+
+
+ 15.0
+ 60.0
+
+
+ 45.0
+ 65.0
+
+
+ 45.0
+ 20.0
+
+
+ 45.0
+ 10.0
+
+
+ 55.0
+ 5.0
+
+
+ 65.0
+ 35.0
+
+
+ 65.0
+ 20.0
+
+
+ 45.0
+ 30.0
+
+
+ 35.0
+ 40.0
+
+
+ 41.0
+ 37.0
+
+
+ 64.0
+ 42.0
+
+
+ 40.0
+ 60.0
+
+
+ 31.0
+ 52.0
+
+
+ 35.0
+ 69.0
+
+
+ 53.0
+ 52.0
+
+
+ 65.0
+ 55.0
+
+
+ 63.0
+ 65.0
+
+
+ 2.0
+ 60.0
+
+
+ 20.0
+ 20.0
+
+
+ 5.0
+ 5.0
+
+
+ 60.0
+ 12.0
+
+
+ 40.0
+ 25.0
+
+
+ 42.0
+ 7.0
+
+
+ 24.0
+ 12.0
+
+
+ 23.0
+ 3.0
+
+
+ 11.0
+ 14.0
+
+
+ 6.0
+ 38.0
+
+
+ 2.0
+ 48.0
+
+
+ 8.0
+ 56.0
+
+
+ 13.0
+ 52.0
+
+
+ 6.0
+ 68.0
+
+
+ 47.0
+ 47.0
+
+
+ 49.0
+ 58.0
+
+
+ 27.0
+ 43.0
+
+
+ 37.0
+ 31.0
+
+
+ 57.0
+ 29.0
+
+
+ 63.0
+ 23.0
+
+
+ 53.0
+ 12.0
+
+
+ 32.0
+ 12.0
+
+
+ 36.0
+ 26.0
+
+
+ 21.0
+ 24.0
+
+
+ 17.0
+ 34.0
+
+
+ 12.0
+ 24.0
+
+
+ 24.0
+ 58.0
+
+
+ 27.0
+ 69.0
+
+
+ 15.0
+ 77.0
+
+
+ 62.0
+ 77.0
+
+
+ 49.0
+ 73.0
+
+
+ 67.0
+ 5.0
+
+
+ 56.0
+ 39.0
+
+
+ 37.0
+ 47.0
+
+
+ 37.0
+ 56.0
+
+
+ 57.0
+ 68.0
+
+
+ 47.0
+ 16.0
+
+
+ 44.0
+ 17.0
+
+
+ 46.0
+ 13.0
+
+
+ 49.0
+ 11.0
+
+
+ 49.0
+ 42.0
+
+
+ 53.0
+ 43.0
+
+
+ 61.0
+ 52.0
+
+
+ 57.0
+ 48.0
+
+
+ 56.0
+ 37.0
+
+
+ 55.0
+ 54.0
+
+
+ 15.0
+ 47.0
+
+
+ 14.0
+ 37.0
+
+
+ 11.0
+ 31.0
+
+
+ 16.0
+ 22.0
+
+
+ 4.0
+ 18.0
+
+
+ 28.0
+ 18.0
+
+
+ 26.0
+ 52.0
+
+
+ 26.0
+ 35.0
+
+
+ 31.0
+ 67.0
+
+
+ 15.0
+ 19.0
+
+
+ 22.0
+ 22.0
+
+
+ 18.0
+ 24.0
+
+
+ 26.0
+ 27.0
+
+
+ 25.0
+ 24.0
+
+
+ 22.0
+ 27.0
+
+
+ 25.0
+ 21.0
+
+
+ 19.0
+ 21.0
+
+
+ 20.0
+ 26.0
+
+
+ 18.0
+ 18.0
+
+
+ 35.0
+ 35.0
+
+
+
+ 0
+
+
+
+ 200
+ 200
+ 200.0
+
+
+
+
+ 18.0
+
+
+ 26.0
+
+
+ 11.0
+
+
+ 30.0
+
+
+ 21.0
+
+
+ 19.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 29.0
+
+
+ 26.0
+
+
+ 37.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 31.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+ 15.0
+
+
+ 22.0
+
+
+ 28.0
+
+
+ 12.0
+
+
+ 6.0
+
+
+ 27.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 29.0
+
+
+ 13.0
+
+
+ 22.0
+
+
+ 25.0
+
+
+ 28.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 24.0
+
+
+ 16.0
+
+
+ 33.0
+
+
+ 15.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 17.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 19.0
+
+
+ 20.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 30.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 15.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 5.0
+
+
+ 19.0
+
+
+ 29.0
+
+
+ 23.0
+
+
+ 21.0
+
+
+ 10.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 41.0
+
+
+ 9.0
+
+
+ 28.0
+
+
+ 8.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 6.0
+
+
+ 19.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 23.0
+
+
+ 26.0
+
+
+ 17.0
+
+
+ 6.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 14.0
+
+
+ 7.0
+
+
+ 27.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 5.0
+
+
+ 25.0
+
+
+ 17.0
+
+
+ 18.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 26.0
+
+
+ 3.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 12.0
+
+
+ 19.0
+
+
+ 23.0
+
+
+ 20.0
+
+
+ 8.0
+
+
+ 19.0
+
+
+ 2.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 18.0
+
+
+ 29.0
+
+
+ 3.0
+
+
+ 6.0
+
+
+ 17.0
+
+
+ 16.0
+
+
+ 16.0
+
+
+ 9.0
+
+
+ 21.0
+
+
+ 27.0
+
+
+ 23.0
+
+
+ 11.0
+
+
+ 14.0
+
+
+ 8.0
+
+
+ 5.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 31.0
+
+
+ 9.0
+
+
+ 5.0
+
+
+ 5.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 16.0
+
+
+ 1.0
+
+
+ 27.0
+
+
+ 36.0
+
+
+ 30.0
+
+
+ 13.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 14.0
+
+
+ 18.0
+
+
+ 2.0
+
+
+ 6.0
+
+
+ 7.0
+
+
+ 18.0
+
+
+ 28.0
+
+
+ 3.0
+
+
+ 13.0
+
+
+ 19.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 20.0
+
+
+ 25.0
+
+
+ 25.0
+
+
+ 36.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 25.0
+
+
+ 9.0
+
+
+ 8.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 3.0
+
+
+ 23.0
+
+
+ 6.0
+
+
+ 26.0
+
+
+ 16.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 41.0
+
+
+ 35.0
+
+
+ 26.0
+
+
+ 9.0
+
+
+ 15.0
+
+
+ 3.0
+
+
+ 1.0
+
+
+ 2.0
+
+
+ 22.0
+
+
+ 27.0
+
+
+ 20.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 17.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT11.xml b/Data/Global_Datasets/Christofides/CMT11.xml
new file mode 100644
index 0000000..98ea92d
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT11.xml
@@ -0,0 +1,866 @@
+
+
+
+ Christofides et al. 1979
+ CMT11
+
+
+
+
+ 25.0
+ 1.0
+
+
+ 25.0
+ 3.0
+
+
+ 31.0
+ 5.0
+
+
+ 32.0
+ 5.0
+
+
+ 31.0
+ 7.0
+
+
+ 32.0
+ 9.0
+
+
+ 34.0
+ 9.0
+
+
+ 46.0
+ 9.0
+
+
+ 35.0
+ 7.0
+
+
+ 34.0
+ 6.0
+
+
+ 35.0
+ 5.0
+
+
+ 47.0
+ 6.0
+
+
+ 40.0
+ 5.0
+
+
+ 39.0
+ 3.0
+
+
+ 36.0
+ 3.0
+
+
+ 73.0
+ 6.0
+
+
+ 73.0
+ 8.0
+
+
+ 24.0
+ 36.0
+
+
+ 76.0
+ 6.0
+
+
+ 76.0
+ 10.0
+
+
+ 76.0
+ 13.0
+
+
+ 78.0
+ 3.0
+
+
+ 78.0
+ 9.0
+
+
+ 79.0
+ 3.0
+
+
+ 79.0
+ 5.0
+
+
+ 79.0
+ 11.0
+
+
+ 82.0
+ 3.0
+
+
+ 82.0
+ 7.0
+
+
+ 90.0
+ 15.0
+
+
+ 84.0
+ 3.0
+
+
+ 84.0
+ 5.0
+
+
+ 84.0
+ 9.0
+
+
+ 85.0
+ 1.0
+
+
+ 87.0
+ 5.0
+
+
+ 85.0
+ 8.0
+
+
+ 87.0
+ 7.0
+
+
+ 86.0
+ 41.0
+
+
+ 86.0
+ 44.0
+
+
+ 86.0
+ 46.0
+
+
+ 85.0
+ 55.0
+
+
+ 89.0
+ 43.0
+
+
+ 89.0
+ 46.0
+
+
+ 89.0
+ 52.0
+
+
+ 92.0
+ 42.0
+
+
+ 92.0
+ 52.0
+
+
+ 94.0
+ 42.0
+
+
+ 94.0
+ 44.0
+
+
+ 94.0
+ 48.0
+
+
+ 96.0
+ 42.0
+
+
+ 99.0
+ 46.0
+
+
+ 99.0
+ 50.0
+
+
+ 83.0
+ 80.0
+
+
+ 83.0
+ 83.0
+
+
+ 85.0
+ 81.0
+
+
+ 85.0
+ 85.0
+
+
+ 85.0
+ 89.0
+
+
+ 87.0
+ 80.0
+
+
+ 87.0
+ 86.0
+
+
+ 90.0
+ 77.0
+
+
+ 90.0
+ 88.0
+
+
+ 93.0
+ 82.0
+
+
+ 93.0
+ 84.0
+
+
+ 93.0
+ 89.0
+
+
+ 94.0
+ 86.0
+
+
+ 95.0
+ 80.0
+
+
+ 99.0
+ 89.0
+
+
+ 37.0
+ 83.0
+
+
+ 50.0
+ 80.0
+
+
+ 35.0
+ 85.0
+
+
+ 35.0
+ 87.0
+
+
+ 44.0
+ 86.0
+
+
+ 46.0
+ 89.0
+
+
+ 46.0
+ 83.0
+
+
+ 46.0
+ 87.0
+
+
+ 46.0
+ 89.0
+
+
+ 48.0
+ 83.0
+
+
+ 50.0
+ 85.0
+
+
+ 50.0
+ 88.0
+
+
+ 54.0
+ 86.0
+
+
+ 54.0
+ 90.0
+
+
+ 10.0
+ 35.0
+
+
+ 10.0
+ 40.0
+
+
+ 18.0
+ 30.0
+
+
+ 17.0
+ 35.0
+
+
+ 16.0
+ 38.0
+
+
+ 14.0
+ 40.0
+
+
+ 15.0
+ 42.0
+
+
+ 11.0
+ 42.0
+
+
+ 18.0
+ 40.0
+
+
+ 21.0
+ 39.0
+
+
+ 20.0
+ 40.0
+
+
+ 18.0
+ 41.0
+
+
+ 20.0
+ 44.0
+
+
+ 22.0
+ 44.0
+
+
+ 16.0
+ 45.0
+
+
+ 20.0
+ 45.0
+
+
+ 25.0
+ 45.0
+
+
+ 30.0
+ 55.0
+
+
+ 20.0
+ 50.0
+
+
+ 22.0
+ 51.0
+
+
+ 18.0
+ 49.0
+
+
+ 16.0
+ 48.0
+
+
+ 20.0
+ 55.0
+
+
+ 18.0
+ 53.0
+
+
+ 14.0
+ 50.0
+
+
+ 15.0
+ 51.0
+
+
+ 16.0
+ 54.0
+
+
+ 28.0
+ 33.0
+
+
+ 33.0
+ 38.0
+
+
+ 30.0
+ 50.0
+
+
+ 13.0
+ 40.0
+
+
+ 15.0
+ 36.0
+
+
+ 18.0
+ 31.0
+
+
+ 25.0
+ 37.0
+
+
+ 30.0
+ 46.0
+
+
+ 25.0
+ 52.0
+
+
+ 16.0
+ 33.0
+
+
+ 25.0
+ 35.0
+
+
+ 5.0
+ 40.0
+
+
+ 5.0
+ 50.0
+
+
+ 10.0
+ 45.0
+
+
+
+ 0
+
+
+
+ 121
+ 121
+ 200.0
+
+
+
+
+ 25.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 6.0
+
+
+ 14.0
+
+
+ 5.0
+
+
+ 11.0
+
+
+ 19.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 15.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 12.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 18.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 4.0
+
+
+ 7.0
+
+
+ 12.0
+
+
+ 13.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 15.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 3.0
+
+
+ 7.0
+
+
+ 2.0
+
+
+ 4.0
+
+
+ 4.0
+
+
+ 18.0
+
+
+ 14.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 20.0
+
+
+ 14.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 5.0
+
+
+ 4.0
+
+
+ 21.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 19.0
+
+
+ 5.0
+
+
+ 17.0
+
+
+ 7.0
+
+
+ 16.0
+
+
+ 14.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 35.0
+
+
+ 5.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 3.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 12.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 21.0
+
+
+ 4.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 4.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 17.0
+
+
+ 12.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 7.0
+
+
+ 8.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 12.0
+
+
+ 13.0
+
+
+ 7.0
+
+
+ 7.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 4.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT12.xml b/Data/Global_Datasets/Christofides/CMT12.xml
new file mode 100644
index 0000000..8d3a2d3
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT12.xml
@@ -0,0 +1,726 @@
+
+
+
+ Christofides et al. 1979
+ CMT12
+
+
+
+
+ 45.0
+ 68.0
+
+
+ 45.0
+ 70.0
+
+
+ 42.0
+ 66.0
+
+
+ 42.0
+ 68.0
+
+
+ 42.0
+ 65.0
+
+
+ 40.0
+ 69.0
+
+
+ 40.0
+ 66.0
+
+
+ 38.0
+ 68.0
+
+
+ 38.0
+ 70.0
+
+
+ 35.0
+ 66.0
+
+
+ 35.0
+ 69.0
+
+
+ 25.0
+ 85.0
+
+
+ 22.0
+ 75.0
+
+
+ 22.0
+ 85.0
+
+
+ 20.0
+ 80.0
+
+
+ 20.0
+ 85.0
+
+
+ 18.0
+ 75.0
+
+
+ 15.0
+ 75.0
+
+
+ 15.0
+ 80.0
+
+
+ 30.0
+ 50.0
+
+
+ 30.0
+ 52.0
+
+
+ 28.0
+ 52.0
+
+
+ 28.0
+ 55.0
+
+
+ 25.0
+ 50.0
+
+
+ 25.0
+ 52.0
+
+
+ 25.0
+ 55.0
+
+
+ 23.0
+ 52.0
+
+
+ 23.0
+ 55.0
+
+
+ 20.0
+ 50.0
+
+
+ 20.0
+ 55.0
+
+
+ 10.0
+ 35.0
+
+
+ 10.0
+ 40.0
+
+
+ 8.0
+ 40.0
+
+
+ 8.0
+ 45.0
+
+
+ 5.0
+ 35.0
+
+
+ 5.0
+ 45.0
+
+
+ 2.0
+ 40.0
+
+
+ 0.0
+ 40.0
+
+
+ 0.0
+ 45.0
+
+
+ 35.0
+ 30.0
+
+
+ 35.0
+ 32.0
+
+
+ 33.0
+ 32.0
+
+
+ 33.0
+ 35.0
+
+
+ 32.0
+ 30.0
+
+
+ 30.0
+ 30.0
+
+
+ 30.0
+ 32.0
+
+
+ 30.0
+ 35.0
+
+
+ 28.0
+ 30.0
+
+
+ 28.0
+ 35.0
+
+
+ 26.0
+ 32.0
+
+
+ 25.0
+ 30.0
+
+
+ 25.0
+ 35.0
+
+
+ 44.0
+ 5.0
+
+
+ 42.0
+ 10.0
+
+
+ 42.0
+ 15.0
+
+
+ 40.0
+ 5.0
+
+
+ 40.0
+ 15.0
+
+
+ 38.0
+ 5.0
+
+
+ 38.0
+ 15.0
+
+
+ 35.0
+ 5.0
+
+
+ 50.0
+ 30.0
+
+
+ 50.0
+ 35.0
+
+
+ 50.0
+ 40.0
+
+
+ 48.0
+ 30.0
+
+
+ 48.0
+ 40.0
+
+
+ 47.0
+ 35.0
+
+
+ 47.0
+ 40.0
+
+
+ 45.0
+ 30.0
+
+
+ 45.0
+ 35.0
+
+
+ 95.0
+ 30.0
+
+
+ 95.0
+ 35.0
+
+
+ 53.0
+ 30.0
+
+
+ 92.0
+ 30.0
+
+
+ 53.0
+ 35.0
+
+
+ 45.0
+ 65.0
+
+
+ 90.0
+ 35.0
+
+
+ 88.0
+ 30.0
+
+
+ 88.0
+ 35.0
+
+
+ 87.0
+ 30.0
+
+
+ 85.0
+ 25.0
+
+
+ 85.0
+ 35.0
+
+
+ 75.0
+ 55.0
+
+
+ 72.0
+ 55.0
+
+
+ 70.0
+ 58.0
+
+
+ 68.0
+ 60.0
+
+
+ 66.0
+ 55.0
+
+
+ 65.0
+ 55.0
+
+
+ 65.0
+ 60.0
+
+
+ 63.0
+ 58.0
+
+
+ 60.0
+ 55.0
+
+
+ 60.0
+ 60.0
+
+
+ 67.0
+ 85.0
+
+
+ 65.0
+ 85.0
+
+
+ 65.0
+ 82.0
+
+
+ 62.0
+ 80.0
+
+
+ 60.0
+ 80.0
+
+
+ 60.0
+ 85.0
+
+
+ 58.0
+ 75.0
+
+
+ 55.0
+ 80.0
+
+
+ 55.0
+ 85.0
+
+
+ 40.0
+ 50.0
+
+
+
+ 0
+
+
+
+ 101
+ 101
+ 200.0
+
+
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 40.0
+
+
+ 40.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 40.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 40.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 50.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 50.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT13.xml b/Data/Global_Datasets/Christofides/CMT13.xml
new file mode 100644
index 0000000..d1931e7
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT13.xml
@@ -0,0 +1,866 @@
+
+
+
+ Christofides et al. 1979
+ CMT13
+
+
+
+
+ 25.0
+ 1.0
+
+
+ 25.0
+ 3.0
+
+
+ 31.0
+ 5.0
+
+
+ 32.0
+ 5.0
+
+
+ 31.0
+ 7.0
+
+
+ 32.0
+ 9.0
+
+
+ 34.0
+ 9.0
+
+
+ 46.0
+ 9.0
+
+
+ 35.0
+ 7.0
+
+
+ 34.0
+ 6.0
+
+
+ 35.0
+ 5.0
+
+
+ 47.0
+ 6.0
+
+
+ 40.0
+ 5.0
+
+
+ 39.0
+ 3.0
+
+
+ 36.0
+ 3.0
+
+
+ 73.0
+ 6.0
+
+
+ 73.0
+ 8.0
+
+
+ 24.0
+ 36.0
+
+
+ 76.0
+ 6.0
+
+
+ 76.0
+ 10.0
+
+
+ 76.0
+ 13.0
+
+
+ 78.0
+ 3.0
+
+
+ 78.0
+ 9.0
+
+
+ 79.0
+ 3.0
+
+
+ 79.0
+ 5.0
+
+
+ 79.0
+ 11.0
+
+
+ 82.0
+ 3.0
+
+
+ 82.0
+ 7.0
+
+
+ 90.0
+ 15.0
+
+
+ 84.0
+ 3.0
+
+
+ 84.0
+ 5.0
+
+
+ 84.0
+ 9.0
+
+
+ 85.0
+ 1.0
+
+
+ 87.0
+ 5.0
+
+
+ 85.0
+ 8.0
+
+
+ 87.0
+ 7.0
+
+
+ 86.0
+ 41.0
+
+
+ 86.0
+ 44.0
+
+
+ 86.0
+ 46.0
+
+
+ 85.0
+ 55.0
+
+
+ 89.0
+ 43.0
+
+
+ 89.0
+ 46.0
+
+
+ 89.0
+ 52.0
+
+
+ 92.0
+ 42.0
+
+
+ 92.0
+ 52.0
+
+
+ 94.0
+ 42.0
+
+
+ 94.0
+ 44.0
+
+
+ 94.0
+ 48.0
+
+
+ 96.0
+ 42.0
+
+
+ 99.0
+ 46.0
+
+
+ 99.0
+ 50.0
+
+
+ 83.0
+ 80.0
+
+
+ 83.0
+ 83.0
+
+
+ 85.0
+ 81.0
+
+
+ 85.0
+ 85.0
+
+
+ 85.0
+ 89.0
+
+
+ 87.0
+ 80.0
+
+
+ 87.0
+ 86.0
+
+
+ 90.0
+ 77.0
+
+
+ 90.0
+ 88.0
+
+
+ 93.0
+ 82.0
+
+
+ 93.0
+ 84.0
+
+
+ 93.0
+ 89.0
+
+
+ 94.0
+ 86.0
+
+
+ 95.0
+ 80.0
+
+
+ 99.0
+ 89.0
+
+
+ 37.0
+ 83.0
+
+
+ 50.0
+ 80.0
+
+
+ 35.0
+ 85.0
+
+
+ 35.0
+ 87.0
+
+
+ 44.0
+ 86.0
+
+
+ 46.0
+ 89.0
+
+
+ 46.0
+ 83.0
+
+
+ 46.0
+ 87.0
+
+
+ 46.0
+ 89.0
+
+
+ 48.0
+ 83.0
+
+
+ 50.0
+ 85.0
+
+
+ 50.0
+ 88.0
+
+
+ 54.0
+ 86.0
+
+
+ 54.0
+ 90.0
+
+
+ 10.0
+ 35.0
+
+
+ 10.0
+ 40.0
+
+
+ 18.0
+ 30.0
+
+
+ 17.0
+ 35.0
+
+
+ 16.0
+ 38.0
+
+
+ 14.0
+ 40.0
+
+
+ 15.0
+ 42.0
+
+
+ 11.0
+ 42.0
+
+
+ 18.0
+ 40.0
+
+
+ 21.0
+ 39.0
+
+
+ 20.0
+ 40.0
+
+
+ 18.0
+ 41.0
+
+
+ 20.0
+ 44.0
+
+
+ 22.0
+ 44.0
+
+
+ 16.0
+ 45.0
+
+
+ 20.0
+ 45.0
+
+
+ 25.0
+ 45.0
+
+
+ 30.0
+ 55.0
+
+
+ 20.0
+ 50.0
+
+
+ 22.0
+ 51.0
+
+
+ 18.0
+ 49.0
+
+
+ 16.0
+ 48.0
+
+
+ 20.0
+ 55.0
+
+
+ 18.0
+ 53.0
+
+
+ 14.0
+ 50.0
+
+
+ 15.0
+ 51.0
+
+
+ 16.0
+ 54.0
+
+
+ 28.0
+ 33.0
+
+
+ 33.0
+ 38.0
+
+
+ 30.0
+ 50.0
+
+
+ 13.0
+ 40.0
+
+
+ 15.0
+ 36.0
+
+
+ 18.0
+ 31.0
+
+
+ 25.0
+ 37.0
+
+
+ 30.0
+ 46.0
+
+
+ 25.0
+ 52.0
+
+
+ 16.0
+ 33.0
+
+
+ 25.0
+ 35.0
+
+
+ 5.0
+ 40.0
+
+
+ 5.0
+ 50.0
+
+
+ 10.0
+ 45.0
+
+
+
+ 0
+
+
+
+ 121
+ 121
+ 200.0
+
+
+
+
+ 25.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 6.0
+
+
+ 14.0
+
+
+ 5.0
+
+
+ 11.0
+
+
+ 19.0
+
+
+ 5.0
+
+
+ 15.0
+
+
+ 15.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 12.0
+
+
+ 18.0
+
+
+ 13.0
+
+
+ 18.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 4.0
+
+
+ 7.0
+
+
+ 12.0
+
+
+ 13.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 15.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 3.0
+
+
+ 7.0
+
+
+ 2.0
+
+
+ 4.0
+
+
+ 4.0
+
+
+ 18.0
+
+
+ 14.0
+
+
+ 12.0
+
+
+ 17.0
+
+
+ 20.0
+
+
+ 14.0
+
+
+ 16.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 5.0
+
+
+ 4.0
+
+
+ 21.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 14.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 16.0
+
+
+ 19.0
+
+
+ 5.0
+
+
+ 17.0
+
+
+ 7.0
+
+
+ 16.0
+
+
+ 14.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 17.0
+
+
+ 13.0
+
+
+ 14.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 13.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 35.0
+
+
+ 5.0
+
+
+ 28.0
+
+
+ 7.0
+
+
+ 3.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 12.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 21.0
+
+
+ 4.0
+
+
+ 15.0
+
+
+ 16.0
+
+
+ 4.0
+
+
+ 16.0
+
+
+ 7.0
+
+
+ 10.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 17.0
+
+
+ 12.0
+
+
+ 11.0
+
+
+ 7.0
+
+
+ 9.0
+
+
+ 11.0
+
+
+ 12.0
+
+
+ 7.0
+
+
+ 8.0
+
+
+ 6.0
+
+
+ 5.0
+
+
+ 12.0
+
+
+ 13.0
+
+
+ 7.0
+
+
+ 7.0
+
+
+ 8.0
+
+
+ 11.0
+
+
+ 13.0
+
+
+ 11.0
+
+
+ 10.0
+
+
+ 7.0
+
+
+ 4.0
+
+
+ 20.0
+
+
+ 13.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/CMT14.xml b/Data/Global_Datasets/Christofides/CMT14.xml
new file mode 100644
index 0000000..5685db6
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/CMT14.xml
@@ -0,0 +1,726 @@
+
+
+
+ Christofides et al. 1979
+ CMT14
+
+
+
+
+ 45.0
+ 68.0
+
+
+ 45.0
+ 70.0
+
+
+ 42.0
+ 66.0
+
+
+ 42.0
+ 68.0
+
+
+ 42.0
+ 65.0
+
+
+ 40.0
+ 69.0
+
+
+ 40.0
+ 66.0
+
+
+ 38.0
+ 68.0
+
+
+ 38.0
+ 70.0
+
+
+ 35.0
+ 66.0
+
+
+ 35.0
+ 69.0
+
+
+ 25.0
+ 85.0
+
+
+ 22.0
+ 75.0
+
+
+ 22.0
+ 85.0
+
+
+ 20.0
+ 80.0
+
+
+ 20.0
+ 85.0
+
+
+ 18.0
+ 75.0
+
+
+ 15.0
+ 75.0
+
+
+ 15.0
+ 80.0
+
+
+ 30.0
+ 50.0
+
+
+ 30.0
+ 52.0
+
+
+ 28.0
+ 52.0
+
+
+ 28.0
+ 55.0
+
+
+ 25.0
+ 50.0
+
+
+ 25.0
+ 52.0
+
+
+ 25.0
+ 55.0
+
+
+ 23.0
+ 52.0
+
+
+ 23.0
+ 55.0
+
+
+ 20.0
+ 50.0
+
+
+ 20.0
+ 55.0
+
+
+ 10.0
+ 35.0
+
+
+ 10.0
+ 40.0
+
+
+ 8.0
+ 40.0
+
+
+ 8.0
+ 45.0
+
+
+ 5.0
+ 35.0
+
+
+ 5.0
+ 45.0
+
+
+ 2.0
+ 40.0
+
+
+ 0.0
+ 40.0
+
+
+ 0.0
+ 45.0
+
+
+ 35.0
+ 30.0
+
+
+ 35.0
+ 32.0
+
+
+ 33.0
+ 32.0
+
+
+ 33.0
+ 35.0
+
+
+ 32.0
+ 30.0
+
+
+ 30.0
+ 30.0
+
+
+ 30.0
+ 32.0
+
+
+ 30.0
+ 35.0
+
+
+ 28.0
+ 30.0
+
+
+ 28.0
+ 35.0
+
+
+ 26.0
+ 32.0
+
+
+ 25.0
+ 30.0
+
+
+ 25.0
+ 35.0
+
+
+ 44.0
+ 5.0
+
+
+ 42.0
+ 10.0
+
+
+ 42.0
+ 15.0
+
+
+ 40.0
+ 5.0
+
+
+ 40.0
+ 15.0
+
+
+ 38.0
+ 5.0
+
+
+ 38.0
+ 15.0
+
+
+ 35.0
+ 5.0
+
+
+ 50.0
+ 30.0
+
+
+ 50.0
+ 35.0
+
+
+ 50.0
+ 40.0
+
+
+ 48.0
+ 30.0
+
+
+ 48.0
+ 40.0
+
+
+ 47.0
+ 35.0
+
+
+ 47.0
+ 40.0
+
+
+ 45.0
+ 30.0
+
+
+ 45.0
+ 35.0
+
+
+ 95.0
+ 30.0
+
+
+ 95.0
+ 35.0
+
+
+ 53.0
+ 30.0
+
+
+ 92.0
+ 30.0
+
+
+ 53.0
+ 35.0
+
+
+ 45.0
+ 65.0
+
+
+ 90.0
+ 35.0
+
+
+ 88.0
+ 30.0
+
+
+ 88.0
+ 35.0
+
+
+ 87.0
+ 30.0
+
+
+ 85.0
+ 25.0
+
+
+ 85.0
+ 35.0
+
+
+ 75.0
+ 55.0
+
+
+ 72.0
+ 55.0
+
+
+ 70.0
+ 58.0
+
+
+ 68.0
+ 60.0
+
+
+ 66.0
+ 55.0
+
+
+ 65.0
+ 55.0
+
+
+ 65.0
+ 60.0
+
+
+ 63.0
+ 58.0
+
+
+ 60.0
+ 55.0
+
+
+ 60.0
+ 60.0
+
+
+ 67.0
+ 85.0
+
+
+ 65.0
+ 85.0
+
+
+ 65.0
+ 82.0
+
+
+ 62.0
+ 80.0
+
+
+ 60.0
+ 80.0
+
+
+ 60.0
+ 85.0
+
+
+ 58.0
+ 75.0
+
+
+ 55.0
+ 80.0
+
+
+ 55.0
+ 85.0
+
+
+ 40.0
+ 50.0
+
+
+
+ 0
+
+
+
+ 101
+ 101
+ 200.0
+
+
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 40.0
+
+
+ 40.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 40.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 40.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 50.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 50.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+ 40.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 10.0
+
+
+ 30.0
+
+
+ 20.0
+
+
+ 10.0
+
+
+ 20.0
+
+
+
diff --git a/Data/Global_Datasets/Christofides/readme.txt b/Data/Global_Datasets/Christofides/readme.txt
new file mode 100644
index 0000000..8dff62d
--- /dev/null
+++ b/Data/Global_Datasets/Christofides/readme.txt
@@ -0,0 +1,8 @@
+Christofides, N., Mingozzi, A., Toth, P. (1979). The vehicle routing problem. In: Christofides, N., Mingozzi, A., Toth, P., Sandi, C. (Eds.), Combinatorial Optimization. Wiley, Chichester, pp. 315– 338.
+------------------------------------------------------------------------------------------
+Remarks:
+ - : attribute type=0 for the depot and 1 for customer nodes
+ - : Unfortunately there is no standard rounding rule for this dataset in the literature. Since the VRP-REP format (V.1.0.0) requires a rounding rule we suggest to round the distances to the closest integer value, following the TSPLIB standard. Be aware, however, that this is not necessarily the rounding rule used by the algorithms which delivered the best known solutions for the dataset registered in the VRP-REP platform.
+
+
+
\ No newline at end of file
diff --git a/Notebooks/Graph_Coarsening_Experiment.ipynb b/Notebooks/Graph_Coarsening_Experiment.ipynb
new file mode 100644
index 0000000..d429228
--- /dev/null
+++ b/Notebooks/Graph_Coarsening_Experiment.ipynb
@@ -0,0 +1,211 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Graph Coarsening"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Importing Libraries\n",
+ "\n",
+ "import numpy as np\n",
+ "from time import time\n",
+ "import csv, os\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "from QuantumLogistics import Route, StandardRouteSolver, DeltaCoarseningEngine, VRPExplorationsEncoder, VRPExplorationsSolver\n",
+ "from QuantumLogistics.LogisticsRoute.VrpRepGraph import vrpRepGraph"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[i] Loading graph file c:\\Users\\USER\\Documents\\GitHub\\Quantum-Vehicle-Routing-Problems\\Data\\Global_Datasets\\Christofides\\CMT01.xml...\n",
+ "Customer_id | Customer_coordinates | Demand\n",
+ "[i] Graph loaded successfully!\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Loading the data\n",
+ "\n",
+ "project_root = os.path.abspath(os.path.join(os.getcwd(), os.pardir))\n",
+ "data_dir = os.path.join(project_root, \"Data\", \"Global_Datasets\", \"Christofides\")\n",
+ "\n",
+ "cmt_file = 'CMT01.xml'\n",
+ "file_path = os.path.join(data_dir, cmt_file)\n",
+ "\n",
+ "print(f\"[i] Loading graph file {file_path}...\")\n",
+ "logistics_network = vrpRepGraph(file_path)\n",
+ "print(\"Customer_id | Customer_coordinates | Demand\")\n",
+ "logistics_network.generate_graph()\n",
+ "\n",
+ "print(\"[i] Graph loaded successfully!\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[[i] Setting graph configurations for CMT01.xml...\n",
+ "[i] Number of nodes: 51\n",
+ "[i] Truck Capacity: 160.0\n",
+ "[i] Depot Node: 0\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Graph & Config\n",
+ "\n",
+ "print(f'[[i] Setting graph configurations for {cmt_file}...')\n",
+ "number_of_nodes = logistics_network.n\n",
+ "truck_capacity = max(logistics_network.nodeCapacities)\n",
+ "depot_node = logistics_network.nodelist.vehicle['arrival_node']\n",
+ "\n",
+ "print(f'[i] Number of nodes: {number_of_nodes}')\n",
+ "print(f'[i] Truck Capacity: {truck_capacity}')\n",
+ "print(f'[i] Depot Node: {depot_node}')\n",
+ "\n",
+ "# Define the route configuration\n",
+ "number_trucks = 6\n",
+ "route_config = {'vehicles': number_trucks, 'depot': depot_node, 'truckCapacity': truck_capacity}\n",
+ "\n",
+ "# Define the coarsening configuration\n",
+ "coarsening_rate = 0.3 # Let's try a rate of 0.7\n",
+ "coarsen_config = {'coarsenRate': coarsening_rate, 'radiusCoefficient': 0.2}\n",
+ "coarsening_engine = DeltaCoarseningEngine(**coarsen_config)\n",
+ "\n",
+ "# Create the Route object\n",
+ "route = Route(logistics_network, coarseningEngine=coarsening_engine, **route_config)\n",
+ "route.coarsen = (coarsening_rate < 1.0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[i] Solving the route...\n",
+ "Coarsening Graph now\n",
+ "Final coarse graph has 15 nodes\n",
+ "\n",
+ "Vehicle Routes (Text):\n",
+ " Vehicle 1: 0 -> 6 -> 48 -> 27 -> 1 -> 32 -> 0\n",
+ " Vehicle 2: 0 -> 18 -> 4 -> 0\n",
+ " Vehicle 3: 0 -> 46 -> 47 -> 12 -> 5 -> 38 -> 11 -> 0\n",
+ " Vehicle 4: 0 -> 28 -> 31 -> 26 -> 8 -> 0\n",
+ " Vehicle 5: 0 -> 29 -> 21 -> 34 -> 50 -> 9 -> 16 -> 0\n",
+ " Vehicle 6: 0 -> 41 -> 13 -> 0\n",
+ " Vehicle 7: 0 -> 25 -> 14 -> 0\n",
+ " Vehicle 8: 0 -> 17 -> 37 -> 44 -> 15 -> 0\n",
+ " Vehicle 9: 0 -> 22 -> 2 -> 0\n",
+ " Vehicle 10: 0 -> 36 -> 35 -> 20 -> 3 -> 0\n",
+ " Vehicle 11: 0 -> 39 -> 30 -> 10 -> 49 -> 0\n",
+ " Vehicle 12: 0 -> 42 -> 40 -> 19 -> 0\n",
+ " Vehicle 13: 0 -> 43 -> 24 -> 23 -> 7 -> 0\n",
+ " Vehicle 14: 0 -> 45 -> 33 -> 0\n",
+ "[i] Solved in 1.69 seconds with a total cost of 976.38\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "C:\\Users\\USER\\Documents\\GitHub\\Quantum-Vehicle-Routing-Problems\\Src\\external\\VRP-explorations\\VRP\\quantum\\BQM_based\\solution_partition_solver.py:266: UserWarning: Unable to find route with given number of vehicles. Extending fleet...\n",
+ " warnings.warn('Unable to find route with given number of vehicles. Extending fleet...')\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Solving - VRP Explorations Solver\n",
+ "\n",
+ "# Define the solver we want to use\n",
+ "encoder = VRPExplorationsEncoder()\n",
+ "solver_alg = VRPExplorationsSolver()\n",
+ "solver = StandardRouteSolver(encoder, solver_alg)\n",
+ "\n",
+ "solver_config = {\"timeLimit\": 300, \"solver\": \"neal\"} # Time limit in seconds\n",
+ "\n",
+ "print(\"[i] Solving the route...\")\n",
+ "solved_route, solve_time, cost = solver.solve(route, config=solver_config)\n",
+ "\n",
+ "print(f\"[i] Solved in {solve_time:.2f} seconds with a total cost of {cost:.2f}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[i] Visualizing the solution...\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Visualizating\n",
+ "\n",
+ "print(\"[i] Visualizing the solution...\")\n",
+ "# Set the plot to be displayed inline in the notebook\n",
+ "%matplotlib inline\n",
+ "route.visualiseSolution(solved_route)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3.12 (qintern_py312)",
+ "language": "python",
+ "name": "qintern_py312"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Src/QuantumLogistics/Graph.py b/Src/QuantumLogistics/Graph.py
new file mode 100644
index 0000000..957a71a
--- /dev/null
+++ b/Src/QuantumLogistics/Graph.py
@@ -0,0 +1,19 @@
+from pygsp import graphs
+import pygsp
+import networkx as nx
+import numpy as np
+
+from typing import Tuple, List
+
+class Graph:
+ """Generate the coordinates of 'n' instances (nodes)"""
+
+ def set_seed(self, seed=None):
+ np.random.seed(seed if seed else self.seed )
+
+
+ def generate_graph(self) -> graphs.Graph:
+ raise NotImplementedError()
+
+ def plotGraph(self):
+ raise NotImplementedError()
diff --git a/Src/QuantumLogistics/LogisticsRoute/GraphCoarsening.py b/Src/QuantumLogistics/LogisticsRoute/GraphCoarsening.py
new file mode 100644
index 0000000..1d1bbd1
--- /dev/null
+++ b/Src/QuantumLogistics/LogisticsRoute/GraphCoarsening.py
@@ -0,0 +1,434 @@
+from abc import ABC, abstractclassmethod
+import math
+import networkx as nx
+import pygsp
+import matplotlib.pyplot as plt
+import numpy as np
+
+from graph_coarsening import coarsening_utils
+from graph_coarsening.coarsening_utils import *
+
+import graph_coarsening.graph_utils
+
+
+class CoarseningEngine(ABC):
+
+ def __init__(self):
+ """
+ General coarsening Engine Class used to coarsen Logistics Graphs in VRP problem
+ """
+ # ratio of coarse nodes to fine nodes
+ self.rate = 1
+
+ return
+
+ @abstractclassmethod
+ def coarsen(self):
+
+ raise NotImplementedError
+
+
+
+
+class BlankCoarseningEngine:
+ def __init__(self):
+ """
+ General coarsening Engine Class used to coarsen Logistics Graphs in VRP problem
+ """
+
+ return
+
+
+ def coarsen(self):
+ print("Using blank coarsening engine, no coarsening algorithm defined")
+ return
+
+
+
+
+
+
+
+
+class DeltaCoarseningEngine:
+
+ def __init__(self, coarsenRate = 0.1, radiusCoefficient = 0.2):
+ """
+ General coarsening Engine Class used to coarsen Logistics Graphs in VRP problem
+
+ Args:
+ coarsening_ration (float, optional): The size of the graph we are interested in preserving. Defaults to 0.2.
+ kmax (float, optional): The size of the subspace we are interested in preserving. Defaults to 0.2.
+ method (str, optional): The method of coarsening. Defaults to 'nearest'.
+
+ """
+
+ # self.edl.values
+ self.rate = coarsenRate
+ self.radiusCoefficient = radiusCoefficient
+
+ return
+
+
+
+
+
+
+
+ def coarsen(self, graph, depot, nodeWeights, maxCapacity):
+ """
+ Accepts a LogisticsRoute object
+ Returns:
+ Coarse graph object
+ Fine to coarse node mapping
+
+ # This currently only handles a single depot - needs to be modified to handle multiple
+ """
+ self.graph = graph
+ self.graphWeights = nodeWeights
+ self.depot = [depot]
+ self.maxCapacity = maxCapacity
+
+ #TODO: Is there any reason this is using networkx? Need to move towards a consistent graph package
+ # Better to remove depot node from network and go from adjacency matrix
+ self.G = nx.from_numpy_array(self.graph.W)
+ self.edgList = { e:self.G.get_edge_data(*e)['weight'] for e in self.G.edges}
+ tempEdgList = self.edgList.copy()
+
+ # removing edges to 0:
+ for key in list(tempEdgList.keys()):
+ if 0 in key:
+ tempEdgList.pop(key)
+
+ pairsToCoarsen = []
+ bounds = 1
+ whileCounter = 0
+
+ while len(pairsToCoarsen) == 0 and whileCounter < 10:
+ # get coarsening radius
+ coarseningRadius = self.generateCoarseningRadius(tempEdgList, bounds*self.radiusCoefficient)
+
+ # print("\n\n\n")
+ # print("COARSENING NEW GRAPH")
+ # print("Coarsening Radius :", coarseningRadius)
+
+ # identify node pairs that can be coarsened in graph
+ pairsToCoarsen = self.identifyCoarseningPairs(coarseningRadius)
+
+ # adjusting bouds if no pairs found
+ bounds = 1.4 * bounds
+
+ whileCounter += 1
+
+
+ # Coarsen Graph - what is the point of this if everything gets overwritten anyway?
+ coarseningMatrix, coarseGraph = self.generateCoarseGraph(pairsToCoarsen)
+
+ plotCoords = False
+ if plotCoords == True:
+ #print(coarseGraph.coords)
+ plt.scatter(coarseGraph.coords[:,0], coarseGraph.coords[:,1])
+ plt.scatter(self.graph.coords[:,0], self.graph.coords[:,1])
+ plt.show()
+
+ return coarseGraph, coarseningMatrix
+
+
+
+
+
+
+
+ def generateCoarseGraph(self, nodePairsToCoarsen):
+ """
+ Generates a coarse graph for a SINGLE STEP of coarsening
+ C : np.array of size n x N
+ The coarsening matrix. Maps n coarse nodes to N fine nodes using formula in Loukas
+ Gc : pygsp Graph
+ The smaller graph.
+ """
+
+ G = self.graph #the original graph
+ GAdjacency = G.W
+
+ # Creating coarsening matrix based on pairs of nodes to contract
+ C = get_coarsening_matrix(G, nodePairsToCoarsen) # level n to level n-1 coarsening Matrix
+
+ #print(C)
+
+ # Coarse Graph Coords:
+ coarseCoords = coarsen_vector(G.coords, C)
+
+ # Coarse Adjacency
+ # Generating a Loukas coarse graph to get a binary adjacency for connectivity:
+ Wc = graph_utils.zero_diag(coarsen_matrix(GAdjacency, C)) # coarsen and remove self-loops
+ Wc = (Wc + Wc.T) / 2 # this is only needed to avoid pygsp complaining for tiny errors
+
+ # constructing own W:
+ nodeNum = coarseCoords.shape[0]
+ adj = Wc
+ distanceAdja = np.zeros((nodeNum, nodeNum))
+ for pointIdx1 in range(nodeNum):
+ for pointIdx2 in range(pointIdx1 + 1, nodeNum):
+ if adj[pointIdx1, pointIdx2] != 0:
+ dist = np.linalg.norm(coarseCoords[pointIdx1] - coarseCoords[pointIdx2])
+ distanceAdja[pointIdx1, pointIdx2] = dist
+ distanceAdja[pointIdx2, pointIdx1] = dist
+
+
+ # Making new coarse graph
+ #Gc = gsp.graphs.Graph(Wc, coords=coarsen_vector(G.coords, iC)) # Some Variable
+ Gc = gsp.graphs.Graph(distanceAdja, coords=coarseCoords) # New euclidean coarse graph
+
+ # Coarsening Matrix
+ # In multilevel coarsening must propogate coarsening matrix:
+ # C = sp.sparse.eye(G.N, format="csc") # Some Variable
+ # C = iC.dot(C) # full coarsening matrix
+
+ return C, Gc
+
+
+
+ def generateCoarseningRadius(self, edgList, partitionCoefficient):
+ """
+ Returns the radius under which nodes are coarsened
+ Based on parition weights
+ """
+ # TODO : FIXIT ?
+ '''
+ (1,2): 2.1,
+ (2,1): 5.1,
+ '''
+ partition = partitionCoefficient
+
+ w = list(edgList.values())
+ w = list(sorted(w))
+
+ size = self.G.number_of_nodes() # 20
+ #size = self.G.N # 20
+ part = math.floor(size * partition) # 4
+
+ coarseningRadius = (w[part] + w[part+1]) / 2
+
+ return coarseningRadius
+
+
+
+
+ def identifyCoarseningPairs(self, coarseningRadius):
+ """
+ Used to identify subgraphs to contract during coarsening
+ """
+ self.visited = []
+ self.collapse = []
+
+ # order nodes based on weights (minimum weight first)
+ sortedIdxs = np.argsort(self.graphWeights)
+
+ for n in sortedIdxs:
+ #for n in self.G.nodes:
+ if n not in self.visited:
+ self.check_collapsable(n, self.edgList, coarseningRadius)
+
+ return self.collapse
+
+
+
+
+ def check_collapsable(self, curr, edgList, coarseningRadius, debug=False):
+ """
+ curr - current node being checked
+ edgList - list of edge lengths
+ """
+ # TODO : Avoid 2 neghbourin... colla..
+
+ # If the current node has been
+ if curr in self.visited:
+ return
+
+ neighbours = self.getNeighbourData(curr, edgList)
+
+ # Possible speed up?
+ for nodes, weight in neighbours.items():
+ a,b = nodes
+ coarsenedNodeCapacity = self.graphWeights[a] + self.graphWeights[b]
+ # Checks the followiung:
+ # If edge is small enough to contract
+ # If a nd b not the depot (cannot contract the depot)
+ # A and B have not already been coarsened/attached to a coarsened node
+ # the combined capacity of a coarsened a+b node is less than the capacity of a given truck
+
+ if weight < coarseningRadius and (a not in self.depot and b not in self.depot) and (a not in self.visited and b not in self.visited) and (coarsenedNodeCapacity < self.maxCapacity):
+ self.collapse += [ nodes ]
+ self.visited += [ *nodes ]
+
+ # adding all neigbour nodes of a and b to visited
+ for node in nodes:
+ listOfNeigbours = [k for v,k in self.getNeighbourData(node, edgList).keys()]
+ self.visited += [ *listOfNeigbours ]
+
+ if debug:
+ print( f"[+] curr : {curr}", neighbours )
+ print(f"Adding Nodes: {nodes}")
+ print(f'updated visitedList: {self.visited}')
+ print("\n")
+
+ return
+
+ self.visited += [ curr ]
+
+ if debug:
+ print( f"[ ] curr : {curr}", neighbours )
+ print(f'updated visitedList: {self.visited}')
+ print("\n")
+
+ for nodes in set([ i for n in list(neighbours.keys()) for i in n ]):
+ self.check_collapsable(nodes, edgList, coarseningRadius)
+
+ return
+
+
+
+ def getNeighbourData(self, node, edgList):
+ # Finds all neighbours who have not been visited
+ # Returns a dict of {(node, neighbourNode):edgeWeight}
+
+ neighbour_data = {}
+
+ size = self.graph.N
+ for ConNode in range(size):
+ if ConNode not in self.visited:
+ edgBase = (node, ConNode)
+ edg = edgBase
+ if ConNode < node:
+ edg = (ConNode, node)
+
+ if edg in edgList:
+ neighbour_data[edgBase] = edgList[edg]
+
+ # sorted on value
+ neighbours = dict(sorted(neighbour_data.items(), key=lambda item: item[1]))
+
+ return neighbours
+
+
+
+
+
+ def inflateSolution(self, solution, fineGraph, coarseningMatrix):
+ """
+ coarseSolution - [[(0,1), (1,5), (5,0)], [(0,2), (2, 4), (4, 0)] sequence of edges in solution
+ fineGraph - the coarse graph object
+ coarseningMatrix - mapping from coarse to fine matrix
+ """
+
+ inflatedSolution = []
+ weightedAdj = fineGraph.W # this needs to be one step ahead
+
+ # Getting coarsening Map:
+ coarseningMap = self.coarseMatrixToMap(coarseningMatrix)
+
+ # make sure it works for one vehicle
+ numVehicles = len(solution)
+
+ for vehicleIdx in range(numVehicles):
+ coarseVehicleRoute = solution[vehicleIdx]
+
+ inflatedRoute = self.inflateSingleRoute(coarseVehicleRoute, coarseningMap, weightedAdj)
+ inflatedSolution.append(inflatedRoute)
+
+ return inflatedSolution
+
+
+
+
+ def coarseMatrixToMap(self, coarseningMatrix):
+
+ # Child to Parent Mapping
+ c, r = np.where((coarseningMatrix.todense() > 0) )
+ coarsenMap = { i: [] for i in range(coarseningMatrix.shape[0]) }
+
+ for (_c, _r) in zip(c, r):
+ coarsenMap[_c] += [_r]
+
+ return coarsenMap
+
+
+
+
+
+ def inflateSingleRoute(self, route, coarsenMap, weightedAdj):
+ """
+ Expands Single Vehicle Route
+ THIS ASSUMES A SINGLE BINARY DECISION AT EACH STEP
+ """
+
+ # reducing solution from [(a,b), (b,c), (c,d)] to [a,b,c,d]
+ route = self.routeEdgeToNode(route)
+ inflatedRoute = [coarsenMap[route[0]][0]]
+
+ # Should assert first and last node belong in depot - requires knowledge of depots in coarse nodes
+ # assert route[0] in self.depot and route[0]
+ for routeStopIdx in range(1, len(route[1:]) + 1):
+
+ #skipping first and last points (they are depots)
+ nodeIdx = route[routeStopIdx]
+ inflatedNode = coarsenMap[nodeIdx]
+
+ if len(inflatedNode) > 1:
+ # choice in direction - which node to go to first
+ # Only works if no contraction neigboursa
+
+ start = coarsenMap[route[routeStopIdx-1]]
+ end = coarsenMap[route[routeStopIdx+1]]
+
+ assert len(start) == 1 and len(end) == 1
+
+ node1 = inflatedNode[0]
+ node2 = inflatedNode[1]
+
+ # Collective travelled distance
+ distance1 = weightedAdj[start[0], node1] + weightedAdj[end[0],node2]
+ distance2 = weightedAdj[start[0], node2] + weightedAdj[end[0],node1]
+
+ if distance2 <= distance1:
+ inflatedNode = [node2, node1]
+
+ inflatedRoute.extend(inflatedNode)
+
+ inflatedRoute = self.routeNodeToEdge(inflatedRoute)
+
+ return inflatedRoute
+
+
+
+
+ def routeEdgeToNode(self, route):
+ """
+ Changing route from [(a,b), (b,c), (c,d)] to [a,b,c,d]
+ """
+ reducedRoute = []
+
+ # adding first vertex of each edge sequentially
+ for edge in route:
+ reducedRoute.append(edge[0])
+
+ # adding last element
+ reducedRoute.append(route[-1][1])
+
+ return reducedRoute
+
+
+
+
+ def routeNodeToEdge(self, route):
+ """
+ Changing route from [a,b,c,d] to [(a,b), (b,c), (c,d)]
+ """
+
+ reducedRoute = [(route[0], route[1])]
+
+ for nodeIdx in range(1, len(route) - 1):
+ reducedRoute.append((route[nodeIdx], route[nodeIdx+1]))
+
+ return reducedRoute
\ No newline at end of file
diff --git a/Src/QuantumLogistics/LogisticsRoute/LogisticsGraph.py b/Src/QuantumLogistics/LogisticsRoute/LogisticsGraph.py
new file mode 100644
index 0000000..bf82c43
--- /dev/null
+++ b/Src/QuantumLogistics/LogisticsRoute/LogisticsGraph.py
@@ -0,0 +1,86 @@
+from pygsp import graphs
+import pygsp
+import networkx as nx
+import numpy as np
+
+from typing import Tuple, List
+
+from ..Graph import Graph
+
+class logisticsGraph(Graph):
+ """Generate the coordinates of 'n' instances (nodes)"""
+
+ def __init__(self, nodeCapacityDefintion, seed = 1543, graph_type = "fully_connected"):
+ """
+ Input:
+ nodeCapacityDefinition: A list of capacities for each node in the graph.
+ seed: used in the generation of a graph
+ graph_type: the type of graph being made
+ """
+ self.nodeCapacities = nodeCapacityDefintion
+ self.n = len(nodeCapacityDefintion)
+ self.seed = seed
+ self.graph_type = graph_type
+ self.set_seed()
+
+ def set_seed(self, seed=None):
+ np.random.seed(seed if seed else self.seed )
+
+ def generate_graph(self) -> graphs.Graph:
+ xc, yc, instance = self.generateGraphPoints()
+
+ # Define a Graph
+ graph = graphs.Graph(instance)
+
+ coords = np.array([c for c in zip(xc, yc)])
+ graph.set_coordinates(coords)
+
+ self.graph = graph
+
+ return graph
+
+ def generateGraphPoints(self) -> Tuple[List, List, np.array]:
+ xy = np.random.rand(2, self.n) + + np.ones((2, self.n)) #What is the ones offset for??
+ xc = xy[0]
+ yc = xy[1]
+ xy = xy.T
+
+ # Creating NetworkX Graph
+ graphCreationFunctions = {"fully_connected" : nx.complete_graph(self.n),
+ "random" : nx.fast_gnp_random_graph(self.n, 0.6),
+ "small_world" : nx.newman_watts_strogatz_graph(self.n, 3, 0.75)}
+
+ G = graphCreationFunctions[self.graph_type]
+
+ # Checking connected:
+ assert nx.is_connected(G) , "Graph must be fully connected, please use a different graph"
+ # print("IS THE GRAPH CONNECTED: ")
+ # print(nx.is_connected(G))
+ # input("")
+
+ # Populate NetworkX Graph with appropiate Weight
+ for (u, v) in G.edges():
+ uc = xy[u]
+ vc = xy[v]
+ G.edges[u,v]['weight'] = np.linalg.norm( uc - vc )
+
+ # Fetch NewtorkX Graph Adjacency Matrix
+ W = nx.adjacency_matrix(G).todense()
+
+ return xc, yc, W
+
+ def plotGraph(self):
+ """
+ Visualises the LogisticsGraph's graph object
+
+ """
+ pygsp.plotting.plot_graph(self.graph)
+ input("Press any to continue")
+
+ return
+
+ def loadGraphPointsFromFile(self):
+ raise NotImplementedError
+
+ def loadGraphFromFile(self):
+ raise NotImplementedError
\ No newline at end of file
diff --git a/Src/QuantumLogistics/LogisticsRoute/LogisticsRoute.py b/Src/QuantumLogistics/LogisticsRoute/LogisticsRoute.py
new file mode 100644
index 0000000..2836f16
--- /dev/null
+++ b/Src/QuantumLogistics/LogisticsRoute/LogisticsRoute.py
@@ -0,0 +1,262 @@
+import matplotlib.pyplot as plt
+from QuantumLogistics.LogisticsRoute.GraphCoarsening import BlankCoarseningEngine
+import numpy as np
+import scipy as sp
+import pygsp
+import copy
+
+class Route(object):
+ def __init__(self, LogisticsGraph, coarseningEngine = None, **config):
+
+ graph = LogisticsGraph.graph
+ self.nodeCapacities = LogisticsGraph.nodeCapacities
+
+ # Keeping the raw data as well
+ self._context = {
+ 'graph': graph
+ }
+
+ self.graph = graph # PyGSP graph object
+ self.n = LogisticsGraph.n # Number of nodes
+ self.depot = config["depot"] # ID of the depot (default 0)
+ self.cursor = config["depot"] # Current location of the cursor vehicle
+ self.vehicles = config["vehicles"] # Number of vehicle
+ self.truckCapacity = config["truckCapacity"] # value of maximum truck capacity
+ self.coords = getattr(graph, 'coords', []) # Coordinates of the nodes
+ self.routes = None # Calculated Routes
+ self.solution = None
+
+ # Coarsening Parameters:
+ self.coarsen = False
+
+ if coarseningEngine == None:
+ self.coarseningEngine = BlankCoarseningEngine()
+ else:
+ self.coarseningEngine = coarseningEngine
+
+ self.coarsenRate = self.coarseningEngine.rate
+
+ #Must ADD Capacities and Time Windows
+
+ def __call__(self, ):
+ pass
+
+
+ def visualiseSolution(self, routeSolution, colormap = "hsv", saveImgFilepath = False):
+ try:
+ routes = routeSolution
+ [xc, yc] = self.graph.coords.T
+ plt.figure()
+ plt.scatter(xc, yc, s=200)
+ # for i in range(len(xc)):
+ # plt.annotate(i, (xc[i] + 0.15, yc[i]), size=16, color="r")
+
+ i = 0
+ for x, y in zip(xc, yc):
+ plt.annotate(i, (x + 0.075, y), size=16, color="r")
+ i += 1
+
+ plt.plot(xc[0], yc[0], "r*", ms=20)
+ plt.grid()
+
+ vehicle_cmap = self.get_cmap(len(routes) + 1, name=colormap)
+ for vehicle in range(len(routes)):
+ tour = routes[vehicle]
+ color = vehicle_cmap(vehicle)
+ for hop in tour:
+ _from, _to = hop
+
+ plt.arrow(
+ xc[_from],
+ yc[_from],
+ xc[_to] - xc[_from],
+ yc[_to] - yc[_from],
+ length_includes_head=True,
+ head_width=0.02,
+ color = color
+ )
+
+ if not saveImgFilepath:
+ #print("THIS IS SHOWING THE THING HERE")
+ plt.show()
+ else:
+ print("SAVING FIGURE")
+ plt.savefig(saveImgFilepath)
+ except:
+ print("error when visualising route")
+ return
+
+ def visualiseGraph(self):
+ pygsp.plotting.plot_graph(self.graph)
+ input("Press any button to continue")
+ return
+
+ def printSolution(self, routeSolution):
+ """
+ Prints the routes for each vehicle in a text format.
+ e.g., Vehicle 1: 0 -> 1 -> 4 -> 5 -> 0
+ """
+ print("\nVehicle Routes (Text):")
+ for i, route in enumerate(routeSolution):
+ if not route:
+ print(f" Vehicle {i+1}: No route")
+ continue
+
+ path = [str(route[0][0])]
+ for edge in route:
+ path.append(str(edge[1]))
+ print(f" Vehicle {i+1}: {' -> '.join(path)}")
+
+ def evalutateKPIS(self, solution):
+ cost = self.calculateCost(solution)
+ return
+
+
+ def get_cmap(self, n, name='hsv'):
+ '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
+ RGB color; the keyword argument name must be a standard mpl colormap name.'''
+ return plt.cm.get_cmap(name, n)
+
+
+ def pygsp_graph(self):
+ """
+ Returns the source graph PyGSP object
+ """
+ return self._context['graph']
+
+
+ def graphEdges2Dict(self, graph):
+ edge_list = graph.get_edge_list()
+ n1, n2, w = edge_list
+ assert len(n1) == len(n2) == len(w)
+ return { (n1[i], n2[i]):w[i] for i in range(len(n1)) }
+
+
+
+ def calculateCost(self, solution):
+ """
+ Needs to be checked fundamentally
+ """
+ _graph = self.pygsp_graph()
+ edl = self.graphEdges2Dict(_graph)
+ cost = 0
+ for route in solution:
+ for (_from, _to) in route:
+ cost += edl.get((_from, _to), edl.get((_to, _from), 0) )
+
+ return cost
+
+
+
+ def recordMetaData(self):
+ """
+ Add important details to self.metaData for later analysis
+ """
+ raise NotImplementedError
+
+
+ def setSolution(self):
+ #Solution to be in form:
+ # [ [list vehicle1 nodes],
+ # [list vehicle2 nodes],
+ # [list vehicle3 nodes],]
+
+ raise NotImplementedError
+
+
+
+ def coarsenGraph(self):
+ """
+ Coarsens the graph using the coarseningEngine defined in the route instantiation
+ """
+ # General parameters
+ coarseningRate = self.coarseningEngine.rate
+ initialGraphSize = self.n
+ newGraphSize = initialGraphSize
+ fineNodeCapacities = self.nodeCapacities
+
+ # History lists
+ self.originalGraph = copy.deepcopy(self.graph) #pygsp object
+ self.coarsenGraphHistory = [self.originalGraph]
+ self.coarsenMappingHistory = [sp.sparse.eye(self.originalGraph.N, format="csc")]
+
+ # Setting graph variable
+ graphToCoarsen = self.graph
+
+ # Coarsening graphs - probably need to do metrics here to compare the original to final
+ while newGraphSize > coarseningRate * initialGraphSize:
+ # Coarsening
+ coarsenedGraph, fineToCoarseMapping = self.coarseningEngine.coarsen(graphToCoarsen, self.depot, fineNodeCapacities, self.truckCapacity)
+
+ # updating node capacities
+ coarseNodeCapacities = self.propogateNodeCapacities(fineNodeCapacities, fineToCoarseMapping)
+
+ # Saving history and iterating
+ self.coarsenGraphHistory.append(coarsenedGraph)
+ self.coarsenMappingHistory.append(fineToCoarseMapping)
+ graphToCoarsen = coarsenedGraph
+ coarseGraphSize = coarsenedGraph.N
+
+ if coarseGraphSize == newGraphSize:
+ print("Has not decreased in size, terminating now: ")
+ break
+
+ newGraphSize = coarseGraphSize
+ fineNodeCapacities = coarseNodeCapacities
+
+ plotCoords = False
+ if plotCoords == True:
+ plt.scatter(self.originalGraph.coords[:,0], self.originalGraph.coords[:,1])
+ plt.scatter(coarsenedGraph.coords[:,0], coarsenedGraph.coords[:,1])
+ plt.show()
+
+ self.graph = graphToCoarsen
+ self.nodeCapacities = fineNodeCapacities
+
+ print("Final coarse graph has {0} nodes".format(self.graph.N))
+
+ return
+
+
+ def propogateNodeCapacities(self, fineNodeCapacities, fineToCoarseMapping):
+ """
+ Updating coarse node capacities
+ """
+ rows,cols = fineToCoarseMapping.nonzero() # When working, it's 13 x 14 i.e. 14 nodes coarsened to 13
+ coarseNodeQty = max(cols) # Thus, this is max of the 14 elements [0...13] ie 13 ]---.
+ coarseNodeCapacities = np.zeros(coarseNodeQty) # | TODO: In case of un-successful
+ # | coarsening, this fineToCoarseMapping
+ for row,col in zip(rows,cols): # | is a square matrix, raising problems
+ coarseNodeCapacities[row] += fineNodeCapacities[col] # < --' $ python3 src/sample.py
+ return coarseNodeCapacities
+
+
+
+
+
+ def inflateGraph(self, solution):
+ """
+ Inflates solution from solver to coarsen engine
+ """
+
+ # need to inflate through graphs:
+ coarseGraphSol = solution #- list of lists for each vehicle
+
+ inflatedRoutes = coarseGraphSol
+
+ # Stepping through history
+ for graphIdx in range(len(self.coarsenGraphHistory) - 1, 0, -1):
+ coarsenedGraph = self.coarsenGraphHistory[graphIdx-1]
+ coarseningMatrix = self.coarsenMappingHistory[graphIdx]
+ inflatedSolution = self.coarseningEngine.inflateSolution(coarseGraphSol, coarsenedGraph, coarseningMatrix)
+ inflatedRoutes.append(inflatedSolution)
+
+ # Setting current inflated to new coarse:
+ coarseGraphSol = inflatedSolution
+
+ return inflatedSolution
+
+
+
+
+
\ No newline at end of file
diff --git a/Src/QuantumLogistics/LogisticsRoute/VrpRepGraph.py b/Src/QuantumLogistics/LogisticsRoute/VrpRepGraph.py
new file mode 100644
index 0000000..49872ca
--- /dev/null
+++ b/Src/QuantumLogistics/LogisticsRoute/VrpRepGraph.py
@@ -0,0 +1,73 @@
+from pygsp import graphs
+import pygsp
+import networkx as nx
+import numpy as np
+
+import math
+
+from typing import Tuple, List
+
+from ..Graph import Graph
+from .vrprep_utils import loaddataset
+
+class vrpRepGraph(Graph):
+ """Generate the coordinates of 'n' instances (nodes)"""
+
+ def __init__(self, file, seed = 1543):
+ """
+ Input:
+ file: the location of xml graph file
+ seed: used in the generation of a graph
+ """
+ self.graphFile = file
+ self.nodelist = loaddataset(self.graphFile)
+ self.n = len(self.nodelist.get_nodes()) + 1
+ self.seed = seed
+ self.set_seed()
+
+ def set_seed(self, seed=None):
+ np.random.seed(seed if seed else self.seed )
+
+ def generate_graph(self) -> graphs.Graph:
+ instance = np.zeros((self.n, self.n))
+ coords = np.array([node.get_pos() for node in self.nodelist.get_all_nodes()])
+
+ # Create the Weight Adjacency
+ for x, points_A in enumerate(coords):
+ for y, points_B in enumerate(coords):
+ instance[x, y] = np.linalg.norm(points_A - points_B)
+
+ np.fill_diagonal(instance, 0)
+
+ # Define a Graph
+ graph = graphs.Graph(instance)
+ graph.set_coordinates(coords)
+
+ self.graph = graph
+
+ # Capacities
+ self.nodeCapacities = [ node.get_dem() for node in self.nodelist.get_all_nodes() ]
+
+ assert len(self.nodeCapacities) == len(coords) == self.n
+
+ # Number of vehicles
+ num_vehicles = math.ceil(sum(self.nodeCapacities) / self.nodelist._capacity)
+
+ return graph
+
+
+ def plotGraph(self):
+ """
+ Visualises the LogisticsGraph's graph object
+
+ """
+ pygsp.plotting.plot_graph(self.graph)
+ input("Press any to continue")
+
+ return
+
+ def loadGraphPointsFromFile(self):
+ raise NotImplementedError
+
+ def loadGraphFromFile(self):
+ raise NotImplementedError
\ No newline at end of file
diff --git a/Src/QuantumLogistics/LogisticsRoute/__init__.py b/Src/QuantumLogistics/LogisticsRoute/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/GraphCoarsening.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/GraphCoarsening.cpython-312.pyc
new file mode 100644
index 0000000..a22495b
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/GraphCoarsening.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsGraph.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsGraph.cpython-312.pyc
new file mode 100644
index 0000000..7fd2894
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsGraph.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsRoute.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsRoute.cpython-312.pyc
new file mode 100644
index 0000000..a9f8eaf
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/LogisticsRoute.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/VrpRepGraph.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/VrpRepGraph.cpython-312.pyc
new file mode 100644
index 0000000..ee52238
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/VrpRepGraph.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/__init__.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..7a2acd0
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/__init__.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/__pycache__/vrprep_utils.cpython-312.pyc b/Src/QuantumLogistics/LogisticsRoute/__pycache__/vrprep_utils.cpython-312.pyc
new file mode 100644
index 0000000..9d8dfc5
Binary files /dev/null and b/Src/QuantumLogistics/LogisticsRoute/__pycache__/vrprep_utils.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/LogisticsRoute/vrprep_utils.py b/Src/QuantumLogistics/LogisticsRoute/vrprep_utils.py
new file mode 100644
index 0000000..b9dc396
--- /dev/null
+++ b/Src/QuantumLogistics/LogisticsRoute/vrprep_utils.py
@@ -0,0 +1,119 @@
+import xml.etree.ElementTree as ET
+import numpy as np
+import networkx as nx
+import matplotlib.pyplot as plt
+
+def loaddataset(filename='dataset/CMT01.xml'):
+ tree = ET.parse(filename)
+ root = tree.getroot()
+
+ capacity = float(root.findall('.//capacity')[0].text) # All vehicles have the same capacity
+ nodes = NodeList(capacity)
+
+ nodes.vehicle = {
+ "departure_node": int(list(root.find('fleet'))[0].find('departure_node').text),
+ "arrival_node": int(list(root.find('fleet'))[0].find('arrival_node').text),
+ "capacity": float(list(root.find('fleet'))[0].find('capacity').text),
+ }
+
+
+ # nodes.vehicle = {
+ # "departure_node": int(root.find('fleet').getchildren()[0].find('departure_node').text),
+ # "arrival_node": int(root.find('fleet').getchildren()[0].find('arrival_node').text),
+ # "capacity": float(root.find('fleet').getchildren()[0].find('capacity').text),
+ # }
+
+
+ for index, node in enumerate(root.iter('vehicle_profile')):
+ assert node.find('arrival_node').text == node.find('departure_node').text
+ id_ = int(node.find('arrival_node').text)
+ demand = float(node.find('capacity').text)
+ depot_node = [ n for n in root.iter('node') if int(n.get('id')) == id_ ][0]
+ x = float(depot_node.find('cx').text)
+ y = float(depot_node.find('cy').text)
+ position = np.array([x, y])
+ depot = Node(id_, 0, position, demand)
+ nodes.append(depot)
+
+ nodes.vehicle = {
+ "departure_node": index,
+ "arrival_node": index,
+ "capacity": demand,
+ }
+
+ for request in root.iter('request'):
+ node = [ n for n in root.iter('node') if int(n.get('id')) == int(request.attrib['node']) ][0]
+ id_ = int(node.get('id'))
+ type_ = int(node.get('type'))
+ x = float(node.find('cx').text)
+ y = float(node.find('cy').text)
+ position = np.array([x, y])
+ demand = float(request.find('quantity').text)
+ node_ = Node(id_, type_, position, demand)
+ nodes.append(node_)
+
+
+ return nodes
+
+
+class Node(object):
+
+ def __init__(self, id_, type_, position, demand):
+ self._id = id_
+ self._type = type_
+ self._position = position
+ self._demand = demand
+
+ # Getter
+ def get_id(self):
+ return self._id
+
+ def get_type(self):
+ return self._type
+
+ def get_pos(self):
+ return self._position
+
+ def get_dem(self):
+ return self._demand
+
+class NodeList(list):
+ def __init__(self, capacity):
+ list.__init__(self)
+ self._capacity = capacity
+ self._depot = None
+ self._is_first_get_depot = True
+ self.vehicle = Node
+
+ def get_depot(self):
+ if self._is_first_get_depot:
+ if 0 not in [ n.get_type() for n in self ]:
+ self[0]._type = 0
+ for node in self:
+ if node.get_type() == 0:
+ self._depot = node
+ self._is_first_get_depot = False
+ return self._depot
+ return self._depot
+
+ def get_nodes(self):
+ return [node for node in self if node.get_type()==1]
+
+ def get_all_nodes(self):
+ return self # sorted([node for node in self], key=lambda n: n._id)
+
+ def get_nodes_id_list(self):
+ return [node.get_id() for node in self if node.get_type()==1]
+
+ def get_node_pos_from_id(self, id_):
+ for node in self:
+ if node.get_id() == id_:
+ return node.get_pos()
+
+ def is_feasible(self, route):
+ amount = 0
+ for node in self:
+ if node.get_id() in route:
+ amount += node.get_dem()
+ is_feasible = (amount < self._capacity)
+ return is_feasible
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/ILPEncoder.py b/Src/QuantumLogistics/RouteSolver/Encoders/ILPEncoder.py
new file mode 100644
index 0000000..118c82d
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/Encoders/ILPEncoder.py
@@ -0,0 +1,278 @@
+import numpy as np
+import pandas as pd
+import math
+import pulp as pl
+import cplex
+
+#Custom Imports
+from QuantumLogistics import Route
+from .StandardEncoder import Encoder
+
+
+class ILPPulpEncoder(Encoder):
+ """
+ Converts VRP problem into a PuLP ILP problem.
+ This is used for classical solvers.
+ """
+ def __init__(self):
+
+ return
+
+
+ def encode(self, route:Route) -> pl.LpProblem:
+ """
+ Uses pulp to return the definition of ILP problem
+ This is based on the Miller Tucker Zemlin formulation of the CVRP problem of an n node graph
+ Decision Vars:
+ dec_x - whether to travel on edge ij [size nxn]
+ dec_u - the 'integral' variable indicating the 'used truck capacity' of the truck at that node
+ """
+ print("Starting problem encoding")
+
+ # to remember the route characteristics
+ self.route = route
+ n = route.graph.N
+ K = route.vehicles
+ graphAdjMatr = route.graph.W.toarray()
+
+ # Capacities:
+ nodeCapacities = route.nodeCapacities
+ Q = self.route.truckCapacity
+
+ # Start the LP problem definition
+ prob = pl.LpProblem("VRP", pl.LpMinimize)
+
+ # define the decision variable
+ dec_x = list(range(n ** 2))
+ dec_u = list(range(dec_x[-1] + 1, dec_x[-1] + n))
+ dec_total = dec_x + dec_u
+
+ var_x = pl.LpVariable.dicts("x", dec_x, 0, 1, cat='Integer')
+ var_u = pl.LpVariable.dicts("u", dec_u, min(nodeCapacities), Q, cat="Continuous")
+
+ # merge both dictionaries
+ l = [var_x, var_u]
+ dec_vars = {**l[0], **l[1]}
+
+ # create the dictonary for the weights:
+ my_obj = list(graphAdjMatr.reshape(1, n ** 2)[0]) + [0.0 for x in range(0, n - 1)]
+ weight_opt = dict(zip(dec_vars, my_obj))
+
+ # Define the Objective function
+ prob += pl.lpSum([weight_opt[i]*dec_vars[i] for i in dec_total])
+
+ # create the array with all the right hand size contrainst values
+ # This is the order in which constraints are made
+ # first line - sum of xijk for each node (depot is idx 0 ) must be either # vehicles or 1. Multipled by 2 for entry and exit
+ # second line - ui values are less than truck capacity
+ # third line - paths from node to node i (self paths) must not be selected
+
+ # subject to the node-visiting and the depot-visiting constraints:
+ # MASS CONSERVATION CONSTRAINTS:
+ entryExitConstraints = [K] + [1 for x in range(0, n - 1)]
+ for ii in range(0, n):
+ # Summing by row - all exits must equal 1 (or # of vehicles for depot)
+ col = [x for x in range(0 + n * ii, n + n * ii)]
+ constraint = entryExitConstraints[ii]
+ prob += pl.lpSum([dec_vars[k] for k in col]) == constraint
+
+ for ii in range(0, n):
+ # Summing by row - all entries must equal 1 (or # of vehicles for depot)
+ col = [x for x in range(0 + ii, n ** 2, n)]
+ constraint = entryExitConstraints[ii]
+ prob += pl.lpSum([dec_vars[k] for k in col]) == constraint
+
+ # Sub-tour elimination constraints through capacities:
+ for ii in range(0, n):
+ for jj in range(0, n):
+ # NOTE : Sub-Tour Elimination
+ if (ii != jj) and (ii * jj > 0): # if i or j not 0
+ col = [ii + (jj * n), n ** 2 + ii - 1, n ** 2 + jj - 1]
+ coef = [Q, 1, -1]
+ capDeltaConstraint = Q - nodeCapacities[jj]
+ prob += pl.lpSum([co*dec_vars[k] for co, k in zip(coef,col)]) <= capDeltaConstraint
+
+ # setting decision variable associated with 0 elements in adjacency to 0:
+ zeroEdges = np.argwhere(graphAdjMatr == 0)
+ for entry in zeroEdges:
+ prob += pl.lpSum([dec_vars[entry[0] + (entry[1] * n)]]) == 0
+
+ # # This also includes - set the diagonal elements to zero , i=j
+ # for ii in range(0, n):
+ # col = [(ii) * (n + 1)]
+ # prob += pl.lpSum([dec_vars[k] for k in col]) == 0
+
+ return prob
+
+
+ def addCapacityConstraints(self):
+ raise NotImplementedError
+
+ def addTWConstraints(self):
+ raise NotImplementedError
+
+
+ def extract(self, solution, verbose = True):
+ """
+ Returns the route lists from the PULP ILP in the correct format
+ Format is:
+
+ """
+ # convert to route solution format
+ #route information
+ n = self.route.graph.N
+ _k = n*n
+ depotIdx = self.route.depot
+ vehicleNumber = self.route.vehicles
+
+ # After solving the Linear Program, it is needed to extract the routes from the solution
+ routes = []
+ _chain = []
+
+ travel_metrices = solution[0:_k].reshape((n, n))
+
+ for ix in range(0, n):
+ for iy in range(0, n):
+ if travel_metrices[ix][iy] > 0:
+ if (ix, iy) not in _chain and ix != iy:
+ _chain += [(ix, iy)]
+
+
+ #self.route.visualiseSolution([_chain])
+
+ for vehicle in range(vehicleNumber):
+ cur = depotIdx
+ route = []
+ travel = True
+ if verbose: print(f"{cur}", end=' ')
+ counter = 0
+ while travel:
+ counter+= 1
+
+ element = [(_from, _to) for (_from, _to) in _chain if _from == cur]
+ (_from, _to) = element[vehicle] if len(element) > 1 else element[0]
+ cur = _to
+ if (_from, _to) in route:
+ print("There is a repeating cycle")
+ print((_from, _to))
+ self.route.visualiseSolution([route])
+ print(ThisWillErrorThingsOut)
+ break
+ route += [(_from, _to)]
+ if verbose: print(f"-> {_to}", end=' ')
+
+ if cur == depotIdx:
+ travel = False
+ #print(route)
+ routes += [route]
+ if verbose: print()
+
+ # Check if all vehicles are accounted for, while calcultaing the routes
+ assert len(routes) == vehicleNumber
+
+ return routes
+
+
+
+
+
+
+
+
+
+
+
+
+class ILPCPLEXEncoder(ILPPulpEncoder):
+ """
+ Converts the route into an ILP problem
+ Inherits the extract() method from the ILPPulpEncoder Class (they have equivalent answers)
+ THIS NEEDS TO BE UPDATED
+ """
+
+ def encode(self,route) -> cplex.Cplex:
+ # to remember the route characteristics
+ self.route = route
+ n = route.n
+ K = route.vehicles
+ graphAdjMatr = route.graph.W.toarray()
+
+ Q = 10
+
+ my_obj = list(graphAdjMatr.reshape(1, n ** 2)[0]) + [0.0 for x in range(0, n - 1)]
+ my_ub = [1 for x in range(0, n ** 2 + n - 1)]
+ my_lb = [0 for x in range(0, n ** 2)] + [0.1 for x in range(0, n - 1)]
+ my_ctype = "".join(["I" for x in range(0, n ** 2)]) + "".join(
+ ["C" for x in range(0, n - 1)]
+ )
+
+ my_rhs = (
+ 2 * ([K] + [1 for x in range(0, n - 1)])
+ + [Q - 0.1 for x in range(0, (n - 1) ** 2 - (n - 1))]
+ + [0 for x in range(0, n)]
+ )
+ my_sense = (
+ "".join(["E" for x in range(0, 2 * n)])
+ + "".join(["L" for x in range(0, (n - 1) ** 2 - (n - 1))])
+ + "".join(["E" for x in range(0, n)])
+ )
+
+ try:
+ my_prob = cplex.Cplex()
+ self.populatebyrow(my_prob, my_obj, my_ub, my_lb, my_ctype, my_sense, my_rhs)
+ except cplex.CplexError as exc:
+ print(exc)
+ return
+
+ return my_prob
+
+
+ def populatebyrow(self, prob, my_obj, my_ub, my_lb, my_ctype, my_sense, my_rhs):
+
+ Q = 10 #THIS NEEDS TO BE PROVED AND INTEGRATED BETTER
+
+ n = self.route.n
+
+ prob.objective.set_sense(prob.objective.sense.minimize)
+ prob.variables.add(obj=my_obj, lb=my_lb, ub=my_ub, types=my_ctype)
+
+ prob.set_log_stream(None)
+ prob.set_error_stream(None)
+ prob.set_warning_stream(None)
+ prob.set_results_stream(None)
+
+ rows = []
+ for ii in range(0, n):
+ col = [x for x in range(0 + n * ii, n + n * ii)]
+ coef = [1 for x in range(0, n)]
+ rows.append([col, coef])
+
+ for ii in range(0, n):
+ col = [x for x in range(0 + ii, n ** 2, n)]
+ coef = [1 for x in range(0, n)]
+
+ rows.append([col, coef])
+
+ # Sub-tour elimination constraints:
+ for ii in range(0, n):
+ for jj in range(0, n):
+ if (ii != jj) and (ii * jj > 0):
+
+ col = [ii + (jj * n), n ** 2 + ii - 1, n ** 2 + jj - 1]
+ coef = [Q, 1, -1]
+
+ rows.append([col, coef])
+
+ for ii in range(0, n):
+ col = [(ii) * (n + 1)]
+ coef = [1]
+ rows.append([col, coef])
+
+ prob.linear_constraints.add(lin_expr=rows, senses=my_sense, rhs=my_rhs)
+
+
+
+
+
+
+
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/StandardEncoder.py b/Src/QuantumLogistics/RouteSolver/Encoders/StandardEncoder.py
new file mode 100644
index 0000000..315af6a
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/Encoders/StandardEncoder.py
@@ -0,0 +1,63 @@
+from abc import ABC, abstractclassmethod, abstractmethod
+from QuantumLogistics import Route # solver #, Encoder, solver
+
+
+
+class Encoder(ABC):
+
+ def __init__(self):
+ """
+ The encoder serves as the interface between the route and solver backend objects.
+
+ The encoder converts the CVRP problem in the route object to a mathematical representation for solving byt the solver backend
+ After solving, the encoder then extracts the information from the solver output and converts it to a route solution list
+ """
+
+ return
+
+ @abstractmethod
+ def encode(self,route: Route):
+ """
+ This encodes the cvrp problem in the route object into a problem be solved by a solver API
+
+ Input:
+ route - route object
+
+ Output:
+ solver api dependant
+
+ """
+
+ # to remember the route characteristics
+ self.route = route
+
+ # Must be output to a standard problem format
+ raise NotImplementedError
+
+ @abstractmethod
+ def extract(self,solution) -> list:
+
+ """
+ This extracts the route solution from the solution given by the solver backend
+
+ Input:
+ problemSolution - solver dependant
+
+ Output:
+ Standard solution List - a list of vehicle routes where each route is a list of edges the vehicle travels (eadges in tuple format)
+
+ i.e routeSol = [[(idxDepot, idx1), (idx1, idx4), (idx4, idx5), (idx5, idxDepot)], # Vehicle 1 route
+ [(idxDepot, idx2), (idx2, idx3), (idx3, idxDepot)], # vehicle 2 route
+ [(idxDepot, idx9), (idx9, idx8), (idx8, idx7), (idx7, idx6), (idx6, idxDepot)]] # vehicle 3 route
+ """
+
+ raise NotImplementedError
+
+
+ def addTWConstraints(self):
+
+ """
+ Not yet implemented - maybe coming soon
+ """
+
+ raise NotImplementedError
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/StandardQUBOEncoders.py b/Src/QuantumLogistics/RouteSolver/Encoders/StandardQUBOEncoders.py
new file mode 100644
index 0000000..5491481
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/Encoders/StandardQUBOEncoders.py
@@ -0,0 +1 @@
+from abc import ABC, abstractclassmethod
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/VRPExplorationsEncoder.py b/Src/QuantumLogistics/RouteSolver/Encoders/VRPExplorationsEncoder.py
new file mode 100644
index 0000000..28b267f
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/Encoders/VRPExplorationsEncoder.py
@@ -0,0 +1,49 @@
+from dataclasses import dataclass
+
+import numpy as np
+from QuantumLogistics import Route
+from .StandardEncoder import Encoder
+
+
+@dataclass
+class VRPInstance:
+ clients_num: int
+ vehicles_num: int
+ cost_matrix: np.ndarray
+ capacity: list
+ demands: list
+ xc: np.ndarray
+ yc: np.ndarray
+
+
+class VRPExplorationsEncoder(Encoder):
+ def encode(self, route: Route):
+ # to remember the route characteristics
+ self.route = route
+
+ coords = list(zip(*route.coords))
+ self.vrp_instance = VRPInstance(
+ clients_num=route.graph.N,
+ vehicles_num=route.vehicles,
+ cost_matrix=route.graph.W.toarray(),
+ capacity=route.truckCapacity,
+ demands=route.nodeCapacities,
+ xc=np.array(coords[0]),
+ yc=np.array(coords[1]),
+ )
+
+ return self.vrp_instance
+
+ def extract(self, solution, verbose=False) -> list:
+ solution, variables = solution
+
+ routeSol = []
+ for i in range(solution.shape[0]):
+ var_list = np.transpose(variables[i]).reshape(-1)
+ sol_list = np.transpose(solution[i]).reshape(-1)
+ active_vars = [var_list[k] for k in range(len(var_list)) if sol_list[k] == 1]
+ route = [int(var.split('.')[2]) for var in active_vars]
+ edgelist = [(0, route[0])] + [(route[j], route[j + 1]) for j in range(len(route) - 1)] + [(route[-1], 0)]
+ routeSol.append(edgelist)
+
+ return routeSol
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/__init__.py b/Src/QuantumLogistics/RouteSolver/Encoders/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/ILPEncoder.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/ILPEncoder.cpython-312.pyc
new file mode 100644
index 0000000..775ba90
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/ILPEncoder.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/StandardEncoder.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/StandardEncoder.cpython-312.pyc
new file mode 100644
index 0000000..9d24ed1
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/StandardEncoder.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/VRPExplorationsEncoder.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/VRPExplorationsEncoder.cpython-312.pyc
new file mode 100644
index 0000000..8c8c24b
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/VRPExplorationsEncoder.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/__init__.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..1619c2e
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/Encoders/__pycache__/__init__.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/RouteSolvers.py b/Src/QuantumLogistics/RouteSolver/RouteSolvers.py
new file mode 100644
index 0000000..b0cccac
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/RouteSolvers.py
@@ -0,0 +1,123 @@
+from abc import ABC, abstractclassmethod
+from time import time
+import pygsp
+
+from QuantumLogistics import Route
+
+class CompositeRouteSolver(ABC):
+ """
+ Abstract class to solve logistics problem on routes
+ This is the most general type of solver that only required a solveAlgorithm and extractSolution definiton.
+ SOLVE() SHOULD *NOT* BE OVERWRITTEN. Only overwrite solveAlgorithm() and extractSolution()
+ """
+
+ def __init__(self):
+ raise NotImplementedError
+
+
+ def solve(self,route:Route, config = None):
+ """
+ DO NOT OVERWRITE METHOD
+ """
+ self.config = config
+ startTime = time()
+
+ # check if graph must be coarsened
+ if route.coarsen:
+ print("Coarsening Graph now")
+ route.coarsenGraph()
+
+ #TODO: Sometimes the solver may not find a feasible solution in the timelimit
+ # Need to develop an exception handling method for this
+ problemSol = self.solveAlgorithm(route)
+ # print("RAW SOLVER OUTPUT:", problemSol) # Used this to check the raw output from the solver
+ # return problemSol # Used this to check the raw output from the solver
+ routeSol = self.extractSolution(problemSol)
+
+ #route.visualiseSolution(routeSol)
+
+ if route.coarsen:
+ routeSol = route.inflateGraph(routeSol)
+ route.graph = route.originalGraph
+
+ # Print the solution in text format
+ route.printSolution(routeSol)
+ #route.visualiseSolution(routeSol)
+
+ # Standard solver details
+ solveTime = time() - startTime
+ costValue = route.calculateCost(routeSol)
+
+ return routeSol, solveTime, costValue
+
+
+ @abstractclassmethod
+ def solveAlgorithm(self, route: Route):
+ """
+ Returns raw output from solver in terms of decision variables.
+ This should only include logic to SOLVE the problem (it should NOT DECODE the solution - this happens in extractSolution)
+
+ Input:
+ route: Route object
+
+ Output:
+ problem solution: solver dependant
+ The output from the solver API/interface (not converted to route form)
+
+ """
+
+ raise NotImplementedError
+
+ @abstractclassmethod
+ def extractSolution(self, problemSol):
+ """
+ Decodes the solution from solver output to a standard route list for plotting and analysis.
+
+ Input:
+ problem solution: solver dependant
+
+ Output:
+ Standard solution List - a list of vehicle routes where each route is a list of edges the vehicle travels (eadges in tuple format)
+
+ i.e routeSol = [[(idxDepot, idx1), (idx1, idx4), (idx4, idx5), (idx5, idxDepot)], # Vehicle 1 route
+ [(idxDepot, idx2), (idx2, idx3), (idx3, idxDepot)], # vehicle 2 route
+ [(idxDepot, idx9), (idx9, idx8), (idx8, idx7), (idx7, idx6), (idx6, idxDepot)]] # vehicle 3 route
+
+ """
+ raise NotImplementedError
+
+
+
+
+
+
+
+
+
+
+class StandardRouteSolver(CompositeRouteSolver):
+
+ def __init__(self, encoder, solver):
+ self.encoder = encoder
+ self.solver = solver
+ return
+
+ def solveAlgorithm(self, route:Route):
+ #Encode problem
+ problem = self.encoder.encode(route)
+
+ #solving problem
+ problemSol = self.solver.solve(problem, config = self.config)
+
+ return problemSol
+
+
+ def extractSolution(self,solverSolution):
+ # must return standard solution
+ return self.encoder.extract(solverSolution, verbose=False)
+
+
+
+
+
+
diff --git a/Src/QuantumLogistics/RouteSolver/SolverAlgorithmModules/__init__.py b/Src/QuantumLogistics/RouteSolver/SolverAlgorithmModules/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Src/QuantumLogistics/RouteSolver/SolverBackends/SolverBackends.py b/Src/QuantumLogistics/RouteSolver/SolverBackends/SolverBackends.py
new file mode 100644
index 0000000..09a9643
--- /dev/null
+++ b/Src/QuantumLogistics/RouteSolver/SolverBackends/SolverBackends.py
@@ -0,0 +1,192 @@
+from abc import ABC, abstractclassmethod
+import pulp as pl
+import numpy as np
+import cplex
+import pandas as pd
+import os
+import sys
+
+# Path to the 'Src' directory.
+# This goes up three levels from the current file's directory
+# (SolverBackends -> RouteSolver -> QuantumLogistics -> Src)
+src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
+
+# Path to the VRP-explorations submodule inside 'Src/external/'
+vrp_explorations_path = os.path.join(src_dir, 'external', 'VRP-explorations')
+
+# Add the submodule to the Python path
+if vrp_explorations_path not in sys.path:
+ sys.path.insert(0, vrp_explorations_path)
+
+from VRP.quantum.BQM_based.solution_partition_solver import CapcSolutionPartitionSolver as CSPS
+
+
+class Solver(ABC):
+ def __init__(self):
+
+ return
+
+ @abstractclassmethod
+ def solve(self, problemFormat, config):
+ """
+ This accepts a standardised problemFormat datatype (dependant on encoder) and runs the problem using a specified solver backend.
+
+ This format should be as general as possible to cater to a wide range of solvers.
+
+ For example:
+ ILP problems accepts a PULP problem which encodes the ILP problem
+ Standard qubo problems will likely accept a standard 'QUBO' format that can be readily converted into DWAVE, QISKIT etc solver format.
+
+ """
+
+ raise NotImplementedError
+
+
+class PulpSolver(Solver):
+ def __init__(self):
+ return
+
+ def defineSolver(self):
+ """
+ """
+ raise NotImplementedError("Use either Gurobi or CBC solvers")
+
+ def solve(self, problem: pl.LpProblem, config=None):
+ # Define the solver - defaults if no config specified
+ if config:
+ gap_rel = config["gapRel"]
+ timeLimit = config["timeLimit"]
+ else:
+ gap_rel = 0.01
+ timeLimit = 300
+ print(
+ f"No config specified, defaulting to gap_rel = {gap_rel} and timeLimit {timeLimit}"
+ )
+
+ self.solver = self.defineSolver(gap_rel=gap_rel, time_lim=timeLimit)
+
+ prob = problem
+ solver = self.solver
+ prob.solve(solver)
+
+ print(f'"Status:", {pl.LpStatus[prob.status]}')
+
+ if prob.status == 0:
+ print(
+ f"Not possible to find a solution with the tolerance {gap_rel} in {timeLimit}s"
+ )
+ return
+
+ elif prob.status == 1:
+ obj = pl.value(prob.objective)
+ print(f"The Objective function Value is: {round(obj,3)}")
+
+ solution = []
+ solution_name = []
+
+ for v in prob.variables():
+ value = round(v.varValue, 4)
+ if v.isInteger():
+ value = round(v.varValue)
+ solution.append(value)
+ solution_name.append(v.name)
+
+ # map the pulp solution format to matchs with CPLEX
+ temp = [
+ (ii, jj, int(jj.split("_")[1]))
+ for ii, jj in zip(solution, solution_name)
+ ]
+ df = pd.DataFrame(temp, columns=["Value", "Name", "position"])
+ df = df.sort_values(by="position")
+ x = df.Value.values
+ solution_name = df.Name.values
+ return x
+
+ else:
+ print("Problem is infeasible")
+ return
+
+ def verifyConstraints(self, prob):
+
+ soln_dict = {i.name: round(i.varValue, 1) for i in prob.variables()}
+
+ for c in prob.constraints.values():
+ c_dict = c.toDict()
+ # print(c_dict)
+ satisfied = False
+
+ LHS = sum(
+ [soln_dict[i["name"]] * i["value"] for i in c_dict["coefficients"]]
+ )
+ LHS = LHS + c_dict["constant"]
+
+ if c_dict["sense"] == 0:
+ satisfied = LHS == 0
+
+ if c_dict["sense"] == -1:
+ satisfied = LHS <= 0
+
+ if c_dict["sense"] == 1:
+ satisfied = LHS >= 0
+
+ if not satisfied:
+ # print('LHS: ', LHS)
+ print(c)
+ print("not satisfied")
+
+ return
+
+
+class GurobiSolver(PulpSolver):
+ def defineSolver(self, gap_rel, time_lim):
+ return pl.GUROBI_CMD(msg=1, gapRel=gap_rel, timeLimit=time_lim)
+
+
+class GurobiSolver2(PulpSolver):
+ def defineSolver(self, gap_rel, time_lim):
+ return pl.GUROBI(msg=1, gapRel=gap_rel, timeLimit=time_lim)
+
+
+class CBCSolver(PulpSolver):
+ def defineSolver(self, gap_rel, time_lim):
+ return pl.PULP_CBC_CMD(msg=1, gapRel=gap_rel, timeLimit=time_lim)
+
+
+class CPLEXSolver(PulpSolver):
+ def defineSolver(self, gap_rel, time_lim):
+ return pl.CPLEX_PY(msg=1, gapRel=gap_rel, timeLimit=time_lim)
+
+
+class CPLEXNativeSolver(Solver):
+ def __init__(self):
+
+ return
+
+ def solve(self, my_prob: cplex.Cplex):
+
+ try:
+ my_prob.solve()
+ except cplex.CplexError as exc:
+ print(exc)
+ return
+
+ x = my_prob.solution.get_values()
+ x = np.array(x)
+ cost = my_prob.solution.get_objective_value()
+
+ # needs a consistent return -
+ return x
+
+
+class VRPExplorationsSolver(Solver):
+
+ def solve(self, problemFormat, config):
+ self.vrp_explorations_solver = CSPS(
+ problemFormat.clients_num - 1,
+ problemFormat.vehicles_num,
+ problemFormat.cost_matrix,
+ problemFormat.capacity,
+ problemFormat.demands
+ )
+ self.vrp_explorations_solver.solve(solver=config['solver'])
+ return self.vrp_explorations_solver.solution, self.vrp_explorations_solver.variables
diff --git a/Src/QuantumLogistics/RouteSolver/SolverBackends/__init__.py b/Src/QuantumLogistics/RouteSolver/SolverBackends/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/SolverBackends.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/SolverBackends.cpython-312.pyc
new file mode 100644
index 0000000..d50a75e
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/SolverBackends.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/__init__.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..d89da93
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/SolverBackends/__pycache__/__init__.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/__init__.py b/Src/QuantumLogistics/RouteSolver/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Src/QuantumLogistics/RouteSolver/__pycache__/RouteSolvers.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/__pycache__/RouteSolvers.cpython-312.pyc
new file mode 100644
index 0000000..ae86996
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/__pycache__/RouteSolvers.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/RouteSolver/__pycache__/__init__.cpython-312.pyc b/Src/QuantumLogistics/RouteSolver/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..b1fff3b
Binary files /dev/null and b/Src/QuantumLogistics/RouteSolver/__pycache__/__init__.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/__init__.py b/Src/QuantumLogistics/__init__.py
new file mode 100644
index 0000000..e472b52
--- /dev/null
+++ b/Src/QuantumLogistics/__init__.py
@@ -0,0 +1,17 @@
+
+# Graph and Route Classes
+from QuantumLogistics.LogisticsRoute.LogisticsGraph import logisticsGraph
+from QuantumLogistics.LogisticsRoute.LogisticsRoute import Route
+from QuantumLogistics.LogisticsRoute.GraphCoarsening import BlankCoarseningEngine, DeltaCoarseningEngine
+
+
+#Interface classes
+from QuantumLogistics.RouteSolver.RouteSolvers import StandardRouteSolver, CompositeRouteSolver
+from QuantumLogistics.RouteSolver.SolverBackends.SolverBackends import Solver
+from QuantumLogistics.RouteSolver.Encoders.StandardEncoder import Encoder
+
+
+# Solvers
+from QuantumLogistics.RouteSolver.Encoders.ILPEncoder import ILPPulpEncoder
+from QuantumLogistics.RouteSolver.Encoders.VRPExplorationsEncoder import VRPExplorationsEncoder
+from QuantumLogistics.RouteSolver.SolverBackends.SolverBackends import GurobiSolver, GurobiSolver2, CBCSolver, VRPExplorationsSolver
diff --git a/Src/QuantumLogistics/__pycache__/Graph.cpython-312.pyc b/Src/QuantumLogistics/__pycache__/Graph.cpython-312.pyc
new file mode 100644
index 0000000..75b8f4e
Binary files /dev/null and b/Src/QuantumLogistics/__pycache__/Graph.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/__pycache__/__init__.cpython-312.pyc b/Src/QuantumLogistics/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000..c1d41d3
Binary files /dev/null and b/Src/QuantumLogistics/__pycache__/__init__.cpython-312.pyc differ
diff --git a/Src/QuantumLogistics/interfaces.py b/Src/QuantumLogistics/interfaces.py
new file mode 100644
index 0000000..4b0f78f
--- /dev/null
+++ b/Src/QuantumLogistics/interfaces.py
@@ -0,0 +1,276 @@
+
+from abc import ABC, abstractclassmethod
+from matplotlib.colors import ListedColormap
+from pygsp import graphs
+
+class VRPGraph:
+ def __init__(self, loadFromFile = False, fileName = None):
+
+ if loadFromFile:
+ self.loadGraphFromFile(fileName)
+ else:
+ self.generateGraph() # needs params etc
+
+ self.coarse = False
+
+ return
+
+
+ def setSeed(self, seed=None):
+
+ raise NotImplementedError
+
+
+ def generateGraph(self) -> graphs.Graph:
+ self.graph = None
+
+ raise NotImplementedError
+
+
+ def loadGraphFromFile(self):
+
+ raise NotImplementedError
+
+
+
+
+ # required functions:
+ # Generate a graph instance (in networkx graph) (generate x,y points and put into graph)
+ # Set seed
+ # Coarsen graph for easier representation
+ # Uncoarsen graph
+
+
+
+
+
+class VRPRoute:
+ """
+ Should include capacity and demand
+ """
+ def __init__(self, graph, config):
+
+ self.status = {'solved':False}
+
+ return
+
+
+
+ def visualiseRoute(self, VRPSolution):
+
+ raise NotImplementedError
+
+
+
+ def evaluateKPIs(self):
+
+
+ raise NotImplementedError
+
+
+ def recordMetaData(self):
+ """
+ Add important details to self.metaData for later analysis
+ """
+ raise NotImplementedError
+
+
+ def coarsenGraph(self, coarsenConfig, coarsenAlg = None):
+ """
+ Coarsen a provided graph to generate a compressed representation
+ """
+ coarseGraph = None
+ coarsenConfig = coarsenConfig
+
+ raise NotImplementedError
+
+
+
+ def inflateGraph(self, coarseGraph):
+ """
+ Is this needed?
+ """
+ raise NotImplementedError
+
+
+
+
+
+class VRPSolver(ABC):
+
+ "ABC with both a solver and model converter"
+
+
+ # required functions:
+ # Solve the route problem
+ # Convert problem to a sufficient model
+ # Solve the problem using either quantum or classical (or both) methods
+ # Validate feasibility
+ # Extract data from solution
+
+
+ def __init__(self, RouteEncoder):
+
+ return
+
+
+ @abstractclassmethod
+ def solveVRP(self, VRPRoute: VRPRoute) -> list:
+ """
+ Needs the route instance
+ """
+ # converts to required format
+ # solves
+ # extracts data
+ # validates feasibility
+ # returns a k-long list of routes (one route for each vehicle)
+ #[[1,2,5,6,1], [8,9,10,8]]
+
+
+
+ return
+
+
+ @abstractclassmethod
+ def validateFeasibility(self):
+
+ return
+
+
+ @abstractclassmethod
+ def extractData(self):
+
+ return
+
+
+
+
+
+
+
+
+
+class VRPVQESolver(VRPSolver):
+
+ def __init__(self, RouteEncoder, ):
+
+ return
+
+
+
+
+
+
+class VRPQASolver(VRPSolver):
+
+ def __init__(self, RouteEncoder, ):
+
+ return
+
+
+
+
+
+
+class VRPQAOASolver(VRPSolver):
+
+ def __init__(self, RouteEncoder, ):
+
+ return
+
+
+
+
+
+
+class VRPClassicalSolver(VRPSolver):
+
+ def __init__(self, RouteEncoder):
+
+ return
+
+
+
+
+
+
+class RouteEncoder(ABC):
+ """ Converts to either a QUBO, ILP etc for solving"""
+
+ def __init__(self, ):
+
+ return
+
+ @abstractclassmethod
+ def encodeRoute():
+
+ return
+
+
+
+class QUBOEncoder(RouteEncoder):
+ def __init__(self, ):
+
+ return
+
+
+
+
+class ILPEncoder(RouteEncoder):
+ def __init__(self, ):
+
+ return
+
+
+
+
+
+class solver_backend():
+ """Collection of solver functions for all interfaces - i.e gurobi, qiskit, dwave"""
+
+
+
+
+
+# Definitions
+# VRP Graph - collection of (x,y) points representing locations. Assumes all locations are fully connected
+# Route - a sequence (or combination of sequences) travelled by a vehicle to reach all (x,y) points in route
+# VRPSolver - an object which
+
+if __name__ == "__main__":
+
+ # example of comparing multiple types of solvers
+
+ # 1. generate graph object - loading in from a saved file
+ graphFileName = 'experimentalGraph.csv'
+ VRPnetwork = VRPGraph(loadFromeFile = True, filename = graphFileName)
+
+ # 2. Define configuration for route:
+ config = { 'vehicles' : 7,
+ 'depot' : 0,
+ 'capacity': -1,
+ 'demand': -1 }
+
+ # 3. Define solvers to compare: (including all variations etc)
+ solverList = [VRPClassicalSolver, VRPQAOASolver, VRPVQESolver, VRPQASolver]
+ solutionList = []
+
+ # 4. Iterate through solver list and solve for each tested
+ for solver in solverList:
+ # define route
+ route = VRPRoute(VRPnetwork, config)
+
+ #route.coarsenGraph()
+
+ # solve route
+ solvedRoute = solver.solve(route, solverConfig)
+
+ # add solved route to list for post-processing
+ solutionList.append(solvedRoute)
+
+ # 5. Post Process - can also do it while solving stuff
+ for solvedRoute in solutionList:
+ results = solvedRoute.evaluateKPIs()
+
+
+
diff --git a/Src/external/VRP-explorations/.gitignore b/Src/external/VRP-explorations/.gitignore
new file mode 100644
index 0000000..d4b0f9c
--- /dev/null
+++ b/Src/external/VRP-explorations/.gitignore
@@ -0,0 +1,5 @@
+# virtual environment
+/_venv_
+
+__pycache__
+.ipynb_checkpoints
\ No newline at end of file
diff --git a/Src/external/VRP-explorations/LICENCE b/Src/external/VRP-explorations/LICENCE
new file mode 100644
index 0000000..6c140c4
--- /dev/null
+++ b/Src/external/VRP-explorations/LICENCE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Asish Kumar Mandoi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Src/external/VRP-explorations/README.md b/Src/external/VRP-explorations/README.md
new file mode 100644
index 0000000..9afa3e0
--- /dev/null
+++ b/Src/external/VRP-explorations/README.md
@@ -0,0 +1,147 @@
+# **Solving the Vehicle Routing Problem**
+*Exploring various quantum annealing-based approaches to solve the vehicle routing problem.*
+
+This project was part of the **QOSF Quantum Computing Mentorship Program 2021 Cohort 4**, mentored by [**Dr. Vesselin G. Gueorguiev**](https://www.linkedin.com/in/vgg-consulting/)
+Mentees: *The Qubit Players*
+ - **Asish Kumar Mandoi**
+ *Junior Undergraduate at Indian Institute of Technology Kanpur, Department of Electrical Engineering*
+ [`Website`](https://asishmandoi.github.io/) ~ [`LinkedIn`](https://www.linkedin.com/in/asish-mandoi-4178581b4/) ~ [`GitHub`](https://github.com/AsishMandoi)
+ - **Arya Bhatta**
+ *Junior Undergraduate at Indian Institute of Technology Kanpur, Department of Electrical Engineering*
+ [`LinkedIn`](https://www.linkedin.com/in/arya-bhatta-26a877200/)
+
+This is now under development as part of a research group at QWorld.
+
+**Any usage of this code is free but do cite this code's authors and the organizations if you use it for research or commercial purposes. Please contact the authors for more information.**
+
+## Introduction
+Vehicle routing is a challenging logistics management problem. More precisely, it is an **NP-hard** combinatorial optimization problem.
+- Problem statement: ***What is the optimal set of routes for a fleet of vehicles to traverse in order to deliver to a given set of customers?***
+- Generalises **The Travelling Salesman Problem (TSP)**.
+
+## Overview
+The primary focus of the project has been on improving the applicability of quantum annealing-based solvers for the Vehicle Routing Problem (VRP) for large numbers of customers and vehicles by using a minimal number of qubits. It includes implementations of three solvers:
+ - Route Activation Solver
+ - GPS Solver (Guillermo, Parfait, Saúl) ~ [[4](https://github.com/AsishMandoi/VRP-explorations#references)]
+ - DBSCAN Solver ~ [[7](https://github.com/AsishMandoi/VRP-explorations#references)]
+
+The first two are non-clustering solvers that give exact solutions for the simplest variant of the VRP for small datasets and the third one is a clustering-based solver that gives approximate solutions for large datasets. The project also demonstrates the usage of the [Binary Quadratic Model](https://docs.ocean.dwavesys.com/en/stable/concepts/bqm.html) and [Constrained Quadratic Model](https://docs.ocean.dwavesys.com/en/stable/concepts/cqm.html) provided by D-Wave to formulate various other solvers including the above. The accuracy and runtimes of these solvers, calculated against the exact solutions obtained by classical implementations using [Google's OR-Tools](https://developers.google.com/optimization), are compared with each other.
+
+
+*The project was inspired from [this video](https://youtu.be/GK8IT0C9Upk) and [this paper](https://link.springer.com/chapter/10.1007/978-3-030-50433-5_42) by [**Paweł Gora**](https://www.mimuw.edu.pl/~pawelg/) and others. A lot of initial ideas were borrowed from [a project on the same topic](https://github.com/VGGatGitHub/QOSF-cohort3) by **Shantom Borah** and others.*
+
+## Get started
+You may start with the `solve_vrp.ipynb` notebook where you can choose to run any solver on any model and get the solutions to the Vehicle Routing Problem for any number of clients and vehicles. You can play with the `time_limit` parameter to see how the solver performs on different datasets, but make sure not to set it too high as you may exhaust your limited monthly resources on your D-Wave Leap account.
+
+The `quantum` subfolder in the VRP folder further contains two more subfolders `CQM_based` and `BQM_based`. The first one contains the implementations of the solvers using the Constrained Quadratic Model (CQM) and the second one contains the implementations of the solvers using the Binary Quadratic Model (BQM).:
+- Constrained Quadratic Model is a new model recently released by D-Wave Systems that is capable of encoding Quadratically Constrained Quadratic Programs (QCQPs)
+- Binary Quadratic Model is a model that encodes Ising or QUBO problems.
+
+### **Directory Structure**
+
+ (click to expand)
+
+ ```bash
+ VRP-explorations
+ ├── _venv_ # (virtual python environment)
+ ├── presentations
+ │ ├── notebook_1.ipynb
+ │ ├── .
+ │ ├── .
+ │ └── notebook_9.ipynb
+ ├── datasets
+ │ ├── generate_dataset_for_vrp.ipynb
+ │ └── dataset.csv
+ ├── results
+ │ ├── sol2.log
+ │ ├── .
+ │ ├── .
+ │ ├── sol11.log
+ │ ├── sol2.csv
+ │ ├── .
+ │ ├── .
+ │ ├── sol11.csv
+ │ └── results.png
+ ├── TSP
+ │ ├── classical
+ │ │ └── gps.py
+ │ └── quantum
+ │ ├── fqs.py
+ │ └── gps.py
+ ├── VRP
+ │ ├── classical
+ │ │ ├── ras.py
+ │ │ └── sps.py
+ │ └── quantum
+ │ ├── BQM_based
+ │ │ ├── full_qubo_solver.py
+ │ │ ├── route_activation_solver.py
+ │ │ ├── solution_partition_solver.py
+ │ │ ├── dbscan_solver.py
+ │ │ └── ...
+ │ └── CQM_based
+ │ ├── fqs.py
+ │ ├── gps.py
+ │ └── ras.py
+ ├── utils.py
+ ├── solve_tsp.py
+ ├── solve_vrp.py
+ ├── vrp_comparision_results.py
+ ├── post_processing_results.py
+ ├── requirements.txt
+ ├── setup.sh
+ ├── .gitignore
+ └── README.md
+ ```
+
+
+## Results
+The following is a concise comparision of results obtained by running (non-clustering) solvers for [this dataset](https://gitlab.com/qworld/qresearch/qintern2021/21_solving-vehicle-routing-problem-and-its-variants-using-quantum-computing_b/-/tree/master/Datasets%20for%20VRP) (`generate_dataset_for_vrp.ipynb`) using the `ConstrainedQuadraticModel` and `LeapHybridCQMSampler` provided by D-Wave.
+
+
+
+
+The results for more instances can be found in the [results](https://github.com/AsishMandoi/VRP-explorations/tree/main/results) folder.
+
+It can be seen that these solvers give exact solutions for upto 7 nodes (6 clients and 1 depot) and are as good as classical ones in terms of accuracy and runtimes, and acceptable solutions till upto 15 nodes.
+
+## Run this repo
+
+### Locally
+Requirements:
+- A bash terminal
+- Python version >= 3.9
+- D-Wave Leap account
+
+```bash
+# Clone this repo
+git clone https://github.com/AsishMandoi/VRP-explorations.git
+
+# Go into the project's main directory and setup the environment to run all codes
+cd VRP-explorations && bash setup.sh
+
+### The `setup.sh` script consists of the following steps:
+# 1. Create a virtual environment (named '_venv_') if it doesn't exist
+# 2. Install the required packages in the virtual environment
+# 3. Run `dwave setup` to get access to the D-Wave backend solvers
+```
+*The above process will also run the `dwave setup` command. This will require your authentication token from your account on D-Wave Leap. Learn more about how to [set up your environment](https://docs.ocean.dwavesys.com/en/latest/overview/install.html#set-up-your-environment) for using `dwave-ocean-sdk`.*
+
+### On D-Wave Leap platform
+*Coming soon*
+
+## Future work
+- [ ] Incorporate solutions for other more general variants of the problem (especially for the CVRPTW)
+- [ ] Make a circuit based algorithm from scratch (that does not use any application modules from any libraries) to solve VRP
+- [ ] Find potential real life applications for VRP (for e.g. Supply Chain, Traffic Flow Optimization)
+
+## References
+1. Borowski, Michal, Gora, Pawel, *"New Hybrid Quantum Annealing Algorithms for Solving Vehicle Routing Problem"* (2020)
+2. Feld, Sebastian, et al. *"A Hybrid Solution Method for the Capacitated Vehicle Routing Problem Using a Quantum Annealer"* (2019)
+3. Fisher, Marshall L., Jaikumar, Ramchandran, *"A generalized assignment heuristic for vehicle routing"* (1981)
+4. Gonzalez-Bermejo, Saul, et al. *"GPS: Improvement in the formulation of the TSP for its generalizations type QUBO"*
+5. The [QOSF cohort - 3 project](https://github.com/VGGatGitHub/QOSF-cohort3) by Shantom, Aniket and Avneesh based on this topic
+6. [Vehicle routing problem - Wikipedia](https://en.wikipedia.org/wiki/Vehicle_routing_problem)
+7. [DBSCAN - Wikipedia](https://en.wikipedia.org/wiki/DBSCAN)
+8. D-Wave's documentations on [Binary Quadratic Model](https://docs.ocean.dwavesys.com/en/stable/concepts/bqm.html) and [Constrained Quadratic Model](https://docs.ocean.dwavesys.com/en/stable/concepts/cqm.html)
+11. [Google's OR-Tools](https://developers.google.com/optimization/routing/vrp)
diff --git a/Src/external/VRP-explorations/VRP/quantum/BQM_based/README.md b/Src/external/VRP-explorations/VRP/quantum/BQM_based/README.md
new file mode 100644
index 0000000..06566bb
--- /dev/null
+++ b/Src/external/VRP-explorations/VRP/quantum/BQM_based/README.md
@@ -0,0 +1,28 @@
+# Vehicle Routing Problem - Core Solvers
+This directory contains the core solvers for solving the Vehicle Routing Problem. API usage instructions may be found in the code docstrings. Example usage is shown in the ***Vehicle Routing.ipynb*** notebook.
+
+## Core Solvers
+Following core solvers have been implemented.
+
+ - ***FQS*** - Full Qubo Solver
+ - ***APS*** - Average Partitioning Solver
+ - ***RAS*** - Route Activation Solver
+ - ***QNS*** - Qiskit Native Solver
+ - ***CTS*** - Clustered Tsp Solver
+ - ***SPS*** - Solution Partitioning Solver
+
+Descriptions of individual solvers may be found in the ***Vehicle Routing.ipynb*** notebook.
+
+## Solver Backends
+Following backend solvers may be used.
+
+ - D-Wave Sampler
+ - D-Wave Hybrid Sampler
+ - Leap Hybrid Sampler
+ - Qiskit QAOA Backend
+
+## Python Files
+Each solver is implemented as a seperate python class in a seperate python file. The solver classes inherit from a base **VehicleRouter** class defined in **vehicle_routing.py**. There are three other files:
+ - **node_clustering.py:** This file implements a **NodeClustering** class for clustering in CTS via Leap's Hybrid DQM Sampler.
+ - **solver_backend.py:** This file contains the backend solvers listed above.
+ - **utility.py:** This file implements general utility functions such as generatinga random VRP instance.
diff --git a/Src/external/VRP-explorations/VRP/quantum/BQM_based/solution_partition_solver.py b/Src/external/VRP-explorations/VRP/quantum/BQM_based/solution_partition_solver.py
new file mode 100644
index 0000000..fff1b2d
--- /dev/null
+++ b/Src/external/VRP-explorations/VRP/quantum/BQM_based/solution_partition_solver.py
@@ -0,0 +1,272 @@
+import warnings
+import numpy as np
+import networkx as nx
+import matplotlib.pyplot as plt
+
+from itertools import product
+from matplotlib.colors import rgb2hex
+from collections import Counter
+from .vehicle_routing import VehicleRouter
+from qiskit_optimization import QuadraticProgram
+
+
+class SolutionPartitionSolver(VehicleRouter):
+
+ """SPS Solver implementation."""
+
+ def __init__(self, n_clients, n_vehicles, cost_matrix, **params):
+
+ """Initializes any required variables and calls init of super class."""
+
+ # Initialize cluster data
+ self.route = None
+ self.start_indices = None
+ self.end_indices = None
+ self.partition_cost = None
+
+ # Call parent initializer
+ super().__init__(n_clients, n_vehicles, cost_matrix, **params)
+
+ def build_quadratic_program(self):
+
+ """Builds the required quadratic program and sets the names of variables in self.variables."""
+
+ # Initialization
+ self.qp = QuadraticProgram(name='Vehicle Routing Problem')
+
+ # Designate variable names
+ self.variables = np.array([[f'x.{i}.{j}' for i in range(1, self.n + 1)] for j in range(1, self.n + 1)])
+
+ # Add variables to quadratic program
+ for var in self.variables.reshape(-1):
+ self.qp.binary_var(name=var)
+
+ # Build objective function
+ edgelist = [(i, j) for i, j in product(range(1, self.n + 1), repeat=2) if i != j]
+ obj_linear_a = {f'x.{i}.{1}': self.cost[0, i] for i in range(1, self.n + 1)}
+ obj_linear_b = {f'x.{i}.{self.n}': self.cost[i, 0] for i in range(1, self.n + 1)}
+ obj_quadratic = {(f'x.{i}.{t}', f'x.{j}.{t + 1}'): self.cost[i, j] for i, j in edgelist
+ for t in range(1, self.n)}
+
+ # Add objective to quadratic program
+ self.qp.minimize(linear=dict(Counter(obj_linear_a) + Counter(obj_linear_b)), quadratic=obj_quadratic)
+
+ # Add constraints - single delivery per client
+ for i in range(1, self.n + 1):
+ constraint_linear = {f'x.{i}.{j}': 1 for j in range(1, self.n + 1)}
+ self.qp.linear_constraint(linear=constraint_linear, sense='==', rhs=1, name=f'single_delivery_{i}')
+
+ # Add constraints - vehicle at one place at one time
+ for j in range(1, self.n + 1):
+ constraint_linear = {f'x.{i}.{j}': 1 for i in range(1, self.n + 1)}
+ self.qp.linear_constraint(linear=constraint_linear, sense='==', rhs=1, name=f'single_location_{j}')
+
+ def evaluate_vrp_cost(self):
+
+ """Evaluate the optimized VRP cost under the optimized solution stored in self.solution.
+ Returns:
+ Optimized VRP cost as a float value.
+ """
+
+ # Return optimized energy
+ return super().evaluate_vrp_cost() + self.partition_cost
+
+ def solve(self, **params):
+
+ """Add additional functionality to the parent solve function to be able to classically partition the TSP
+ solution after quantum sampling.
+ Args:
+ params: Parameters to send to the selected backend solver. You may also specify the solver to select a
+ different solver and override the specified self.solver.
+ """
+
+ # Solve TSP
+ super().solve(**params)
+
+ # Evaluate route
+ var_list = self.variables.reshape(-1)
+ sol_list = self.solution.reshape(-1)
+ active_vars = [var_list[k] for k in range(len(var_list)) if sol_list[k] == 1]
+ self.route = [int(var.split('.')[1]) for var in active_vars]
+
+ # Evaluate partition costs
+ partition_costs = np.zeros(self.n - 1)
+ for i in range(self.n - 1):
+ partition_costs[i] = self.cost[self.route[i], 0] + self.cost[0, self.route[i + 1]] - \
+ self.cost[self.route[i], self.route[i + 1]]
+
+ # Evaluate minimum cost partition
+ cut_indices = np.argsort(partition_costs)[:(self.m - 1)]
+ self.start_indices = np.sort(cut_indices) + 1
+ self.start_indices = [0] + list(self.start_indices)
+ self.end_indices = np.sort(cut_indices)
+ self.end_indices = list(self.end_indices) + [self.n - 1]
+ self.partition_cost = sum(partition_costs[cut_indices])
+
+ def visualize(self, xc=None, yc=None):
+
+ """Visualizes solution.
+ Args:
+ xc: x coordinates of nodes. Defaults to random values.
+ yc: y coordinates of nodes. Defaults to random values.
+ """
+
+ # Resolve coordinates
+ if xc is None:
+ xc = (np.random.rand(self.n + 1) - 0.5) * 10
+ if yc is None:
+ yc = (np.random.rand(self.n + 1) - 0.5) * 10
+
+ # Initialize figure
+ plt.figure()
+ ax = plt.gca()
+ ax.set_title(f'Vehicle Routing Problem - {self.n} Clients & {self.m} Cars')
+ cmap = plt.cm.get_cmap('Accent')
+
+ # Build graph
+ G = nx.MultiDiGraph()
+ G.add_nodes_from(range(self.n + 1))
+
+ # Plot nodes
+ pos = {i: (xc[i], yc[i]) for i in range(self.n + 1)}
+ labels = {i: str(i) for i in range(self.n + 1)}
+ nx.draw_networkx_nodes(G, pos=pos, ax=ax, node_color='b', node_size=500, alpha=0.8)
+ nx.draw_networkx_labels(G, pos=pos, labels=labels, font_size=16)
+
+ # Loop through cars
+ for i in range(len(self.start_indices)):
+
+ # Extract edge list
+ route = [self.route[j] for j in range(self.start_indices[i], self.end_indices[i] + 1)]
+ edgelist = [(0, route[0])] + [(route[j], route[j + 1]) for j in range(len(route) - 1)] + [(route[-1], 0)]
+
+ # Plot edges
+ G.add_edges_from(edgelist)
+ nx.draw_networkx_edges(G, pos=pos, edgelist=edgelist, width=2, edge_color=rgb2hex(cmap(i)))
+
+ # Show plot
+ plt.grid(True)
+ plt.show()
+
+
+class CapcSolutionPartitionSolver(SolutionPartitionSolver):
+
+ """Capacitated SPS Solver implementation."""
+
+ def __init__(self, n_clients, n_vehicles, cost_matrix, capacity, demand, **params):
+
+ """Initializes any required variables and calls init of super class."""
+
+ # Store capacity data
+ self.capacity = capacity
+ self.demand = demand
+
+ # Call parent initializer
+ super().__init__(n_clients, n_vehicles, cost_matrix, **params)
+
+ def build_partition_graph(self):
+
+ """Build partition graph for post TSP partitioning."""
+
+ # Initialize graph
+ G = nx.DiGraph()
+ G.add_nodes_from(range(self.n + 1))
+
+ # Loop over nodes
+ for i in range(self.n + 1):
+
+ # Initialize
+ j = i + 1
+ demand = self.demand[self.route[j - 1] - 1] if j <= self.n else None
+ cost = self.cost[0, self.route[j - 1]] if j <= self.n else None
+
+ # Loop over target nodes
+ while j <= self.n and demand <= self.capacity:
+ trip_cost = cost + self.cost[self.route[j - 1], 0]
+ G.add_edge(i, j, weight=trip_cost)
+ j += 1
+ if j <= self.n:
+ demand += self.demand[self.route[j - 1] - 1]
+ cost += self.cost[self.route[j - 2], self.route[j - 1]]
+
+ # Return graph
+ return G
+
+ @staticmethod
+ def shortest_walk(dG, sink, m):
+
+ """Function to find shortest path with at most m edges.
+ Args:
+ dG: Input graph.
+ sink: Destination Node.
+ m: Max number of edges.
+ Returns:
+ Boolean value indicating successful pathfinding, the path length and the path. None returned for last 2
+ fields if path not found.
+ """
+
+ # d(v,m) is the shortest walk length from source(0) to v using at most m edges
+ n = dG.number_of_nodes() - 1
+ d = [float('inf')] * (n + 1)
+ path = [None] * (n + 1) # store path to v with atmost m edges
+ path[0] = [0]
+ d[0] = 0 # d(0,0) = 0
+
+ # Initialization
+ d_nextround = [float('inf')] * (n + 1)
+ d_nextround[0] = 0
+ path_nextround = [None] * (n + 1)
+ path_nextround[0] = [0]
+
+ # Main loop
+ for i in range(m):
+ for v in range(1, n + 1):
+ path_dists = [(u, d[u]+dG.edges[u, v]['weight']) for u in dG.predecessors(v)]
+ min_path_dists = min(dist for (vertex, dist) in path_dists)
+ if min_path_dists < d[v]:
+ d_nextround[v] = min_path_dists
+ for (vertex, dist) in path_dists:
+ if dist == min_path_dists:
+ path_nextround[v] = path[int(vertex)] + [v]
+ else:
+ d_nextround[v] = d[v]
+ path_nextround[v] = path[v]
+ d = d_nextround.copy()
+ path = path_nextround.copy()
+
+ # Return output
+ if d[sink] == float('inf'):
+ return False, None, None
+ else:
+ path_length = d[sink]
+ return True, path_length, path[sink]
+
+ def solve(self, **params):
+
+ """Add additional functionality to the parent solve function to be able to classically partition the TSP
+ solution after quantum sampling.
+ Args:
+ params: Parameters to send to the selected backend solver. You may also specify the solver to select a
+ different solver and override the specified self.solver.
+ """
+
+ # Solve TSP
+ VehicleRouter.solve(self, **params)
+
+ # Evaluate route
+ var_list = self.variables.reshape(-1)
+ sol_list = self.solution.reshape(-1)
+ active_vars = [var_list[k] for k in range(len(var_list)) if sol_list[k] == 1]
+ self.route = [int(var.split('.')[1]) for var in active_vars]
+
+ # Evaluate minimum cost partition
+ G = self.build_partition_graph()
+ success, path_length, path = self.shortest_walk(G, self.n, self.m)
+ if not success:
+ warnings.warn('Unable to find route with given number of vehicles. Extending fleet...')
+ path_length, path = nx.single_source_dijkstra(G, source=0, target=self.n)
+
+ # Extract cuts from partition
+ self.start_indices = path[:-1]
+ self.end_indices = [j - 1 for j in path[1:]]
+ self.partition_cost = path_length - VehicleRouter.evaluate_vrp_cost(self)
diff --git a/Src/external/VRP-explorations/VRP/quantum/BQM_based/solver_backend.py b/Src/external/VRP-explorations/VRP/quantum/BQM_based/solver_backend.py
new file mode 100644
index 0000000..4283ca6
--- /dev/null
+++ b/Src/external/VRP-explorations/VRP/quantum/BQM_based/solver_backend.py
@@ -0,0 +1,216 @@
+import time
+# from dwave_qbsolv.dimod_wrapper import QBSolv
+import hybrid
+import dwave.inspector
+
+# from greedy import SteepestDescentSolver
+from dwave.system import LeapHybridSampler, DWaveSampler, EmbeddingComposite
+from dwave.samplers import SimulatedAnnealingSampler
+from qiskit_optimization.algorithms import MinimumEigenOptimizer
+from qiskit_algorithms import QAOA, NumPyMinimumEigensolver
+from qiskit_aer import Aer
+
+
+class SolverBackend:
+
+ """Class containing all backend solvers that may be used to solve the Vehicle Routing Problem."""
+
+ def __init__(self, vrp):
+
+ """Initializes required variables and stores the supplied instance of the VehicleRouter object."""
+
+ # Store relevant data
+ self.vrp = vrp
+
+ # Solver dictionary
+ self.solvers = {'dwave': self.solve_dwave,
+ 'leap': self.solve_leap,
+ 'hybrid': self.solve_hybrid,
+ 'neal': self.solve_neal,
+ 'qaoa': self.solve_qaoa,
+ 'npme': self.solve_npme}
+
+ # Initialize necessary variables
+ self.dwave_result = None
+ self.result_dict = None
+
+ self.solver_limit = 4
+
+ def solve(self, solver, **params):
+
+ """Takes the solver as input and redirects control to the corresponding solver.
+ Args:
+ solver: The selected solver.
+ params: Parameters to send to the selected backend solver..
+ """
+
+ # Select solver and solve
+ solver = self.solvers[solver]
+ solver(**params)
+
+ def solve_dwave(self, **params):
+
+ """Solve using DWaveSampler and EmbeddingComposite.
+ Args:
+ params: inspect: Defaults to False. Set to True to run D-Wave inspector for the sampled solution.
+ params: post_process: Defaults to False. Set to True to run classical post processing for improving the
+ D-Wave solution.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'dwave'
+ inspect = params.setdefault('inspect', False)
+ post_process = params.setdefault('post_process', False)
+
+ # Solve
+ sampler = EmbeddingComposite(DWaveSampler())
+ result = sampler.sample(self.vrp.bqm, num_reads=self.vrp.num_reads, chain_strength=self.vrp.chain_strength)
+
+ # Post process
+ if not post_process:
+ self.vrp.result = result
+ else:
+ post_processor = SteepestDescentSolver()
+ self.vrp.result = post_processor.sample(self.vrp.bqm, num_reads=self.vrp.num_reads, initial_states=result)
+
+ # Extract solution
+ self.vrp.timing.update(result.info["timing"])
+ self.result_dict = self.vrp.result.first.sample
+ self.vrp.extract_solution(self.result_dict)
+
+ # Inspection
+ self.dwave_result = result
+ if inspect:
+ dwave.inspector.show(result)
+
+ def solve_hybrid(self, **params):
+
+ """Solve using dwave-hybrid.
+ Args:
+ params: Additional parameters that may be required by a solver. Not required here.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'hybrid'
+
+ # Build sampler workflow
+ workflow = hybrid.Loop(
+ hybrid.RacingBranches(
+ hybrid.InterruptableTabuSampler(),
+ hybrid.EnergyImpactDecomposer(size=30, rolling=True, rolling_history=0.75)
+ | hybrid.QPUSubproblemAutoEmbeddingSampler()
+ | hybrid.SplatComposer()) | hybrid.ArgMin(), convergence=3)
+
+ # Solve
+ sampler = hybrid.HybridSampler(workflow)
+ self.vrp.result = sampler.sample(self.vrp.bqm, num_reads=self.vrp.num_reads,
+ chain_strength=self.vrp.chain_strength)
+
+ # Extract solution
+ self.result_dict = self.vrp.result.first.sample
+ self.vrp.extract_solution(self.result_dict)
+
+ def solve_leap(self, **params):
+
+ """Solve using Leap Hybrid Sampler.
+ Args:
+ params: Additional parameters that may be required by a solver. Not required here.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'leap'
+
+ # Solve
+ sampler = LeapHybridSampler()
+ self.vrp.result = sampler.sample(self.vrp.bqm)
+
+ # Extract solution
+ self.vrp.timing.update(self.vrp.result.info)
+ self.result_dict = self.vrp.result.first.sample
+ self.vrp.extract_solution(self.result_dict)
+
+ def solve_neal(self, **params):
+
+ """Solve using Simulated Annealing Sampler.
+ Args:
+ params: Additional parameters that may be required by a solver. Not required here.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'neal'
+
+ # Solve
+ sampler = SimulatedAnnealingSampler()
+ self.vrp.result = sampler.sample(self.vrp.bqm)
+
+ # Extract solution
+ self.vrp.timing.update(self.vrp.result.info)
+ self.result_dict = self.vrp.result.first.sample
+ self.vrp.extract_solution(self.result_dict)
+
+# REMOVED CODE FOR QB SOLVER
+ # def solve_qbsolv(self, **params):
+
+ # """Solve using Simulated Annealing Sampler.
+ # Args:
+ # params: Additional parameters that may be required by a solver. Not required here.
+ # """
+
+ # # Resolve parameters
+ # params['solver'] = 'qbsolv'
+
+ # # Solve
+ # self.vrp.result = QBSolv().sample(self.vrp.bqm, solver_limit=self.solver_limit)
+
+ # # Extract solution
+ # self.vrp.timing.update(self.vrp.result.info)
+ # self.result_dict = self.vrp.result.first.sample
+ # self.vrp.extract_solution(self.result_dict)
+
+ def solve_qaoa(self, **params):
+
+ """Solve using qiskit Minimum Eigen Optimizer based on a QAOA backend.
+ Args:
+ params: Additional parameters that may be required by a solver. Not required here.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'qaoa'
+ self.vrp.clock = time.time()
+
+ # Build optimizer and solve
+ solver = QAOA(quantum_instance=Aer.get_backend('qasm_simulator'))
+ optimizer = MinimumEigenOptimizer(min_eigen_solver=solver)
+ self.vrp.result = optimizer.solve(self.vrp.qp)
+ self.vrp.timing['qaoa_solution_time'] = (time.time() - self.vrp.clock) * 1e6
+
+ # Build result dictionary
+ self.result_dict = {self.vrp.result.variable_names[i]: self.vrp.result.x[i]
+ for i in range(len(self.vrp.result.variable_names))}
+
+ # Extract solution
+ self.vrp.extract_solution(self.result_dict)
+
+ def solve_npme(self, **params):
+
+ """Solve using qiskit Minimum Eigen Optimizer based on NumPyMinimumEigensolver().
+ Args:
+ params: Additional parameters that may be required by a solver. Not required here.
+ """
+
+ # Resolve parameters
+ params['solver'] = 'npme'
+ self.vrp.clock = time.time()
+
+ # Build optimizer and solve
+ solver = NumPyMinimumEigensolver()
+ optimizer = MinimumEigenOptimizer(min_eigen_solver=solver)
+ self.vrp.result = optimizer.solve(self.vrp.qp)
+ self.vrp.timing['npme_solution_time'] = (time.time() - self.vrp.clock) * 1e6
+
+ # Build result dictionary
+ self.result_dict = {self.vrp.result.variable_names[i]: self.vrp.result.x[i]
+ for i in range(len(self.vrp.result.variable_names))}
+
+ # Extract solution
+ self.vrp.extract_solution(self.result_dict)
diff --git a/Src/external/VRP-explorations/VRP/quantum/BQM_based/vehicle_routing.py b/Src/external/VRP-explorations/VRP/quantum/BQM_based/vehicle_routing.py
new file mode 100644
index 0000000..0525ed3
--- /dev/null
+++ b/Src/external/VRP-explorations/VRP/quantum/BQM_based/vehicle_routing.py
@@ -0,0 +1,166 @@
+import numpy as np
+import dimod
+import time
+
+from functools import partial
+from .solver_backend import SolverBackend
+from dwave.embedding.chain_strength import uniform_torque_compensation
+from qiskit_optimization.converters import QuadraticProgramToQubo
+from qiskit_optimization.algorithms import OptimizationResult
+
+
+class VehicleRouter:
+
+ """Abstract Class for solving the Vehicle Routing Problem. To build a VRP solver, simply inherit from this class
+ and overide the build_quadratic_program function in this class."""
+
+ def __init__(self, n_clients, n_vehicles, cost_matrix, **params):
+
+ """Initializes the VRP by storing all inputs, initializing variables for storing the quadratic structures and
+ results and calls the rebuild function to build all quadratic structures.
+ Args:
+ n_clients: No. of nodes in the problem (excluding the depot).
+ n_vehicles: No. of vehicles available for delivery.
+ cost_matrix: (n_clients + 1) x (n_clients + 1) matrix describing the cost of moving from node i to node j.
+ penalty: Penalty value to use for constraints in the QUBO. Defaults to automatic calculation by qiskit
+ converters.
+ chain_strength: Chain strength to be used for D-Wave sampler. Defaults to automatic chain strength
+ calculation via uniform torque compensation.
+ num_reads: Number of samples to read. Defaults to 1000.
+ solver: Select a backend solver. Defaults to 'dwave'.
+ """
+
+ # Store critical inputs
+ self.n = n_clients
+ self.m = n_vehicles
+ self.cost = np.array(cost_matrix)
+
+ # Extract parameters
+ self.penalty = params.setdefault('constraint_penalty', None)
+ self.chain_strength = params.setdefault('chain_strength', partial(uniform_torque_compensation, prefactor=2))
+ self.num_reads = params.setdefault('num_reads', 1000)
+ self.solver = params.setdefault('solver', 'dwave')
+
+ # Initialize quadratic structures
+ self.qp = None
+ self.qubo = None
+ self.bqm = None
+ self.variables = None
+
+ # Initialize result containers
+ self.result = None
+ self.solution = None
+
+ # Initialize timer
+ self.clock = None
+ self.timing = {}
+
+ # Initialize backend
+ self.backend = SolverBackend(self)
+
+ # Build quadratic models
+ self.rebuild()
+
+ def build_quadratic_program(self):
+
+ """Dummy function to be overriden in child class. Required to set self.variables to contain the names of all
+ variables in the form of a numpy array and self.qp to contain the quadratic program to be solved."""
+
+ # Dummy. Override in child class.
+ pass
+
+ def build_bqm(self):
+
+ """Converts the quadratic program in self.qp to a QUBO by appending all constraints to the objective function
+ in the form of penalties and then builds a BQM from the QUBO for solving by D-Wave."""
+
+ # Convert to QUBO
+ converter = QuadraticProgramToQubo(penalty=self.penalty)
+ self.qubo = converter.convert(self.qp)
+
+ # Extract qubo data
+ Q = self.qubo.objective.quadratic.to_dict(use_name=True)
+ g = self.qubo.objective.linear.to_dict(use_name=True)
+ c = self.qubo.objective.constant
+
+ # Build BQM
+ self.bqm = dimod.BQM(g, Q, c, dimod.BINARY)
+
+ def rebuild(self):
+
+ """Builds the quadratic program by calling build_quadratic_program and then the QUBO and BQM by calling
+ build_bqm."""
+
+ # Begin stopwatch
+ self.clock = time.time()
+
+ # Rebuild quadratic models
+ self.build_quadratic_program()
+ self.build_bqm()
+
+ # Record build time
+ self.timing['qubo_build_time'] = (time.time() - self.clock) * 1e6
+
+ def extract_solution(self, result_dict):
+
+ """Uses a result dictionary mapping variable names to the solved solution to build the self.solution variable
+ in the same shape as self.variables and containing the corresponding solutions.
+ Args:
+ result_dict: Dictionary mapping variable names to solved values for these variables.
+ """
+
+ # Extract solution from result dictionary
+ var_list = self.variables.reshape(-1)
+ self.solution = np.zeros(var_list.shape)
+ for i in range(len(var_list)):
+ self.solution[i] = result_dict[var_list[i]]
+
+ # Reshape result
+ self.solution = self.solution.reshape(self.variables.shape)
+
+ def evaluate_vrp_cost(self):
+
+ """Evaluate the optimized VRP cost under the optimized solution stored in self.solution.
+ Returns:
+ Optimized VRP cost as a float value.
+ """
+
+ # Return optimized energy
+ if type(self.result) == OptimizationResult:
+ return self.result.fval
+ else:
+ return self.result.first.energy
+
+ def evaluate_qubo_feasibility(self, data=None):
+
+ """Evaluates whether the QUBO is feasible under the supplied data as inputs. If this data is not
+ supplied, the self.solution variable is used instead.
+ Args:
+ data: Values of the variables in the solution to be tested. Defaults to self.solution.
+ Returns:
+ A 3-tuple containing a boolean value indicating whether the QUBO is feasible or not, a list of variables
+ that violate constraints, and the list of violated constraints. If feasible, (True, [], []) is returned.
+ """
+
+ # Resolve data
+ if data is None:
+ data = self.solution.reshape(-1)
+ else:
+ data = np.array(data).reshape(-1)
+
+ # Get constraint violation data
+ return self.qp.get_feasibility_info(data)
+
+ def solve(self, **params):
+
+ """Solve the QUBO using the selected solver.
+ Args:
+ params: Parameters to send to the selected backend solver. You may also specify the solver to select a
+ different solver and override the specified self.solver.
+ """
+
+ # Resolve solver
+ params.setdefault('solver', self.solver)
+
+ # Solve
+ self.backend.solve(**params)
diff --git a/Src/external/VRP-explorations/post_processing_results.ipynb b/Src/external/VRP-explorations/post_processing_results.ipynb
new file mode 100644
index 0000000..ca1cf4e
--- /dev/null
+++ b/Src/external/VRP-explorations/post_processing_results.ipynb
@@ -0,0 +1,313 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "\n",
+ "with open('Results/sol9_2.log', 'r') as file:\n",
+ " data = file.read()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rows_list = []\n",
+ "for dline in data.split('\\n\\n'):\n",
+ " if dline.startswith('n = '):\n",
+ " lines=dline.split('\\n')\n",
+ " for line in lines:\n",
+ " if line.startswith('n = '):\n",
+ " words=line.split(', ')\n",
+ " for word in words:\n",
+ " if word.startswith('n = '):\n",
+ " n=int(word.strip('n = '))\n",
+ " if word.startswith('m = '):\n",
+ " k=int(word.strip('m = '))\n",
+ " if word.startswith('instance = '):\n",
+ " instance=word.strip('instance = ')\n",
+ " \n",
+ " if line.startswith('Classical cost from best known solution: '):\n",
+ " classical_cost=f\"{float(line.strip('Classical cost from best known solution: ')):.5f}\"\n",
+ "\n",
+ " if line.startswith('RAS: '):\n",
+ " words=line.split(' \\t ')\n",
+ " for word in words:\n",
+ " if word.startswith('quantum cost = '):\n",
+ " ras_quantum_cost=f\"{float(word.strip('quantum cost = ')):.5f}\" if word.strip('quantum cost = ') != 'None' else None\n",
+ " if word.startswith('approximation ratio = '):\n",
+ " ras_approximation_ratio=f\"{float(word.strip('approximation ratio = ')):.5f}\" if word.strip('approximation ratio = ') != 'None' else None\n",
+ " if word.startswith('number of variables = '):\n",
+ " ras_no_of_variables=int(word.strip('number of variables = '))\n",
+ " if word.startswith('runtime = '):\n",
+ " ras_runtime=f\"{float(word.strip('runtime = ')):.5f}\"\n",
+ " \n",
+ " if line.startswith('FQS: '):\n",
+ " words=line.split(' \\t ')\n",
+ " for word in words:\n",
+ " if word.startswith('quantum cost = '):\n",
+ " fqs_quantum_cost=f\"{float(word.strip('quantum cost = ')):.5f}\" if word.strip('quantum cost = ') != 'None' else None\n",
+ " if word.startswith('approximation ratio = '):\n",
+ " fqs_approximation_ratio=f\"{float(word.strip('approximation ratio = ')):.5f}\" if word.strip('approximation ratio = ') != 'None' else None\n",
+ " if word.startswith('number of variables = '):\n",
+ " fqs_no_of_variables=int(word.strip('number of variables = '))\n",
+ " if word.startswith('runtime = '):\n",
+ " fqs_runtime=f\"{float(word.strip('runtime = ')):.5f}\"\n",
+ " \n",
+ " if line.startswith('GPS: '):\n",
+ " words=line.split(' \\t ')\n",
+ " for word in words:\n",
+ " if word.startswith('quantum cost = '):\n",
+ " gps_quantum_cost=f\"{float(word.strip('quantum cost = ')):.5f}\" if word.strip('quantum cost = ') != 'None' else None\n",
+ " if word.startswith('approximation ratio = '):\n",
+ " gps_approximation_ratio=f\"{float(word.strip('approximation ratio = ')):.5f}\" if word.strip('approximation ratio = ') != 'None' else None\n",
+ " if word.startswith('number of variables = '):\n",
+ " gps_no_of_variables=int(word.strip('number of variables = '))\n",
+ " if word.startswith('runtime = '):\n",
+ " gps_runtime=f\"{float(word.strip('runtime = ')):.5f}\"\n",
+ " \n",
+ " rows_list.append({'n': n, 'k': k, 'instance': instance, 'Classical Cost': classical_cost, 'RAS: Quantum Cost': ras_quantum_cost, 'RAS: Approximation Ratio': ras_approximation_ratio, 'RAS: No. of Variables': ras_no_of_variables, 'RAS: Runtime': ras_runtime, 'FQS: Quantum Cost': fqs_quantum_cost, 'FQS: Approximation Ratio': fqs_approximation_ratio, 'FQS: No. of Variables': fqs_no_of_variables, 'FQS: Runtime': fqs_runtime, 'GPS: Quantum Cost': gps_quantum_cost, 'GPS: Approximation Ratio': gps_approximation_ratio, 'GPS: No. of Variables': gps_no_of_variables, 'GPS: Runtime': gps_runtime})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame(rows_list)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " n | \n",
+ " k | \n",
+ " instance | \n",
+ " Classical Cost | \n",
+ " RAS: Quantum Cost | \n",
+ " RAS: Approximation Ratio | \n",
+ " RAS: No. of Variables | \n",
+ " RAS: Runtime | \n",
+ " FQS: Quantum Cost | \n",
+ " FQS: Approximation Ratio | \n",
+ " FQS: No. of Variables | \n",
+ " FQS: Runtime | \n",
+ " GPS: Quantum Cost | \n",
+ " GPS: Approximation Ratio | \n",
+ " GPS: No. of Variables | \n",
+ " GPS: Runtime | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 0 | \n",
+ " 2469.37768 | \n",
+ " 2634.50684 | \n",
+ " 1.06687 | \n",
+ " 88 | \n",
+ " 19333.92600 | \n",
+ " 5234.77500 | \n",
+ " 2.11988 | \n",
+ " 64 | \n",
+ " 18005.31900 | \n",
+ " 2909.98054 | \n",
+ " 1.17843 | \n",
+ " 272 | \n",
+ " 18020.55200 | \n",
+ "
\n",
+ " \n",
+ " | 8 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 3207.80446 | \n",
+ " 3831.77242 | \n",
+ " 1.19452 | \n",
+ " 88 | \n",
+ " 18037.08600 | \n",
+ " 4798.10412 | \n",
+ " 1.49576 | \n",
+ " 64 | \n",
+ " 18022.49200 | \n",
+ " 4167.10341 | \n",
+ " 1.29905 | \n",
+ " 272 | \n",
+ " 18042.71700 | \n",
+ "
\n",
+ " \n",
+ " | 16 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 2 | \n",
+ " 3098.30384 | \n",
+ " 3434.60946 | \n",
+ " 1.10855 | \n",
+ " 88 | \n",
+ " 18004.57100 | \n",
+ " 8359.03974 | \n",
+ " 2.69794 | \n",
+ " 64 | \n",
+ " 18035.49800 | \n",
+ " 3853.37937 | \n",
+ " 1.24371 | \n",
+ " 272 | \n",
+ " 17994.78600 | \n",
+ "
\n",
+ " \n",
+ " | 24 | \n",
+ " 9 | \n",
+ " 1 | \n",
+ " 3 | \n",
+ " 2650.11637 | \n",
+ " 3882.88179 | \n",
+ " 1.46517 | \n",
+ " 88 | \n",
+ " 18540.49600 | \n",
+ " 7189.44152 | \n",
+ " 2.71288 | \n",
+ " 64 | \n",
+ " 17967.93600 | \n",
+ " 2650.11637 | \n",
+ " 1.00000 | \n",
+ " 272 | \n",
+ " 17992.76200 | \n",
+ "
\n",
+ " \n",
+ " | 1 | \n",
+ " 9 | \n",
+ " 2 | \n",
+ " 0 | \n",
+ " 2382.06276 | \n",
+ " 2855.66993 | \n",
+ " 1.19882 | \n",
+ " 96 | \n",
+ " 18030.94600 | \n",
+ " 3195.34779 | \n",
+ " 1.34142 | \n",
+ " 128 | \n",
+ " 17998.24900 | \n",
+ " 4553.22378 | \n",
+ " 1.91146 | \n",
+ " 488 | \n",
+ " 18061.10500 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " n k instance Classical Cost RAS: Quantum Cost RAS: Approximation Ratio \\\n",
+ "0 9 1 0 2469.37768 2634.50684 1.06687 \n",
+ "8 9 1 1 3207.80446 3831.77242 1.19452 \n",
+ "16 9 1 2 3098.30384 3434.60946 1.10855 \n",
+ "24 9 1 3 2650.11637 3882.88179 1.46517 \n",
+ "1 9 2 0 2382.06276 2855.66993 1.19882 \n",
+ "\n",
+ " RAS: No. of Variables RAS: Runtime FQS: Quantum Cost \\\n",
+ "0 88 19333.92600 5234.77500 \n",
+ "8 88 18037.08600 4798.10412 \n",
+ "16 88 18004.57100 8359.03974 \n",
+ "24 88 18540.49600 7189.44152 \n",
+ "1 96 18030.94600 3195.34779 \n",
+ "\n",
+ " FQS: Approximation Ratio FQS: No. of Variables FQS: Runtime \\\n",
+ "0 2.11988 64 18005.31900 \n",
+ "8 1.49576 64 18022.49200 \n",
+ "16 2.69794 64 18035.49800 \n",
+ "24 2.71288 64 17967.93600 \n",
+ "1 1.34142 128 17998.24900 \n",
+ "\n",
+ " GPS: Quantum Cost GPS: Approximation Ratio GPS: No. of Variables \\\n",
+ "0 2909.98054 1.17843 272 \n",
+ "8 4167.10341 1.29905 272 \n",
+ "16 3853.37937 1.24371 272 \n",
+ "24 2650.11637 1.00000 272 \n",
+ "1 4553.22378 1.91146 488 \n",
+ "\n",
+ " GPS: Runtime \n",
+ "0 18020.55200 \n",
+ "8 18042.71700 \n",
+ "16 17994.78600 \n",
+ "24 17992.76200 \n",
+ "1 18061.10500 "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.sort_values(by=['n', 'k', 'instance'], inplace=True)\n",
+ "df.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df.to_csv('Results/sol9_2.csv', index=False)"
+ ]
+ }
+ ],
+ "metadata": {
+ "interpreter": {
+ "hash": "a2afd0ddbcfb87ec4f087e6612d43180006366a8f4c127a029466ae157c416c8"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.9.7 64-bit ('_venv_': venv)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Src/external/VRP-explorations/requirements.txt b/Src/external/VRP-explorations/requirements.txt
new file mode 100644
index 0000000..c34cf7d
--- /dev/null
+++ b/Src/external/VRP-explorations/requirements.txt
@@ -0,0 +1,4 @@
+matplotlib
+jupyter
+dwave-ocean-sdk
+qiskit-optimization
\ No newline at end of file
diff --git a/Src/external/VRP-explorations/setup.sh b/Src/external/VRP-explorations/setup.sh
new file mode 100644
index 0000000..4b67a69
--- /dev/null
+++ b/Src/external/VRP-explorations/setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+echo "Hello World!"
+echo
+
+if [ -d "_venv_" ] ; then
+ echo "Existing virtual environment found."
+else
+ echo "Creating new virtual environment..."
+ python -m venv _venv_
+fi
+
+source _venv_/Scripts/activate
+
+echo
+echo "Installing requirements..."
+python -m pip install -U pip
+python -m pip install -r requirements.txt
+
+echo
+echo "Running 'dwave setup'..."
+echo
+
+dwave setup
+
+echo
+echo "You're all set!"
\ No newline at end of file
diff --git a/Src/external/VRP-explorations/solve_tsp.ipynb b/Src/external/VRP-explorations/solve_tsp.ipynb
new file mode 100644
index 0000000..3dff04d
--- /dev/null
+++ b/Src/external/VRP-explorations/solve_tsp.ipynb
@@ -0,0 +1,154 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils import random_routing_instance\n",
+ "\n",
+ "from TSP.classical.gps import GPS as GPSc\n",
+ "from TSP.quantum.gps import GPS as GPSq\n",
+ "from TSP.quantum.fqs import FQS as FQSq\n",
+ "\n",
+ "n=8\n",
+ "\n",
+ "cost, xc, yc = random_routing_instance(n, seed=0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Minimum cost: 5636.0\n",
+ "\n",
+ "Time taken to solve: 243.060 ms\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcwAAAFHCAYAAAAsrHydAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABLo0lEQVR4nO3dd3xb5b0/8M/R3t47dhJnh0wgEBJGmYESCpdAC6SsUqA/KJTRXKC30FugpdD2kibMS1t6SymllFlaaEmBZkAIYSWMhFjK8N5D1pbO8/tDtmxZ8ozko/F5v155xZaPpEdPFH38jPM9khBCgIiIiEakUroBRERE6YCBSURENAYMTCIiojFgYBIREY0BA5OIiGgMGJhERERjoFG6ATS57r33Xrz//vsAALvdjoqKChgMBgDAs88+G/k60erq6nDOOefgo48+wsaNG9HZ2Ym77roLV199NW677TbMnDkzIc/zxBNP4NVXX4UQArIs44QTTsDNN98MnU434v3mzJmDd999F/n5+QlpR7Kccsop0Gq1MBgMkCQJgUAAK1euxO233w6Vauy//w7+N4j3HL/61a+wcOHCRDZ9VC6XCz/4wQ9gt9shyzLWrFmDq666Ku6xdrsd69evx4EDByBJEmw2G2666SYcffTRUe+1Z555Bk6nE9dcc82E2lRbW4sHHngAGzduPJyXRhmCgZllfvjDH0a+PuWUU/CLX/xi0j8YB3viiScS9livvfYaNm3aFAl+n8+HG2+8EQ899BBuueWWhD2P0gb/m/n9flx66aX44x//iG9+85sKt+zw/Pa3v4XBYMCrr76K3t5enH322Vi2bBkWLVoUdZzD4cDll1+O++67DyeccAIA4N1338V3vvMdPPPMMzAajZFjL7744sNqU0NDA/bv339Yj0GZg4FJERs3bsTHH3+MlpYWzJkzB7fffjvuuusutLe3o7W1FRUVFVi/fj2++OIL3H///fjrX/8KAOjp6cGpp56KTZs2wev14u6770ZjYyMCgQDOPvtsfOc73xn2OftHM263Gw8++CAqKyuxb98++P1+3HXXXVi+fDk6Ojpwxx134NChQ8jNzUVRURFmzZqFG264IeqxWltbEQqF4PV6YTAYoNfrceedd6KjowMAsH//ftx9991wu91oaWnB3LlzsX79euj1+qjHee655/DMM89AlmXk5ubizjvvxIwZM7Bz50787Gc/gyzLAIBrr70Wq1atwu233w69Xo/du3ejra0NZ511FvLz8/HWW2+htbUV9957L4477rgRn3/hwoW45pprsG3bNrS0tOCyyy7DFVdcMeq/mU6nw1FHHQWHw4G6ujqsXbsWM2bMQH19PZ566ins2rULDz30EEKhECwWC+64445IANntdqxduxbd3d2YN28efvSjH8FisUQ9/ptvvolHH30UgUAABoMBt912G5YuXYqNGzfi0KFDqK2tRUtLCxYtWoSVK1fipZdeQl1dHdatW4fVq1eP2v7BQqEQXC4XgsEgfD4fZFmOOzPwxBNPYM2aNZGwBIDjjjsOv/zlL2NmSAaPpJubm+O+N+vq6nDFFVfgpJNOwieffILu7m7cfPPNWLVqFX74wx+iubkZV111FR5//HHcc889+PDDD6HVajFlyhTcd999MJvN43qdlMYEZa2TTz5Z7Nq1K/L9hg0bxKpVq0QgEBBCCPG73/1OPP7440IIIWRZFt/+9rfFb37zGyHLctR9n376aXHrrbcKIYS49NJLxb/+9S8hhBBer1dceuml4m9/+5uora0VS5YsiTzPj3/846g2bN++XcybN098/vnnQgghfvOb34i1a9cKIYS4+eabxQMPPCCEEKK5uVmsXLlSbNiwIeb19PT0iCuvvFIcccQR4utf/7q47777xI4dOyI//9nPfiZeeuklIYQQfr9frF69Wrz++utCCCFmz54t2tvbxXvvvScuueQS4Xa7hRBCbNmyRZx11llCCCEuu+wy8eqrrwohhPjiiy/Ef//3fwshhLjtttvEhRdeKPx+v2hpaRGzZ88Wv//97yN9eOWVV47p+Z966ikhhBC7d+8WCxYsEF6vd9R/s6amJnHmmWeK119/XdTW1orZs2eL999/XwghRE1NjVixYoU4dOiQEEKId955R6xcuVI4nU6xYcMG8ZWvfEW0t7cLWZbFrbfeGunj/ufYv3+/WL16tejo6BBCCPHll1+KlStXCpfLJTZs2CBOPvlk0dPTIzwej1i2bJm47777hBBCvPHGG+KMM86IaftonE6nOO+888Ty5cvFggULIo831OrVq8Xbb7897OMM914b6b05e/Zs8eabbwohhHj99dfFV77yFSGEENu3bxdnn322EEKI999/X5x55plClmUhhBAPPPCA+OCDD8b9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",
+ "image/svg+xml": "\n\n\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "GPSc(n, cost, xc, yc)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Runtime: 6392.454 ms\n",
+ "Number of variables: 64\n",
+ "38 feasible solutions of 51.\n",
+ "Minimum value of objective: 5636.0\n",
+ "Minimum total cost: 5636.0\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcwAAAFHCAYAAAAsrHydAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAABLo0lEQVR4nO3dd3xb5b0/8M/R3t47dhJnh0wgEBJGmYESCpdAC6SsUqA/KJTRXKC30FugpdD2kibMS1t6SymllFlaaEmBZkAIYSWMhFjK8N5D1pbO8/tDtmxZ8ozko/F5v155xZaPpEdPFH38jPM9khBCgIiIiEakUroBRERE6YCBSURENAYMTCIiojFgYBIREY0BA5OIiGgMGJhERERjoFG6ATS57r33Xrz//vsAALvdjoqKChgMBgDAs88+G/k60erq6nDOOefgo48+wsaNG9HZ2Ym77roLV199NW677TbMnDkzIc/zxBNP4NVXX4UQArIs44QTTsDNN98MnU434v3mzJmDd999F/n5+QlpR7Kccsop0Gq1MBgMkCQJgUAAK1euxO233w6Vauy//w7+N4j3HL/61a+wcOHCRDZ9VC6XCz/4wQ9gt9shyzLWrFmDq666Ku6xdrsd69evx4EDByBJEmw2G2666SYcffTRUe+1Z555Bk6nE9dcc82E2lRbW4sHHngAGzduPJyXRhmCgZllfvjDH0a+PuWUU/CLX/xi0j8YB3viiScS9livvfYaNm3aFAl+n8+HG2+8EQ899BBuueWWhD2P0gb/m/n9flx66aX44x//iG9+85sKt+zw/Pa3v4XBYMCrr76K3t5enH322Vi2bBkWLVoUdZzD4cDll1+O++67DyeccAIA4N1338V3vvMdPPPMMzAajZFjL7744sNqU0NDA/bv339Yj0GZg4FJERs3bsTHH3+MlpYWzJkzB7fffjvuuusutLe3o7W1FRUVFVi/fj2++OIL3H///fjrX/8KAOjp6cGpp56KTZs2wev14u6770ZjYyMCgQDOPvtsfOc73xn2OftHM263Gw8++CAqKyuxb98++P1+3HXXXVi+fDk6Ojpwxx134NChQ8jNzUVRURFmzZqFG264IeqxWltbEQqF4PV6YTAYoNfrceedd6KjowMAsH//ftx9991wu91oaWnB3LlzsX79euj1+qjHee655/DMM89AlmXk5ubizjvvxIwZM7Bz50787Gc/gyzLAIBrr70Wq1atwu233w69Xo/du3ejra0NZ511FvLz8/HWW2+htbUV9957L4477rgRn3/hwoW45pprsG3bNrS0tOCyyy7DFVdcMeq/mU6nw1FHHQWHw4G6ujqsXbsWM2bMQH19PZ566ins2rULDz30EEKhECwWC+64445IANntdqxduxbd3d2YN28efvSjH8FisUQ9/ptvvolHH30UgUAABoMBt912G5YuXYqNGzfi0KFDqK2tRUtLCxYtWoSVK1fipZdeQl1dHdatW4fVq1eP2v7BQqEQXC4XgsEgfD4fZFmOOzPwxBNPYM2aNZGwBIDjjjsOv/zlL2NmSAaPpJubm+O+N+vq6nDFFVfgpJNOwieffILu7m7cfPPNWLVqFX74wx+iubkZV111FR5//HHcc889+PDDD6HVajFlyhTcd999MJvN43qdlMYEZa2TTz5Z7Nq1K/L9hg0bxKpVq0QgEBBCCPG73/1OPP7440IIIWRZFt/+9rfFb37zGyHLctR9n376aXHrrbcKIYS49NJLxb/+9S8hhBBer1dceuml4m9/+5uora0VS5YsiTzPj3/846g2bN++XcybN098/vnnQgghfvOb34i1a9cKIYS4+eabxQMPPCCEEKK5uVmsXLlSbNiwIeb19PT0iCuvvFIcccQR4utf/7q47777xI4dOyI//9nPfiZeeuklIYQQfr9frF69Wrz++utCCCFmz54t2tvbxXvvvScuueQS4Xa7hRBCbNmyRZx11llCCCEuu+wy8eqrrwohhPjiiy/Ef//3fwshhLjtttvEhRdeKPx+v2hpaRGzZ88Wv//97yN9eOWVV47p+Z966ikhhBC7d+8WCxYsEF6vd9R/s6amJnHmmWeK119/XdTW1orZs2eL999/XwghRE1NjVixYoU4dOiQEEKId955R6xcuVI4nU6xYcMG8ZWvfEW0t7cLWZbFrbfeGunj/ufYv3+/WL16tejo6BBCCPHll1+KlStXCpfLJTZs2CBOPvlk0dPTIzwej1i2bJm47777hBBCvPHGG+KMM86IaftonE6nOO+888Ty5cvFggULIo831OrVq8Xbb7897OMM914b6b05e/Zs8eabbwohhHj99dfFV77yFSGEENu3bxdnn322EEKI999/X5x55plClmUhhBAPPPCA+OCDD8b9Oil9cYRJUZYsWQKNJvy2uPzyy7Fz5048+eSTOHDgAPbt24fFixdDkiRccMEFePHFF7Fw4UK88MILWLduHdxuN95//310d3fjV7/6FQDA7XZjz549MdNq8ZSXl2PevHkAgPnz5+PFF18EAPz73/+OfF1cXIwzzzwz7v2tVit++9vfora2Ftu3b8eOHTtwzTXX4JJLLsG6deuwbt06bNu2DU888QQOHDiAlpYWuN3uqMd4++23cfDgQVx00UWR27q7u9HV1YWzzjoLd999N958802sWLEiapr35JNPhlarRVFREUwmU2T0U1VVha6uLgAY9flPPfVUAMARRxwBv98Pt9sdM/oFgO9///swGAyQZRlarRYXXnghVq1ahbq6Omg0GixZsgQAsH37dixfvhyVlZUAwqOw/Px8fPrppwCA008/PbJmu2bNGjzwwANRz9M/2h080pUkCYcOHQIArFixAlarNfLvEu81j8fdd9+NlStX4pZbbkFbWxuuvPJKLF26FKtWrYo6TpKkyCh/rEZ7b2q1Wpx00kkAwu+9eO2fPXs21Go1LrzwQhx//PFYtWrVmN7XlDkYmBTFZDJFvv75z3+OXbt2Yc2aNTj22GMRDAYh+koPr1mzBueddx4uvPBCOJ1OHHvssejt7YUQAn/6058i60gdHR3Q6/Xo7Owc9bkHT6dJkhR5Lo1GE/kawLCbW5544gkcddRROPLII1FZWYkLL7wQO3fuxNVXX41169bhlltuQSgUwllnnYWvfOUraGxsjHpcAJBlGeeeey7WrVsX+b6lpQU5OTm46KKLcPLJJ2Pbtm3YsmULHnroIbzyyisAEDN12P9Lx2CjPX9/OEqSBAAxbes30rqzTqeLPHe8+wshEAwGAQBqtTrq9qFtlmUZxx13HNavXx+5rbGxEcXFxXjjjTfG9JoHe+aZZ/CnP/0JALBgwQL85Cc/ifr5G2+8gVdeeQUqlSryi9F7770XE5hLlizBxx9/jJNPPjnq9oceeghVVVU48sgjY55bluUR35tarTbyvurv/6FsNhtefvllfPjhh9i+fTtuuummMU+dU2bgaSU0rK1bt+Lyyy/Heeedh4KCArzzzjsIhUIAgJKSEixevBh33XUXLrjgAgCAxWLBkiVL8OSTTwIIr21efPHF+Ne//nVY7TjppJPwl7/8BQDQ2dmJTZs2xf1Q83q9+OUvfxk1Oti/fz/mz58feT3XX389vvrVr0KSJHzyySeR19Nv5cqV+Nvf/oaWlhYA4Q/5yy+/HABw0UUX4YsvvsD555+Pe+65Bz09Peju7h7z6xjL8yfS8uXLsW3bNtTW1gIIb4xpbGzE4sWLAYTXJ7u7uxEKhfDss8/ixBNPjHt/u90OIDzS/9rXvgafzzeh9lx88cV4+eWX8fLLL8eEJRAe2b322msAwqO/LVu2RNo62FVXXYXnnnsOW7dujdy2efNmPPXUU5g7d27c557oe1OtViMQCAAA3nrrLVxxxRVYunQpbrjhBpx33nnYs2fP2F48ZQSOMGlY119/PR544AE88sgjUKvVOPLIIyPTcQBw4YUX4nvf+x4effTRyG2/+MUvcM899+Ccc86B3+/H6tWr8bWvfQ11dXUTbscdd9yBH/7whzjnnHOQm5uL8vLyuKe/XHfddZAkCRdddFFk2m7BggWREdLNN9+M66+/Hjk5OTAajVi2bFnU6wGAE044AVdffTW+9a1vQZIkWCwWPPTQQ5AkCd///vfx05/+FOvXr4dKpcJ3v/tdTJkyZcyvYyzPn0gzZ87Ej370I3z3u99FKBSCwWDAY489FplGnTFjBq699lr09PTgqKOOijn1YtasWbj77rtxyy23REagjz76aNQsRCLdf//9uPvuu/HSSy9BpVLhrLPOwrnnnhtz3NSpU/HYY49h/fr1uP/++yHLMvLz8/Hoo49i9uzZw77XJvLenDVrFtRqNS644AI8++yz2Lx5M1avXg2TyYScnBzcc889CXv9lPokMdy8D1GKePrppzF//nwsXboUfr8fl1xyCW644YbImhMR0WTgCJNS3syZM3HPPfdAlmUEAgGceeaZDEsimnQcYRIREY0BN/0QERGNAQOTiIhoDBiYREREYzDipp/WVmfSnjgvz4TOTvfoB2YJ9kc09kcs9kk09kc09kesifZJUZE17u2KjTA1GvXoB2UR9kc09kcs9kk09kc09kesRPcJp2SJiIjGgIFJREQ0BgxMIiKiMRixcEEwGOK8OBEREUbZJZvMHVdFRdak7sJNN+yPaOyPWOyTaOyPaOyPWBPtk5TbJUtERJROGJhERERjwMAkIiIaAwYmERHRGDAwiYiIxoCBSURENAYMTCIiojFgYBIREY0BA5OIiGgMGJhERERjMGJpvFTU4/ajsc0FtzcIk0GDskIzbCad0s0iIqIMlxaBKYTA3kNd2OVox8EmJ0IhGZIECAFo1CpMLbVi4YwCzKnMhSRJSjeXiIgyUMoHZq/bj+c3O9DY5oJKFQ7D/r8lCZCFwP7GHtjru1FWaMaaE6th4YiTiIgSLKXXMHvdfjy96Us0tQ+E5XBUKglN7S48velL9Lr9k9RCIiLKFikbmEIIPL/ZgS6nL+40675dW7Dhtq9G3SZJErqcPryw2YERLvNJREQ0bikbmHsPdaGxzRU3LDtb6/DvVx6FEHLMzyRJQkObC3truyahlURElC1SNjB3OdrjTsMG/F787amf4CvnXT/sfVUqCbvt7clsHhERZZmUDMwetx8Hm+JfJfuNP/8Si1ecg6Ky6hEf42CTEz1cyyQiogRJycBsbHMhFIqdbv1o60uQVGosXP7VOPeKFgzJaGp3J6N5RESUhVLytBK3N4h4p1N+tuN1BPxe/N8DVyEUCiIY8OP/HrgKa669H5acwshxQgiEnE502vcjlD8barN5EltPRESZKCUD02TQQAjEhOY3b3ks8nV3eyN+d/+VuPw/fxNzfxEIwNfUiN7P/gb7H1qhyS+AvrIy/GdKFfSVldAWFUNSpeQAm4iIUlBKBmZZoRlqtWrCp4aodDpYZs7EEV+bC11LA3y1tfDVHYJr9y5ADk/1Sjod9FOmRAI0/PcUqAzGRL4UIiLKECkZmDaTDlNLrTjQ2DPsMTkFZfjeA68P+/PpU/JQetRMAEsjt8l+P/wNDfDVHQqHaO0hOHfuQPfmtyPHaIuKBkK0L0g1hYUsuUdElOVSMjABYFF1ARz13aNW+IlHlgUWziiIuV2l08EwbRoM06ZFbhNCINjRAV/tIfjqaiN/9378YbhYLQCV0Qj9lEropgya1q2ogEqvn/DrIyKi9JKygTmnKhdlhWY0tccvXjAcIQTKCs2YU5k7puMlSYK2oADaggJYlgwajfp84QCtq42MRnve2Qbh8/bfEdqSktjRaF4eR6NERBkoZQNTkiSsObEaT2/6ctjyeEMJIZBj1OD8E6Yfdmip9HoYZ8yEccbMgceXZQTa2gZGo3W18B3Yj96dOwbuZzZDX1kF/ZTK8J/KSujKK6DSag+rPUREpKyUDUwAsJh0WHva7JirlcQjywKluTosfWUjWraZIJ9/AazHHAOVNnFXLpFUKuiKi6ErLob1qKMjt4fcbvjr6wZN69aie/PbEP6+wgkqFXSlZVG7dPWVldDk5CasbURElFySGGEramtr/Go7iVBUZB3z4wshsLe2C7vt4ethBodeD7PMioXVBZhdYUPNddcAoRCA8Ggv9yunIP+rqyd9vVHIMgItzZHp3P4gDXZ2RI5RW22R8CycPxv+nCLoSssgaVL695hJMZ73R7Zgn0Rjf0Rjf8SaaJ8UFVnj3p4Wn8ySJGFuVR7mVuWhx+1HU7sbbm8QJoMGpQUm2AZd/9I0/wi4d+8CAMguFzr+9lfoSstgO27F5La5b1SpKy2DddkxkdtDvb0Dm4tqw9O6Xf/ahM5/hHf8ShoNdGXlQ0ajVVBbLJPafiIiipYWgTmYzaSLCsihTHPnRQITAKzHLo8KLKWpLRaY5s6Dae68yG0iGITZ70TTri8iIer6dDd63tkWOUaTl9e3JloVWRvVlpSy+AIR0SRJu8AcjWnO3MjXklYLb20t5EAA6hSe5pQ0GpjLqmAz5QHLB24PdncP2qkbHpG6Pv8sMuUsabXQVUyJBGg4TKdAbWIpQCKiREvdFJkgfdVU5J52OkzzF0Cl1aJu/S/R+PgjqLjhJkhqtdLNGxdNTg40OTkwH7EgcpscCMDf2BAZifpqD6H34w/Rs3XzwP0KCqJGovopVdAWFXE0SkR0GDIuMCWVCsUXrY18X7L2MjT//km0/OmPKFl7qYItSwyVVgtD1VQYqqZGbhNCINjVBV/tIfgHj0Y/+ThSfEHSG/pKAQ4ajVZMgcpgUOiVEBGllxF3yQaDIWg06TUqi2f/k/+HhpdewfSrr0L56tEvDZYpQj4f3Idq4dp/AO4DB+DafwCugwcRcvVd9kySYCgtgXnaNJinT4Np2jSYp0+FvqiIxReIiIZIi9NKDpeQZTQ8+hBcH3+E8htugmXR4kl53vGYrP4QQiDY3hY1peurq0OgpTlyTH8pwME7dXUVU6DSJe6c1tFwi3ws9kk09kc09kesrDyt5HBJKhXKvn0tau//KRoffxRVt/8X9JWVSjdLEZIkQVtYBG1hESxLj4zcLnu98PUXX+gL0+5tWyF8vv47QldSGpnO1fXt2NXk5nI0SkRj1uP2o7HNFTk1sKzQPOKZD6kkKwITCJe6K7/hJhz6yY9Rv/FBVP3XXay0M4jKYIhfCrC1deDqLnW18DjscL4/qBSgxRJzuouurJylAIkoQgiBvYe6sMsRLj4TGlp8ptSKhTMKMKcytX8Bz5rABABtXh4qbrgJtff/FA0PbcCUdbdP6jRjupFUKuhKSqArKYH1qGWR20NuF3x1Q0ajb78JEQiED1CrB0oBRoK0ChqbTaFXQkRK6XX7Y8qb9v8tSYAsBPY39sBe342yQjPWnFgNS4qOOLMqMAHAMHUayq7+Dhoe2Yim3z6Bsmv+H0+3GCe1yQzT7DkwzZ4TuU2EQvA3Nw+61mgtPHv3wLn93YH75eREFaXXV1ZBV1LKUoBEGarX7Y9cQGO0SzWqVBKa2l14etOXWHva7JQMzaz8pLIsPRKFF3wdbc89i/biEhSef4HSTUp7kloNfXk59OXlwDED1RdCTufAJdL6wrRz0z8Hii9oNNCVVwwpvlAJDLPoTkTpQQiB5zc7xny1KSC8x6LL6cMLmx24dNWclJuezcrABIC8M85EoLkJHX9/FdqSUuSsPF7pJmUktdUK07z5MM2bH7lNBIPwNzVGhahr9y70vLM1ckxtQQG0kSpG4Z262uISzgYQpYm9h7riXmVq364t2Pbak5AkCQaTFasuWofcworIzyVJQkObC3truzC3Km+ymz2irA1MSZJQfMmlCLS2ovn3T0JbVBQ1xUjJI2k0kalZYKAofrC7KzKdi9ZG9NQ44Pp0NyDL4fvpdNBXTOk73WVgt67aaFTolRDRcHY52mPCMuD34W9/+AkuX/dr5BVNwc63n8O/XtiINdf8LOo4lUrCbns7AzOVSBoNyr5zPWrvuxcND29A1Q/ugq6kROlmZS1NTi40ObkwL1gYOX9KDvjhb2iIGo06d+5E9+Z/R+6nLSyCblCI6qdUQltYyNEoURKFenvR/urLMC9YCNP8BVH/33rcfhxsij3/UYgQIAR8XhcAIODzQKOJv1Z5sMmJHrc/pU45yerABAC12YzyG2/GoZ/ejfoND6Lqjh/yUlopRKXVwTB1GgxTp0VuE0Ig2NkxqPhCOExdH38UKQWoMhjChen7pnP7R7STfV1UokzlcdSga9Mb6Nr0BjSFRcg75TTYjj8eapMZjW0uhEJyzAhTpzfh9AtvwTPrvwuD2QYhy7j4exvjPn4wJKOp3c3ATDW64mJUXH8j6n75ABoeexhTbrqVOzdTmCRJ0OYXQJtfAMviJZHbZZ8Pvvr6yEjUX1cL53vvovvtN/vvCG1x8ZDzRqugyc9Puc0FREoSoRBktxshtwshlxuy2xX5Xna7EXK54GtsiBwfbGtF65+fQeufn0HFrevgVhcj3n+p1gYH3v3n/+HKO36H3MIKfPjv5/HKkz/CZet+HfN/UJIAtzeY7Jc6LkyFPsZZs1Fy+bfQ9Jv/RfMffo+Sy6/kh2iaUen1MFZXw1hdHblNCIFgW1vU6S6+QwfR+8HOgfuZzOHC9JHRaBV0FeVQaVPnN1ui8ZIDgUFBFw452e1CyO2G7Bp0u9sF2dV3e9/xstc74mNLGg2kOBdu0BQWQldaBpNTghCICc0De3agfPrCyCafJSech7deehgeVzdMltyoY4UATIbUiqjUao3CbMetgL+5ER2v/hW6klLkn5U9hdozlSRJ0BYVQVtUBMvSoyK3hzwe+OvqBlUxOoTuLf+G8PvDB6hU0JWWRmrp9k/rqnNStxJJOpcco1hCCAi/PxJkIdfA6E72uAe+7wu8xoAPvm5nZBQYeS8PQ9LroTaZoTKZoDaZoC0shNpUBZXJDLV54HaVyRw+zmyK/K3S6hDs6oTj+zcDCAdl8cXfhHnRYkiShDK9H2q1CkNLlZdMmY2PtrwIl7MDZms+anZvRU5BaUxYAuEKQKUFpoT1ZyIwMIco+Np/INDcjLYXnoO2pATWI48a/U6UdtRGI4yzZsE4a1bkNiHLCLS0hEO0b23UU7MPzh3bB+5nsUbt0u0vBajUFH6mlBzLVEIIyF5vdOANDcDINGff7W4XZJcbsscNERx5SlJlNPYFmxmGXBt0paV9AWcK32429wWgadDt4b8P9z2rtuXAesxy6KdMQe7pq6LKYdpMOkwtteJAY0/UfapmH4llp1yEZzfeBLVGC4PJivOu+kncx59aak25X/iy4mol4yX7/aj7xf3w1dWi8j9/AMO0aUl/zlTuDyWkUn+EXK6Y4gv++rqBDzO1Grqy8pgg1VgTWwpwaJ/EKzkWjyyLlC85NhGTdoUfWYbs8USCLBxw/Wt7Q7/vn9ocCML+06LikqRI4KnMg4Kuf+TXH3hDA7Dv+8E7U1Pp/wwA7DnYiZe2OEat8BOPLAucd2L1YZ9WwquVTAKVTofy628M75zduB5V/3UXtPn5SjeLFKI2m2GaMxemOXMjt4VLATb1rYuGR6Tuzz+H8913Bu6Xkxs7Gi0phaQ+/GvMZlrJsWQTwSBCHvegwHPHD8A4U52y1xvZfR2XWj0o4ExQWyzQFZcMTGEOnto0DwpCowkqgyFjT3+aU5WLskIzmtpd45rdECL8C96cytzkNW6COMIcga++DrX33QttUTEqb/sBVHEWuRMlHfpjMqVrfwSdPVEh6quthb+xYaAUoFYbLgU46Fqj+imVUJvNUY/j3rsHTb9+HIUXfgO2vlKD/X0ihMDv/7F3Yh9EBeaULDk2FnLA3xdw4ZGcRSvQ2dA2KADdfZtXhq71uSF8o2xi0WrjTF0OHfnFWdszmyHpdCnRn6n4f2bwL3Zj6SMhBHKt+oT9YpfoESYDcxSuT3eh/lcPwrxoMcqvvzFpvw2mS39MlkzqDxEMwt/YMDCt2ze1G3IOvD5NfsGg0WglXJ9+ip6tmwEAOSedjKKLLkZJeQFaW50jTnUJIfD6H3+GwrLpWHbKRTE/T9RU10RENrEM2a0ZWdMbGniRtb7w35Gr4QxD0hvCgWc0DQq2OFOdkZFff0CaMmJHdKr+nxm8dBDOTCnuKSeyLFBeaMb5J82AxZiYywNySnaSmRcsQvHFa9Hyxz+g7blnUfSNi5VuEqUZSaPpm5KtAo4L3yaEQKi7O/p0l7pDcO3eFbPm1f3vt9D7yUcw3XkHkFMSt+QYALQ3HcSm59ej8cDnKCybHrcth1tyTAgB2eOJXqsbGoBRU5/Ra3v9I+3hqIzGvoALB56urHzY3ZoFFUXo8SH8vfHwN7FQclhMOly2ag721nbhnT//A42SBeqSsujNaWVWLKxO/c1pfIeNQe4pp8Hf1ITON/4BbWkpck86WekmUZqTJAma3FxocnNhXrAocrsc8MNf34Dan98H4fNFbg91daFmwyOw3fpfcUuOAcBHW1/EgmPOgi23eMTnPtDUg87WTphFYPTdmy53XwAOjPxGXM9TqaI3rZhM0OQXDprq7A+8OKcrGI3jmsGxFlnhTcERFcWSJAlzyq1Q2/8F9cpTEDzp+MjpT6UFppTbDTscBuYYFX3jYvhbWtDy9FPQFhbBfMQCpZtEGUil1UFXVhYJS5XZDPOixTBUz0T12adh+572uCXHAOC0C24CABz68oMRn8O1/wA+/PEzqPS2xj+gfxNLX5CpLVboSkqG3a3ZP/2pMpnDm1hSeIRAyvHV1UIEAiiaMwPWFNzQMxYMzDGS1GqUXfv/UPuzn6DxsYdReced4Ws/EiWYSq9H+Y03QWO1QT91WmTUpTGb4fY2x13/GQ9tfgH0s05HaUV/0EUHYKpsYqHM4rHXAAAMM2Yo3JKJy8z9zEmiNhpRcePNkLRaNGx4EEFnz+h3IpoAy6IlMEyvjpmiNBk0I86IjoXaYkHx8mNgW7ESliVLYZo9B/qKKdDm5UGl1zMsKSm8djvUubnQ5KXvKXoMzHHSFhSg/Ls3IdjdhYaHNkAOjFx+iiiRygrNUKsP779tKpYco8znddhhnDEzrX8hY2BOgLG6GqVXXQ2vvQbNv/ttTL1EomTpLzl2OFKx5BhltmB3NwJtrTBUp+90LMA1zAmzHn0M/P/RjPYXn4eutAwF55yrdJMoSyyqLoCjvnvYCj9nrb1j2PvKssDCGQXJahpRXF5HeP3SWD1T4ZYcHo4wD0P+V1fDtmIl2l9+ET3vbR/9DkQJ0F9ybLwzG6lccowym8duB9Rq6KdNVboph4WBeRgkSULxpVfAOGs2mp/8NTw1+5RuEmUBSZKw5sRq5Fr1Yw7N/pJja06sTus1JEpPXocdhqqpaV9RiYF5mFRaLcqvuwGavHw0PLwBgdZhzm0jSiCLSYe1p81GaYEZsjxyaMpyuIbs2tPnZGXhdVKWCAbhPbA/rU8n6cfATAC11YqK790MEQqhfuOD4RJgREnWX3LsvBOrMb3MBpUkQZZFuHydLKCSJEwvt+G8E6tx6ao5CavPSTQevro6CL8/7Tf8ANz0kzC60jKUX3cD6h78BRoffyR8vmYCLuNENBJJkjC3Kg9zq/LQ4/ajqd2dliXHKHNFNvzMSO8NPwBHmAllmjsPJd+8DO7PPkXLM0/zdBOaVDaTDrMrc7FkViFmV+YyLCkleOx2qHNyoclP/93ZHGEmWM4JJ4ULtf/jNehKS5F32hlKN4mISDFeRw2M1TMyYrPZiIGZl2eCRpO8acXhrjmW7gq/8y3s6WpH67PPoHDmVOQvO3pM98vU/pgo9kcs9kk09ke0VOsPf1c3Aq2tKP/qmYq1LZHPO2JgdnYmb/NKql7sNFHyL7sKrsZm7Pn5/6Dq9v8KXwtxBJneH+PF/ojFPonG/oiWiv3R+/EnAAC5tFKRtiX6AtJcw0wSlV6PihtvgtpkQv2G9Qh2dSndJCKiSeWx14QLFkydpnRTEoKBmUSa3DyU33ATQq5e1D/0K8iDLghMRJTpvPYa6CuroNJlxgY0BmaSGaqmouya/wffwQNo+s3/Qsiy0k0iIko6EQrBe2A/jBlw/mU/BuYksCxZiqILv4HeDz9A24vPK90cIqKk89X3FSzIgPMv+/G0kkmSe/qq8Okmr/0NupJS5Bx/gtJNIiJKGq+9/wolmTPCZGBOEkmSUHzJNxFobUXzU7+DtrAQprnzlG4WEVFSeBx2qG02aAoLlW5KwnBKdhJJGg3K/t910BWXoOGRh+BvalK6SURESeG122GYMTMjChb0Y2BOMrXJjPIbb4KkUoULtff2Kt0kIqKECjp7EGhpTvsLRg/FwFSArqgY5dffiGB7Oxoe2QgRDCrdJCKihPHa7QCQEZf0GoyBqRDjrFkoueJb8Hy5F82//x0LtRNRxvA67IBaDUOGFCzox8BUkG35CuSfcy563tmK+udfVLo5REQJ4XHYoZ9SCZVer3RTEoqBqbCCr50H6zHH4uBTT8O5832lm0NEdFhEKATvfkdGXDB6KJ5WojBJklBy5VVAdxeafvO/0BYUwDC9WulmERFNiL+hHsLngzHD1i8BjjBTgkqrw9wf3AZ1Tg7qH/oVAu3tSjeJiGhCPH0FCzKpwk8/BmaK0OXmoOKGmyH8ftRvXA/Z61G6SURE4+a126G22qAtLFK6KQnHwEwh+ooKlF17HfwN9Wj838dYqJ2I0o7HYYdhxoyMKljQj4GZYswLFqL44m/CtesTtP75GaWbQ0Q0ZqHeXgSamzKqfuxg3PSTgnJPPgX+5kZ0bXoDupIy5J58itJNIiIalceRueuXAAMzZRV9/WIEWlrQ8swfoC0qgnnBQqWbREQ0Iq/dDqhUMEybrnRTkoJTsilKUqlQds13oCuvQOPjj8BXX690k4iIRuTN0IIF/RiYKUxlMKLihpsg6XSo3/gggj09SjeJiCguIcvwOBwZVz92MAZmitMWFKDiu99DqKcHDQ9vgBzwK90kIqIY/vp6CJ83465QMhgDMw0Yplej9FtXw2uvQfOTv2GhdiJKOR5H3xVKMnSHLMDATBvWo5eh8PwL4NzxHtpfeUnp5hARRfHaa6C2WKEtLla6KUnDXbJpJO+ss+FvbkbHX1+GrqQEtuUrlG4SERGA8CklmVqwoB9HmGlEkiSUXHo5jLPnoPl3v4Vn3z6lm0REFC5Y0NSU0dOxAAMz7UgaDcqvuwGaggI0PLwB/tYWpZtERFnOu98BADBmaMGCfgzMNKS2WMKF2mUZDb96ECG3S+kmEVEW89hrAEnK2IIF/RiYaUpXWory674Lf2sLGh99BCIYVLpJRJSlvHY79FOmQGUwKN2UpGJgpjHT3HkoufQKuL/4DC3P/IGnmxDRpBOyDO9+OwwZfP5lP+6STXM5x58Af3MTOl/7G3Qlpcg740ylm0REWcTf2ADZ68349UuAgZkRCv9jDQItzWh97lloi0tgWbJU6SYRUZbw2PuvUJLZO2QBQBIjzOMFgyFoNOrJbA9NUMjnw6c/uBPuunosvO8eWKqrlW4SEWWBfRseRseO93HMU09m9DmYwCiB2drqTNoTFxVZk/r46SYR/RHs6sKhn9wNQKDyB3dBm5eXmMYpgO+PWOyTaOyPaEr1x4E7fwBtUREqbrx50p97NBPtk6Iia9zbuekng2hyc1Fx400IuT1o2Lgess+ndJOIKIOFXC74GxsyvmBBPwZmhtFXVqHsmu/AV3sIjb9+HEKWlW4SEWUo7/5wwfVs2PADMDAzkmXxEhR9/SK4PvoQbS/8RenmEFGG8tjt4YIF0zO7YEE/7pLNULmnnQF/czM6X/87dMUlyDnxJKWbREQZxuuwQ1cxBSqDUemmTAoGZoaSJAnFF69FoLUFzU//HtqiIpjmzY86psftR2ObC25vECaDBmWFZthMOoVaTETpRMgyvA47rMccq3RTJg0DM4NJajXKrr0OtT+7Fw2PPoSqH9wJbUkp9h7qwi5HOw42OREKyZAkQAhAo1ZhaqkVC2cUYE5lbsZvESeiifM3NUL2eLJmww/AwMx4apMJFTfcjEM/vRv7f/cUti/5GhrbXFCpwmHY/7ckAbIQ2N/YA3t9N8oKzVhzYjUsHHESURzevoIF2bLhB+Cmn6ygLSpC3vf+E5sqjkdT+0BYDkelktDU7sLTm75Er9s/Sa0konTisduhMpmhLSlVuimThoGZBYQQ+OseF3pV+jFPs0qShC6nDy9sdrCoOxHF8DpqYKiekVVLN5ySzQJ7D3VFTcP2+3DLC/hk2ysAgNzCCpzxje/DbB2oDiRJEhraXNhb24W5VelbNYiIEivkdsHf0ADrsuzZ8ANwhJkVdjnaY8KyqXYvdr75LC753kO48vbfIa+oAtv+/tuY+6pUEnbb2yerqUSUBrz79wMADFm0fgkwMDNej9uPg02xtRRLK+fgqh8+Db3RgmDAh96uNhjNtriPcbDJiR6uZRJRH6+9pq9gQXZd5IFTshmusc2FUEiOu9FHrdZg364t+OezP4dao8PKr34r7mMEQzKa2t08R5OIAAAehx268gqojdlRsKAfR5gZzu0NYqQ1+VmLTsD1P3kFK868An95bF3c2rOSFH4cIqL+ggXGLLj+5VAMzAxnMmgQb5NrZ2sd6hy7It8vOPYs9HQ0w+uJnb4VIvw4ABB09sD16S60v/oKnDvfT1q7iSg1+ZuaILvdMFRn1/olwCnZjFdWaIZarYo5NcTV04FXf383Llv3a5gsufhi5yYUlk2H0ZwT8xgatQrB/3sY+xoPQQy6ZJh+ejWsRy9LSru7nD7sPdTJsn1EKcbrCBcsyKYKP/0YmBnOZtJhaqkVBxp7om6fMmMRlp9+KZ596CaoVGpYcgpx7lX3xn2MqlIrdO81xVxfU6XTwVdbC92UKQk5F0sIESnb19jhhscTYNk+ohTjddihMpmgK82eggX9GJhZYFF1ARz13TEbf5Ycfy6WHH/uiPeVZYFFMwpQ/bOfo+HhDXB/8XnkZ569e3Dwx3dCbbPBNP8ImOcvgGn+fGhyx3/OZq/bj+c3OyLni2q1GpbtI0pBHrs9XLBAlX0regzMLDCnKhdlhWY0tbvGNTITQqCs0BwZ0VV87xY0P/V/6Nm2BZJGg6of/wTemi/h/vwzuD/7DM7t7wIAdOUVMM0/Ivxnzlyo9PoRn6fX7cfTm75El9M3rrJ9a0+bzdAkmkQhtxv+hvqkLcWkOgZmFpAkCWtOrI6E0lhCUwiBXKsea06sjhwvaTQoueJb0JWXA0JAX1ICfUkJclaeACHL8NfXwfXZp3B//hm6//0Wujb9E1CrYZw5q28EegT0U6dF/WYqhMDzmx0x7fp0xz+w/Y0/AgC0OgNOOf8GlFbNjbye/rJ9l66aw+lZokniPbAfECIr1y8BBmbWsJh0WHva7Khpz+HIskB5oRnnnzQDFqM26meSJCF/1Vkx95FUKugrq6CvrEL+mV+F7PfDU7Ovb/T5KdpffB7tLz4PldkM09x5MM1fAPP8I2B3a2La09F8CG+++AguvfV/YckpgOPz7Xj5t3fh2v/+c1Q7WLaPaHJla8GCfgzMLGIx6XDZqjnYW9uF3fbw9TCDQ6+HWWbFwurD31ij0ulg7htV4oKvI9jTA/cXn4cD9PNP0fvBTgDAjuMugspYHHVftUaLr669DZacAgBASeUcuJwdCAUDUGsGAry/bB8Dk2hyeOx26MrKoTaZlG6KIhiYSSYLGd2+nlGPU7mD6PT2jnhMjt4GlXR4C+2SJGFuVR7mVuWhx+1HU7s7cupGaYEpKaduCFmG2mKB7djlsB27HEII+Bsb0bL7CzQ2mjA0lnMKylBYWolAIAghBN5+6WHMWLAiKiz79Zft4yknRMnVX7DAcuRRSjdFMQzMJOv29eDxXb+DWjVyV+u0avgDoWF/HpKDuHbRFcgz5CasbTaTblKC5tC9P0awswO241bCdtxK6CsroS8vhztohGh1xARmP7/Pg9f/+DM4u1qw5toH4h7Dsn1EkyPQ0gzZ7crKCj/9GJiTQK3SQDtKYGrVGohQ5m1eEUJA9noQcjrR+c/X0fnP16G2WpF7ymlwz1kxbNm+7o4mPPfobcgvqcLXr18PrS7+TluW7SOaHB57X8GCLLtCyWAMTDosIY8HwY4OBDvbEejoQLCzM/x9RwcCne0IdnZGVQcCgJDTCeeHH8C0+EQIgZjQ9Lh68PT6G3DEslVYceYVIz7/4LJ9RJQ8XrsdKqMRutIypZuiGH7S0LBknw/Bjv4gDIdhoKO9LyDD38seT/SdJAnqnBxo8/Khr5gC84JF8Npr4N3vACQJkkaDwjVfR+4pp8LpDcYt2/fJtpfR09GMfbu2YN+uLZHbv379/8SU7tOoVSgtyM4NCESTyePI3oIF/RiYCqt57wu89eRrkIMhFE0rxdk3Xwi92ZD055X9/nDodXQMCsTo72W3O+Z+apsNmrx8aEtKYZo7H5r8/PD3+fnhr3NyIWmi31Ydf38V3v0OmObNR8nlV0JbUAhg+LJ9y8+4FCecfSUCgdGnWqeWWrl+SZRkstcDf30dLEuPVLopimJgKsjV1YtX/+fPuOx/rkPp9DK8/ugreOvJ13Dmd//jsB5XDgTCU6N9ARjsHBSKHR0IdHZA7o3dkau2WKHJy4O2sBDG2bOhzcuPBKImPx+a3DyotLE7VUeTe8ppMM6aA8PMmTGnqgxXtm9Mr1MWWDijYNz3I6Lx8e4PFywwZvH6JcDAVNT+D79E2exK5FcUAQCOPHs5fnPdeqy6/rxhz4EUwSCCXZ3R64VD1g9DztjTWFQmMzT54ZGgobq6b1RY0BeIedDk5UOlS85ITWUwwDhrVtyfJaJsHxElV2TDT5YWLOjHwFRQT2s3bEUDa3K2ohz43F743b6YadlAczMOvvjfaG3pxtALXKqMxsgoUF9VFQ7Cvu+1eXnQ5BeMWs9VKYkq20dEyeN19BUsMJuVboqiGJgKGrrZpZ+kjl1UlzQamObORf4xJQNTpX3TpWqjMdlNTapEle0josQTQsDjsMOyZKnSTVHciIGZl2eCRqNO2pMXFVmT9tipQuUOQqdVQ6uO7er8snw0fVkLnS78M2+3CwarERZb7K5PqbQYc8//NgpMmVkGrgjArd/Mx2eOduz8ohk1dV1Qq9UDZfs0EmZNycVR80pwRHVB1o4ss+H/zHiwP6Iloz889Q2Qe3tRtPiItOzvRLZ5xMDs7IzdJZkoRUVWtLY6k/b4qaLT2wt/IBS3KEHV4pn4x6OvoGl/I0qnl+G9l7Zh9vIj4PfH7g4NyCG0t/dCdmX2pECJTY+zj62C9qSZ+GxfS9yyfW1tI5cQzFTZ8n9mrNgf0ZLVHz07dwEAgsVT0q6/J9onw4VsZn/6pjhzrgWrb7kQL9z7B8ihEHJL83HOuouUblZKyLXqMZsbeogU57HXhAsWlJUr3RTFMTAVNvOYeZh5zDzodJq4I0siIiV5HTUwTK/O6oIF/dgDREQUl+z1wldXl7UXjB6KgUlERHF5D7BgwWAMTCIiiosFC6IxMImIKC6vvQba0lKoLRalm5ISuOlnEoTkOJt5AgFgUF1WKSQQkEe+gDQR0WQRQsDrcMC8aLHSTUkZDMwky9HbcO2iKyLfC1mg6clfw7PnC1TceBP0lVUAgIICC9rbRz6/MEdvS2ZTiYgiAi0tCPU6s/qC0UMxMJNMJamQZ8gFEC6c3vjbJ6D56DNYAVjcMix9PyswWTO+KAERpQ+vI7x+aZzBHbL9+Ak9SWSfDw2PbIT7s08jt4V6uhVsERHR8DwOO1QGA3TlFUo3JWVw088k6XpzU1RYAkCwq0uZxhARjcJrt7NgwRDsiUliO/4E5J6xChhUNJyBSUSpSPb54KurhYHTsVEYmJNEY7XBuvRoQAjknHIaLMccC/OCBUo3i4gohne/A5BlVvgZgmuYk6h72xZIej2Kzr8AKoNh9DsQESnA67ADAIzV3CE7GEeYk0T2+eB8fwesRy1jWBJRSvM47NCWsGDBUAzMSdL7wU4Inxe2lccr3RQiomEJIeC11/B0kjgYmJOk+52t0BYVwTh7jtJNISIaVqCtFSGnk+uXcTAwJ0GgtRWePV/AtuJ4SIN2yRIRpRqvvb9gAdcvh2JgToLud7YCkgTbCk7HElFq89jtkPR66CqmKN2UlMPATDIhy+h5ZytMc+dDW1CgdHOIiEbkdbBgwXDYI0nm2bsHwfZ22I7n6JKIUlt/wQIj1y/jYmAmWfe2LVAZjbAsPUrpphARjch78AAQCvEKJcNgYCZRyO1G74cfwHrMsVDpdEo3h4hoRP0bfgzV1Qq3JDUxMJPIuXMHhN8P28oTlG4KEdGoPA47tMUl0Fh57d14GJhJ1LNtK3SlZTBM529rRJTa+gsWsOD68BiYSeJvaoTXXgPbyhN47iURpbxgWxtCPT2sHzsCBmaSdG/bCqhUsB23QummEBGNytNXcJ0jzOExMJNAyDJ63t0G84KF0OTmKt0cIqJRee01kPR66FmwYFgMzCRwf/YpQl1dLLRORGnD47DDMG06JLVa6aakLAZmEnRv2wKVxQLL4qVKN4WIaFSy3w9f7SEWXB8FAzPBQr29cH38EWzHHgdJw+tzE1Hq8/UVLGDB9ZExMBPMuWM7RDDI6VgiShueSMECjjBHMuIQKC/PBI0mefPZRUXWpD22Uurfexfm6dNQedSCcd83E/vjcLA/YrFPorE/ok20P9rqDsJQWoqyGRUJbpHyEvkeGTEwOzvdCXuioYqKrGhtdSbt8ZXgq6uFy25H0UWXjPu1ZWJ/HA72Ryz2STT2R7SJ9ocQAt1f7IFp7vyM68+J9slwIcsp2QTq3rYVUKthO/Y4pZtCRDQmwY52hLq7YeT5l6NiYCaICAbh3P4OLIuXQG3lNBERpYfI+iU3/IyKgZkgrt2fIOR0stA6EaUVr8MOSadjwYIxYGAmSPe2rVDn5MC8YKHSTSEiGjOvva9gAU+DGxUDMwGC3d1w7foEtuUrWCWDiNKGHPDDe+ggTycZIwZmAjjfexeQZU7HElFa8R042FewgIE5FgzMwySEQPe2rTBUV0NfXq50c4iIxszj6C9YwA0/Y8HAPEy+gwfgr6+DbQUr+xBRevE67NAWFkGTk6N0U9ICA/MwdW/bAkmrhfWYY5VuChHRmAkh4LHX8PqX48DAPAxywA/ne9thWXoU1Caz0s0hIhqzYGcHQl1d3PAzDgzMw+D66CPIbjcLrRNR2vHa7QDAK5SMAwPzMHRv2wJNfj5M8+Yr3RQionHx2GsgabXQT6lUuilpg4E5QYHOTrg//wy2FSshqdiNRJRevI4aFiwYJ37ST5Dz3W2AELCt4LmXRJRe5EAAvkOHuH45TgzMCQife7kFxtlzoCsuVro5RETj4jt0ECIYZMH1cWJgToC3pgaB5mZu9iGitOTtu0KJkSPMcWFgTkD3ti2Q9HpYj1qmdFOIiMbN47BDU1AATW6u0k1JKwzMcZJ9Pjjf3wHrUcugMhiUbg4R0bh57XaeTjIBDMxx6v1gJ4TPC9vx3OxDROkn0NGBYGcH68dOAANznLrf2QptUTGMs2Yr3RQionHzOsIFC7hDdvwYmOMQaG2FZ88XsK08HpIkKd0cIqJx8/YVLDBUVSndlLTDwByH7ne2ApIE24qVSjeFiGhCPA479FOnsWDBBDAwx0jIMnre2QrTvPnQ5hco3RwionGTAwH4Dh7g6SQTxMAcI8/ePQi2t8O2kpt9iCg9+WoP9RUsYGBOBANzjLq3bYHKaIRl6ZFKN4WIaEIiBQt4SsmEMDDHIOR2o/fDD2A95liodDqlm0NENCEeux2a/AJocvOUbkpaYmCOgXPnDgi/n9OxRJTWvA47Tyc5DAzMMejZthW6snIYplcr3RQiogkJdnUi2NEOI9cvJ4yBOQp/UyO89hqee0lEac3Tt37JK5RMHANzFN3btgIqFWzHrVC6KUREE+a12yFpNNBXsmDBRDEwRyBkGT3vboN5wUJocnKVbg4R0YT1FyxQabVKNyVtMTBH4P7sU4S6urjZh4jSmggG4TuwnwULDtOItZHy8kzQaNRJe/KiImvSHjsR2ne+C43VimmnHj8pv5Wlen9MNvZHLPZJNPZHtOH6w/nlPohgEMVLF6Iwy/oske+REQOzs9OdsCcaqqjIitZWZ9Ie/3CFenvR8d77yDnpZLR3eQF4k/p8qd4fk439EYt9Eo39EW2k/uj8YDcAwF9YnlV9NtH3yHAhyynZYTh3bIcIBmFbebzSTSEiOixeRw00efnQ5ucr3ZS0xsAcRve2rdBXVsFQNVXpphARHRaPvYb1YxOAgRmHr64WvoMHuNmHiNJesKsLwfZ2bvhJAAZmHN3btgJqNWzHLle6KUREh8XjsANgwYJEYGAOIYJBOLe/A8uSpVBbs2s3GRFlHq+9JlywgMtLh42BOYRr9ycIOZ2wreBmHyJKf16HHfqqKhYsSAAG5hDd27ZCnZMD84KFSjeFiOiwiGAQ3gP7YajmdGwiMDAHCXZ3w7XrE9iWr4CkTl7BBiKiyeCrq4UIBHjB6ARhYA7ifO9dQJa5O5aIMsLAFUq4QzYRGJh9hBDo3rYVhupq6MvLlW4OEdFh8zrsUOfmQpPHggWJwMDs4zt4AP76Oo4uiShjeO12GGfM5LV8E4SB2ad72xZIWi2sy45VuilERIct2N2NQFsrDCxYkDAMTABywA/ne9thOfIoqE0mpZtDRHTYvI7w+qWRO2QThoEJwPXRR5Ddbp57SUQZw2O3A2o19NNYsCBRGJgIT8dq8vNhmjdf6aYQESWE12GHoWoqVFqd0k3JGFkfmIGODrg//wy2FSshqbK+O4goA0QKFvB0koTK+oRwbn8HEAK2FdwdS0SZwVdfB+H3c8NPgmV1YIbPvdwC4+w50BUXK90cIqKE8PYVLGCFn8TK6sD01tQg0NwM20pu9iGizOGx26HOyYUmv0DppmSUrA7M7m1bIOn1sB61TOmmEBEljNdhh7F6BgsWJFjWBqbs88H5/g5Yjz4GKoNB6eYQESVEsKcHgdYWbvhJgqwNzN4PdkL4vJyOJaKM4nXYAXD9MhmyNjC7t22BtqgYxlmzlW4KEVHCeOw14YIFU6cp3ZSMk5WBGWhthWfvHthWHs85fiLKKF6HHfrKKqh0LFiQaFkZmN3vbAUkCbYVK5VuChFRwohQCN79Dhh5/mVSZF1gCllGzztbYZo3H1puuSaiDBIpWMD1y6TIusD07N2DYHs7r3tJRBnHa+/b8MMRZlJkXWB2b9sCldEIy9IjlW4KEVFCeRw1UNts0BQWKt2UjJRVgRlyu9H74QewHnMsF8SJKON47XYYZszkZsYkyarAdO7cAeH3czqWiDJOoKcHgZZmTscmUVYFZs+2rdCVlcMwvVrpphARJZRz75cAwA0/SZQ1gelvaoTXXsNzL4koIzn37AXUahhYsCBpNCP9MC/PBI1GnbQnLyqyJu2xhzrw2suASoXpq8+ALm/ynnc8JrM/0gH7Ixb7JBr7Y8Cne7+Eedo0lEzhhp/BEvkeGTEwOzvdCXuioYqKrGhtdSbt8QcTsoymf70F84KF6A5qgEl63vGYzP5IB+yPWOyTaOyPAUKW4dxXA+txK9kng0z0PTJcyI4YmOmqx+1HY5sLbm8QJoMGhSovQl1dyPnm5Uo3jYgo4fz1dZC9Xhh5hZKkypjAFEJg76Eu7HK042CTE6GQDEkChAA0ahUqz78Vcv4UzBGCa5hElFE89hoA3PCTbBkRmL1uP57f7EBjmwsqVTgM+/+WJEAWAge7Ati/2YGyQjPWnFgNi4nnYRJRZvA67NDm2KAtLFK6KRkt7XfJ9rr9eHrTl2hqHwjL4ahUEpraXXh605fodfsnqYVERMnlsdthnTOHs2dJltYjTCEEnt/sQJfTF/NGaW1w4F/P/wp+rwuSSoXTv34rSivDb6gupw8vbHbg0lV8g1G0oevfZYVm2DgbQSks1NuLQHMTrGecqnRTMl5aB+beQ11R07D9An4v/vLY97Hqov9E9fzlqNm9FX9/6l586wdPAQAkSUJDmwt7a7swtypPiaZTChlt/XtqqRULZxRgTmUuf8GilONxhNcvrXNmg/NmyZXWgbnL0R53GvbAnveRW1CO6vnLAQAzFqxETkFZ1DEqlYTd9vaYwPTV16H732/BcuTRMM2dl7zGU0oYy/r3/sYe2Ou7uf5NKcnrsAMqFSyzZqLDGVC6ORktbQOzx+3Hwab459d0ttbBZMvH6888gNaGGuiNFpx0zndijjvY5ESP2w+rUQvPvi/R8fdX4f50NwBAyIKBmeH617+7nL5xrX+vPW02Q5NShtduh35KJdQGA8DATKq0DczGNhdCITnuB50cCmL/5+/hG9c/iLJp81Gzeyue/9/bcM2PnoVGM/BBFwzJaGp3o23jPQh2tEc9huvT3Wh47GFIWi1UWi0kjRaSduCPatDXkkYz6HZdzLEDj9F3nDp51ZNobIZb/37rpUfw5cdvw2AKn7icX1yFc674EQBw/ZtSjpBleBwO2FasULopWSFtA9PtDWK4zytzTiHyS6pQNm0+AGDmwuPxjz/9HN1tjSgonRo5TpLCj5NfWBgTmMLng7+uDnIwABHo+xMMQvgTsEqgUg0JUi3qjHqEJHUkgFXaOKEbJ4gljTbusTG3Dwp1SaPJ+g/74da/G/Z/itWX34WK6Qvi3o/r35RK/A31ED4vr1AySdI2ME0GDYRA3NCsnncM/v3yI2iq3YvSyjmotX8CSBJyCkqjjhMi/DhV/3kHfA31aHv+L3B98hEAIPeUU1Fwzrkxjy2EAEIhyIFBQdr3Rw4EIKICdtDt8Y4PBiACQYhAADqVgNfliRwf9HiGPE4w8vgIhQ67/4YPY03UCDkmjDXRQR93JD00oOMdr1L2jKZ469/BoB8t9fuw861nsem5B5FbWIGT/+N62PJKoo4bbv2baLJ57HYAgKGaBQsmQ9oGZlmhGWq1KhxgQ5htBTj3qnux6bn1CPg90Gh0OPdbd0Oj1Ucdp1GrUFpgAgDoyytQccP34Nm3D51vvgHTEQvjPq8kSYBGA7VGAxiNCXs946l5KEKh8Gh3uDAODro9GCfUo44Nxg172e2O/QVg0H0Om1o9Yug2mwwICikqpOMGeCTsNWM6VtJo0RuS4q5/93a3o2rWkTjh7KuRV1yJ9996Fi/9+r9w6fefiBmR969/959yIgcC6P3wA0CWYTuO02OUXIHWVgSdTnj2fQm1xQptcbHSTcoKaRuYNpMOU0utONDYE/fnlTMW45u3PDriY0wttcacY2ecNQvGWbMS1s5kkNTq8DqoXg8lVkOFLEOEgsMH77Aj7+DoI+++sJd9PgTd3mGPRZxflMaqdfGJCOUtjhlh5haUYc2190e+X3byN7D9H79Hd0cTcofssu5f/zb0tKN787/RvXUzZLcbKoOBgUlJ1/jrx+HtK4enMprQ9uc/IfeSC5HGH+lpIa17d1F1ARz13aPucIxHlgUWzihIQqsyn6RSQVLpAG3ydoqONuIWoVDsqDkYL6Rjw7tTXwapPnZau7XBjpZ6O45YdsbA80BAHWeTliQBtX95Afhsc3S7AHT8/VWorVaorbbw3xYr1FYrVEZj1q8dU2LoysojgSl73Oh84x9or66CZtlKhVuW2dI6MOdU5aKs0Iymdte4PoiEECgrNGNOZW7yGkdJFRllGwzjHmXnHuqEqHPErn9LEt58YQMqqhcit6AMH297GUXlM2DNjZ3uEgLInVoBaa8maopa+Hxoe+Ev8dus0UBlsUDTH6T9fywD4Tr4ZyqTiQFLcZnmzEXP1oFf1gwzZqDk9FPR3uVVsFWZL60DU5IkrDmxOnIu3Vg+XIQQyLXqsebEan4YZanh1r+Lyqpx6pob8eITd0DIMqy5RVh92Z1xH0OjVmHWmSfDvOp4tL34PLrffhMAYF64CGXXXodQrxMhZ/hPsKcn6vuQM/x9oLUFIacTsneYDzm1GmqLJTJC7SjMR1BnjA5bqw1qixUaqxUqs1nxzVQ0OYxz5ka+VttyUH7djVBptQAYmMmU1oEJABaTDmtPmx1TrSUeWRYoLzTj/JNmwGLUTmIrKZWMtP49/+gzMP/oM+LcK9rA+rcOJd+8DDnHn4DWv/wZ5oWLodLrodLroS0oHFN75IB/UJgO+tMbHba9djv8Xd2QPZ74DyRJkXAdOoLVWK1Q22xRo1m1xcKATVPa/HxIOh2E34+KG2+GJidH6SZlhbQPTCAcmpetmoO9tV3YbQ/XAw0OrQdaZsXCatYDpbBEr38bpk1H5fdvm1BbVFodVPkF0OaPvKbev64rgsFIiMaOXgfC1ldXi1CPE7LbFf8BJQkqsxma/pCNBOrAH03fCFZtCwcvi26kjsKvXwxJkmCYNk3ppmSNjAhMIDw9O7cqD3Or8tDj9qOp3R254kRpgYlXnKAo6bz+LWk00OTmQZObB/3oh4cD1tUbFajBXidCPT2RcA05nfA3NIS/d/UOuwtZZTIPCdS+NVhb9AYntdUGjdUKSZMxHzEpIepqOtVLUFZoVrpJWSUj3802k44BSSPKpvVvSaOBJicXmpzcMR0vZDkcsD0D662RoB00gg00N8NbU4NQr3P4gDUa4waqZug6bP9GpyTuvE5XY72aTmGhRemmZryMDEyiseD6d3ySSgWN1QaN1QagYtTjhSxDdrsRcvYMBKqzJ2p6OOR0ItDWBu/+/eGAHaZalaQ3DBumQ8M2ZM3sfwdgfFfT+cTRgbOPqeSFAZKIgUlZjevfh09Sqfp281qgKxv9eCFEX8D2B+rgoB0I22BnJ3y1hxByOuNWl9oPQNLpYnYLxw3bvqCV9Ia0+Tcc79V06lt6eTWdJGNgUtbj+vfkkiQJarMZarMZKC0d9XghBGSvd8jItQcG2Y+eprbwemzfbf6GunDABuJf5krSaGKCtH+9VR1n85NSxSbiXU3nsx3/wM63/xw5xud1oberFdf++DmYrfm8ms4kYGASDcL179QjSRLURiPURiMwqGbqcNWghBAQPt/AmmtvX8j2DPq672f+5qZwwPp88Z87UmzCCrWlL2htQ4tNDEwZq0ymhJyqE+9qOkccswpHHLMKABAKBfGnDTfi2FMvgdmaH9VXvJpO8jAwiSijSJIEyWCAymCAtqhoTPeRfb6Y03OCzkG7iPtO3wm0ja/YhCbu9PDoxSbiXU1nsB3/+iNM1jwsXvm1mJ/xajrJw8Akoqw3sWITvQNhOrjYxKANT96DBxFy9oxSbMISFariiCU42GQa9rndvV3Y+dafcen3nxj2mKFX06HEYGASEY1TuNhEPrT5+aMfDEQXm4izwWlwsYlmfRFC2hnDjjB3vfsqZi5YGXMFncH6r6bDwEwsBiYRUZKNp9hE15etkN4/NOzP9370Fk45/4aRn08C3N4EXLeWorCQJBFRCjEZNMNe7tXrdqKzrR7l0xeM+BhChB+HEouBSUSUQvqvphNPZ1s9LLZ8qNUjh6FGrUJpwfDroDQxDEwiohTSfzWdeMqq5uLbP/zjqI8xcDUdSiQGJhFRillUXQBZHmZedhTxrqZDiSGJoVfRHSQYDEGj4eV8iIgmkxACD//lE9S39I77ajpTii247oLFrPSTBCMGZrwqGokyXJWObMX+iMb+iMU+iZbp/TG4luxYwk+jUcNsULOW7CATfY8UFcWfEueULBFRCuq/mk5pgXnU6VlZFphSYsHa0+cwLJOI+46JiFLUeK6mc/yRlWhr61W6yRmNgUlElMLGejUdrlkmHwOTiChN8Go6yuIaJhER0RgwMImIiMaAgUlERDQGDEwiIqIxYGASERGNAQOTiIhoDBiYREREY8DAJCIiGgMGJhER0RgwMImIiMaAgUlERDQGDEwiIqIxYGASERGNAQOTiIhoDBiYREREYyAJIYTSjSAiIkp1HGESERGNAQOTiIhoDBiYREREY8DAJCIiGgMGJhER0RgwMImIiMbg/wMy6ptmNcPc1AAAAABJRU5ErkJggg==",
+ "image/svg+xml": "\n\n\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fqs = FQSq(n, cost, xc, yc)\n",
+ "res = fqs.solve()\n",
+ "fqs.visualize()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Runtime: 6272.929 ms\n",
+ "Number of variables: 216\n",
+ "29 feasible solutions of 50.\n",
+ "Minimum value of objective: 6302.0\n",
+ "Minimum total cost: 6302.0\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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",
+ "image/svg+xml": "\n\n\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "gps = GPSq(n, cost, xc, yc)\n",
+ "res = gps.solve()\n",
+ "gps.visualize()"
+ ]
+ }
+ ],
+ "metadata": {
+ "interpreter": {
+ "hash": "0e7816a9375d24982caaf7808db0b7b92b4219a28bbe82f81d56470da3fa9de7"
+ },
+ "kernelspec": {
+ "display_name": "Python 3.9.7 64-bit ('the-quibit-players-venv39': venv)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ },
+ "orig_nbformat": 4
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Src/external/VRP-explorations/solve_vrp.ipynb b/Src/external/VRP-explorations/solve_vrp.ipynb
new file mode 100644
index 0000000..3aa1a04
--- /dev/null
+++ b/Src/external/VRP-explorations/solve_vrp.ipynb
@@ -0,0 +1,232 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Results obtained using various solvers for the Vehicle Routing Problem\n",
+ "The `cost` acts as a parameter of comparison between different solvers. In this project it is the total sum of distances of the routes by each vehicle.\n",
+ "The approximation ratio is the ratio of the cost of the obtained from the solver to that of the best known solution. The closer it is to 1, the better the solver is.\n",
+ "\n",
+ "By default the `LeapHybridCQMSampler` lets the solver run for around **5 seconds**. For better results this can be increased by passing a parameter `time_limit` into the solver's `.solve()` method. However, one needs to be careful about it as running it for too long may exhaust the limit of resources that D-Wave provides."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "class Initializer:\n",
+ "\n",
+ " def __init__(self, n, a, b):\n",
+ " self.n = n\n",
+ " self.a = a\n",
+ " self.b = b\n",
+ "\n",
+ " def generate_nodes_and_weight_matrix(self):\n",
+ "\n",
+ " n = self.n\n",
+ " a = self.a\n",
+ " b = self.b\n",
+ " \n",
+ " np.random.seed(100*a + b)\n",
+ "\n",
+ " x = (np.random.rand(n) - 0.5) * 50\n",
+ " y = (np.random.rand(n) - 0.5) * 50\n",
+ "\n",
+ " weight_matrix = np.zeros([n, n])\n",
+ " for i in range(n):\n",
+ " for j in range(i+1, n):\n",
+ " weight_matrix[i, j] = (x[i] - x[j]) ** 2 + (y[i] - y[j]) ** 2\n",
+ " weight_matrix[j, i] = weight_matrix[i, j]\n",
+ "\n",
+ " return x, y, weight_matrix"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from utils import VRPSolver, compare_solvers, random_routing_instance\n",
+ "\n",
+ "n=10 # number of clients\n",
+ "m=3 # number of vehicles\n",
+ "\n",
+ "initializer = Initializer(n+1, n+1, 3)\n",
+ "xc, yc, cost = initializer.generate_nodes_and_weight_matrix()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "### Select the type of model to solve VRP\n",
+ "# 1: Constrained Quadratic Model - A new model released by D-Wave Systems capable of encoding Quadratically Constrained Quadratic Programs (QCQPs)\n",
+ "# 2: Binary Quadratic Model - A model that encodes Ising or QUBO problems\n",
+ "model = 'CQM'\n",
+ "\n",
+ "\n",
+ "### The time limit (in seconds) for the solvers to run on the `LeapHybridCQMSampler` backend\n",
+ "time_limit = 25\n",
+ "\n",
+ "\n",
+ "### Select solver\n",
+ "# 1: RAS (Route Activation Solver)\n",
+ "# 2: FQS (Full QUBO Solver)\n",
+ "# 3: GPS (Guillermo, Parfait, Saúl) (only using CQM)\n",
+ "# 4: DBSCANS (Density-Based Spatial Clustering of Applications with Noise - Solver)\n",
+ "# 5: SPS (Solution Partition Solver)\n",
+ "solver = 'fqs'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "FULL QUBO SOLVER (Constrained Quadratic Model)\n",
+ "7 feasible solutions of 35.\n",
+ "Minimum total cost: 5399.969725142379 ____(X)\n",
+ "Minimum total cost: 7097.597752649794\n",
+ "Number of variables: 429\n",
+ "Runtime: 24992.293 ms\n"
+ ]
+ }
+ ],
+ "source": [
+ "vrps = VRPSolver(n, m, cost, xc, yc, model=model, solver=solver, time_limit=time_limit)\n",
+ "vrps.solve_vrp()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcwAAAFHCAYAAAAsrHydAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAB1LklEQVR4nO3dd3zU9f3A8df3dm4kl3FZkLD33iIgiOw9xYU4alurdlft0GqrrbV2WVdtfyriQiDsoSDI3iB7jxDI3rm73P7+/ggJhAwCGTfyeT4ePEhufL/vyyX3/n7W+yPJsiwjCIIgCEKtFP4OQBAEQRCCgUiYgiAIglAHImEKgiAIQh2IhCkIgiAIdSASpiAIgiDUgUiYgiAIglAHImEGmblz5/Kf//ynyu0ffPABP/zhD2t83uXLl+nTp0+1933++ee8//77tZ535MiRHDly5JZiHTlyJGPHjmXq1KlMmzaNCRMmMGnSJLZs2XJLx7nRW2+9xYYNGwD417/+xbJly+p1vHK7d++mZ8+eFfFOnTqVGTNmsHHjxls+Vk0/r927dzNp0qSGCPe2/etf/+IPf/hDpdvee+89xo0bx+jRo/n3v/9NTavNiouLeeWVV5g8eXLFz2nRokUV95e/7iNHjvDjH/+4XnE+9thj5Ofn39JzUlNTue+++5g8eTLf//73sVqtNT52zZo1TJ48mcmTJ/Pwww9z8eLFGh+7dOlS5syZw9SpU5kwYQIvvPACxcXFtxSbEAJkIaisXbtWHjNmTJXbx44dK2/durXG56Wlpcm9e/e+7fPefffd8uHDh+v9nLVr18pDhgy57ThkWZYfeughee3atfU6RnV27dolT5w4sdJtJ06ckHv37i3n5eXd0rFq+nlVd46mkpGRIT/zzDNyz5495Zdffrni9m+//VaeOnWqbLPZZIfDIT/44IPy6tWrqzzf4XDIkydPlt9//33Z7XbLsizLly9flkeNGiV/+eWXsizf3u9JTTp27HjLP/dnn31Wfu+992RZluVHH320Iq4b5eTkyAMGDJDT09NlWZblBQsWyI899li1j3333Xfl+++/X87JyZFlWZZdLpf80ksvyffff/8txSYEP5W/E7Zwa0aNGsWrr77Kvn376N+/PwB79uxBlmWGDBlCVlYWf/jDH8jIyMDtdjNx4sSKlqfX6+XFF1/kyJEjFBcX8+yzzzJ27Fj+/e9/U1BQwIsvvsiFCxd48cUXyc/PR6FQ8OSTTzJhwoRKMWzcuJF3330Xt9uNTqfjueeeq7H1ej1Zlrl8+TIREREVt7399tusXr0apVJJmzZteOGFF7BYLMydO5cHH3yQcePGAVR8n5eXx9GjR3n99ddRKpV88803dOjQgccff5wePXrw/e9/n+3bt5Odnc3DDz/MI488gtfr5fXXX2fjxo2YTCZ69uzJuXPnWLBgwU1j7ty5MzqdjitXrvDpp5/y3XffkZ2dTadOnfjzn//Ma6+9xs6dO1EqlfTs2ZNf//rXGI1GAD777DNOnjyJy+Xi0UcfZdasWZWO7XK5eOONN9i7dy9er5euXbvyu9/9DqPRyMiRI5k0aRLffvsthYWFPPPMMxw4cIBjx46hUql49913iYuLu2n811u8eDH9+vWjbdu2lVpH69evZ9KkSej1egBmzJjBihUrqrzva9asQa/X88QTT1Tc1qJFC/75z3/idrsrPXb37t388Y9/ZNWqVTd9ndOnT2fnzp1kZGQwfvx4nn32WX79618DMG/ePN5//302bdrEF198gVqtRqvV8oc//IH27dtXeY0dO3Zk06ZNjBo1iitXrtC7d+9qfxYxMTFs374dtVqNx+PhypUrmM3mKo+z2+385z//YenSpcTExACgVqt59tlnWb9+PS6Xi+LiYl588UXy8vLIycmp+JlER0czcuRIevbsyalTp/j5z39OTk5OnV6HEJhEl2yQUalUzJkzh8WLF1fctnDhQh544AEkSeJXv/oVM2fOJCUlhcWLF7Njxw7WrFkDgNPpZMiQISxdupTnn3+ev/71r1WO//Of/5xx48axevVq3n//ff7+979X6ta6ePEi//jHP3j//fdZtmwZf/zjH3nmmWew2+3VxvvLX/6SqVOnMnz4cIYPH8758+d57733AFiyZAlbt25l8eLFrFy5kg4dOvD888/X+voffPBBunfvzrPPPsvo0aMr3edyuYiMjOSLL77gzTff5G9/+xtOp5NFixZx7NgxVq1axRdffEFaWlrdftjA119/jUKhqPhQu3LlCkuXLuWNN97g3XffJTs7m+XLl7N8+XJ8Ph+vv/56xXO1Wi1Lly7lgw8+4G9/+xtnzpypdOz3338fpVJJSkoKK1asIDY2ljfeeKPifqfTyYoVK3j++ed58cUXmTdv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",
+ "image/svg+xml": "\n\n\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "vrps.plot_solution()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Number of iterations to get the average approximation ratio for a particular solver\n",
+ "# Warning! More iterations will take more time and resources to run\n",
+ "n_iter = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n",
+ "EXACT (CLASSICAL) SOLVER\n",
+ "Minimum cost: 2510.6938880123944\n",
+ "Time taken to solve: 404.192 ms\n",
+ "\n",
+ "ROUTE ACTIVATION SOLVER (Constrained Quadratic Model)\n",
+ "26 feasible solutions of 51.\n",
+ "Minimum total cost: 4942.760053612643\n",
+ "Number of variables: 150\n",
+ "Runtime: 25501.136 ms\n",
+ "\n",
+ "FULL QUBO SOLVER (Constrained Quadratic Model)\n",
+ "No feasible solutions.\n",
+ "Number of variables: 429\n",
+ "Runtime: 24951.941 ms\n",
+ "\n",
+ "GUILLERMO, PARFAIT, SAÚL SOLVER (Constrained Quadratic Model)\n",
+ "No feasible solutions.\n",
+ "Number of variables: 1080\n",
+ "Runtime: 25010.818 ms\n"
+ ]
+ }
+ ],
+ "source": [
+ "comparison_table = compare_solvers(n, m, cost, xc, yc, n_iter=n_iter, time_limit=time_limit)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Minimum cost of best known solution: 2510.6938880123944\n",
+ "RAS: \t average min cost = 4942.760053612643 \t average runtime = 25501.136 \t number of variables = 150 \t approximation ratio = 1.9686828717799636\n",
+ "FQS: \t average min cost = None \t average runtime = 24951.941 \t number of variables = 429 \t approximation ratio = None\n",
+ "GPS: \t average min cost = None \t average runtime = 25010.818 \t number of variables = 1080 \t approximation ratio = None\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Minimum cost of best known solution:', comparison_table[0]['exact_min_cost'])\n",
+ "for solver_id in comparison_table[1]:\n",
+ " print(f'{solver_id}:', '\\t', f'average min cost = {comparison_table[1][solver_id][\"avg_min_cost\"]}',\n",
+ " '\\t', f'average runtime = {comparison_table[1][solver_id][\"avg_runtime\"]}',\n",
+ " '\\t', f'number of variables = {comparison_table[1][solver_id][\"num_vars\"]}',\n",
+ " '\\t', f'approximation ratio = {comparison_table[1][solver_id][\"approximation_ratio\"]}'\n",
+ " )"
+ ]
+ }
+ ],
+ "metadata": {
+ "interpreter": {
+ "hash": "59ac870e08e47474f04ccef05d6bd545f403758435a4e924a6ca0eac1d024fcf"
+ },
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Src/external/VRP-explorations/utils.py b/Src/external/VRP-explorations/utils.py
new file mode 100644
index 0000000..cf006cd
--- /dev/null
+++ b/Src/external/VRP-explorations/utils.py
@@ -0,0 +1,161 @@
+import numpy as np
+
+from VRP.classical.ras import RAS as ExactSolver
+from VRP.classical.sps import SPS as SPS_c
+from VRP.quantum.CQM_based.fqs import FQS as FQS_cqm
+from VRP.quantum.CQM_based.ras import RAS as RAS_cqm
+from VRP.quantum.CQM_based.gps import GPS as GPS_cqm
+from VRP.quantum.BQM_based.full_qubo_solver import FullQuboSolver as FQS_bqm
+from VRP.quantum.BQM_based.route_activation_solver import RouteActivationSolver as RAS_bqm
+from VRP.quantum.BQM_based.dbscan_solver import DBSCANSolver as DBSS_bqm
+from VRP.quantum.BQM_based.solution_partition_solver import SolutionPartitionSolver as SPS_bqm
+
+class VRPSolver:
+ '''Class to solve VRP'''
+
+ def __init__(self, n, m, cost, xc, yc, **params):
+
+ params.setdefault('model', 'CQM')
+ params.setdefault('solver', 'ras')
+ params.setdefault('time_limit', 5)
+
+ self.n = n
+ self.m = m
+ self.cost = cost
+ self.xc = xc
+ self.yc = yc
+ self.params = params
+
+ self.solver = None
+ self.sol = None
+
+ def solve_vrp(self):
+
+ time_limit = self.params['time_limit']
+ model = self.params['model']
+
+ solver = {
+ 'CQM': {
+ 'fqs': FQS_cqm,
+ 'ras': RAS_cqm,
+ 'gps': GPS_cqm,
+ # 'dbss': DBSS_cqm,
+ # 'sps': SPS_cqm
+ },
+ 'BQM': {
+ 'fqs': FQS_bqm,
+ 'ras': RAS_bqm,
+ 'dbss': DBSS_bqm,
+ 'sps': SPS_bqm
+ }
+ }[model][self.params['solver']]
+
+ self.solver = solver(self.n, self.m, self.cost, xc=self.xc, yc=self.yc)
+ if model == 'BQM':
+ self.solver.solve(solver='neal')
+ else:
+ self.solver.solve(time_limit=time_limit)
+
+ def plot_solution(self):
+ if self.solver != None:
+ if self.params['model'] == 'BQM':
+ self.solver.visualize(xc=self.xc, yc=self.yc)
+ else:
+ self.solver.visualize()
+ else:
+ print('No solution to plot!')
+
+
+def compare_solvers(n, m, cost, xc, yc, **params):
+ params.setdefault('n_iter', 1)
+ params.setdefault('time_limit', 5)
+
+ n_iter = params['n_iter']
+ time_limit = params['time_limit']
+
+
+ sol = ExactSolver(n, m, cost, xc, yc).formulate_and_solve()
+ exact_min_cost = sol['min_cost']
+
+ solversList = [RAS_cqm, FQS_cqm, GPS_cqm] # RAS_bqm, FQS_bqm, DBSS_bqm, SPS_bqm
+
+ sum_min_costs = [0] * len(solversList)
+ sum_runtimes = [0] * len(solversList)
+ num_vars = [None] * len(solversList)
+ for i in range(n_iter):
+ for j, solver in enumerate(solversList):
+ sol = solver(n, m, cost, xc, yc).solve(time_limit=time_limit)
+ sum_min_costs[j] += sol['min_cost'] if sol['min_cost'] is not None else 0
+ sum_runtimes[j] += sol['runtime']
+ num_vars[j] = sol['num_vars']
+
+ avg_min_costs = [sum_min_costs[i] / n_iter if sum_min_costs[i] != 0 else None for i in range(len(solversList))]
+ avg_runtimes = [sum_runtimes[i] / n_iter for i in range(len(solversList))]
+ approximation_ratios = [avg_min_costs[i] / exact_min_cost if avg_min_costs[i] is not None else None for i in range(len(solversList))]
+
+ comparison_table = {solversList[i].__name__: {'avg_min_cost': avg_min_costs[i], 'avg_runtime': avg_runtimes[i], 'num_vars': num_vars[i], 'approximation_ratio': approximation_ratios[i]} for i in range(len(solversList))}
+
+ comparison_table = [{'exact_min_cost': exact_min_cost}, comparison_table]
+ return comparison_table
+
+
+def random_routing_instance(n, seed=None):
+ """
+ Generate a random TSP instance (n+1 random coordinates and a cost matrix which is same as the distance between them).
+ Args:
+ n: No. of nodes exclusing depot.
+ seed: Seed value for random number generator. Defaults to None, which sets a random seed.
+ Returns:
+ A list of (n + 1) x coordinates, a list of (n + 1) y coordinates and an (n + 1) x (n + 1) numpy array as the
+ cost matrix.
+ """
+
+ # Set seed
+ if seed is not None:
+ np.random.seed(seed)
+
+ # Generate TSP distance_matrix
+ xc = (np.random.rand(n + 1) - 0.5) * 20
+ yc = (np.random.rand(n + 1) - 0.5) * 20
+ xc[0], yc[0] = 0, 0
+ dist_mat = np.zeros((n + 1, n + 1))
+ for i in range(n + 1):
+ for j in range(i + 1, n + 1):
+ dist_mat[i, j] = np.sqrt((xc[i] - xc[j]) ** 2 + (yc[i] - yc[j]) ** 2) * 100
+ dist_mat[j, i] = dist_mat[i, j]
+
+ # Return output
+ return dist_mat.astype(int), xc, yc
+
+
+def custom_routing_instance(n):
+ """
+ Generate a custom TSP instance (n+1 coordinates and a cost matrix which is same as the distance between them).
+ Args:
+ n: No. of nodes exclusing depot.
+ Returns:
+ A list of (n + 1) x coordinates, a list of (n + 1) y coordinates and an (n + 1) x (n + 1) numpy array as the
+ cost matrix.
+ """
+
+ custom_coords = [
+ ([0, 9.68397635, -21.91415037, 8.33057986, 2.96044684, -20.74446885], [0, -5.37904717, -0.14612363, -8.39254627, -7.88307738, -6.71815846]),
+ ([0, -14.62374849, 0.64433429, -22.06068663, -24.17317981, 12.94189313], [0, 7.79525625, -2.17971286, -9.13602211, 19.52634242, 17.35703871]),
+ ([0, -20.547731, 0.21868276, 22.94555096, -21.60056947, -12.77923658], [0, -21.68070314, 3.85064948, 10.24842767, 5.33432128, -23.79246391]),
+ ([0, -23.95905211, -1.81608017, 5.17390474, 14.4451113, 7.92617635], [0, 11.01641074, -11.25120004, -23.69568939, 2.42716362, 11.41399686]),
+ ([0, 15.56202638, -8.1563987, -14.75819874, -16.40754363, 0.99306327], [0, 2.10506766, 14.74870063, 4.10311324, 20.76978131, -9.60709729]),
+ ([0, 17.53090505, -10.37294117, -13.84557367, -15.11426717, -6.10549414], [0, -18.07329384, -24.45858156, -20.871561, 22.97596238, 11.09926968]),
+ ([0, 17.39440017, -24.6850199, -19.22633574, -21.8862367, 10.20874553], [0, -2.42883951, -23.66801217, 9.19644146, 15.24107506, -24.45443753]),
+ ([0, -24.23999789, 24.44285518, 8.72046533, -2.01580788, -6.19607689], [0, -11.48069452, -17.60094231, 2.67137847, -13.23332478, -8.5483955 ]),
+ ([0, -8.72775711, 19.45745275, -4.44703119, -16.1182592, -12.93482615], [0, 19.96848055, 2.78356029, -3.79202314, -24.46107761, 23.34860146]),
+ ([0, 12.79365238, -12.45608602, 10.29188926, -6.11647882, 11.14503212], [0, 5.35068747, 8.78709806, -18.40157431, 23.6464964, -13.89138151])
+ ]
+
+ xc, yc = custom_coords[0][0], custom_coords[0][1]
+ dist_mat = np.zeros((n + 1, n + 1))
+ for i in range(n + 1):
+ for j in range(i + 1, n + 1):
+ dist_mat[i, j] = np.sqrt((xc[i] - xc[j]) ** 2 + (yc[i] - yc[j]) ** 2) * 100
+ dist_mat[j, i] = dist_mat[i, j]
+
+ return dist_mat.astype(int), xc, yc
diff --git a/Src/external/VRP-explorations/vrp_comparison_results.ipynb b/Src/external/VRP-explorations/vrp_comparison_results.ipynb
new file mode 100644
index 0000000..2847a4a
--- /dev/null
+++ b/Src/external/VRP-explorations/vrp_comparison_results.ipynb
@@ -0,0 +1,380 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "d47c6802-5846-4830-ba6c-66a678e6ad13",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "from utils import compare_solvers"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "9308e40c-493e-4962-93b2-95c82d7b7c2b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "class Initializer:\n",
+ "\n",
+ " def __init__(self, n, a, b):\n",
+ " self.n = n\n",
+ " self.a = a\n",
+ " self.b = b\n",
+ "\n",
+ " def generate_nodes_and_weight_matrix(self):\n",
+ "\n",
+ " n = self.n\n",
+ " a = self.a\n",
+ " b = self.b\n",
+ " \n",
+ " np.random.seed(100*a + b)\n",
+ "\n",
+ " x = (np.random.rand(n) - 0.5) * 50\n",
+ " y = (np.random.rand(n) - 0.5) * 50\n",
+ "\n",
+ " weight_matrix = np.zeros([n, n])\n",
+ " for i in range(n):\n",
+ " for j in range(i+1, n):\n",
+ " weight_matrix[i, j] = (x[i] - x[j]) ** 2 + (y[i] - y[j]) ** 2\n",
+ " weight_matrix[j, i] = weight_matrix[i, j]\n",
+ "\n",
+ " return x, y, weight_matrix"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "002a0699",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "### Select the type of model to solve VRP\n",
+ "# 1: Constrained Quadratic Model - A new model released by D-Wave Systems capable of encoding Quadratically Constrained Quadratic Programs (QCQPs)\n",
+ "# 2: Binary Quadratic Model - A model that encodes Ising or QUBO problems\n",
+ "model = 'CQM'\n",
+ "\n",
+ "\n",
+ "### The time limit (in seconds) for the solvers to run on the `LeapHybridCQMSampler` backend\n",
+ "time_limit = 5\n",
+ "\n",
+ "\n",
+ "### Select solver\n",
+ "# 1: RAS (Route Activation Solver)\n",
+ "# 2: FQS (Full QUBO Solver)\n",
+ "# 3: GPS (Guillermo, Parfait, Saúl) (only using CQM)\n",
+ "# 4: DBSCANS (Density-Based Spatial Clustering of Applications with Noise - Solver)\n",
+ "# 5: SPS (Solution Partition Solver)\n",
+ "solver = 'ras'\n",
+ "\n",
+ "# Number of iterations to get the average approximation ratio for a particular solver\n",
+ "# Warning! More iterations will take more time and resources to run\n",
+ "n_iter = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2a2505f-c24e-4ccd-a86f-9c66b3589b42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for n in range(10, 13): ### Here, (2, 6) could be replaced with the some other range of no. of locations you want.\n",
+ " for instance in range(4): ### Here, (10) could be replaced with some other number of instcnces you want to generate for a particular no. of locations.\n",
+ " initializer = Initializer(n, n, instance)\n",
+ " xc, yc, cost = initializer.generate_nodes_and_weight_matrix()\n",
+ " for m in range(1, n):\n",
+ " comparison_table = compare_solvers(n-1, m, cost, xc, yc, n_iter=n_iter, time_limit=time_limit)\n",
+ " print(f'\\nn = {n}, m = {m}, instance = {instance}')\n",
+ " print('Classical cost from best known solution:', comparison_table[0]['exact_min_cost'])\n",
+ " for solver_id in comparison_table[1]:\n",
+ " print(f'{solver_id}:', '\\t', f'quantum cost = {comparison_table[1][solver_id][\"avg_min_cost\"]}',\n",
+ " '\\t', f'runtime = {comparison_table[1][solver_id][\"avg_runtime\"]}',\n",
+ " '\\t', f'number of variables = {comparison_table[1][solver_id][\"num_vars\"]}',\n",
+ " '\\t', f'approximation ratio = {comparison_table[1][solver_id][\"approximation_ratio\"]}'\n",
+ " )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2a2505f-c24e-4ccd-a86f-9c66b3589b42",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# for n in range(2, 6): ### Here, (2, 6) could be replaced with the some other range of no. of locations you want.\n",
+ "# for instance in range(10): ### Here, (10) could be replaced with some other number of instcnces you want to generate for a particular no. of locations.\n",
+ "# initializer = Initializer(n, n, instance)\n",
+ "# xc, yc, cost = initializer.generate_nodes_and_weight_matrix()\n",
+ "# for m in range(1, n):\n",
+ "# comparison_table = compare_solvers(n-1, m, cost, xc, yc, n_iter=n_iter, time_limit=time_limit)\n",
+ "# print(f'n = {n}, m = {m}, instance = {instance}')\n",
+ "# print('Classical cost from best known solution:', comparison_table[0]['exact_min_cost'])\n",
+ "# for solver_id in comparison_table[1]:\n",
+ "# print(f'{solver_id}:', '\\t', f'quantum cost = {comparison_table[1][solver_id][\"avg_min_cost\"]}',\n",
+ "# '\\t', f'runtime = {comparison_table[1][solver_id][\"avg_runtime\"]}',\n",
+ "# '\\t', f'number of variables = {comparison_table[1][solver_id][\"num_vars\"]}',\n",
+ "# '\\t', f'approximation ratio = {comparison_table[1][solver_id][\"approximation_ratio\"]}'\n",
+ "# )"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Qiskit v0.29.0",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {
+ "077e48dacd4241a1bcb13cc6f04fe8c3": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "0ccb960c96bd4cb0b550d285502f6f7e": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "2139e56d73f04b5eb34d809be9bc6570": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "margin": "0px 0px 10px 0px"
+ }
+ },
+ "245cebcefbbf415bbea93cc356d8fac0": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_d781a3ac6b164ca1980812c179848d57",
+ "style": "IPY_MODEL_66065865fed4434383aece37ee7f339f",
+ "value": "Status
"
+ }
+ },
+ "29adc2fb292f446ea618cda7b7c729ee": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "GridBoxModel",
+ "state": {
+ "children": [
+ "IPY_MODEL_9e895d6266614f6e9818cdc666b909da"
+ ],
+ "layout": "IPY_MODEL_f588cad6d5bb474abe78c0a15f7004ae"
+ }
+ },
+ "4625f7bfca024dac9a1b50a1e0faff48": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_74dfc470cf60472496abe28f8746d360",
+ "style": "IPY_MODEL_7daa150b7a4740d98e0403417538e6cb",
+ "value": "Message
"
+ }
+ },
+ "4fe5fe099f6d4fc693dcd4ff60fbe70e": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "width": "70px"
+ }
+ },
+ "66065865fed4434383aece37ee7f339f": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "72233de611af4579af4ec63e6e2ed2f7": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_bdee412afa9846dd807883b72a804551",
+ "style": "IPY_MODEL_0ccb960c96bd4cb0b550d285502f6f7e",
+ "value": "Job ID
"
+ }
+ },
+ "74dfc470cf60472496abe28f8746d360": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {}
+ },
+ "7daa150b7a4740d98e0403417538e6cb": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "7e9a6673d2da47dc911f04ccc2156b80": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_d44f083eb17140b5b71e730a88b2f7a1",
+ "style": "IPY_MODEL_baea0097e85a4a66bed9be4317a2026f",
+ "value": "Backend
"
+ }
+ },
+ "942c9cca77d34d728a7d24ddd88bf229": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_4fe5fe099f6d4fc693dcd4ff60fbe70e",
+ "style": "IPY_MODEL_077e48dacd4241a1bcb13cc6f04fe8c3",
+ "value": "Queue
"
+ }
+ },
+ "9e895d6266614f6e9818cdc666b909da": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "ButtonModel",
+ "state": {
+ "button_style": "primary",
+ "description": "Clear",
+ "layout": "IPY_MODEL_d6c683955ec14ccd8106bdc1fb7f67b1",
+ "style": "IPY_MODEL_ab9ce09d7fd94ad7a7bf62246e496eb4"
+ }
+ },
+ "a6aaa738e07641f69deaa2b5dfc6f09f": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "ab9ce09d7fd94ad7a7bf62246e496eb4": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "ButtonStyleModel",
+ "state": {}
+ },
+ "baea0097e85a4a66bed9be4317a2026f": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "DescriptionStyleModel",
+ "state": {
+ "description_width": ""
+ }
+ },
+ "bdee412afa9846dd807883b72a804551": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "width": "190px"
+ }
+ },
+ "c74de40434c54b928b3d4b295bafdb41": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HBoxModel",
+ "state": {
+ "children": [
+ "IPY_MODEL_72233de611af4579af4ec63e6e2ed2f7",
+ "IPY_MODEL_7e9a6673d2da47dc911f04ccc2156b80",
+ "IPY_MODEL_245cebcefbbf415bbea93cc356d8fac0",
+ "IPY_MODEL_942c9cca77d34d728a7d24ddd88bf229",
+ "IPY_MODEL_4625f7bfca024dac9a1b50a1e0faff48"
+ ],
+ "layout": "IPY_MODEL_d7a3ec3b13674c4a98be2b964d41a3f6"
+ }
+ },
+ "d44f083eb17140b5b71e730a88b2f7a1": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "width": "145px"
+ }
+ },
+ "d6c683955ec14ccd8106bdc1fb7f67b1": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "grid_area": "right",
+ "padding": "0px 0px 0px 0px",
+ "width": "70px"
+ }
+ },
+ "d781a3ac6b164ca1980812c179848d57": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "width": "95px"
+ }
+ },
+ "d7a3ec3b13674c4a98be2b964d41a3f6": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "margin": "0px 0px 0px 37px",
+ "width": "600px"
+ }
+ },
+ "f588cad6d5bb474abe78c0a15f7004ae": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "1.2.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "grid_template_areas": "\n \". . . . right \"\n ",
+ "grid_template_columns": "20% 20% 20% 20% 20%",
+ "width": "100%"
+ }
+ },
+ "ffdb00faddb747588388de3f5333b709": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "1.5.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "layout": "IPY_MODEL_2139e56d73f04b5eb34d809be9bc6570",
+ "style": "IPY_MODEL_a6aaa738e07641f69deaa2b5dfc6f09f",
+ "value": "Circuit Properties
"
+ }
+ }
+ },
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Src/setup.py b/Src/setup.py
new file mode 100644
index 0000000..1316ee2
--- /dev/null
+++ b/Src/setup.py
@@ -0,0 +1,62 @@
+from setuptools import find_packages, setup
+
+long_description = '''
+ QIntern 2021
+Implementation of space-efficient variational algorithms
+for the Graph Coloring or Traveling Salesperson problems
+in Qiskit
+'''
+
+setup(
+ name="QuantumLogistics",
+ version="0.0.1",
+ description="A quantum optimisation toolkit for the Vehicle routing problem",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ url="https://gitlab.com/qworld/qresearch/qintern2021/21_solving-vehicle-routing-problem-and-its-variants-using-quantum-computing_b",
+ project_urls={
+ "HomePage": "https://qworld.net/",
+ },
+ keywords='quantum logistics',
+ packages=find_packages(),
+ install_requires=[
+ "matplotlib==3.5.1",
+ "cplex",
+ "pygsp",
+ "networkx",
+ "qiskit",
+ "qiskit_optimization",
+ "dwave-ocean-sdk",
+ "pulp",
+ "pytest",
+ "pandas",
+ "graph_coarsening @ git+https://github.com/loukasa/graph-coarsening",
+ ],
+ classifiers=[
+ # Project Maturity
+ "Development Status :: 1 - Planning",
+
+ # Topic
+ "Topic :: Communications",
+ "Topic :: Scientific/Engineering :: Physics",
+
+ # Intended Audience
+ "Intended Audience :: Science/Research",
+
+ # Compatibility
+ "Operating System :: Microsoft :: Windows",
+ "Operating System :: MacOS",
+ "Operating System :: POSIX :: Linux",
+
+ # Python Version
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11"
+ ],
+)
\ No newline at end of file