diff --git a/data.py b/data.py deleted file mode 100644 index ae6724d19dfe19b8164076cf3fb94052f174c01e..0000000000000000000000000000000000000000 --- a/data.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -data.py -""" -import dataclasses - -import numpy as np - - -@dataclasses.dataclass(frozen=True) -class Grid: - points: np.array - no_x: int - no_y: int - - -@dataclasses.dataclass(frozen=True) -class Point: - x: int - y: int diff --git a/scenario.py b/scenario.py deleted file mode 100644 index 1458ce519a74331de14b578cf9dc58cd4eb5fec2..0000000000000000000000000000000000000000 --- a/scenario.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -scenario.py -""" -import dataclasses - -from data import Point - - -@dataclasses.dataclass(frozen=True) -class Radar: - angles: tuple[tuple[float, float], ...] - constant: float - - -@dataclasses.dataclass(frozen=True) -class Aircraft: - name: str - position: Point - direction: tuple[int, int] - radars: tuple[str, ...] - - -@dataclasses.dataclass -class Scenario: - name: str - aircraft: tuple[Aircraft, ...] - no_x: int - no_y: int - - -@dataclasses.dataclass -class DecisionConfig: - no_aircraft: int - max_no_aircraft: int - radar_choices: tuple[Radar] diff --git a/visualise.py b/visualise.py deleted file mode 100644 index 7ec2277461518530187d6648e8ee51f37015e40a..0000000000000000000000000000000000000000 --- a/visualise.py +++ /dev/null @@ -1,225 +0,0 @@ -""" -visualise.py -""" -import math -from typing import Callable -import subprocess - -import numpy as np -from scenario import Aircraft, DecisionConfig, Scenario -import seaborn as sns -import matplotlib.pyplot as plt -import gurobipy - -from data import Grid, Point -from scenario import Scenario, Aircraft, Radar - - -def visualise_grid(grid: list[Grid], name="", show=False): - #for point in grid.points: - # print(point) - - #fig, axs = plt.subplots(ncols=len(grids)) - array = grid_to_np_array(grid) - - ax = sns.heatmap(array, vmin=0, vmax=1)#, ax=axs[num]) - if show: - plt.show() - plt.clf() - else: - plt.savefig(name + ".png") - plt.clf() - print(name) - - -def grid_to_np_array(grid: Grid) -> np.array: - return grid.points - - -def radar_f(points: np.array, center: Point, constant: float) -> np.array: - return 1 / (constant * (1 + ((points[0] - center.x) ** 4 + (points[1] - center.y) ** 4) ** (1 / 4))) - - -def circle_f(points: np.array, center: Point, constant: float) -> np.array: - return 1 / (constant * (1 + ((points[0] - center.x) ** 2 + (points[1] - center.y) ** 2) ** (1 / 2))) - - -def max_grids(grids: list[Grid]) -> Grid: - info = np.maximum.reduce([grid.points for grid in grids]) - - return Grid(info, grids[0].no_x, grids[0].no_y) - - -def degregate_grid(grid: Grid, factor) -> Grid: - info = factor * grid.points - return Grid(info, grid.no_x, grid.no_y) - - -def info_grid(center: Point, angle_ranges: list[tuple[float, float]], f: Callable, constant: float, no_x: int = 300, no_y: int = 300) -> Grid: - zeros = np.zeros([no_x, no_y]) - indices = np.indices([no_x, no_y]) - - angles = 180 + np.arctan2((indices[0] - center.x), (indices[1] - center.y)) * 180 / math.pi - - info = f(indices, center, constant) - grid_points = np.where(angle_ranges[0][0] <= angles, info, zeros) - grid_points = np.where(angles <= angle_ranges[0][1], grid_points, zeros) - - return Grid(grid_points, no_x, no_y) - - -def empty_grid(no_x: int = 300, no_y: int = 300) -> Grid: - return Grid(np.zeros([no_x, no_y]), no_x, no_y) - - -def create_scenario1() -> Scenario: - aircraft1 = Aircraft("Aircraft1", Point(210, 55), (-2, 8), tuple()) - radar = Radar(((130, 200), ), 0.03) - aircraft2 = Aircraft("Aircraft2", Point(200, 15), (-3, 7), tuple([radar])) - aircraft3 = Aircraft("Aircraft3", Point(20, 45), (2, 7), tuple()) - aircraft4 = Aircraft("Aircraft4", Point(30, 25), (3, 8), tuple()) - scenario = Scenario("TestScenario1", (aircraft1, aircraft2, aircraft3, aircraft4), 300, 300) - return scenario - - -def create_scenario1p() -> Scenario: - aircraft1 = Aircraft("Aircraft1", Point(410, 55), (-1, 8), tuple()) - aircraft2 = Aircraft("Aircraft2", Point(400, 15), (-1, 7), tuple()) - aircraft3 = Aircraft("Aircraft3", Point(220, 45), (1, 7), tuple()) - aircraft4 = Aircraft("Aircraft4", Point(230, 25), (1, 8), tuple()) - scenario = Scenario("TestScenario1p", (aircraft1, aircraft2, aircraft3, aircraft4), 600, 600) - return scenario - - -def create_scenario2() -> Scenario: - aircraft1 = Aircraft("Aircraft1", Point(210, 55), (-2, 8), tuple()) - radar = Radar(((130, 200), ), 0.03) - aircraft2 = Aircraft("Aircraft2", Point(200, 15), (-3, 7), tuple([radar])) - aircraft3 = Aircraft("Aircraft3", Point(20, 45), (2, 7), tuple()) - radar = Radar(((150, 220), ), 0.03) - aircraft4 = Aircraft("Aircraft4", Point(30, 25), (3, 8), tuple([radar])) - scenario = Scenario("TestScenario2", (aircraft1, aircraft2, aircraft3, aircraft4), 300, 300) - return scenario - - -def create_scenario3() -> Scenario: - aircraft1 = Aircraft("Aircraft1", Point(210, 55), (-2, 8), tuple()) - radar = Radar(((150, 190), ), 0.02) - aircraft2 = Aircraft("Aircraft2", Point(200, 15), (-3, 7), tuple([radar])) - aircraft3 = Aircraft("Aircraft3", Point(20, 45), (2, 7), tuple()) - radar = Radar(((160, 200), ), 0.02) - aircraft4 = Aircraft("Aircraft4", Point(30, 25), (3, 8), tuple([radar])) - scenario = Scenario("TestScenario3", (aircraft1, aircraft2, aircraft3, aircraft4), 300, 300) - return scenario - - -def run_scenario(scenario: Scenario, time_steps: int = 20) -> None: - time_grid = empty_grid(scenario.no_x, scenario.no_y) - for time in range(time_steps): - grids = [time_grid] - for aircraft in scenario.aircraft: - aircraft_pos = Point(aircraft.position.x + time * aircraft.direction[0], aircraft.position.y + time * aircraft.direction[1]) - aircraft_grid = info_grid(aircraft_pos, [(0, 360)], circle_f, 0.1, scenario.no_x, scenario.no_y) - grids.append(aircraft_grid) - - for radar in aircraft.radars: - radar_grid = info_grid(aircraft_pos, radar.angles, radar_f, radar.constant, scenario.no_x, scenario.no_y) - grids.append(radar_grid) - - time_grid = max_grids(grids) - visualise_grid(time_grid, f"{scenario.name}_{time:03d}") - time_grid = degregate_grid(time_grid, 0.8) - subprocess.call(["convert", "-delay", "20", "-loop", "0", f"{scenario.name}*.png", f"{scenario.name}.gif"]) - - -def run_scenario_with_opt(scenario: Scenario, config: DecisionConfig, time_steps: int = 20) -> None: - time_grid = empty_grid(scenario.no_x, scenario.no_y) - for time in range(time_steps): - grids = [time_grid] - aircraft_pos_list = list() - for aircraft in scenario.aircraft: - aircraft_pos = Point(aircraft.position.x + time * aircraft.direction[0], aircraft.position.y + time * aircraft.direction[1]) - aircraft_grid = info_grid(aircraft_pos, [(0, 360)], circle_f, 0.1, scenario.no_x, scenario.no_y) - grids.append(aircraft_grid) - aircraft_pos_list.append(aircraft_pos) - - time_grid = max_grids(grids) - - decision_grid = optimize_decision(time_grid, aircraft_pos_list, config) - - time_grid = max_grids([time_grid, decision_grid]) - visualise_grid(time_grid, f"{scenario.name}_{time:03d}") - time_grid = degregate_grid(time_grid, 0.8) - subprocess.call(["convert", "-delay", "20", "-loop", "0", f"{scenario.name}*.png", f"{scenario.name}.gif"]) - - -def optimize_decision(basic_grid: Grid, aircraft_positions: list[Point], config: DecisionConfig) -> Grid: - LB = 0.1 - model = gurobipy.Model() - - STEP = 30 - - assert len(aircraft_positions) == config.no_aircraft - - # Calculate grid - print("Calculate grids") - grid_dict = dict() - for aircraft_no, aircraft_pos in enumerate(aircraft_positions): - for radar_no, radar in enumerate(radar_choices): - radar_grid = info_grid(aircraft_pos, radar.angles, radar_f, radar.constant, basic_grid.no_x, basic_grid.no_y) - grid_dict[aircraft_no, radar_no] = radar_grid - - vars = dict() - print("i variables") - for x in range(0, basic_grid.no_x, STEP): - for y in range(0, basic_grid.no_y, STEP): - vars["i", x, y] = model.addVar(obj=-1, name=f"i_({x},{y})", vtype=gurobipy.GRB.BINARY) - - for aircraft_no in range(config.no_aircraft): - for radar_no, _ in enumerate(config.radar_choices): - vars["d", aircraft_no, radar_no] = model.addVar(name=f"d_({aircraft_no},{radar_no}", vtype=gurobipy.GRB.BINARY) - - print("i constraints") - for x in range(0, basic_grid.no_x, STEP): - for y in range(0, basic_grid.no_y, STEP): - i = vars["i", x, y] - info = basic_grid.points[x][y] + sum(grid_dict[aircraft_no, radar_no].points[x][y] * vars["d", aircraft_no, radar_no] for aircraft_no in range(config.no_aircraft) for radar_no in range(len(config.radar_choices))) - expr = info >= LB * i - model.addConstr(expr, name=f"info_({x},{y})") - - # Only one decision per aircraft - for aircraft_no in range(config.no_aircraft): - expr = sum(vars["d", aircraft_no, radar_no] for radar_no in range(len(config.radar_choices))) <= 1 - model.addConstr(expr, name=f"one_decision_per_aircraft_({aircraft_no})") - - expr = sum(vars["d", aircraft_no, radar_no] for radar_no in range(len(config.radar_choices)) for aircraft_no in range(config.no_aircraft)) <= config.max_no_aircraft - model.addConstr(expr, name=f"max_no_radars") - - model.optimize() - - grids = list() - for aircraft_no in range(config.no_aircraft): - for radar_no, _ in enumerate(config.radar_choices): - if round(vars["d", aircraft_no, radar_no].X) == 1: - grids.append(grid_dict[aircraft_no, radar_no]) - - return max_grids(grids) - - -if __name__ == '__main__': - #run_scenario(create_scenario1()) - #run_scenario(create_scenario2()) - #run_scenario(create_scenario3()) - - d1 = info_grid(Point(30, 30), [(160, 200)], radar_f, 0.03) - d2 = info_grid(Point(30, 30), [(150, 210)], radar_f, 0.02) - d3 = info_grid(Point(30, 30), [(140, 180)], radar_f, 0.03) - d4 = info_grid(Point(30, 30), [(170, 230)], radar_f, 0.02) - - radar_choices_narrow = [Radar(((angle, angle + 40), ), 0.02) for angle in range(120, 200, 10)] - radar_choices_normal = [Radar(((angle, angle + 60), ), 0.03) for angle in range(120, 180, 10)] - - radar_choices = tuple(radar_choices_narrow + radar_choices_normal) - config = DecisionConfig(4, 2, radar_choices) - - run_scenario_with_opt(create_scenario1p(), config, 40)