File size: 3,544 Bytes
13a141d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53e926d
 
 
 
 
 
 
 
 
 
 
 
13a141d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import heapq


class SimulationWorld:

    def __init__(self, engine, num_nodes):
        self.engine = engine
        self.num_nodes = num_nodes
        self.rescued_pool = 0

    def get_node_state(self, node_id):
        node = self.engine.get_node_state(node_id)
        if node_id == 0:
            node.survivors = self.rescued_pool
            node.temperature = 20.0
            node.water_level = 0.0
            node.is_collapsed = False
            node.stability = 1.0
            node.status.infra_health = 1.0
            node.pvi = 0.0
            return node

        return node

    def get_neighbors(self, node_id):
        return self.engine.get_neighbors(node_id)

    def allocate_resources(self, node_id, resource, amount):
        self.engine.allocate_resources(node_id, resource, amount)

    def clear_debris(self, node_id, amount):
        self.engine.clear_debris(node_id, amount)

    def apply_impact(self, node_id, t_delta, w_delta, p_delta):
        self.engine.apply_impact(node_id, t_delta, w_delta, p_delta)

    def step(self):
        self.engine.step()

    def notify_extraction(self, node_id, count):
        if node_id == 0:
            return
        actual = self.engine.decrement_survivors(node_id, count)
        if actual > 0:
            self.rescued_pool += actual

    def notify_evacuation(self, node_id, count):
        self.notify_extraction(node_id, count)

    def transfer_survivors(self, source_id, target_id, count):
        if source_id == 0:
            source_count = self.rescued_pool
        else:
            source_count = self.engine.get_node_state(source_id).survivors

        actual = min(count, source_count)

        if source_id == 0:
            self.rescued_pool -= actual
        else:
            self.engine.decrement_survivors(source_id, actual)

        if target_id == 0:
            self.rescued_pool += actual
        else:
            self.engine.increment_survivors(target_id, actual)

        return actual

    def get_snapshot(self):
        return {
            "engine_snapshot": self.engine.get_snapshot(),
            "rescued_pool": self.rescued_pool,
            "num_nodes": self.num_nodes
        }

    def restore_snapshot(self, snapshot):
        self.engine.restore_snapshot(snapshot["engine_snapshot"])
        self.rescued_pool = snapshot["rescued_pool"]
        self.num_nodes = snapshot["num_nodes"]

    def next_hop(self, start: int, target: int):
        if start == target:
            return start
        dist = {start: 0.0}
        parent = {start: None}
        heap = [(0.0, start)]
        while heap:
            cost, node = heapq.heappop(heap)
            if node == target:
                break
            if cost > dist.get(node, float("inf")):
                continue
            for nb in self.get_neighbors(node):
                nb_state = self.get_node_state(nb)
                if nb_state.is_collapsed or nb_state.water_level > 7:
                    continue

                edge_w = 1.0 + (1.0 - nb_state.status.infra_health) * 2.0
                if nb == 0 and target != 0:
                    edge_w += 10.0

                new_cost = cost + edge_w
                if new_cost < dist.get(nb, float("inf")):
                    dist[nb] = new_cost
                    parent[nb] = node
                    heapq.heappush(heap, (new_cost, nb))
        if target not in parent:
            return None
        node = target
        while parent[node] != start:
            node = parent[node]
        return node