diff --git a/debug/charging_stations.json b/debug/charging_stations.json
new file mode 100644
index 0000000000000000000000000000000000000000..5565d630e1a8d1c569210e0b2a1a025035042dbb
--- /dev/null
+++ b/debug/charging_stations.json
@@ -0,0 +1 @@
+[{"lon":6.947762,"lat":51.750832,"power":22.0},{"lon":6.99896,"lat":51.7589,"power":22.0}]
\ No newline at end of file
diff --git a/debug/classic.csv b/debug/classic.csv
new file mode 100644
index 0000000000000000000000000000000000000000..f2a88c57248be07997b4312dc7d65bfdb7da9c29
--- /dev/null
+++ b/debug/classic.csv
@@ -0,0 +1,121 @@
+start_node,target_node,query_time,trip_time,nodes,edges,charging_stations,dijkstra_rank
+278788097,278788064,3.6123998143011704e-05,2.544455887440966,513591,775628,921,4
+1974276840,304743827,4.0936000004876405e-05,5.468344830265442,513591,775628,921,4
+4379640612,251721242,4.584600173984654e-05,4.400673382656193,513591,775628,921,4
+7052016254,7052035885,4.489799903240055e-05,4.910422549620248,513591,775628,921,4
+297358502,296505210,4.975599949830212e-05,6.006005554923204,513591,775628,921,4
+4001179266,279803170,4.0498998714610934e-05,6.787909702485399,513591,775628,921,4
+370260513,15934136,3.024999750778079e-05,3.6488563422704834,513591,775628,921,4
+253688476,253688478,4.657600220525637e-05,5.102975420893581,513591,775628,921,4
+670244222,670244208,4.483399970922619e-05,2.8777689306919836,513591,775628,921,4
+295812797,1186947550,4.6608998673036695e-05,2.305732311136417,513591,775628,921,4
+2092158041,110968707,3.09450006170664e-05,10.348220071064414,513591,775628,921,4
+1019862577,310740297,5.166999835637398e-05,3.1150150790654334,513591,775628,921,4
+1596409452,21349599,2.5798999558901414e-05,6.226881406984204,513591,775628,921,4
+3629862160,35341595,4.756199996336363e-05,4.243324937022972,513591,775628,921,4
+5116240898,5116240897,3.0107003112789243e-05,1.7214481834825603,513591,775628,921,4
+9201751,9193591,4.026600072393194e-05,10.338578998313869,513591,775628,921,4
+325718780,1398513311,3.746799848158844e-05,7.194162255941293,513591,775628,921,4
+384931335,384931529,2.9496000934159383e-05,7.172397044818459,513591,775628,921,4
+3655203260,3655203230,4.6779998228885233e-05,26.340009684234197,513591,775628,921,4
+1772688730,1772688731,4.06340004701633e-05,1.8021178538349452,513591,775628,921,4
+3779253653,21605682,3.820599886239506e-05,6.440256144606137,513591,775628,921,16
+3442894702,1288303198,8.64629982970655e-05,10.174488131976736,513591,775628,921,16
+2734232768,1368463837,7.194700083346106e-05,24.979432711128094,513591,775628,921,16
+324460984,324460952,8.43620000523515e-05,34.855892541880934,513591,775628,921,16
+1388209924,1376143875,7.31250001990702e-05,23.369454475567824,513591,775628,921,16
+3296257345,33024617,5.04890012962278e-05,73.35269873617314,513591,775628,921,16
+21516057,21516060,6.770400068489835e-05,44.07024744026253,513591,775628,921,16
+4278663465,31927910,6.415900134015828e-05,17.381704300263863,513591,775628,921,16
+7010426275,7010426240,7.610299871885218e-05,11.550300725435491,513591,775628,921,16
+4451772155,2151728158,8.008000077097677e-05,21.968863349225796,513591,775628,921,16
+530230113,5220432715,6.3292001868831e-05,17.91782716089565,513591,775628,921,16
+995959176,996113704,6.185500024002977e-05,65.0727740633652,513591,775628,921,16
+281260920,2799020208,7.42839984013699e-05,36.80301813801878,513591,775628,921,16
+560149740,2337055488,7.689500125707127e-05,40.163722333537585,513591,775628,921,16
+1978950983,111007577,5.8395999076310545e-05,62.312263177665606,513591,775628,921,16
+82533584,82533589,0.00010228799874312244,22.531355395225866,513591,775628,921,16
+367526344,322828416,0.00014162099978420883,26.592301250432616,513591,775628,921,16
+2088441607,296969297,0.00010998300058417954,50.33670383622816,513591,775628,921,16
+1844442623,357475749,0.000112900001113303,62.81023925748234,513591,775628,921,16
+1028144237,1056964046,9.897800191538408e-05,68.73549942625228,513591,775628,921,16
+3220840672,201851149,0.0001950309997482691,174.32355211015434,513591,775628,921,64
+36748523,2388848,0.00019567200070014223,121.32580835738597,513591,775628,921,64
+3130347756,3130347329,0.0002424809972580988,108.27118302141959,513591,775628,921,64
+1547069810,411133732,0.0001613509994058404,256.40308180241857,513591,775628,921,64
+3597248342,1674603507,0.00023229100042954087,34.85652333729989,513591,775628,921,64
+3790253212,59975819,0.00016300100105581805,107.86232786378116,513591,775628,921,64
+2895826757,297507303,0.00016575200061197393,107.45826802804294,513591,775628,921,64
+1736934595,20966465,0.00017126899911090732,159.1639460794961,513591,775628,921,64
+319615593,2518878954,0.00023569699988001958,43.45869902592796,513591,775628,921,64
+5002927891,3754266159,0.00021129200104041956,57.98113603320815,513591,775628,921,64
+2579137172,5063570813,0.0002142390003427863,61.5366358276483,513591,775628,921,64
+312763593,134701949,0.00022530500064021908,108.1307587387181,513591,775628,921,64
+3369654275,1473378283,0.000288334002107149,109.99002882889786,513591,775628,921,64
+249633765,249633758,0.00024689299971214496,47.61533465071713,513591,775628,921,64
+4291056236,4291055580,0.0001970149969565682,261.1600903088694,513591,775628,921,64
+1637802213,320226813,0.00026519899984123185,28.070885122314884,513591,775628,921,64
+616611038,2583559409,0.0002618830003484618,37.246881034372066,513591,775628,921,64
+36318594,11666598,0.00024141800167853944,44.57229612596537,513591,775628,921,64
+383521,5095604737,0.00019654999778140336,174.0467542346948,513591,775628,921,64
+2068590974,318895208,0.0002688839995244052,36.21930872762024,513591,775628,921,64
+3247535208,25626731,0.0004903619992546737,634.8937297982908,513591,775628,921,256
+461546,653603498,0.0005161930021131411,881.3305760058632,513591,775628,921,256
+581195,581141,0.0004575650018523447,695.575903128425,513591,775628,921,256
+979225594,6783606326,0.0004905160021735355,432.4076961369738,513591,775628,921,256
+26261827,410452925,0.0007324520011025015,71.44640860941952,513591,775628,921,256
+2143163767,470897387,0.0005068809987278655,172.57630372344587,513591,775628,921,256
+1448902129,33958260,0.0004416499978106003,966.3231357738559,513591,775628,921,256
+509267256,508577799,0.00042274699808331206,333.6962081339936,513591,775628,921,256
+530798414,82538716,0.0005942719981248956,490.2426858850804,513591,775628,921,256
+3594887294,1664388881,0.0006805939992773347,173.17787222910795,513591,775628,921,256
+1444721834,2083020058,0.0006834269988758024,123.41660204450442,513591,775628,921,256
+453231089,600514464,0.0007116740016499534,80.29099386719858,513591,775628,921,256
+515323,77924156,0.000465983001049608,869.837002491225,513591,775628,921,256
+34004398,260977399,0.0005460020001919474,237.7417902569312,513591,775628,921,256
+346932262,3129578003,0.0007214979996206239,98.94681154802963,513591,775628,921,256
+319048125,287464702,0.0007328450010390952,104.10802402818534,513591,775628,921,256
+3556528925,357489219,0.0006546719996549655,136.23245421330063,513591,775628,921,256
+139541,293536918,0.0004627560010703746,770.2121702120756,513591,775628,921,256
+2131942265,2071408447,0.0006551229998876806,164.71708692338362,513591,775628,921,256
+2600312295,323125728,0.0006524159980472177,225.57100183204827,513591,775628,921,256
+319442900,2887934658,0.0024950549995992333,407.2932625146748,513591,775628,921,1024
+32008898,268772387,0.0015889329988567624,2803.148662897562,513591,775628,921,1024
+1111574411,6767508665,0.0015920830010145437,2625.511934495633,513591,775628,921,1024
+1969643540,14001867,0.001886399000795791,2293.8522997773557,513591,775628,921,1024
+1885077335,456744,0.0018805790023179725,1770.0419997862678,513591,775628,921,1024
+60263679,2489316973,0.0026386400022602174,444.55292443906046,513591,775628,921,1024
+3738929332,6560433799,0.0016814640002849046,3274.6931931857334,513591,775628,921,1024
+49874983,3674012436,0.001833171998441685,2070.5750652362267,513591,775628,921,1024
+5119369026,1940161211,0.0027592480000748765,410.0405387921802,513591,775628,921,1024
+6551313413,7049979601,0.0023089040005288552,2374.7962222547726,513591,775628,921,1024
+3071384878,306251709,0.0026317410010960884,435.8936768859933,513591,775628,921,1024
+1485262466,1482777851,0.0017236380008398555,1929.423503079553,513591,775628,921,1024
+134697348,303266729,0.002748591999989003,115.17308427261189,513591,775628,921,1024
+2362354369,3740059705,0.0027479170021251775,301.2279449750924,513591,775628,921,1024
+5116240907,5119483566,0.0016262169992842246,1366.491107180064,513591,775628,921,1024
+241863215,3137765348,0.0019644699968921486,850.4136645128996,513591,775628,921,1024
+501002,1306947734,0.001808911001717206,2646.78472328243,513591,775628,921,1024
+3124949600,1649447784,0.0022134210012154654,999.3340981015767,513591,775628,921,1024
+4523763498,1856510925,0.0022163489993545227,669.239035967434,513591,775628,921,1024
+3223961182,2337151916,0.001684728002146585,1366.2368261840381,513591,775628,921,1024
+345545628,2260191455,0.008373068998480448,3719.196155948357,513591,775628,921,4096
+3192919201,5726480086,0.0070519789987884,16132.529041698832,513591,775628,921,4096
+1205905007,5501907575,0.011622191002970794,295.4047787417922,513591,775628,921,4096
+17294385,146739,0.007572518003144069,6210.995751802389,513591,775628,921,4096
+1598126176,3585723044,0.007197785998869222,4283.211503733242,513591,775628,921,4096
+324150617,300414752,0.010200359000009485,1625.86832497776,513591,775628,921,4096
+295207349,4431275625,0.011280605998763349,418.1311220240191,513591,775628,921,4096
+2898144982,367726156,0.007909354000730673,2224.6100681615776,513591,775628,921,4096
+254043139,29750343,0.007265272997756256,5038.120186733389,513591,775628,921,4096
+357130628,524422773,0.010862682000151835,590.976768156467,513591,775628,921,4096
+447113,1753939781,0.0074761439973372035,3006.594288140207,513591,775628,921,4096
+2654951621,4733405417,0.0066350830020383,4938.75483840242,513591,775628,921,4096
+304392060,561314049,0.011186251998879015,674.9023483434884,513591,775628,921,4096
+256225555,3445560484,0.011652896999294171,786.5613711924018,513591,775628,921,4096
+251332730,292272335,0.008115971999359317,2718.092432316061,513591,775628,921,4096
+148648471,2165134791,0.007913038996775867,1809.9876798503608,513591,775628,921,4096
+5062779692,2071316312,0.011333256999932928,676.5217399000071,513591,775628,921,4096
+1902094309,3805108849,0.007831605998944724,3874.210860820841,513591,775628,921,4096
+25468519,31292241,0.007029169999441365,5912.370671266628,513591,775628,921,4096
+2400252153,350036028,0.011470358997030417,378.81892011281525,513591,775628,921,4096
diff --git a/debug/debug.csv b/debug/debug.csv
new file mode 100644
index 0000000000000000000000000000000000000000..e347114f06d5b5476d5fe9ad4175b6876d7e22d1
--- /dev/null
+++ b/debug/debug.csv
@@ -0,0 +1,59 @@
+,start_node,target_node
+142,317840524,418009813
+143,2598987516,2554184473
+144,318260732,574727048
+145,2600724522,7140363811
+146,318015025,1253880618
+147,418009818,1505052514
+148,365070091,2611370483
+149,4903537220,574470582
+150,2616470680,7321870099
+151,2611493296,2626186155
+152,3379248585,2997117859
+153,574449271,426948334
+154,2616462230,2611494644
+155,7140363796,574470582
+156,563188710,1830470690
+157,7322098542,574482746
+158,6448459779,418009254
+159,317766814,574482738
+160,1927634061,2639932980
+161,7346826313,474997358
+162,7074500834,508823982
+163,5113940074,5095519272
+164,574482753,7030609383
+165,7140363800,574470582
+166,473666763,2611494654
+167,764105824,574470582
+168,2612706786,549924787
+169,2634485459,2997117859
+170,1927634075,2639932980
+171,2709911575,1929118150
+172,2701786796,1505992711
+173,45216804,7321870097
+174,317839015,34053457
+175,317839014,1757602462
+176,426930265,764105823
+177,1821085018,2700412804
+178,2635792146,365070092
+179,2616462248,7140363808
+180,1828263557,2335713764
+181,34053441,318266814
+182,360747407,469733542
+183,418009802,574457833
+184,2616315928,764105823
+185,1447654177,34053439
+186,7031746250,4016873396
+187,7182110436,2952086992
+188,4016874254,1757602462
+189,318260713,6943345426
+190,574449274,426948334
+191,1827268604,2598981720
+192,563191195,1830470690
+193,7321902569,574470582
+194,3111465597,7321975020
+195,318261619,440870146
+196,2598868763,2608394380
+197,2635713659,288947127
+198,317838695,2600670564
+199,600861115,574457831
diff --git a/debug/debug.py b/debug/debug.py
new file mode 100644
index 0000000000000000000000000000000000000000..2420fb9a6ed6757d6ab9748a80d99b1c02a117f5
--- /dev/null
+++ b/debug/debug.py
@@ -0,0 +1,66 @@
+import json
+import datetime
+import pickle
+import pandas as pd
+from time import perf_counter
+
+from evrouting.osm.imports import OSMGraph
+from evrouting import charge
+from evrouting.graph_tools import consumption_function_time_factory
+
+
+def get_graph():
+    print('Getting graph..')
+    with open('medium_nurnberg.pck', 'rb') as f:
+        G: OSMGraph = pickle.load(f)
+    G.rebuild_rtree()
+    return G
+
+
+def get_tasks():
+    print('Getting tasks..')
+    df = pd.read_csv('classic.csv', dtype={'start_node': str, 'target_node': str})
+    return [(row['start_node'], row['target_node']) for _, row in df.iterrows()]
+
+
+def get_charging_stations():
+    print('Getting charging stations..')
+    with open('charging_stations.json', 'r') as f:
+        charging_stations = json.load(f)
+    return charging_stations
+
+
+if __name__ == '__main__':
+    """Full tank is enough to get there. Must be equal to shortest path."""
+    tasks = get_tasks()
+    charging_stations = get_charging_stations()
+    G = get_graph()
+    G.insert_charging_stations(charging_stations)
+
+    c = consumption_function_time_factory(0.5)
+    mu_s = 40000
+    mu_t = 0
+    capacity = 40000
+
+    total_tasks = len(tasks)
+    for i, (s, t) in enumerate(tasks):
+        now = datetime.datetime.now().strftime("%H:%M:%S")
+        print(f'{now}: {i}/{total_tasks} ({(i / total_tasks) * 100:.2f} %)')
+        # nodes_before = set(G.nodes)
+        # edges_before = set(G.edges)
+        start = perf_counter()
+        charge.routing.shortest_path(
+            G=G,
+            charging_stations=G.charging_stations,
+            s=s,
+            t=t,
+            initial_soc=mu_s,
+            final_soc=mu_t,
+            capacity=capacity,
+            c=c
+        )
+        runtime = perf_counter() - start
+
+        # assert nodes_before ^ set(G.nodes) == set()
+        # assert edges_before ^ set(G.edges) == set()
+        # assert runtime < 100
diff --git a/debug/map.pck b/debug/map.pck
new file mode 100644
index 0000000000000000000000000000000000000000..f012192fcb0a2f6eeae82e2284ccf70e82812fbf
Binary files /dev/null and b/debug/map.pck differ
diff --git a/debug/medium_nurnberg.pck b/debug/medium_nurnberg.pck
new file mode 100644
index 0000000000000000000000000000000000000000..7930dec4a17dcd19838146483eb2b5b512e8698f
Binary files /dev/null and b/debug/medium_nurnberg.pck differ
diff --git a/evaluation/configs/bigger_gasstation.yaml b/evaluation/configs/bigger_gasstation.yaml
deleted file mode 100644
index 37c210a39fcf5b77e578385aac72554a377b4dbc..0000000000000000000000000000000000000000
--- a/evaluation/configs/bigger_gasstation.yaml
+++ /dev/null
@@ -1,44 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: query
-charging_stations: charging_stations.json
-maps:
-  - medium_nurnberg.osm
-queries_per_setup: 10
-setups:
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 1 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: charge
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 2 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: charge
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 4 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: charge
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 8 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: charge
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 10 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: charge
-      consumption_coefficient: 0.1 # kWh/s
diff --git a/evaluation/configs/debug_charge.yaml b/evaluation/configs/debug_charge.yaml
deleted file mode 100644
index 2caeec93fbcc3f50edaa670d3123e474a9c3012d..0000000000000000000000000000000000000000
--- a/evaluation/configs/debug_charge.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: query
-charging_stations: charging_stations.json
-maps:
-  - map.osm
-queries_per_setup: 10
-setups:
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 10 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: time
-      consumption_coefficient: 0.5 # kWh/s
diff --git a/evaluation/configs/example.yaml b/evaluation/configs/example.yaml
deleted file mode 100644
index 723efe1690814eaf3f85c6172e49e07929a7de17..0000000000000000000000000000000000000000
--- a/evaluation/configs/example.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: query
-charging_stations: charging_stations.json
-maps:
-  - map.osm
-queries_per_setup: 10
-setups:
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 1 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 2 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 3 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
diff --git a/evaluation/configs/example_init.yaml b/evaluation/configs/example_init.yaml
deleted file mode 100644
index 0f57289431680a6de00172c98ade34cd93060b91..0000000000000000000000000000000000000000
--- a/evaluation/configs/example_init.yaml
+++ /dev/null
@@ -1,58 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: init
-charging_stations: charging_stations.json
-maps:
-  - medium_nurnberg.osm
-queries_per_setup: 10
-setups:
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 1 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 2 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 4 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 6 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 8 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 10 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-
diff --git a/evaluation/configs/example_init_query.yaml b/evaluation/configs/example_init_query.yaml
deleted file mode 100644
index b8b65a4963d74ba58934fa279bb91d8bddcc4713..0000000000000000000000000000000000000000
--- a/evaluation/configs/example_init_query.yaml
+++ /dev/null
@@ -1,57 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: query
-charging_stations: charging_stations.json
-maps:
-  - medium_nurnberg.osm
-queries_per_setup: 100
-setups:
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 1 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 2 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 4 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 6 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 8 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
-  - mu_s: 300 # Start and Target Soc
-    mu_t: 0
-    charging_stations: 10 # Max Number of charging Stations to be inserted.
-    capacity: 300 # kWh
-    algorithms: [charge]
-    consumption:
-      type: time
-      consumption_coefficient: 0.1 # kWh/s
diff --git a/evaluation/configs/example_rank.yaml b/evaluation/configs/example_rank.yaml
deleted file mode 100644
index a4376273ead7b2811a54c94e51d112d8f5a3e730..0000000000000000000000000000000000000000
--- a/evaluation/configs/example_rank.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-description: >
-  Compare charge and gasstation problem by assuming for the charge
-  algorithm also an consumption proportional to driving time.
-type: rank
-charging_stations: charging_stations.json
-maps:
-  - medium_nurnberg.osm
-queries_per_rank: 20
-ranks: [2, 4, 6, 8, 10, 12, 14, 16]
-setups:
-  - mu_s: 40 # Start and Target Soc
-    mu_t: 0
-    capacity: 40 # kWh
-    consumption:
-      type: distance
-      consumption_coefficient: 0.5 # kWh/km = Wh/m
diff --git a/evaluation/configs/init.yaml b/evaluation/configs/init.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9f534917ca2149cb34d526e39df66d0a79cdceb8
--- /dev/null
+++ b/evaluation/configs/init.yaml
@@ -0,0 +1,15 @@
+type: init
+description: >
+  Compare charge and gasstation problem by assuming for the charge
+  algorithm also an consumption proportional to driving time.
+paths:
+  charging_stations: charging_stations.json
+  map: medium_nurnberg.osm
+queries_per_row: 10
+mu_s: 300 # Start and Target Soc
+mu_t: 0
+capacity: 300 # kWh
+charging_stations: [1, 2, 3]
+consumption:
+  type: time
+  consumption_coefficient: 0.1 # kWh/s
diff --git a/evaluation/configs/init_query.yaml b/evaluation/configs/init_query.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..496b3106f497c4d3f26c08d2fb709350c7708e5d
--- /dev/null
+++ b/evaluation/configs/init_query.yaml
@@ -0,0 +1,16 @@
+type: query
+description: >
+  Compare charge and gasstation problem by assuming for the charge
+  algorithm also an consumption proportional to driving time.
+paths:
+  charging_stations: charging_stations.json
+  map: medium_nurnberg.osm
+queries_per_row: 100
+algorithms: [charge]
+mu_s: 300 # Start and Target Soc
+mu_t: 0
+capacity: 300 # kWh
+charging_stations: [1, 2, 3]
+consumption:
+  type: time
+  consumption_coefficient: 0.1 # kWh/s
diff --git a/evaluation/configs/rank.yaml b/evaluation/configs/rank.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..23723ffe686c700d38d5b73b6dd4bd856cee03e8
--- /dev/null
+++ b/evaluation/configs/rank.yaml
@@ -0,0 +1,16 @@
+type: rank
+description: >
+  Compare charge and gasstation problem by assuming for the charge
+  algorithm also an consumption proportional to driving time.
+paths:
+  charging_stations: charging_stations.json
+  map: medium_nurnberg.osm
+queries_per_rank: 20
+ranks: [10, 12]
+algorithms: [classic, charge]
+mu_s: 40 # Start and Target Soc
+mu_t: 0
+capacity: 40 # kWh
+consumption:
+  type: distance
+  consumption_coefficient: 0.5 # kWh/km = Wh/m
diff --git a/evaluation/lib/benchmarks.py b/evaluation/lib/benchmarks.py
index c7109df35610751e5088bec28558f8c35f9a5142..ac8dc1b3370f4df84a3a6940e6ad4d454a43ea33 100644
--- a/evaluation/lib/benchmarks.py
+++ b/evaluation/lib/benchmarks.py
@@ -1,6 +1,9 @@
 import logging
 import random
