106 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- encoding: utf-8 -*-
 | |
| 
 | |
| import itertools
 | |
| import re
 | |
| import sys
 | |
| 
 | |
| from docplex.mp.model import Model
 | |
| 
 | |
| lines = sys.stdin.read().splitlines()
 | |
| 
 | |
| pipes: dict[str, tuple[int, list[str]]] = {}
 | |
| for line in lines:
 | |
|     r = re.match(
 | |
|         R"Valve ([A-Z]+) has flow rate=([0-9]+); tunnels? leads? to valves? (.+)",
 | |
|         line,
 | |
|     ).groups()
 | |
| 
 | |
|     pipes[r[0]] = (int(r[1]), r[2].split(", "))
 | |
| 
 | |
| 
 | |
| start_pipe = "AA"
 | |
| max_time = 30
 | |
| 
 | |
| #
 | |
| max_time = 26
 | |
| ee = [0, 1]
 | |
| 
 | |
| m = Model()
 | |
| 
 | |
| present_at = m.binary_var_dict(
 | |
|     (e, t, pipe) for e, t, pipe in itertools.product(ee, range(max_time), pipes)
 | |
| )
 | |
| open_at = m.binary_var_dict(
 | |
|     (e, t, pipe) for e, t, pipe in itertools.product(ee, range(max_time), pipes)
 | |
| )
 | |
| 
 | |
| for e in ee:
 | |
|     m.add_constraint(present_at[e, 0, start_pipe] == 1)
 | |
| 
 | |
| for e, pipe in itertools.product(ee, pipes):
 | |
|     m.add_constraint(open_at[e, 0, pipe] == 0)
 | |
| 
 | |
| for e, t in itertools.product(ee, range(max_time)):
 | |
|     m.add_constraint(m.sum(present_at[e, t, pipe] for pipe in pipes) == 1)
 | |
| 
 | |
| for e, t, pipe in itertools.product(ee, range(1, max_time), pipes):
 | |
|     m.add_constraint(
 | |
|         present_at[e, t, pipe]
 | |
|         <= present_at[e, t - 1, pipe]
 | |
|         + m.sum(present_at[e, t - 1, pipe2] for pipe2 in pipes[pipe][1])
 | |
|     )
 | |
| 
 | |
|     for pipe2 in pipes:
 | |
|         if pipe2 != pipe:
 | |
|             m.add_constraint(present_at[e, t, pipe] <= 1 - open_at[e, t - 1, pipe2])
 | |
| 
 | |
| for e, t, pipe in itertools.product(ee, range(1, max_time), pipes):
 | |
|     m.add_constraint(open_at[e, t, pipe] <= present_at[e, t, pipe])
 | |
| 
 | |
| # keeps flowing
 | |
| flowing_at = m.binary_var_dict(
 | |
|     (t, pipe) for t, pipe in itertools.product(range(max_time), pipes)
 | |
| )
 | |
| 
 | |
| for t, pipe in itertools.product(range(max_time), pipes):
 | |
|     m.add_constraint(
 | |
|         flowing_at[t, pipe]
 | |
|         == m.sum(open_at[e, t2, pipe] for e, t2 in itertools.product(ee, range(0, t)))
 | |
|     )
 | |
| 
 | |
| 
 | |
| # objective
 | |
| m.set_objective(
 | |
|     "max",
 | |
|     m.sum(
 | |
|         flowing_at[t, pipe] * pipes[pipe][0]
 | |
|         for t, pipe in itertools.product(range(max_time), pipes)
 | |
|     ),
 | |
| )
 | |
| 
 | |
| m.log_output = True
 | |
| s = m.solve()
 | |
| 
 | |
| print(s.get_objective_value())
 | |
| 
 | |
| 
 | |
| # for t in range(max_time):
 | |
| #     present = {
 | |
| #         e: [pipe for pipe in pipes if s.get_value(present_at[e, t, pipe]) > 1e-6]
 | |
| #         for e in ee
 | |
| #     }
 | |
| #     opent = {
 | |
| #         e: [pipe for pipe in pipes if s.get_value(open_at[e, t, pipe]) > 1e-6]
 | |
| #         for e in ee
 | |
| #     }
 | |
| #     flowing = [
 | |
| #         pipe
 | |
| #         for pipe in pipes
 | |
| #         if any(s.get_value(flowing_at[e, t, pipe]) > 1e-6 for e in ee)
 | |
| #     ]
 | |
| 
 | |
| #     p = [present[e][0] for e in ee]
 | |
| #     o = [opent[e][0] if opent[e] else "-" for e in ee]
 | |
| 
 | |
| #     print(f"t={t}, at={p}, open={o}, flowing={flowing}")
 |