From a9a010623c75610cafe67d4ce7accc678f94937b Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 11 Jan 2017 18:23:31 +0100 Subject: WIP food delivery --- food_delivery/generate-food.py | 129 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100755 food_delivery/generate-food.py (limited to 'food_delivery/generate-food.py') diff --git a/food_delivery/generate-food.py b/food_delivery/generate-food.py new file mode 100755 index 0000000..0e0295d --- /dev/null +++ b/food_delivery/generate-food.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +import sys + +# Number of steps +m = 64 if len(sys.argv) <= 1 else int(sys.argv[1]) +truck_capacity = 240 if len(sys.argv) <= 2 else int(sys.argv[2]) + +states = "SABCD" + +capacities = [ +None, +120, +160, +100, +120 +] + +# Possible transitions from x to y and the travel cost c. +# trans[x, y] = c +# trans[x, y] = None if there is no such transition. +trans = {} +trans[0, 1] = 15 +trans[0, 3] = 15 +trans[1, 2] = 17 +trans[1, 3] = 12 +trans[2, 3] = 10 +trans[2, 4] = 20 +trans[3, 4] = 20 +# and the other direction +for (x, y), c in dict(trans).items(): + trans[y, x] = c + +if False: + # Print table for debugging + for x in range(len(states)): + for y in range(len(states)): + c = trans.get((x, y)) + if c: + print(" %2d " % c, end="") + else: + print(" -- ", end="") + print("") + +def fillin(cases, template_vars): + if type(cases) == str: + return cases.format(**template_vars) + return [template.format(**template_vars) for template in cases] + +literals = [] +preds = [] + +# s0_j is the current stock of the truck +# s1_j is the current stock of village 1 +for j in range(m + 1): + literals += ["s%d_%d" % (i, j) for i in range(len(states))] + literals += ["l%d" % j] + +# Initially the villages have 80 food, +# the truck is at the supply (l=0), +# and the truck is fully loaded +for i in range(1, len(states)): + preds += ["(= s%d_0 80)" % i] +preds += ["(= l0 0)"] +preds += ["(= s0_0 %d)" % truck_capacity] + +# The truck and village capacity should never drop below zero in any state. +for j in range(m + 1): + for i, capacity in enumerate(capacities): + preds += ["(>= s%d_%d 0)" % (i, j)] + # The village also has a maximum capacity + if i > 0: + preds += ["(<= s%d_%d %d)" % (i, j, capacity)] + +# For every step, any of the edge transitions can be done. +for j in range(1, m + 1): + altpreds = [] + jprev = j - 1 + for (x, y), cost in trans.items(): + # Preds for this choice + cpreds = fillin([ + "(= l{jprev} {x})", + "(= l{j} {y})", + ], vars()) + # Villages other than the next village just lose time + # The new village are additionally restocked. + for i in range(1, len(states)): + newval = "(- s{i}_{jprev} {cost})" + if i == y: + drop = "(- s0_{jprev} s0_{j})" + newval = "(+ %s %s)" % (newval, drop) + cpreds += fillin([ + "(>= %s 0)" % drop, + ], vars()) + cpreds += fillin([ + # Can only do the step if there was sufficient time + "(>= s{i}_{jprev} {cost})", + "(= s{i}_{j} %s)" % newval, + ], vars()) + # If next is truck, restock. + if y == 0: + cpreds += fillin([ + "(= s0_{j} {truck_capacity})", + ], vars()) + altpreds += ["(and %s)" % " ".join(cpreds)] + preds += ["(or %s)" % "\n".join(altpreds)] + +# Begin generator +s = """(benchmark test.smt +:logic QF_UFLIA +:extrafuns ( +""" +s += "\n".join("(%s Int)" % x for x in literals) +s += """ +) +:formula (and +""" +s += "\n".join(preds) +s += """ +)) +""" + +try: + import sys + print(s) + # Hack to avoid printing a ugly error in case stdin of next pipe is closed. + sys.stdout.flush() + sys.stdout.close() +except BrokenPipeError: + pass -- cgit v1.2.1