+from typing import TextIO, Union, Type
 from time import perf_counter
+from pathlib import Path
+from dataclasses import asdict, fields
 
 import networkx as nx
 from networkx.algorithms.shortest_paths.weighted import _weight_function
@@ -8,21 +11,11 @@ from networkx.algorithms.shortest_paths.weighted import _weight_function
 from evrouting.graph_tools import DISTANCE_KEY
 
 from evaluation.lib.algorithm import _dijkstra_multisource
-from evaluation.lib.export import write_head, write_row
 from evaluation.lib import queries
+from evaluation.lib.config import RankConf, QueryConf, InitConf, AnyConf
 
 logger = logging.getLogger(__name__)
 
-file_names = {
-    queries.classic_query: 'classic.csv',
-    queries.astar_query: 'astar.csv',
-    queries.bidirectional_query: 'bidirectional.csv',
-    queries.charge_query: 'charge.csv',
-    queries.gasstation_query: 'gasstation.csv',
-    queries.init_gasstation_queries: 'init.csv',
-    queries.insert_nodes_into_state_graph: 'insert.csv'
-}
-
 conf_algorithms = {
     'classic': queries.classic_query,
     'astar': queries.astar_query,
@@ -31,6 +24,31 @@ conf_algorithms = {
     'gasstation': queries.gasstation_query
 }
 
+QueryRow = Union[
+    queries.InsertQueryRow,
+    queries.InitQueryRow,
+    queries.ClassicQueryRow,
+    queries.ChargeQueryRow,
+    queries.GasstationQueryRow,
+    queries.AStarQueryRow,
+    queries.QueryRow
+]
+
+SEP = ','
+
+
+def write_head(f: TextIO, row_class: Type[QueryRow]):
+    head = SEP.join([field.name for field in fields(row_class)])
+    f.write(head + '\n')
+
+
+def write_row(f: TextIO, row: QueryRow):
+    f.write(SEP.join([str(i) for i in asdict(row).values()]) + "\n")
+
+
+def fname(algorithm_name: str) -> str:
+    return f'{algorithm_name}.csv'
+
 
 def _insert_charging_stations(graph, charging_stations, number=None):
     start = perf_counter()
@@ -43,29 +61,43 @@ def _insert_charging_stations(graph, charging_stations, number=None):
     ))
 
 
-def _init_result_files(result_dir, q=None):
-    if q is None:
-        q = conf_algorithms.values()
+def _init_result_files(result_dir, conf: AnyConf):
+    files = []
+    if type(conf) == InitConf:
+        files = [
+            (queries.InitQueryRow, 'init.csv'),
+            (queries.InsertQueryRow, 'insert.csv')
+        ]
+    elif type(conf) in [RankConf, QueryConf]:
+        algorithm_map = {
+            'classic': queries.ClassicQueryRow,
+            'astar': queries.AStarQueryRow,
+            'bidirectional': queries.QueryRow,
+            'gassation': queries.GasstationQueryRow,
+            'charge': queries.ChargeQueryRow,
+        }
+        files = [(algorithm_map[alg], fname(alg)) for alg in conf.algorithms]
 
     # Remove existing results and write heads
-    for query in q:
-        with result_dir.joinpath(file_names[query]).open('w') as f:
-            write_head(f, queries.row_classes[query])
+    for row_class, filename in files:
+        with result_dir.joinpath(filename).open('w') as f:
+            write_head(f, row_class)
+
 
+def _run_queries(func, start_nodes, target_nodes, file: TextIO, **kwargs):
+    logger.info(f'Running {len(start_nodes)} times {func.__name__}..')
+    num_total = len(start_nodes)
 
-def _run_queries(graph, start_nodes, target_nodes, setup, q, result_dir):
-    for func in q:
-        logger.info(f'Running {len(start_nodes)} times {func.__name__}')
+    for i, (s, t) in enumerate(zip(start_nodes, target_nodes)):
+        logger.debug(f'{i + 1}/{num_total}')
+        result_data = func(s=s, t=t, **kwargs)
+        write_row(file, result_data)
 
-        for i, (s, t) in enumerate(zip(start_nodes, target_nodes)):
-            logger.debug(f'{i + 1}/{len(start_nodes)}')
-            result_data = func(graph, setup, s, t)
-            with result_dir.joinpath(file_names[func]).open('a') as f:
-                write_row(f, result_data)
-        logger.debug(f'Queries completed.')
-        # Delete cached graphs
-        for key in list(queries.CACHE.keys()):
-            del queries.CACHE[key]
+    # Delete cached graphs
+    for key in list(queries.CACHE.keys()):
+        del queries.CACHE[key]
+
+    logger.debug(f'Queries completed.')
 
 
 def _get_target_with_rank(graph, start_node, rank):
@@ -78,7 +110,7 @@ def _get_target_with_rank(graph, start_node, rank):
     )
 
 
-def _get_ranked_tasks(graph, rank, number):
+def _get_ranked_tasks(G, rank, number):
     """
     Generate <number> start and target nodes with Dijkstra Rank of <rank>.
 
@@ -94,9 +126,9 @@ def _get_ranked_tasks(graph, rank, number):
     # If not enough nodes can be found, return what you have.
     while len(target_nodes) < number and attempts < 3:
         attempts += 1
-        for s in random.sample(list(graph.nodes), number):
+        for s in random.sample(list(G.nodes), number):
             try:
-                target_nodes.append(_get_target_with_rank(graph, s, rank))
+                target_nodes.append(_get_target_with_rank(G, s, rank))
             except nx.NetworkXNoPath:
                 continue
             start_nodes.append(s)
@@ -106,84 +138,75 @@ def _get_ranked_tasks(graph, rank, number):
     return start_nodes, target_nodes
 
 
-def query(graphs, charging_stations, conf, result_dir):
-    _init_result_files(result_dir)
-    for map_name, G in zip(conf['maps'], graphs):
-        for setup in conf['setups']:
-            nodes = random.sample(list(G.nodes), k=2 * conf['queries_per_setup'])
-            # Random start and target nodes
-            start_nodes = nodes[:int(len(nodes) / 2)]
-            target_nodes = nodes[int(len(nodes) / 2):]
-
-            # Random adding of charging stations
-            _insert_charging_stations(G, charging_stations, setup['charging_stations'])
-
-            # Get algorithms for this setup
-            algorithms = setup.get('algorithms', [
-                'classic', 'astar', 'bidirectional', 'gasstation', 'charge'
-            ])
-            q = [conf_algorithms[key] for key in algorithms]
-
-            logger.info(f"Running queries on map {map_name}")
-            _run_queries(G, start_nodes, target_nodes, setup, q, result_dir)
-
-
-def rank(graphs, charging_stations, conf, result_dir):
-    ranks = conf['ranks']
-    queries_per_rank = conf['queries_per_rank']
-    algorithms = ['classic', 'charge']
-    q = [conf_algorithms[k] for k in algorithms]
-
-    _init_result_files(result_dir, q)
-
-    for graph in graphs:
-        _insert_charging_stations(graph, charging_stations)
-
-        for r in ranks:
-            logger.debug(
-                f'Getting {queries_per_rank} target nodes with rank {r}.')
-
-            start = perf_counter()
-            start_nodes, target_nodes = _get_ranked_tasks(graph, r, queries_per_rank)
-            end = perf_counter() - start
-
-            logger.debug(f'Ranked nodes generated in {end:.2f} s')
-
-            for setup in conf['setups']:
-                _run_queries(graph, start_nodes, target_nodes,
-                             setup, q, result_dir)
-
-
-def init(graphs, charging_stations, conf, result_dir):
-    _init_result_files(result_dir, [
-        queries.init_gasstation_queries,
-        queries.insert_nodes_into_state_graph
-    ])
-
-    for map_name, G in zip(conf['maps'], graphs):
-        nodes = random.sample(list(G.nodes), k=2 * conf['queries_per_setup'])
+def query(G, charging_stations, conf: QueryConf, result_dir):
+    _init_result_files(result_dir, conf)
+    for n_cs in conf.charging_stations:
+        # Random start and target nodes
+        nodes = random.sample(list(G.nodes), k=2 * conf.queries_per_row)
         start_nodes = nodes[:int(len(nodes) / 2)]
         target_nodes = nodes[int(len(nodes) / 2):]
 
-        for setup in conf['setups']:
+        # Random adding of n_cs charging stations
+        _insert_charging_stations(G, charging_stations, number=n_cs)
+
+        for alg in conf.algorithms:
+            func = conf_algorithms[alg]
+            filename = result_dir.joinpath(fname(alg))
+            with filename.open('a') as file:
+                _run_queries(func,
+                             start_nodes,
+                             target_nodes,
+                             file,
+                             G=G,
+                             conf=conf)
+
+
+def rank(G, charging_stations, conf: RankConf, result_dir: Path):
+    _init_result_files(result_dir, conf)
+    _insert_charging_stations(G, charging_stations)  # Add all charging stations
+
+    for r in conf.ranks:
+        logger.debug(f'Getting {conf.queries_per_rank} targets with rank {r}.')
+        start = perf_counter()
+        start_nodes, target_nodes = _get_ranked_tasks(G, r, conf.queries_per_rank)
+        end = perf_counter() - start
+        logger.debug(f'Ranked nodes generated in {end:.2f} s')
+
+        for alg in conf.algorithms:
+            func = conf_algorithms[alg]
+            filename = result_dir.joinpath(fname(alg))
+            with filename.open('a') as file:
+                _run_queries(func,
+                             start_nodes,
+                             target_nodes,
+                             file,
+                             G=G,
+                             conf=conf)
+
+
+def init(G, charging_stations, conf: InitConf, result_dir: Path):
+    _init_result_files(result_dir, conf)
+
+    # Nodes for insertion
+    nodes = random.sample(list(G.nodes), k=2 * conf.queries_per_row)
+    start_nodes = nodes[:int(len(nodes) / 2)]
+    target_nodes = nodes[int(len(nodes) / 2):]
+
+    result_init = result_dir.joinpath('init.csv')
+    result_insert = result_dir.joinpath('insert.csv')
+    with result_init.open('a') as out_init, result_insert.open('a') as out_insert:
+        for n_cs in conf.charging_stations:
             # Random adding of charging stations
-            _insert_charging_stations(G, charging_stations, setup['charging_stations'])
-
-            result_data = queries.init_gasstation_queries(G, setup)
-            filename = file_names[queries.init_gasstation_queries]
-            with result_dir.joinpath(filename).open('a') as f:
-                write_row(f, result_data)
+            _insert_charging_stations(G, charging_stations, n_cs)
+            result_data = queries.init_gasstation_queries(G, conf)
+            write_row(out_init, result_data)
 
-            # random start and target nodes of state graph
+            # Make insertion
             _run_queries(
-                G,
+                queries.insert_nodes_into_state_graph,
                 start_nodes,
                 target_nodes,
-                setup,
-                [queries.insert_nodes_into_state_graph],
-                result_dir
-            )
-
-            # Delete cached graphs
-            for key in list(queries.CACHE.keys()):
-                del queries.CACHE[key]
+                out_insert,
+                G=G,
+                conf=conf,
+            )
\ No newline at end of file
diff --git a/evaluation/lib/config.py b/evaluation/lib/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..90e66e9f1746e4985a53650bc0efe71025ac227b
--- /dev/null
+++ b/evaluation/lib/config.py
@@ -0,0 +1,70 @@
+from typing import List, Union
+from dataclasses import dataclass, field
+
+
+@dataclass
+class PathsConf:
+    charging_stations: str
+    map: str
+
+
+@dataclass
+class ConsumptionConf:
+    consumption_coefficient: float
+    type: str
+
+
+@dataclass
+class BaseConf:
+    type: str
+    description: str
+    paths: PathsConf
+    mu_s: float
+    mu_t: float
+    capacity: float
+    consumption: ConsumptionConf
+
+    def __post_init__(self):
+        self.paths = PathsConf(**self.paths)
+        self.consumption = ConsumptionConf(**self.consumption)
+
+
+@dataclass
+class RankConf(BaseConf):
+    queries_per_rank: int
+    ranks: List[int]
+    algorithms: List[str]
+
+
+@dataclass
+class QueryConf(BaseConf):
+    queries_per_row: int
+    charging_stations: List[int]
+    algorithms: List[str] = field(
+        default_factory=[
+            'classic',
+            'astar',
+            'bidirectional',
+            'gasstation',
+            'charge'
+        ])
+
+
+@dataclass
+class InitConf(BaseConf):
+    queries_per_row: int
+    charging_stations: List[int]
+
+
+def apply_conversions(conf: BaseConf):
+    """kWh to Wh"""
+    conf.capacity *= 1000
+    if conf.consumption.type == 'time':
+        conf.consumption.consumption_coefficient *= 1000
+    conf.mu_s *= 1000
+    conf.mu_t *= 1000
+
+    return conf
+
+
+AnyConf = Union[RankConf, QueryConf, InitConf]
diff --git a/evaluation/lib/export.py b/evaluation/lib/export.py
index bcc012ae5844d9240b1e0befa90a7e738c01bff2..8b137891791fe96927ad78e64b0aad7bded08bdc 100644
--- a/evaluation/lib/export.py
+++ b/evaluation/lib/export.py
@@ -1,15 +1 @@
-from typing import TextIO
-from dataclasses import asdict, fields
 
-from evaluation.lib.queries import QueryRow
-
-SEP = ','
-
-
-def write_head(f: TextIO, row_class: QueryRow):
-    head = SEP.join([field.name for field in fields(row_class)])
-    f.write(head + '\n')
-
-
-def write_row(f: TextIO, row: QueryRow):
-    f.write(SEP.join([str(i) for i in asdict(row).values()]) + "\n")
diff --git a/evaluation/lib/queries.py b/evaluation/lib/queries.py
index 508a4138716e11abb68a9e2b92f81d3a894c0b38..1746336fada272066b8ed7a2638e85ad687b2bdc 100644
--- a/evaluation/lib/queries.py
+++ b/evaluation/lib/queries.py
@@ -1,5 +1,6 @@
 import logging
 import gc
+from typing import Union
 from dataclasses import dataclass
 
 from time import perf_counter
@@ -20,6 +21,7 @@ from evrouting.osm.routing import (
 )
 
 from evaluation.lib.algorithm import ranked_dijkstra
+from evaluation.lib.config import InitConf, QueryConf, RankConf, AnyConf
 
 
 @dataclass
@@ -104,7 +106,6 @@ def cached(key):
 
 def no_gc(func):
     """Run func without garbage collection."""
-
     def inner(*args, **kwargs):
         gcold = gc.isenabled()
         gc.disable()
@@ -130,28 +131,28 @@ _cache_state_graph_key = 'state_graph'
 
 
 @cached(_cache_contraction_graph_key)
-def get_contracted_graph(graph, conf, f):
+def get_contracted_graph(G, conf: AnyConf, f):
     start = perf_counter()
     contracted_graph = gasstation.routing.contract_graph(
-        G=graph,
-        charging_stations=graph.charging_stations,
-        capacity=conf['capacity'],
+        G=G,
+        charging_stations=G.charging_stations,
+        capacity=conf.capacity,
         f=f
     )
     contraction_time = perf_counter() - start
     logging.info('Contracted graph with {} stations in {:.2f} s.'.format(
-        len(graph.charging_stations),
+        len(G.charging_stations),
         contraction_time
     ))
     return contracted_graph, contraction_time
 
 
 @cached(_cache_state_graph_key)
-def get_state_graph(contracted_graph, conf, f):
+def get_state_graph(contracted_graph, conf: AnyConf, f):
     start = perf_counter()
     state_graph = gasstation.routing.state_graph(
         contracted_graph,
-        conf['capacity'],
+        conf.capacity,
         f
     )
     state_graph_time = perf_counter() - start
@@ -162,13 +163,13 @@ def get_state_graph(contracted_graph, conf, f):
 
 
 @no_gc
-def init_gasstation_queries(graph, conf):
-    f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient'])
-    contracted_graph, contraction_time = get_contracted_graph(graph, conf, f)
+def init_gasstation_queries(G, conf: InitConf):
+    f = GasstationAccessFunctions(conf.consumption.consumption_coefficient)
+    contracted_graph, contraction_time = get_contracted_graph(G, conf, f)
     state_graph, state_graph_time = get_state_graph(contracted_graph, conf, f)
 
     return InitQueryRow(
-        charging_stations=len(graph.charging_stations),
+        charging_stations=len(G.charging_stations),
         time_contracted_graph=contraction_time,
         time_state_graph=state_graph_time,
         nodes_state_graph=len(state_graph.nodes),
@@ -179,20 +180,20 @@ def init_gasstation_queries(graph, conf):
 
 
 @no_gc
-def insert_nodes_into_state_graph(graph, conf, s, t):
-    f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient'])
-    contracted_graph, contraction_time = get_contracted_graph(graph, conf, f)
+def insert_nodes_into_state_graph(G, conf: InitConf, s, t):
+    f = GasstationAccessFunctions(conf.consumption.consumption_coefficient)
+    contracted_graph, contraction_time = get_contracted_graph(G, conf, f)
     state_graph, state_graph_time = get_state_graph(contracted_graph, conf, f)
 
     start = perf_counter()
     gasstation.routing.insert_start_node(
         s,
-        graph,
+        G,
         contracted_graph,
-        graph.charging_stations,
+        G.charging_stations,
         state_graph,
-        conf['capacity'],
-        conf['mu_s'],
+        conf.capacity,
+        conf.mu_s,
         f
     )
     time_insertion = perf_counter() - start
@@ -200,11 +201,11 @@ def insert_nodes_into_state_graph(graph, conf, s, t):
     start = perf_counter()
     gasstation.routing.insert_final_node(
         t,
-        graph,
-        graph.charging_stations,
+        G,
+        G.charging_stations,
         state_graph,
-        conf['capacity'],
-        conf['mu_t'],
+        conf.capacity,
+        conf.mu_t,
         f
     )
     time_target = perf_counter() - start
@@ -212,27 +213,27 @@ def insert_nodes_into_state_graph(graph, conf, s, t):
     return InsertQueryRow(
         start_node=s,
         target_node=t,
-        charging_stations=len(graph.charging_stations),
+        charging_stations=len(G.charging_stations),
         time_insert_start=time_insertion,
         time_insert_target=time_target
     )
 
 
 @no_gc
-def gasstation_query(graph, conf, s, t):
-    f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient'])
-    contracted_graph, contraction_time = get_contracted_graph(graph, conf, f)
+def gasstation_query(G, conf: Union[QueryRow, RankConf], s, t):
+    f = GasstationAccessFunctions(conf.consumption.consumption_coefficient)
+    contracted_graph, contraction_time = get_contracted_graph(G, conf, f)
     state_graph, state_graph_time = get_state_graph(contracted_graph, conf, f)
 
     start = perf_counter()
     result = gasstation.routing.shortest_path(
-        G=graph,
-        charging_stations=graph.charging_stations,
+        G=G,
+        charging_stations=G.charging_stations,
         s=s,
         t=t,
-        initial_soc=conf['mu_s'],
-        final_soc=conf['mu_t'],
-        capacity=conf['capacity'],
+        initial_soc=conf.mu_s,
+        final_soc=conf.mu_t,
+        capacity=conf.capacity,
         f=f,
         extended_graph=state_graph,
         contracted_graph=contracted_graph
@@ -245,9 +246,9 @@ def gasstation_query(graph, conf, s, t):
         target_node=t,
         query_time=query_time,
         trip_time=result.trip_time,
-        nodes=len(graph.nodes),
-        edges=len(graph.edges),
-        charging_stations=len(graph.charging_stations),
+        nodes=len(G.nodes),
+        edges=len(G.edges),
+        charging_stations=len(G.charging_stations),
         time_contracted_graph=contraction_time,
         time_state_graph=state_graph_time,
         charging_stops=len(charge_stops),
@@ -258,64 +259,66 @@ def gasstation_query(graph, conf, s, t):
 
 
 @no_gc
-def charge_query(graph, conf, s, t):
-    if conf['consumption'].get('type', 'distance') == 'time':
-        c = consumption_function_time_factory(conf['consumption']['consumption_coefficient'])
+def charge_query(G, conf: Union[QueryRow, RankConf], s, t):
+    coefficient = conf.consumption.consumption_coefficient
+    if conf.consumption.type == 'time':
+        c = consumption_function_time_factory(coefficient)
     else:
-        c = consumption_function_distance_factory(conf['consumption']['consumption_coefficient'])
+        c = consumption_function_distance_factory(coefficient)
+
     start = perf_counter()
     result = charge.shortest_path(
-        G=graph,
-        charging_stations=graph.charging_stations,
+        G=G,
+        charging_stations=G.charging_stations,
         s=s,
         t=t,
-        initial_soc=conf['mu_s'],
-        final_soc=conf['mu_t'],
-        capacity=conf['capacity'],
+        initial_soc=conf.mu_s,
+        final_soc=conf.mu_t,
+        capacity=conf.capacity,
         c=c
     )
     runtime = perf_counter() - start
     charge_stops = [t for n, t in result.charge_path if t > 0]
     return ChargeQueryRow(
-        start_node=_format_node(graph, s),
-        target_node=_format_node(graph, s),
+        start_node=s,
+        target_node=t,
         query_time=runtime,
         trip_time=result.trip_time,
-        nodes=len(graph.nodes),
-        edges=len(graph.edges),
-        charging_stations=len(graph.charging_stations),
+        nodes=len(G.nodes),
+        edges=len(G.edges),
+        charging_stations=len(G.charging_stations),
         charging_stops=len(charge_stops),
         charging_time=sum(charge_stops)
     )
 
 
 @no_gc
-def classic_query(graph, conf, s, t):
+def classic_query(G, conf, s, t):
     start = perf_counter()
     try:
-        result, rank = ranked_dijkstra(graph, s, t, weight=DISTANCE_KEY)
+        result, rank = ranked_dijkstra(G, s, t, weight=DISTANCE_KEY)
     except nx.NetworkXNoPath:
         result, rank = None, None
     runtime = perf_counter() - start
 
     return ClassicQueryRow(
-        start_node=_format_node(graph, s),
-        target_node=_format_node(graph, t),
+        start_node=s,
+        target_node=t,
         query_time=runtime,
         trip_time=result,
-        nodes=len(graph.nodes),
-        edges=len(graph.edges),
-        charging_stations=len(graph.charging_stations),
+        nodes=len(G.nodes),
+        edges=len(G.edges),
+        charging_stations=len(G.charging_stations),
         dijkstra_rank=rank
     )
 
 
 @no_gc
-def bidirectional_query(graph, conf, s, t):
+def bidirectional_query(G, conf, s, t):
     start = perf_counter()
     try:
         result, _ = nx.algorithms.bidirectional_dijkstra(
-            graph, s, t, weight=DISTANCE_KEY)
+            G, s, t, weight=DISTANCE_KEY)
     except nx.NetworkXNoPath:
         result = None
     runtime = perf_counter() - start
@@ -325,21 +328,21 @@ def bidirectional_query(graph, conf, s, t):
         target_node=t,
         query_time=runtime,
         trip_time=result,
-        nodes=len(graph.nodes),
-        edges=len(graph.edges),
-        charging_stations=len(graph.charging_stations),
+        nodes=len(G.nodes),
+        edges=len(G.edges),
+        charging_stations=len(G.charging_stations),
     )
 
 
 @no_gc
-def astar_query(graph, conf, s, t):
+def astar_query(G, conf, s, t):
     start = perf_counter()
     try:
         result = nx.astar_path_length(
-            graph,
+            G,
             s, t,
             weight=DISTANCE_KEY,
-            heuristic=a_start_heuristic(graph, car)
+            heuristic=a_start_heuristic(G, car)
         )
     except nx.NetworkXNoPath:
         result = None
@@ -350,18 +353,7 @@ def astar_query(graph, conf, s, t):
         target_node=t,
         query_time=runtime,
         trip_time=result,
-        nodes=len(graph.nodes),
-        edges=len(graph.edges),
-        charging_stations=len(graph.charging_stations)
+        nodes=len(G.nodes),
+        edges=len(G.edges),
+        charging_stations=len(G.charging_stations)
     )
-
-
-row_classes = {
-    classic_query: ClassicQueryRow,
-    astar_query: AStarQueryRow,
-    bidirectional_query: QueryRow,
-    gasstation_query: GasstationQueryRow,
-    charge_query: ChargeQueryRow,
-    init_gasstation_queries: InitQueryRow,
-    insert_nodes_into_state_graph: InsertQueryRow
-}
diff --git a/evaluation/run.py b/evaluation/run.py
index ce244f3d85b5f0809963a4111732d97835b706fd..442350d88606ba9e9e3058af0867165cbf2aabcb 100644
--- a/evaluation/run.py
+++ b/evaluation/run.py
@@ -9,7 +9,13 @@ from pathlib import Path
 import yaml
 
 from evrouting.osm.imports import read_osm
-from evaluation.lib import benchmarks
+from evaluation.lib.config import (
+    InitConf, RankConf, QueryConf, AnyConf, apply_conversions
+)
+from evaluation.lib.benchmarks import init, rank, query
+
+conf_map = {'init': InitConf, 'rank': RankConf, 'query': QueryConf}
+benchmarks_map = {'init': init, 'rank': rank, 'query': query}
 
 
 def get_map(osm_path: Path, backup_dir=None):
@@ -34,15 +40,24 @@ def get_map(osm_path: Path, backup_dir=None):
     return graph
 
 
-def apply_conversions(conf):
-    """kWh to Wh"""
-    for setup in conf['setups']:
-        setup['capacity'] = 1000 * setup['capacity']
-        if setup['consumption'].get('type') == 'time':
-            setup['consumption']['consumption_coefficient'] = \
-                1000 * setup['consumption']['consumption_coefficient']
-        setup['mu_s'] = 1000 * setup['mu_s']
-        setup['mu_t'] = 1000 * setup['mu_t']
+def setup_parser():
+    parser = argparse.ArgumentParser(description='Run Benchmark Scripts.')
+    parser.add_argument(
+        'configs',
+        help='List of filenames to benchmark YAML configs in ./configs.',
+        type=Path,
+        nargs='+'
+    )
+
+    return parser
+
+
+def parse_config(path: Path) -> AnyConf:
+    logging.info(f'Processing {path}..')
+    with base.joinpath('configs/', path).open() as f:
+        conf = yaml.load(f, Loader=yaml.Loader)
+    conf = conf_map[conf['type']](**conf)
+    conf = apply_conversions(conf)
     return conf
 
 
@@ -51,68 +66,29 @@ if __name__ == '__main__':
         format='%(asctime)s %(message)s',
         datefmt='%m/%d/%Y %I:%M:%S %p',
         level=logging.DEBUG)
+    # Directories
     base = Path(__file__).parent
-
     static_dir = base.joinpath('static')
     maps_dir = static_dir.joinpath('maps')
     maps_cache_dir = static_dir.joinpath('mapcache')
-
-    parser = argparse.ArgumentParser(description='Run Benchmark Scripts.')
-    parser.add_argument(
-        '--configs',
-        help='List of filenames to benchmark YAML configs in ./configs.',
-        type=Path,
-        nargs='+'
-    )
-
     r = base.joinpath('results')
     r.mkdir(exist_ok=True)
     r = r.joinpath(datetime.datetime.now().isoformat())
     r.mkdir()
 
-    args = parser.parse_args()
-    path: Path
+    args = setup_parser().parse_args()
     for path in args.configs:
         benchmark_dir = r.joinpath(path.with_suffix(''))
         benchmark_dir.mkdir(exist_ok=True)
 
-        logging.info(f'Processing {path}..')
-        
-        path = path.with_suffix('.yaml')
-
-        with base.joinpath('configs/', path).open() as f:
-            conf = yaml.load(f, Loader=yaml.Loader)
-        conf = apply_conversions(conf)
-
-        graphs = [
-            get_map(maps_dir.joinpath(m), maps_cache_dir)
-            for m in conf['maps']
-        ]
+        conf = parse_config(path.with_suffix('.yaml'))
+        graph = get_map(maps_dir.joinpath(conf.paths.map), maps_cache_dir)
 
-        with static_dir.joinpath(conf['charging_stations']).open() as f:
+        with static_dir.joinpath(conf.paths.charging_stations).open() as f:
             charging_stations = json.load(f)
 
-        if conf['type'] == 'query':
-            results_dir = benchmark_dir.joinpath('queries')
-            results_dir.mkdir(exist_ok=True)
-            benchmarks.query(graphs=graphs,
-                             charging_stations=charging_stations,
-                             conf=conf,
-                             result_dir=results_dir
-                             )
-        elif conf['type'] == 'rank':
-            results_dir = benchmark_dir.joinpath('ranked')
-            results_dir.mkdir(exist_ok=True)
-            benchmarks.rank(graphs=graphs,
-                            charging_stations=charging_stations,
-                            conf=conf,
-                            result_dir=results_dir
-                            )
-        elif conf['type'] == 'init':
-            results_dir = benchmark_dir.joinpath('init')
-            results_dir.mkdir(exist_ok=True)
-            benchmarks.init(graphs=graphs,
-                            charging_stations=charging_stations,
-                            conf=conf,
-                            result_dir=results_dir
-                            )
+        benchmarks_map[conf.type](G=graph,
+                                  charging_stations=charging_stations,
+                                  conf=conf,
+                                  result_dir=benchmark_dir
+                                  )