From c6b1d35215c3e266ecbee1c7138acd78774fea1c Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Thu, 4 Jul 2024 20:45:42 +0100 Subject: [PATCH 01/42] #2967 - Enhance AirSpace simulation with dynamic environment and bandwidth/channel management This commit introduces several key enhancements to the AirSpace class, improving the realism and configurability of the wireless network. Major additions include the AirSpaceEnvironmentType and ChannelWidth enums, dynamic adjustment of interface speeds based on environmental settings, and comprehensive bandwidth management features. Additionally, the software now supports configuration of channel widths via the config file, incorporates accurate SNR and capacity calculations, and enforces bandwidth limits more effectively across wireless interfaces. Updated tests ensure that the new functionalities integrate seamlessly with existing systems. --- CHANGELOG.md | 35 +- docs/source/configuration/simulation.rst | 13 +- docs/source/simulation.rst | 1 + .../network/airspace.rst | 100 +++ .../network/nodes/wireless_router.rst | 13 +- src/primaite/game/game.py | 6 + src/primaite/simulator/network/airspace.py | 721 +++++++++++++++--- src/primaite/simulator/network/container.py | 2 + .../simulator/network/hardware/base.py | 17 +- .../hardware/nodes/network/wireless_router.py | 26 +- .../network/transmission/data_link_layer.py | 5 +- .../configs/wireless_wan_network_config.yaml | 2 + ...s_wan_wifi_5_80_channel_width_blocked.yaml | 81 ++ ...ess_wan_wifi_5_80_channel_width_urban.yaml | 81 ++ .../test_airspace_capacity_configuration.py | 106 +++ ...ndwidth_load_checks_before_transmission.py | 138 ++++ 16 files changed, 1238 insertions(+), 109 deletions(-) create mode 100644 docs/source/simulation_components/network/airspace.rst create mode 100644 tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml create mode 100644 tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml create mode 100644 tests/integration_tests/network/test_airspace_capacity_configuration.py create mode 100644 tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 17bf3557..0ed09b94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,42 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Added + +- **AirSpaceEnvironmentType Enum Class**: Introduced in `airspace.py` to define different environmental settings affecting wireless network behavior. +- **ChannelWidth Enum Class**: Added in `airspace.py` to specify channel width options for wireless network interfaces. +- **Channel Width Attribute**: Incorporated into the `WirelessNetworkInterface` class to allow dynamic setting based on `AirSpaceFrequency` and `AirSpaceEnvironmentType`. +- **SNR and Capacity Calculation Functions**: Functions `estimate_snr` and `calculate_total_channel_capacity` added to `airspace.py` for computing signal-to-noise ratio and capacity based on frequency and channel width. +- **Dynamic Speed Setting**: WirelessInterface speed attribute now dynamically adjusts based on the operational environment, frequency, and channel width. +- **airspace_key Attribute**: Added to `WirelessNetworkInterface` as a tuple of frequency and channel width, serving as a key for bandwidth/channel management. +- **airspace_environment_type Attribute**: Determines the environmental type for the airspace, influencing data rate calculations and capacity sharing. +- **show_bandwidth_load Function**: Displays current bandwidth load for each frequency and channel width in the airspace. +- **Configuration Schema Update**: The `simulation.network` config file now includes settings for the `airspace_environment_type`. +- **Bandwidth Tracking**: Tracks data transmission across each frequency/channel width pairing. +- **Configuration Support for Wireless Routers**: `channel_width` can now be configured in the config file under `wireless_access_point`. +- **New Tests**: Added to validate the respect of bandwidth capacities and the correct parsing of airspace configurations from YAML files. + +### Changed + +- **NetworkInterface Speed Type**: The `speed` attribute of `NetworkInterface` has been changed from `int` to `float`. +- **Transmission Feasibility Check**: Updated `_can_transmit` function in `Link` to account for current load and total bandwidth capacity, ensuring transmissions do not exceed limits. +- **Frame Size Details**: Frame `size` attribute now includes both core size and payload size in bytes. +- **WirelessRouter Configuration Function**: `configure_wireless_access_point` function now accepts `channel_width` as a parameter. +- **Interface Grouping**: `WirelessNetworkInterfaces` are now grouped by both `AirSpaceFrequency` and `ChannelWidth`. +- **Interface Frequency/Channel Width Adjustment**: Changing an interface's settings now involves removal from the airspace, recalculation of its data rate, and re-addition under new settings. +- **Transmission Blocking**: Enhanced `AirSpace` logic to block transmissions that would exceed the available capacity. + +### Fixed + +- **Transmission Permission Logic**: Corrected the logic in `can_transmit_frame` to accurately prevent overloads by checking if the transmission of a frame stays within allowable bandwidth limits after considering current load. + + +[//]: # (This file needs tidying up between 2.0.0 and this line as it hasn't been segmented into 3.0.0 and 3.1.0 and isn't compliant with https://keepachangelog.com/en/1.1.0/) + ## 3.0.0b9 - Removed deprecated `PrimaiteSession` class. - Added ability to set log levels via configuration. diff --git a/docs/source/configuration/simulation.rst b/docs/source/configuration/simulation.rst index 2bcc8b66..d585711d 100644 --- a/docs/source/configuration/simulation.rst +++ b/docs/source/configuration/simulation.rst @@ -7,7 +7,7 @@ ============== In this section the network layout is defined. This part of the config follows a hierarchical structure. Almost every component defines a ``ref`` field which acts as a human-readable unique identifier, used by other parts of the config, such as agents. -At the top level of the network are ``nodes`` and ``links``. +At the top level of the network are ``nodes``, ``links`` and ``airspace``. e.g. @@ -19,6 +19,9 @@ e.g. ... links: ... + airspace: + ... + ``nodes`` --------- @@ -101,3 +104,11 @@ This accepts an integer value e.g. if port 1 is to be connected, the configurati ``bandwidth`` This is an integer value specifying the allowed bandwidth across the connection. Units are in Mbps. + +``airspace`` +------------ + +This is where the airspace settings for wireless networks arte set. + +``airspace_environment_type`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/source/simulation.rst b/docs/source/simulation.rst index a8870cb4..cc723e40 100644 --- a/docs/source/simulation.rst +++ b/docs/source/simulation.rst @@ -27,6 +27,7 @@ Contents simulation_components/network/nodes/firewall simulation_components/network/switch simulation_components/network/network + simulation_components/network/airspace simulation_components/system/internal_frame_processing simulation_components/system/sys_log simulation_components/system/pcap diff --git a/docs/source/simulation_components/network/airspace.rst b/docs/source/simulation_components/network/airspace.rst new file mode 100644 index 00000000..dcd762d4 --- /dev/null +++ b/docs/source/simulation_components/network/airspace.rst @@ -0,0 +1,100 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + +.. _airspace: + +AirSpace +======== + + +1. Introduction +--------------- + +The AirSpace class is the central component for wireless networks in PrimAITE and is designed to model and manage the behavior and interactions of wireless network interfaces within a simulated wireless network environment. This documentation provides a detailed overview of the AirSpace class, its components, and how they interact to create a realistic simulation of wireless network dynamics. + +2. Overview of the AirSpace System +---------------------------------- + +The AirSpace is a virtual representation of a physical wireless environment, managing multiple wireless network interfaces that simulate devices connected to the wireless network. These interfaces communicate over radio frequencies, with their interactions influenced by various factors modeled within the AirSpace. + +2.1 Key Components +^^^^^^^^^^^^^^^^^^ + +- **Wireless Network Interfaces**: Representations of network interfaces connected physical devices like routers, computers, or IoT devices that can send and receive data wirelessly. +- **Environmental Settings**: Different types of environments (e.g., urban, rural) that affect signal propagation and interference. +- **Channel Management**: Handles channels and their widths (e.g., 20 MHz, 40 MHz) to determine data transmission over different frequencies. +- **Bandwidth Management**: Tracks data transmission over channels to prevent overloading and simulate real-world network congestion. + +3. AirSpace Environment Types +----------------------------- + +The AirspaceEnvironmentType is a critical component that simulates different physical environments: + +- Urban, Suburban, Rural, etc. +- Each type simulates different levels of electromagnetic interference and signal propagation characteristics. +- Changing the AirspaceEnvironmentType impacts data rates by affecting the signal-to-noise ratio (SNR). + +4. Simulation of Environment Changes +------------------------------------ + +When an AirspaceEnvironmentType is set or changed, the AirSpace: + +1. Recalculates the maximum data transmission capacities for all managed frequencies and channel widths. +2. Updates all wireless interfaces to reflect new capacities. + +5. Managing Wireless Network Interfaces +--------------------------------------- + +- Interfaces can be dynamically added or removed. +- Configurations can be changed in real-time. +- The AirSpace handles data transmissions, ensuring data sent by an interface is received by all other interfaces on the same frequency and channel. + +6. Signal-to-Noise Ratio (SNR) Calculation +------------------------------------------ + +SNR is crucial in determining the quality of a wireless communication channel: + +.. math:: + + SNR = \frac{\text{Signal Power}}{\text{Noise Power}} + +- Impacted by environment type, frequency, and channel width +- Higher SNR indicates a clearer signal, leading to higher data transmission rates + +7. Total Channel Capacity Calculation +------------------------------------- + +Channel capacity is calculated using the Shannon-Hartley theorem: + +.. math:: + + C = B \cdot \log_2(1 + SNR) + +Where: + +- C: channel capacity in bits per second (bps) +- B: bandwidth of the channel in hertz (Hz) +- SNR: signal-to-noise ratio + +Implementation in AirSpace: + +1. Convert channel width from MHz to Hz. +2. Recalculate SNR based on new environment or interface settings. +3. Apply Shannon-Hartley theorem to determine new maximum channel capacity in Mbps. + +8. Shared Maximum Capacity Across Devices +----------------------------------------- + +While individual devices have theoretical maximum data rates, the actual achievable rate is often less due to: + +- Shared wireless medium among all devices on the same frequency and channel width +- Interference and congestion from multiple devices transmitting simultaneously + +9. AirSpace Inspection +---------------------- + +The AirSpace class provides methods for visualizing network behavior: + +- ``show_wireless_interfaces()``: Displays current state of all interfaces +- ``show_bandwidth_load()``: Shows channel loads and bandwidth utilization diff --git a/docs/source/simulation_components/network/nodes/wireless_router.rst b/docs/source/simulation_components/network/nodes/wireless_router.rst index 29110a52..eb7f95e3 100644 --- a/docs/source/simulation_components/network/nodes/wireless_router.rst +++ b/docs/source/simulation_components/network/nodes/wireless_router.rst @@ -37,7 +37,7 @@ additional steps to configure wireless settings: .. code-block:: python from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter - from primaite.simulator.network.airspace import AirSpaceFrequency + from primaite.simulator.network.airspace import AirSpaceFrequency, ChannelWidth # Instantiate the WirelessRouter wireless_router = WirelessRouter(hostname="MyWirelessRouter") @@ -49,7 +49,8 @@ additional steps to configure wireless settings: wireless_router.configure_wireless_access_point( port=1, ip_address="192.168.2.1", subnet_mask="255.255.255.0", - frequency=AirSpaceFrequency.WIFI_2_4 + frequency=AirSpaceFrequency.WIFI_2_4, + channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) @@ -71,7 +72,7 @@ ICMP traffic, ensuring basic network connectivity and ping functionality. .. code-block:: python - from primaite.simulator.network.airspace import AIR_SPACE, AirSpaceFrequency + from primaite.simulator.network.airspace import AirSpaceFrequency, ChannelWidth from primaite.simulator.network.container import Network from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.network.router import ACLAction @@ -130,13 +131,15 @@ ICMP traffic, ensuring basic network connectivity and ping functionality. port=1, ip_address="192.168.1.1", subnet_mask="255.255.255.0", - frequency=AirSpaceFrequency.WIFI_2_4 + frequency=AirSpaceFrequency.WIFI_2_4, + channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) router_2.configure_wireless_access_point( port=1, ip_address="192.168.1.2", subnet_mask="255.255.255.0", - frequency=AirSpaceFrequency.WIFI_2_4 + frequency=AirSpaceFrequency.WIFI_2_4, + channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) # Configure routes for inter-router communication diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 8a79d068..38bd3597 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -15,6 +15,7 @@ from primaite.game.agent.scripted_agents.probabilistic_agent import Probabilisti from primaite.game.agent.scripted_agents.random_agent import PeriodicAgent from primaite.game.agent.scripted_agents.tap001 import TAP001 from primaite.game.science import graph_has_cycle, topological_sort +from primaite.simulator.network.airspace import AirspaceEnvironmentType from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC @@ -233,6 +234,11 @@ class PrimaiteGame: simulation_config = cfg.get("simulation", {}) network_config = simulation_config.get("network", {}) + airspace_cfg = network_config.get("airspace", {}) + airspace_environment_type_str = airspace_cfg.get("airspace_environment_type", "urban") + + airspace_environment_type: AirspaceEnvironmentType = AirspaceEnvironmentType(airspace_environment_type_str) + net.airspace.airspace_environment_type = airspace_environment_type nodes_cfg = network_config.get("nodes", []) links_cfg = network_config.get("links", []) diff --git a/src/primaite/simulator/network/airspace.py b/src/primaite/simulator/network/airspace.py index 5fec098b..6060d969 100644 --- a/src/primaite/simulator/network/airspace.py +++ b/src/primaite/simulator/network/airspace.py @@ -3,9 +3,11 @@ from __future__ import annotations from abc import ABC, abstractmethod from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Tuple -from prettytable import PrettyTable +import numpy as np +from prettytable import MARKDOWN, PrettyTable +from pydantic import BaseModel, computed_field, Field, model_validator from primaite import getLogger from primaite.simulator.network.hardware.base import Layer3Interface, NetworkInterface, WiredNetworkInterface @@ -15,90 +17,29 @@ from primaite.simulator.system.core.packet_capture import PacketCapture _LOGGER = getLogger(__name__) -__all__ = ["AirSpaceFrequency", "WirelessNetworkInterface", "IPWirelessNetworkInterface"] +def format_hertz(hertz: float, format_terahertz: bool = False, decimals: int = 3) -> str: + """ + Convert a frequency in Hertz to a formatted string using the most appropriate unit. -class AirSpace: - """Represents a wireless airspace, managing wireless network interfaces and handling wireless transmission.""" + Optionally includes formatting for Terahertz. - def __init__(self): - self._wireless_interfaces: Dict[str, WirelessNetworkInterface] = {} - self._wireless_interfaces_by_frequency: Dict[AirSpaceFrequency, List[WirelessNetworkInterface]] = {} - - def show(self, frequency: Optional[AirSpaceFrequency] = None): - """ - Displays a summary of wireless interfaces in the airspace, optionally filtered by a specific frequency. - - :param frequency: The frequency band to filter devices by. If None, devices for all frequencies are shown. - """ - table = PrettyTable() - table.field_names = ["Connected Node", "MAC Address", "IP Address", "Subnet Mask", "Frequency", "Status"] - - # If a specific frequency is provided, filter by it; otherwise, use all frequencies. - frequencies_to_show = [frequency] if frequency else self._wireless_interfaces_by_frequency.keys() - - for freq in frequencies_to_show: - interfaces = self._wireless_interfaces_by_frequency.get(freq, []) - for interface in interfaces: - status = "Enabled" if interface.enabled else "Disabled" - table.add_row( - [ - interface._connected_node.hostname, # noqa - interface.mac_address, - interface.ip_address if hasattr(interface, "ip_address") else None, - interface.subnet_mask if hasattr(interface, "subnet_mask") else None, - str(freq), - status, - ] - ) - - print(table) - - def add_wireless_interface(self, wireless_interface: WirelessNetworkInterface): - """ - Adds a wireless network interface to the airspace if it's not already present. - - :param wireless_interface: The wireless network interface to be added. - """ - if wireless_interface.mac_address not in self._wireless_interfaces: - self._wireless_interfaces[wireless_interface.mac_address] = wireless_interface - if wireless_interface.frequency not in self._wireless_interfaces_by_frequency: - self._wireless_interfaces_by_frequency[wireless_interface.frequency] = [] - self._wireless_interfaces_by_frequency[wireless_interface.frequency].append(wireless_interface) - - def remove_wireless_interface(self, wireless_interface: WirelessNetworkInterface): - """ - Removes a wireless network interface from the airspace if it's present. - - :param wireless_interface: The wireless network interface to be removed. - """ - if wireless_interface.mac_address in self._wireless_interfaces: - self._wireless_interfaces.pop(wireless_interface.mac_address) - self._wireless_interfaces_by_frequency[wireless_interface.frequency].remove(wireless_interface) - - def clear(self): - """ - Clears all wireless network interfaces and their frequency associations from the airspace. - - After calling this method, the airspace will contain no wireless network interfaces, and transmissions cannot - occur until new interfaces are added again. - """ - self._wireless_interfaces.clear() - self._wireless_interfaces_by_frequency.clear() - - def transmit(self, frame: Frame, sender_network_interface: WirelessNetworkInterface): - """ - Transmits a frame to all enabled wireless network interfaces on a specific frequency within the airspace. - - This ensures that a wireless interface does not receive its own transmission. - - :param frame: The frame to be transmitted. - :param sender_network_interface: The wireless network interface sending the frame. This interface will be - excluded from the list of receivers to prevent it from receiving its own transmission. - """ - for wireless_interface in self._wireless_interfaces_by_frequency.get(sender_network_interface.frequency, []): - if wireless_interface != sender_network_interface and wireless_interface.enabled: - wireless_interface.receive_frame(frame) + :param hertz: Frequency in Hertz. + :param format_terahertz: Whether to format frequency in Terahertz, default is False. + :param decimals: Number of decimal places to round to, default is 3. + :returns: Formatted string with the frequency in the most suitable unit. + """ + format_str = f"{{:.{decimals}f}}" + if format_terahertz and hertz >= 1e12: # Terahertz + return format_str.format(hertz / 1e12) + " THz" + elif hertz >= 1e9: # Gigahertz + return format_str.format(hertz / 1e9) + " GHz" + elif hertz >= 1e6: # Megahertz + return format_str.format(hertz / 1e6) + " MHz" + elif hertz >= 1e3: # Kilohertz + return format_str.format(hertz / 1e3) + " kHz" + else: # Hertz + return format_str.format(hertz) + " Hz" class AirSpaceFrequency(Enum): @@ -110,12 +51,478 @@ class AirSpaceFrequency(Enum): """WiFi 5 GHz. Known for its higher data transmission speeds and reduced interference from other devices.""" def __str__(self) -> str: + hertz_str = format_hertz(hertz=self.value) if self == AirSpaceFrequency.WIFI_2_4: - return "WiFi 2.4 GHz" - elif self == AirSpaceFrequency.WIFI_5: - return "WiFi 5 GHz" - else: - return "Unknown Frequency" + return f"WiFi {hertz_str}" + if self == AirSpaceFrequency.WIFI_5: + return f"WiFi {hertz_str}" + return "Unknown Frequency" + + +class ChannelWidth(Enum): + """ + Enumeration representing the available channel widths in MHz for wireless communications. + + This enum facilitates standardising and validating channel width configurations. + + Attributes: + WIDTH_20_MHZ (int): Represents a channel width of 20 MHz, commonly used for basic + Wi-Fi connectivity with standard range and interference resistance. + WIDTH_40_MHZ (int): Represents a channel width of 40 MHz, offering higher data + throughput at the expense of potentially increased interference. + WIDTH_80_MHZ (int): Represents a channel width of 80 MHz, typically used in modern + Wi-Fi setups for high data rate applications but with higher susceptibility to interference. + WIDTH_160_MHZ (int): Represents a channel width of 160 MHz, used for ultra-high-speed + network applications, providing maximum data throughput with significant + requirements on the spectral environment to minimize interference. + """ + + WIDTH_20_MHZ = 20 + """ + Represents a channel width of 20 MHz, commonly used for basic Wi-Fi connectivity with standard range and + interference resistance + """ + + WIDTH_40_MHZ = 40 + """ + Represents a channel width of 40 MHz, offering higher data throughput at the expense of potentially increased + interference. + """ + + WIDTH_80_MHZ = 80 + """ + Represents a channel width of 80 MHz, typically used in modern Wi-Fi setups for high data rate applications but + with higher susceptibility to interference. + """ + + WIDTH_160_MHZ = 160 + """ + Represents a channel width of 160 MHz, used for ultra-high-speed network applications, providing maximum data + throughput with significant requirements on the spectral environment to minimize interference. + """ + + def __str__(self) -> str: + """ + Returns a string representation of the channel width. + + :return: String in the format of " MHz" indicating the channel width. + """ + return f"{self.value} MHz" + + +AirSpaceKeyType = Tuple[AirSpaceFrequency, ChannelWidth] + + +class AirspaceEnvironmentType(Enum): + """Enum representing different types of airspace environments which affect wireless communication signals.""" + + RURAL = "rural" + """ + A rural environment offers clear channel conditions due to low population density and minimal electronic device + presence. + """ + + OUTDOOR = "outdoor" + """ + Outdoor environments like parks or fields have minimal electronic interference. + """ + + SUBURBAN = "suburban" + """ + Suburban environments strike a balance with fewer electronic interferences than urban but more than rural. + """ + + OFFICE = "office" + """ + Office environments have moderate interference from numerous electronic devices and overlapping networks. + """ + + URBAN = "urban" + """ + Urban environments are characterized by tall buildings and a high density of electronic devices, leading to + significant interference. + """ + + INDUSTRIAL = "industrial" + """ + Industrial areas face high interference from heavy machinery and numerous electronic devices. + """ + + TRANSPORT = "transport" + """ + Environments such as subways and buses where metal structures and high mobility create complex interference + patterns. + """ + + DENSE_URBAN = "dense_urban" + """ + Dense urban areas like city centers have the highest level of signal interference due to the very high density of + buildings and devices. + """ + + JAMMING_ZONE = "jamming_zone" + """ + A jamming zone environment where signals are actively interfered with, typically through the use of signal jammers + or scrambling devices. This represents the environment with the highest level of interference. + """ + + BLOCKED = "blocked" + """ + A jamming zone environment with total levels of interference. Airspace is completely blocked. + """ + + @property + def snr_impact(self) -> int: + """ + Returns the SNR impact associated with the environment. + + :return: SNR impact in dB. + """ + impacts = { + AirspaceEnvironmentType.RURAL: 0, + AirspaceEnvironmentType.OUTDOOR: 1, + AirspaceEnvironmentType.SUBURBAN: -5, + AirspaceEnvironmentType.OFFICE: -7, + AirspaceEnvironmentType.URBAN: -10, + AirspaceEnvironmentType.INDUSTRIAL: -15, + AirspaceEnvironmentType.TRANSPORT: -12, + AirspaceEnvironmentType.DENSE_URBAN: -20, + AirspaceEnvironmentType.JAMMING_ZONE: -40, + AirspaceEnvironmentType.BLOCKED: -100, + } + return impacts[self] + + def __str__(self) -> str: + return f"{self.value.title()} Environment (SNR Impact: {self.snr_impact})" + + +def estimate_snr( + frequency: AirSpaceFrequency, environment_type: AirspaceEnvironmentType, channel_width: ChannelWidth +) -> float: + """ + Estimate the Signal-to-Noise Ratio (SNR) based on the communication frequency, environment, and channel width. + + This function considers both the base SNR value dependent on the frequency and the impact of environmental + factors and channel width on the SNR. + + The SNR is adjusted by reducing it for wider channels, reflecting the increased noise floor from a broader + frequency range. + + :param frequency: The operating frequency as defined by AirSpaceFrequency enum, influencing the base SNR. Higher + frequencies like 5 GHz generally start with a higher base SNR due to less noise. + :param environment_type: The type of environment from AirspaceEnvironmentType enum, which adjusts the SNR based on + expected environmental noise and interference levels. + :param channel_width: The channel width from ChannelWidth enum, where wider channels (80 MHz and 160 MHz) decrease + the SNR slightly due to an increased noise floor. + :return: Estimated SNR in dB, calculated as the base SNR modified by environmental and channel width impacts. + """ + base_snr = 40 if frequency == AirSpaceFrequency.WIFI_5 else 30 + snr_impact = environment_type.snr_impact + + # Adjust SNR impact based on channel width + if channel_width == ChannelWidth.WIDTH_80_MHZ or channel_width == ChannelWidth.WIDTH_160_MHZ: + snr_impact -= 3 # Assume wider channels have slightly lower SNR due to increased noise floor + + return base_snr + snr_impact + + +def calculate_total_channel_capacity( + channel_width: ChannelWidth, frequency: AirSpaceFrequency, environment_type: AirspaceEnvironmentType +) -> float: + """ + Calculate the total theoretical data rate for the channel using the Shannon-Hartley theorem. + + This function determines the channel's capacity by considering the bandwidth (derived from channel width), + and the signal-to-noise ratio (SNR) adjusted by frequency and environmental conditions. + + The Shannon-Hartley theorem states that channel capacity C (in bits per second) can be calculated as: + ``C = B * log2(1 + SNR)`` where B is the bandwidth in Hertz and SNR is the signal-to-noise ratio. + + :param channel_width: The width of the channel as defined by ChannelWidth enum, converted to Hz for calculation. + :param frequency: The operating frequency as defined by AirSpaceFrequency enum, influencing the base SNR and part + of the SNR estimation. + :param environment_type: The type of environment as defined by AirspaceEnvironmentType enum, used in SNR estimation. + :return: Theoretical total data rate in Mbps for the entire channel. + """ + bandwidth_hz = channel_width.value * 1_000_000 # Convert MHz to Hz + snr_db = estimate_snr(frequency, environment_type, channel_width) + snr_linear = 10 ** (snr_db / 10) + + total_capacity_bps = bandwidth_hz * np.log2(1 + snr_linear) + total_capacity_mbps = total_capacity_bps / 1_000_000 + + return total_capacity_mbps + + +def calculate_individual_device_rate( + channel_width: ChannelWidth, + frequency: AirSpaceFrequency, + environment_type: AirspaceEnvironmentType, + device_count: int, +) -> float: + """ + Calculate the theoretical data rate available to each individual device on the channel. + + This function first calculates the total channel capacity and then divides this capacity by the number + of active devices to estimate each device's share of the bandwidth. This reflects the practical limitation + that multiple devices must share the same channel resources. + + :param channel_width: The channel width as defined by ChannelWidth enum, used in total capacity calculation. + :param frequency: The operating frequency as defined by AirSpaceFrequency enum, used in total capacity calculation. + :param environment_type: The environment type as defined by AirspaceEnvironmentType enum, impacting SNR and + capacity. + :param device_count: The number of devices sharing the channel. If zero, returns zero to avoid division by zero. + :return: Theoretical data rate in Mbps available per device, based on shared channel capacity. + """ + total_capacity_mbps = calculate_total_channel_capacity(channel_width, frequency, environment_type) + if device_count == 0: + return 0 # Avoid division by zero + individual_device_rate_mbps = total_capacity_mbps / device_count + + return individual_device_rate_mbps + + +class AirSpace(BaseModel): + """ + Represents a wireless airspace, managing wireless network interfaces and handling wireless transmission. + + This class provides functionalities to manage a collection of wireless network interfaces, each associated with + specific frequencies and channel widths. It includes methods to calculate and manage bandwidth loads, add and + remove wireless interfaces, and handle data transmission across these interfaces. + """ + + airspace_environment_type_: AirspaceEnvironmentType = AirspaceEnvironmentType.URBAN + wireless_interfaces: Dict[str, WirelessNetworkInterface] = Field(default_factory=lambda: {}) + wireless_interfaces_by_frequency_channel_width: Dict[AirSpaceKeyType, List[WirelessNetworkInterface]] = Field( + default_factory=lambda: {} + ) + bandwidth_load: Dict[AirSpaceKeyType, float] = Field(default_factory=lambda: {}) + frequency_channel_width_max_capacity_mbps: Dict[AirSpaceKeyType, float] = Field(default_factory=lambda: {}) + + def model_post_init(self, __context: Any) -> None: + """ + Initialize the airspace metadata after instantiation. + + This method is called to set up initial configurations like the maximum capacity of each channel width and + frequency based on the current environment setting. + + :param __context: Contextual data or settings, typically used for further initializations beyond + the basic constructor. + """ + self._set_frequency_channel_width_max_capacity_mbps() + + def _set_frequency_channel_width_max_capacity_mbps(self): + """ + Private method to compute and set the maximum channel capacity in Mbps for each frequency and channel width. + + Based on the airspace environment type, this method calculates the maximum possible data transmission + capacity for each combination of frequency and channel width available and stores these values. + These capacities are critical for managing and limiting bandwidth load during operations. + """ + print( + f"Rebuilding the frequency channel width maximum capacity dictionary based on " + f"airspace environment type {self.airspace_environment_type_}" + ) + for frequency in AirSpaceFrequency: + for channel_width in ChannelWidth: + max_capacity = calculate_total_channel_capacity( + frequency=frequency, channel_width=channel_width, environment_type=self.airspace_environment_type + ) + self.frequency_channel_width_max_capacity_mbps[frequency, channel_width] = max_capacity + + @computed_field + @property + def airspace_environment_type(self) -> AirspaceEnvironmentType: + """ + Gets the current environment type of the airspace. + + :return: The AirspaceEnvironmentType representing the current environment type. + """ + return self.airspace_environment_type_ + + @airspace_environment_type.setter + def airspace_environment_type(self, value: AirspaceEnvironmentType) -> None: + """ + Sets a new environment type for the airspace and updates related configurations. + + Changing the environment type triggers a re-calculation of the maximum channel capacities and + adjustments to the current setup of wireless interfaces to ensure they are aligned with the + new environment settings. + + :param value: The new environment type as an AirspaceEnvironmentType. + """ + if value != self.airspace_environment_type_: + print(f"Setting airspace_environment_type to {value}") + self.airspace_environment_type_ = value + self._set_frequency_channel_width_max_capacity_mbps() + wireless_interface_keys = list(self.wireless_interfaces.keys()) + for wireless_interface_key in wireless_interface_keys: + wireless_interface = self.wireless_interfaces[wireless_interface_key] + self.remove_wireless_interface(wireless_interface) + self.add_wireless_interface(wireless_interface) + + def show_bandwidth_load(self, markdown: bool = False): + """ + Prints a table of the current bandwidth load for each frequency and channel width combination on the airspace. + + This method prints a tabulated view showing the utilisation of available bandwidth capacities for all configured + frequency and channel width pairings. The table includes the current capacity usage as a percentage of the + maximum capacity, alongside the absolute maximum capacity values in Mbps. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = ["Frequency", "Channel Width", "Current Capacity (%)", "Maximum Capacity (Mbit)"] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = "Airspace Frequency Channel Loads" + for key, load in self.bandwidth_load.items(): + frequency, channel_width = key + maximum_capacity = self.frequency_channel_width_max_capacity_mbps[key] + load_percent = load / maximum_capacity + if load_percent > 1.0: + load_percent = 1.0 + table.add_row( + [format_hertz(frequency.value), str(channel_width), f"{load_percent:.0%}", f"{maximum_capacity:.3f}"] + ) + print(table) + + def show_wireless_interfaces(self, markdown: bool = False): + """ + Prints a table of wireless interfaces in the airspace. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = [ + "Connected Node", + "MAC Address", + "IP Address", + "Subnet Mask", + "Frequency", + "Channel Width", + "Speed (Mbps)", + "Status", + ] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"Devices on Air Space - {self.airspace_environment_type}" + + for interface in self.wireless_interfaces.values(): + status = "Enabled" if interface.enabled else "Disabled" + table.add_row( + [ + interface._connected_node.hostname, # noqa + interface.mac_address, + interface.ip_address if hasattr(interface, "ip_address") else None, + interface.subnet_mask if hasattr(interface, "subnet_mask") else None, + format_hertz(interface.frequency.value), + str(interface.channel_width), + f"{interface.speed:.3f}", + status, + ] + ) + print(table.get_string(sortby="Frequency")) + + def show(self, markdown: bool = False): + """ + Prints a summary of the current state of the airspace, including both wireless interfaces and bandwidth loads. + + This method is a convenient wrapper that calls two separate methods to display detailed tables: one for + wireless interfaces and another for bandwidth load across all frequencies and channel widths managed within the + airspace. It provides a holistic view of the operational status and performance metrics of the airspace. + + :param markdown: Flag indicating if output should be in markdown format. + """ + self.show_wireless_interfaces(markdown) + self.show_bandwidth_load(markdown) + + def add_wireless_interface(self, wireless_interface: WirelessNetworkInterface): + """ + Adds a wireless network interface to the airspace if it's not already present. + + :param wireless_interface: The wireless network interface to be added. + """ + if wireless_interface.mac_address not in self.wireless_interfaces: + self.wireless_interfaces[wireless_interface.mac_address] = wireless_interface + if wireless_interface.airspace_key not in self.wireless_interfaces_by_frequency_channel_width: + self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key] = [] + self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key].append( + wireless_interface + ) + speed = calculate_total_channel_capacity( + wireless_interface.channel_width, wireless_interface.frequency, self.airspace_environment_type + ) + wireless_interface.set_speed(speed) + + def remove_wireless_interface(self, wireless_interface: WirelessNetworkInterface): + """ + Removes a wireless network interface from the airspace if it's present. + + :param wireless_interface: The wireless network interface to be removed. + """ + if wireless_interface.mac_address in self.wireless_interfaces: + self.wireless_interfaces.pop(wireless_interface.mac_address) + self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key].remove( + wireless_interface + ) + + def clear(self): + """ + Clears all wireless network interfaces and their frequency associations from the airspace. + + After calling this method, the airspace will contain no wireless network interfaces, and transmissions cannot + occur until new interfaces are added again. + """ + self.wireless_interfaces.clear() + self.wireless_interfaces_by_frequency_channel_width.clear() + + def reset_bandwidth_load(self): + """ + Resets the bandwidth load tracking for all frequencies in the airspace. + + This method clears the current load metrics for all operating frequencies, effectively setting the load to zero. + """ + self.bandwidth_load = {} + + def can_transmit_frame(self, frame: Frame, sender_network_interface: WirelessNetworkInterface) -> bool: + """ + Determines if a frame can be transmitted by the sender network interface based on the current bandwidth load. + + This method checks if adding the size of the frame to the current bandwidth load of the frequency used by the + sender network interface would exceed the maximum allowed bandwidth for that frequency. It returns True if the + frame can be transmitted without exceeding the limit, and False otherwise. + + :param frame: The frame to be transmitted, used to check its size against the frequency's bandwidth limit. + :param sender_network_interface: The network interface attempting to transmit the frame, used to determine the + relevant frequency and its current bandwidth load. + :return: True if the frame can be transmitted within the bandwidth limit, False if it would exceed the limit. + """ + if sender_network_interface.airspace_key not in self.bandwidth_load: + self.bandwidth_load[sender_network_interface.airspace_key] = 0.0 + return ( + self.bandwidth_load[sender_network_interface.airspace_key] + frame.size_Mbits + <= self.frequency_channel_width_max_capacity_mbps[sender_network_interface.airspace_key] + ) + + def transmit(self, frame: Frame, sender_network_interface: WirelessNetworkInterface): + """ + Transmits a frame to all enabled wireless network interfaces on a specific frequency within the airspace. + + This ensures that a wireless interface does not receive its own transmission. + + :param frame: The frame to be transmitted. + :param sender_network_interface: The wireless network interface sending the frame. This interface will be + excluded from the list of receivers to prevent it from receiving its own transmission. + """ + self.bandwidth_load[sender_network_interface.airspace_key] += frame.size_Mbits + for wireless_interface in self.wireless_interfaces_by_frequency_channel_width.get( + sender_network_interface.airspace_key, [] + ): + if wireless_interface != sender_network_interface and wireless_interface.enabled: + wireless_interface.receive_frame(frame) class WirelessNetworkInterface(NetworkInterface, ABC): @@ -139,7 +546,135 @@ class WirelessNetworkInterface(NetworkInterface, ABC): """ airspace: AirSpace - frequency: AirSpaceFrequency = AirSpaceFrequency.WIFI_2_4 + frequency_: AirSpaceFrequency = AirSpaceFrequency.WIFI_2_4 + channel_width_: ChannelWidth = ChannelWidth.WIDTH_40_MHZ + + @model_validator(mode="after") # noqa + def validate_channel_width_for_2_4_ghz(self) -> "WirelessNetworkInterface": + """ + Validate the wireless interface's channel width settings after model changes. + + This method serves as a model validator to ensure that the channel width settings for the 2.4 GHz frequency + comply with accepted standards (either 20 MHz or 40 MHz). It's triggered after model instantiation. + + Ensures that the channel width is appropriate for the current frequency setting, particularly checking + and adjusting the settings for the 2.4 GHz frequency band to not exceed 40 MHz. This is crucial for + avoiding interference and ensuring optimal performance in densely populated wireless environments. + """ + self._check_wifi_24_channel_width() + return self + + def model_post_init(self, __context: Any) -> None: + """Initialise the model after its creation, setting the speed based on the calculated channel capacity.""" + speed = calculate_total_channel_capacity( + channel_width=self.channel_width, + frequency=self.frequency, + environment_type=self.airspace.airspace_environment_type, + ) + self.set_speed(speed) + + def _check_wifi_24_channel_width(self) -> None: + """ + Ensures that the channel width for 2.4 GHz frequency does not exceed 40 MHz. + + This method checks the current frequency and channel width settings and adjusts the channel width + to 40 MHz if the frequency is set to 2.4 GHz and the channel width exceeds 40 MHz. This is done to + comply with typical Wi-Fi standards for 2.4 GHz frequencies, which commonly support up to 40 MHz. + + Logs a SysLog warning if the channel width had to be adjusted, logging this change either to the connected + node's system log or the global logger, depending on whether the interface is connected to a node. + """ + if self.frequency_ == AirSpaceFrequency.WIFI_2_4 and self.channel_width_.value > 40: + self.channel_width_ = ChannelWidth.WIDTH_40_MHZ + msg = ( + f"Channel width must be either 20 Mhz or 40 Mhz when using {AirSpaceFrequency.WIFI_2_4}. " + f"Overriding value to use {ChannelWidth.WIDTH_40_MHZ}." + ) + if self._connected_node: + self._connected_node.sys_log.warning(f"Wireless Interface {self.port_num}: {msg}") + else: + _LOGGER.warning(msg) + + @computed_field + @property + def frequency(self) -> AirSpaceFrequency: + """ + Get the current operating frequency of the wireless interface. + + :return: The current frequency as an AirSpaceFrequency enum value. + """ + return self.frequency_ + + @frequency.setter + def frequency(self, value: AirSpaceFrequency) -> None: + """ + Set the operating frequency of the wireless interface and update the network configuration. + + This setter updates the frequency of the wireless interface if the new value differs from the current setting. + It handles the update by first removing the interface from the current airspace management to avoid conflicts, + setting the new frequency, ensuring the channel width remains compliant, and then re-adding the interface + to the airspace with the new settings. + + :param value: The new frequency to set, as an AirSpaceFrequency enum value. + """ + if value != self.frequency_: + self.airspace.remove_wireless_interface(self) + self.frequency_ = value + self._check_wifi_24_channel_width() + self.airspace.add_wireless_interface(self) + + @computed_field + @property + def channel_width(self) -> ChannelWidth: + """ + Get the current channel width setting of the wireless interface. + + :return: The current channel width as a ChannelWidth enum value. + """ + return self.channel_width_ + + @channel_width.setter + def channel_width(self, value: ChannelWidth) -> None: + """ + Set the channel width of the wireless interface and manage configuration compliance. + + Updates the channel width of the wireless interface. If the new channel width is different from the existing + one, it first removes the interface from the airspace to prevent configuration conflicts, sets the new channel + width, checks and adjusts it if necessary (especially for 2.4 GHz frequency to comply with typical standards), + and then re-registers the interface in the airspace with updated settings. + + :param value: The new channel width to set, as a ChannelWidth enum value. + """ + if value != self.channel_width_: + self.airspace.remove_wireless_interface(self) + self.channel_width_ = value + self._check_wifi_24_channel_width() + self.airspace.add_wireless_interface(self) + + @property + def airspace_key(self) -> tuple: + """ + The airspace bandwidth/channel identifier for the wireless interface based on its frequency and channel width. + + :return: A tuple containing the frequency and channel width, serving as a bandwidth/channel key. + """ + return self.frequency_, self.channel_width_ + + def set_speed(self, speed: float): + """ + Sets the network interface speed to the specified value and logs this action. + + This method updates the speed attribute of the network interface to the given value, reflecting + the theoretical maximum data rate that the interface can support based on the current settings. + It logs the new speed to the system log of the connected node if available. + + :param speed: The speed in Mbps to be set for the network interface. + """ + self.speed = speed + if self._connected_node: + self._connected_node.sys_log.info( + f"Wireless Interface {self.port_num}: Setting theoretical maximum data rate to {speed:.3f} Mbps." + ) def enable(self): """Attempt to enable the network interface.""" @@ -188,8 +723,12 @@ class WirelessNetworkInterface(NetworkInterface, ABC): if self.enabled: frame.set_sent_timestamp() self.pcap.capture_outbound(frame) - self.airspace.transmit(frame, self) - return True + if self.airspace.can_transmit_frame(frame, self): + self.airspace.transmit(frame, self) + return True + else: + # Cannot send Frame as the frequency bandwidth is at capacity + return False # Cannot send Frame as the network interface is not enabled return False diff --git a/src/primaite/simulator/network/container.py b/src/primaite/simulator/network/container.py index 2b9f3e53..0408acde 100644 --- a/src/primaite/simulator/network/container.py +++ b/src/primaite/simulator/network/container.py @@ -96,6 +96,8 @@ class Network(SimComponent): """Apply pre-timestep logic.""" super().pre_timestep(timestep) + self.airspace.reset_bandwidth_load() + for node in self.nodes.values(): node.pre_timestep(timestep) diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 01745215..743b2e76 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -87,7 +87,7 @@ class NetworkInterface(SimComponent, ABC): mac_address: str = Field(default_factory=generate_mac_address) "The MAC address of the interface." - speed: int = 100 + speed: float = 100.0 "The speed of the interface in Mbps. Default is 100 Mbps." mtu: int = 1500 @@ -679,11 +679,20 @@ class Link(SimComponent): return self.endpoint_a.enabled and self.endpoint_b.enabled def _can_transmit(self, frame: Frame) -> bool: + """ + Determines whether a frame can be transmitted considering the current Link load and the Link's bandwidth. + + This method assesses if the transmission of a given frame is possible without exceeding the Link's total + bandwidth capacity. It checks if the current load of the Link plus the size of the frame (expressed in Mbps) + would remain within the defined bandwidth limits. The transmission is only feasible if the Link is active + ('up') and the total load including the new frame does not surpass the bandwidth limit. + + :param frame: The frame intended for transmission, which contains its size in Mbps. + :return: True if the frame can be transmitted without exceeding the bandwidth limit, False otherwise. + """ if self.is_up: frame_size_Mbits = frame.size_Mbits # noqa - Leaving it as Mbits as this is how they're expressed - # return self.current_load + frame_size_Mbits <= self.bandwidth - # TODO: re add this check once packet size limiting and MTU checks are implemented - return True + return self.current_load + frame.size_Mbits <= self.bandwidth return False def transmit_frame(self, sender_nic: WiredNetworkInterface, frame: Frame) -> bool: diff --git a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py index e329f7a1..dda9e4f8 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py @@ -1,10 +1,10 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from ipaddress import IPv4Address -from typing import Any, Dict, Union +from typing import Any, Dict, Optional, Union from pydantic import validate_call -from primaite.simulator.network.airspace import AirSpace, AirSpaceFrequency, IPWirelessNetworkInterface +from primaite.simulator.network.airspace import AirSpace, AirSpaceFrequency, ChannelWidth, IPWirelessNetworkInterface from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router, RouterInterface from primaite.simulator.network.transmission.data_link_layer import Frame @@ -153,7 +153,8 @@ class WirelessRouter(Router): self, ip_address: IPV4Address, subnet_mask: IPV4Address, - frequency: AirSpaceFrequency = AirSpaceFrequency.WIFI_2_4, + frequency: Optional[AirSpaceFrequency] = AirSpaceFrequency.WIFI_2_4, + channel_width: Optional[ChannelWidth] = ChannelWidth.WIDTH_40_MHZ, ): """ Configures a wireless access point (WAP). @@ -170,13 +171,23 @@ class WirelessRouter(Router): enum. This determines the frequency band (e.g., 2.4 GHz or 5 GHz) the access point will use for wireless communication. Default is AirSpaceFrequency.WIFI_2_4. """ + if not frequency: + frequency = AirSpaceFrequency.WIFI_2_4 + if not channel_width: + channel_width = ChannelWidth.WIDTH_40_MHZ + self.sys_log.info("Configuring wireless access point") + self.wireless_access_point.disable() # Temporarily disable the WAP for reconfiguration + network_interface = self.network_interface[1] + network_interface.ip_address = ip_address network_interface.subnet_mask = subnet_mask - self.sys_log.info(f"Configured WAP {network_interface}") + self.wireless_access_point.frequency = frequency # Set operating frequency + self.wireless_access_point.channel_width = channel_width self.wireless_access_point.enable() # Re-enable the WAP with new settings + self.sys_log.info(f"Configured WAP {network_interface}") @property def router_interface(self) -> RouterInterface: @@ -258,7 +269,12 @@ class WirelessRouter(Router): ip_address = cfg["wireless_access_point"]["ip_address"] subnet_mask = cfg["wireless_access_point"]["subnet_mask"] frequency = AirSpaceFrequency[cfg["wireless_access_point"]["frequency"]] - router.configure_wireless_access_point(ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency) + channel_width = cfg["wireless_access_point"].get("channel_width") + if channel_width: + channel_width = ChannelWidth(channel_width) + router.configure_wireless_access_point( + ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency, channel_width=channel_width + ) if "acl" in cfg: for r_num, r_cfg in cfg["acl"].items(): diff --git a/src/primaite/simulator/network/transmission/data_link_layer.py b/src/primaite/simulator/network/transmission/data_link_layer.py index 776a5bfb..159eca7f 100644 --- a/src/primaite/simulator/network/transmission/data_link_layer.py +++ b/src/primaite/simulator/network/transmission/data_link_layer.py @@ -133,10 +133,11 @@ class Frame(BaseModel): def size(self) -> float: # noqa - Keep it as MBits as this is how they're expressed """The size of the Frame in Bytes.""" # get the payload size if it is a data packet + payload_size = 0.0 if isinstance(self.payload, DataPacket): - return self.payload.get_packet_size() + payload_size = self.payload.get_packet_size() - return float(len(self.model_dump_json().encode("utf-8"))) + return float(len(self.model_dump_json().encode("utf-8"))) + payload_size @property def size_Mbits(self) -> float: # noqa - Keep it as MBits as this is how they're expressed diff --git a/tests/assets/configs/wireless_wan_network_config.yaml b/tests/assets/configs/wireless_wan_network_config.yaml index c8f61bad..684acaf7 100644 --- a/tests/assets/configs/wireless_wan_network_config.yaml +++ b/tests/assets/configs/wireless_wan_network_config.yaml @@ -9,6 +9,8 @@ game: simulation: network: + airspace: + airspace_environment_type: blocked nodes: - type: computer hostname: pc_a diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml new file mode 100644 index 00000000..21b0fe5e --- /dev/null +++ b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml @@ -0,0 +1,81 @@ +game: + max_episode_length: 256 + ports: + - ARP + protocols: + - ICMP + - TCP + - UDP + +simulation: + network: + airspace: + airspace_environment_type: blocked + nodes: + - type: computer + hostname: pc_a + ip_address: 192.168.0.2 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.0.1 + start_up_duration: 0 + + - type: computer + hostname: pc_b + ip_address: 192.168.2.2 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.2.1 + start_up_duration: 0 + + - type: wireless_router + hostname: router_1 + start_up_duration: 0 + + router_interface: + ip_address: 192.168.0.1 + subnet_mask: 255.255.255.0 + + wireless_access_point: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + frequency: WIFI_5 + channel_width: 80 + acl: + 1: + action: PERMIT + routes: + - address: 192.168.2.0 # PC B subnet + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.2 + metric: 0 + + - type: wireless_router + hostname: router_2 + start_up_duration: 0 + + router_interface: + ip_address: 192.168.2.1 + subnet_mask: 255.255.255.0 + + wireless_access_point: + ip_address: 192.168.1.2 + subnet_mask: 255.255.255.0 + frequency: WIFI_5 + channel_width: 80 + acl: + 1: + action: PERMIT + routes: + - address: 192.168.0.0 # PC A subnet + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.1 + metric: 0 + links: + - endpoint_a_hostname: pc_a + endpoint_a_port: 1 + endpoint_b_hostname: router_1 + endpoint_b_port: 2 + + - endpoint_a_hostname: pc_b + endpoint_a_port: 1 + endpoint_b_hostname: router_2 + endpoint_b_port: 2 diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml new file mode 100644 index 00000000..ed27cd35 --- /dev/null +++ b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml @@ -0,0 +1,81 @@ +game: + max_episode_length: 256 + ports: + - ARP + protocols: + - ICMP + - TCP + - UDP + +simulation: + network: + airspace: + airspace_environment_type: urban + nodes: + - type: computer + hostname: pc_a + ip_address: 192.168.0.2 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.0.1 + start_up_duration: 0 + + - type: computer + hostname: pc_b + ip_address: 192.168.2.2 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.2.1 + start_up_duration: 0 + + - type: wireless_router + hostname: router_1 + start_up_duration: 0 + + router_interface: + ip_address: 192.168.0.1 + subnet_mask: 255.255.255.0 + + wireless_access_point: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + frequency: WIFI_5 + channel_width: 80 + acl: + 1: + action: PERMIT + routes: + - address: 192.168.2.0 # PC B subnet + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.2 + metric: 0 + + - type: wireless_router + hostname: router_2 + start_up_duration: 0 + + router_interface: + ip_address: 192.168.2.1 + subnet_mask: 255.255.255.0 + + wireless_access_point: + ip_address: 192.168.1.2 + subnet_mask: 255.255.255.0 + frequency: WIFI_5 + channel_width: 80 + acl: + 1: + action: PERMIT + routes: + - address: 192.168.0.0 # PC A subnet + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.1 + metric: 0 + links: + - endpoint_a_hostname: pc_a + endpoint_a_port: 1 + endpoint_b_hostname: router_1 + endpoint_b_port: 2 + + - endpoint_a_hostname: pc_b + endpoint_a_port: 1 + endpoint_b_hostname: router_2 + endpoint_b_port: 2 diff --git a/tests/integration_tests/network/test_airspace_capacity_configuration.py b/tests/integration_tests/network/test_airspace_capacity_configuration.py new file mode 100644 index 00000000..f91f1290 --- /dev/null +++ b/tests/integration_tests/network/test_airspace_capacity_configuration.py @@ -0,0 +1,106 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import yaml + +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.airspace import ( + AirspaceEnvironmentType, + AirSpaceFrequency, + calculate_total_channel_capacity, + ChannelWidth, +) +from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter +from tests import TEST_ASSETS_ROOT + + +def test_wireless_wan_wifi_5_80_channel_width_urban(): + config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_urban.yaml" + + with open(config_path, "r") as f: + config_dict = yaml.safe_load(f) + network = PrimaiteGame.from_config(cfg=config_dict).simulation.network + + airspace = network.airspace + + assert airspace.airspace_environment_type == AirspaceEnvironmentType.URBAN + + router_1: WirelessRouter = network.get_node_by_hostname("router_1") + router_2: WirelessRouter = network.get_node_by_hostname("router_2") + + expected_speed = calculate_total_channel_capacity( + channel_width=ChannelWidth.WIDTH_80_MHZ, + frequency=AirSpaceFrequency.WIFI_5, + environment_type=AirspaceEnvironmentType.URBAN, + ) + + assert router_1.wireless_access_point.speed == expected_speed + assert router_2.wireless_access_point.speed == expected_speed + + pc_a = network.get_node_by_hostname("pc_a") + pc_b = network.get_node_by_hostname("pc_b") + + assert pc_a.ping(pc_a.default_gateway), "PC A should ping its default gateway successfully." + assert pc_b.ping(pc_b.default_gateway), "PC B should ping its default gateway successfully." + + assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." + assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." + + +def test_wireless_wan_wifi_5_80_channel_width_blocked(): + config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_blocked.yaml" + + with open(config_path, "r") as f: + config_dict = yaml.safe_load(f) + network = PrimaiteGame.from_config(cfg=config_dict).simulation.network + + airspace = network.airspace + + assert airspace.airspace_environment_type == AirspaceEnvironmentType.BLOCKED + + router_1: WirelessRouter = network.get_node_by_hostname("router_1") + router_2: WirelessRouter = network.get_node_by_hostname("router_2") + + expected_speed = calculate_total_channel_capacity( + channel_width=ChannelWidth.WIDTH_80_MHZ, + frequency=AirSpaceFrequency.WIFI_5, + environment_type=AirspaceEnvironmentType.BLOCKED, + ) + + assert router_1.wireless_access_point.speed == expected_speed + assert router_2.wireless_access_point.speed == expected_speed + + pc_a = network.get_node_by_hostname("pc_a") + pc_b = network.get_node_by_hostname("pc_b") + + assert pc_a.ping(pc_a.default_gateway), "PC A should ping its default gateway successfully." + assert pc_b.ping(pc_b.default_gateway), "PC B should ping its default gateway successfully." + + assert not pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers unsuccessfully." + assert not pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers unsuccessfully." + + +def test_wireless_wan_blocking_and_unblocking_airspace(): + config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_urban.yaml" + + with open(config_path, "r") as f: + config_dict = yaml.safe_load(f) + network = PrimaiteGame.from_config(cfg=config_dict).simulation.network + + airspace = network.airspace + + assert airspace.airspace_environment_type == AirspaceEnvironmentType.URBAN + + pc_a = network.get_node_by_hostname("pc_a") + pc_b = network.get_node_by_hostname("pc_b") + + assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." + assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." + + airspace.airspace_environment_type = AirspaceEnvironmentType.BLOCKED + + assert not pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers unsuccessfully." + assert not pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers unsuccessfully." + + airspace.airspace_environment_type = AirspaceEnvironmentType.URBAN + + assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." + assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." diff --git a/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py b/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py new file mode 100644 index 00000000..cf03ea8e --- /dev/null +++ b/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py @@ -0,0 +1,138 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from primaite.simulator.file_system.file_type import FileType +from primaite.simulator.network.hardware.nodes.network.router import ACLAction +from primaite.simulator.system.services.ftp.ftp_client import FTPClient +from primaite.simulator.system.services.ftp.ftp_server import FTPServer +from tests.integration_tests.network.test_wireless_router import wireless_wan_network +from tests.integration_tests.system.test_ftp_client_server import ftp_client_and_ftp_server + + +def test_wireless_link_loading(wireless_wan_network): + client, server, router_1, router_2 = wireless_wan_network + + # Configure Router 1 ACLs + router_1.acl.add_rule(action=ACLAction.PERMIT, position=1) + + # Configure Router 2 ACLs + router_2.acl.add_rule(action=ACLAction.PERMIT, position=1) + + airspace = router_1.airspace + + client.software_manager.install(FTPClient) + ftp_client: FTPClient = client.software_manager.software.get("FTPClient") + ftp_client.start() + + server.software_manager.install(FTPServer) + ftp_server: FTPServer = server.software_manager.software.get("FTPServer") + ftp_server.start() + + client.file_system.create_file(file_name="mixtape", size=10 * 10**6, file_type=FileType.MP3, folder_name="music") + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape.mp3", + dest_folder_name="music", + ) + + # Reset the physical links between the host nodes and the routers + client.network_interface[1]._connected_link.pre_timestep(1) + server.network_interface[1]._connected_link.pre_timestep(1) + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape1.mp3", + dest_folder_name="music", + ) + + # Reset the physical links between the host nodes and the routers + client.network_interface[1]._connected_link.pre_timestep(1) + server.network_interface[1]._connected_link.pre_timestep(1) + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape2.mp3", + dest_folder_name="music", + ) + + # Reset the physical links between the host nodes and the routers + client.network_interface[1]._connected_link.pre_timestep(1) + server.network_interface[1]._connected_link.pre_timestep(1) + + assert not ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape3.mp3", + dest_folder_name="music", + ) + + # Reset the physical links between the host nodes and the routers + client.network_interface[1]._connected_link.pre_timestep(1) + server.network_interface[1]._connected_link.pre_timestep(1) + + airspace.reset_bandwidth_load() + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape3.mp3", + dest_folder_name="music", + ) + + +def test_wired_link_loading(ftp_client_and_ftp_server): + ftp_client, computer, ftp_server, server = ftp_client_and_ftp_server + + link = computer.network_interface[1]._connected_link # noqa + + assert link.is_up + + link.pre_timestep(1) + + computer.file_system.create_file( + file_name="mixtape", size=10 * 10**6, file_type=FileType.MP3, folder_name="music" + ) + link_load = link.current_load + assert link_load == 0.0 + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape.mp3", + dest_folder_name="music", + ) + + new_link_load = link.current_load + assert new_link_load > link_load + + assert not ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape1.mp3", + dest_folder_name="music", + ) + + link.pre_timestep(2) + + link_load = link.current_load + assert link_load == 0.0 + + assert ftp_client.send_file( + src_file_name="mixtape.mp3", + src_folder_name="music", + dest_ip_address=server.network_interface[1].ip_address, + dest_file_name="mixtape1.mp3", + dest_folder_name="music", + ) + + new_link_load = link.current_load + assert new_link_load > link_load From 9468adb6060bc067f3b4ccd857db424c896f718d Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Thu, 4 Jul 2024 20:52:20 +0100 Subject: [PATCH 02/42] #2967 - Updated the airspace configuration description in simulation.rst --- docs/source/configuration/simulation.rst | 26 +++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/source/configuration/simulation.rst b/docs/source/configuration/simulation.rst index d585711d..bd66914d 100644 --- a/docs/source/configuration/simulation.rst +++ b/docs/source/configuration/simulation.rst @@ -108,7 +108,31 @@ This is an integer value specifying the allowed bandwidth across the connection. ``airspace`` ------------ -This is where the airspace settings for wireless networks arte set. +This section configures settings specific to the wireless network's virtual airspace. It defines how wireless interfaces within the simulation will interact and perform under various environmental conditions. ``airspace_environment_type`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This setting specifies the environmental conditions of the airspace which affect the propagation and interference characteristics of wireless signals. Changing this environment type impacts how signal noise and interference are calculated, thus affecting the overall network performance, including data transmission rates and signal quality. + +**Configurable Options** + +- **rural**: A rural environment offers clear channel conditions due to low population density and minimal electronic device presence. + +- **outdoor**: Outdoor environments like parks or fields have minimal electronic interference. + +- **suburban**: Suburban environments strike a balance with fewer electronic interferences than urban but more than rural. + +- **office**: Office environments have moderate interference from numerous electronic devices and overlapping networks. + +- **urban**: Urban environments are characterized by tall buildings and a high density of electronic devices, leading to significant interference. + +- **industrial**: Industrial areas face high interference from heavy machinery and numerous electronic devices. + +- **transport**: Environments such as subways and buses where metal structures and high mobility create complex interference patterns. + +- **dense_urban**: Dense urban areas like city centers have the highest level of signal interference due to the very high density of buildings and devices. + +- **jamming_zone**: A jamming zone environment where signals are actively interfered with, typically through the use of signal jammers or scrambling devices. This represents the environment with the highest level of interference. + +- **blocked**: A jamming zone environment with total levels of interference. Airspace is completely blocked. From 2a0695d0d123def6f9310ea761db4d3b9775e2f6 Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Fri, 5 Jul 2024 15:06:17 +0100 Subject: [PATCH 03/42] #2688: apply the request validators + fixing the fix duration test + refactor test class names --- .../simulator/network/hardware/base.py | 90 ++++++++++++++++++- .../system/applications/application.py | 53 ++++++++++- .../simulator/system/services/service.py | 84 +++++++++++++++-- .../assets/configs/software_fix_duration.yaml | 3 + tests/conftest.py | 15 ++-- .../test_software_fix_duration.py | 34 +++---- .../actions/test_node_request_permission.py | 1 + .../network/test_broadcast.py | 32 +++---- .../system/test_application_on_node.py | 4 +- .../test_simulation/test_request_response.py | 12 +-- 10 files changed, 263 insertions(+), 65 deletions(-) create mode 100644 tests/integration_tests/game_layer/actions/test_node_request_permission.py diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 6942d280..e728ae97 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -130,10 +130,25 @@ class NetworkInterface(SimComponent, ABC): More information in user guide and docstring for SimComponent._init_request_manager. """ + _is_network_interface_enabled = NetworkInterface._EnabledValidator(network_interface=self) + _is_network_interface_disabled = NetworkInterface._DisabledValidator(network_interface=self) + rm = super()._init_request_manager() - rm.add_request("enable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.enable()))) - rm.add_request("disable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.disable()))) + rm.add_request( + "enable", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.enable()), + validator=_is_network_interface_disabled, + ), + ) + rm.add_request( + "disable", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.disable()), + validator=_is_network_interface_enabled, + ), + ) return rm @@ -332,6 +347,50 @@ class NetworkInterface(SimComponent, ABC): super().pre_timestep(timestep) self.traffic = {} + class _EnabledValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the NetworkInterface is enabled. + + This is useful because most actions should be being resolved if the NetworkInterface is disabled. + """ + + network_interface: NetworkInterface + """Save a reference to the node instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Return whether the NetworkInterface is enabled or not.""" + return self.network_interface.enabled + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on NetworkInterface " + f"'{self.network_interface.mac_address}' because it is not enabled." + ) + + class _DisabledValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the NetworkInterface is disabled. + + This is useful because some actions should be being resolved if the NetworkInterface is disabled. + """ + + network_interface: NetworkInterface + """Save a reference to the node instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Return whether the NetworkInterface is disabled or not.""" + return not self.network_interface.enabled + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on NetworkInterface " + f"'{self.network_interface.mac_address}' because it is not disabled." + ) + class WiredNetworkInterface(NetworkInterface, ABC): """ @@ -878,6 +937,25 @@ class Node(SimComponent): """Message that is reported when a request is rejected by this validator.""" return f"Cannot perform request on node '{self.node.hostname}' because it is not turned on." + class _NodeIsOffValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the node is off. + + This is useful because some actions require the node to be in an off state. + """ + + node: Node + """Save a reference to the node instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Return whether the node is on or off.""" + return self.node.operating_state == NodeOperatingState.OFF + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return f"Cannot perform request on node '{self.node.hostname}' because it is not turned off." + def _init_request_manager(self) -> RequestManager: """ Initialise the request manager. @@ -940,6 +1018,7 @@ class Node(SimComponent): return RequestResponse.from_bool(False) _node_is_on = Node._NodeIsOnValidator(node=self) + _node_is_off = Node._NodeIsOffValidator(node=self) rm = super()._init_request_manager() # since there are potentially many services, create an request manager that can map service name @@ -969,7 +1048,12 @@ class Node(SimComponent): func=lambda request, context: RequestResponse.from_bool(self.power_off()), validator=_node_is_on ), ) - rm.add_request("startup", RequestType(func=lambda request, context: RequestResponse.from_bool(self.power_on()))) + rm.add_request( + "startup", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.power_on()), validator=_node_is_off + ), + ) rm.add_request( "reset", RequestType(func=lambda request, context: RequestResponse.from_bool(self.reset()), validator=_node_is_on), diff --git a/src/primaite/simulator/system/applications/application.py b/src/primaite/simulator/system/applications/application.py index 848e1ef0..dc16a725 100644 --- a/src/primaite/simulator/system/applications/application.py +++ b/src/primaite/simulator/system/applications/application.py @@ -1,10 +1,12 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from __future__ import annotations + from abc import abstractmethod from enum import Enum from typing import Any, ClassVar, Dict, Optional, Set, Type -from primaite.interface.request import RequestResponse -from primaite.simulator.core import RequestManager, RequestType +from primaite.interface.request import RequestFormat, RequestResponse +from primaite.simulator.core import RequestManager, RequestPermissionValidator, RequestType from primaite.simulator.system.software import IOSoftware, SoftwareHealthState @@ -64,9 +66,27 @@ class Application(IOSoftware): More information in user guide and docstring for SimComponent._init_request_manager. """ - rm = super()._init_request_manager() + _is_application_running = Application._StateValidator(application=self, state=ApplicationOperatingState.RUNNING) - rm.add_request("close", RequestType(func=lambda request, context: RequestResponse.from_bool(self.close()))) + rm = super()._init_request_manager() + rm.add_request( + "scan", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.scan()), validator=_is_application_running + ), + ) + rm.add_request( + "close", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.close()), validator=_is_application_running + ), + ) + rm.add_request( + "fix", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.fix()), validator=_is_application_running + ), + ) return rm @abstractmethod @@ -169,3 +189,28 @@ class Application(IOSoftware): :return: True if successful, False otherwise. """ return super().receive(payload=payload, session_id=session_id, **kwargs) + + class _StateValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the application is in the correct state. + + This is useful because most actions require the application to be in a specific state. + """ + + application: Application + """Save a reference to the application instance.""" + + state: ApplicationOperatingState + """The state of the application to validate.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Return whether the application is in the state we are validating for.""" + return self.application.operating_state == self.state + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on application '{self.application.name}' because it is not in the " + f"{self.state.name} state." + ) diff --git a/src/primaite/simulator/system/services/service.py b/src/primaite/simulator/system/services/service.py index e6ce2c87..8167a8a9 100644 --- a/src/primaite/simulator/system/services/service.py +++ b/src/primaite/simulator/system/services/service.py @@ -1,11 +1,13 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from __future__ import annotations + from abc import abstractmethod from enum import Enum from typing import Any, Dict, Optional from primaite import getLogger -from primaite.interface.request import RequestResponse -from primaite.simulator.core import RequestManager, RequestType +from primaite.interface.request import RequestFormat, RequestResponse +from primaite.simulator.core import RequestManager, RequestPermissionValidator, RequestType from primaite.simulator.system.software import IOSoftware, SoftwareHealthState _LOGGER = getLogger(__name__) @@ -40,6 +42,7 @@ class Service(IOSoftware): restart_duration: int = 5 "How many timesteps does it take to restart this service." + restart_countdown: Optional[int] = None "If currently restarting, how many timesteps remain until the restart is finished." @@ -86,15 +89,55 @@ class Service(IOSoftware): More information in user guide and docstring for SimComponent._init_request_manager. """ + _is_service_running = Service._StateValidator(service=self, state=ServiceOperatingState.RUNNING) + _is_service_stopped = Service._StateValidator(service=self, state=ServiceOperatingState.STOPPED) + _is_service_paused = Service._StateValidator(service=self, state=ServiceOperatingState.PAUSED) + rm = super()._init_request_manager() - rm.add_request("scan", RequestType(func=lambda request, context: RequestResponse.from_bool(self.scan()))) - rm.add_request("stop", RequestType(func=lambda request, context: RequestResponse.from_bool(self.stop()))) - rm.add_request("start", RequestType(func=lambda request, context: RequestResponse.from_bool(self.start()))) - rm.add_request("pause", RequestType(func=lambda request, context: RequestResponse.from_bool(self.pause()))) - rm.add_request("resume", RequestType(func=lambda request, context: RequestResponse.from_bool(self.resume()))) - rm.add_request("restart", RequestType(func=lambda request, context: RequestResponse.from_bool(self.restart()))) + rm.add_request( + "scan", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.scan()), validator=_is_service_running + ), + ) + rm.add_request( + "stop", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.stop()), validator=_is_service_running + ), + ) + rm.add_request( + "start", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.start()), validator=_is_service_stopped + ), + ) + rm.add_request( + "pause", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.pause()), validator=_is_service_running + ), + ) + rm.add_request( + "resume", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.resume()), validator=_is_service_paused + ), + ) + rm.add_request( + "restart", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.restart()), validator=_is_service_running + ), + ) rm.add_request("disable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.disable()))) rm.add_request("enable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.enable()))) + rm.add_request( + "fix", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.fix()), validator=_is_service_running + ), + ) return rm @abstractmethod @@ -191,3 +234,28 @@ class Service(IOSoftware): self.sys_log.debug(f"Restarting finished for service {self.name}") self.operating_state = ServiceOperatingState.RUNNING self.restart_countdown -= 1 + + class _StateValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the service is in the correct state. + + This is useful because most actions require the service to be in a specific state. + """ + + service: Service + """Save a reference to the service instance.""" + + state: ServiceOperatingState + """The state of the service to validate.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Return whether the service is in the state we are validating for.""" + return self.service.operating_state == self.state + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on service '{self.service.name}' because it is not in the " + f"{self.state.name} state." + ) diff --git a/tests/assets/configs/software_fix_duration.yaml b/tests/assets/configs/software_fix_duration.yaml index beb176d1..1acb05a9 100644 --- a/tests/assets/configs/software_fix_duration.yaml +++ b/tests/assets/configs/software_fix_duration.yaml @@ -177,6 +177,9 @@ simulation: default_gateway: 192.168.10.1 dns_server: 192.168.1.10 applications: + - type: NMAP + options: + fix_duration: 1 - type: RansomwareScript options: fix_duration: 1 diff --git a/tests/conftest.py b/tests/conftest.py index 980e4aa9..e36a2460 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -51,11 +51,11 @@ class TestService(Service): pass -class DummyApplication(Application, identifier="DummyApplication"): +class TestDummyApplication(Application, identifier="TestDummyApplication"): """Test Application class""" def __init__(self, **kwargs): - kwargs["name"] = "DummyApplication" + kwargs["name"] = "TestDummyApplication" kwargs["port"] = Port.HTTP kwargs["protocol"] = IPProtocol.TCP super().__init__(**kwargs) @@ -85,15 +85,18 @@ def service_class(): @pytest.fixture(scope="function") -def application(file_system) -> DummyApplication: - return DummyApplication( - name="DummyApplication", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="dummy_application") +def application(file_system) -> TestDummyApplication: + return TestDummyApplication( + name="TestDummyApplication", + port=Port.ARP, + file_system=file_system, + sys_log=SysLog(hostname="dummy_application"), ) @pytest.fixture(scope="function") def application_class(): - return DummyApplication + return TestDummyApplication @pytest.fixture(scope="function") diff --git a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py b/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py index bf325946..04160f8f 100644 --- a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py +++ b/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py @@ -1,35 +1,23 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import copy -from ipaddress import IPv4Address from pathlib import Path from typing import Union import yaml -from primaite.config.load import data_manipulation_config_path -from primaite.game.agent.interface import ProxyAgent -from primaite.game.agent.scripted_agents.data_manipulation_bot import DataManipulationAgent -from primaite.game.agent.scripted_agents.probabilistic_agent import ProbabilisticAgent -from primaite.game.game import APPLICATION_TYPES_MAPPING, PrimaiteGame, SERVICE_TYPES_MAPPING -from primaite.simulator.network.container import Network +from primaite.game.game import PrimaiteGame, SERVICE_TYPES_MAPPING from primaite.simulator.network.hardware.nodes.host.computer import Computer +from primaite.simulator.system.applications.application import Application from primaite.simulator.system.applications.database_client import DatabaseClient -from primaite.simulator.system.applications.red_applications.data_manipulation_bot import DataManipulationBot -from primaite.simulator.system.applications.red_applications.dos_bot import DoSBot -from primaite.simulator.system.applications.web_browser import WebBrowser from primaite.simulator.system.services.database.database_service import DatabaseService from primaite.simulator.system.services.dns.dns_client import DNSClient -from primaite.simulator.system.services.dns.dns_server import DNSServer -from primaite.simulator.system.services.ftp.ftp_client import FTPClient -from primaite.simulator.system.services.ftp.ftp_server import FTPServer -from primaite.simulator.system.services.ntp.ntp_client import NTPClient -from primaite.simulator.system.services.ntp.ntp_server import NTPServer -from primaite.simulator.system.services.web_server.web_server import WebServer from tests import TEST_ASSETS_ROOT TEST_CONFIG = TEST_ASSETS_ROOT / "configs/software_fix_duration.yaml" ONE_ITEM_CONFIG = TEST_ASSETS_ROOT / "configs/fix_duration_one_item.yaml" +TestApplications = ["TestDummyApplication", "TestBroadcastClient"] + def load_config(config_path: Union[str, Path]) -> PrimaiteGame: """Returns a PrimaiteGame object which loads the contents of a given yaml path.""" @@ -62,9 +50,12 @@ def test_fix_duration_set_from_config(): assert client_1.software_manager.software.get(service).fixing_duration == 3 # in config - applications take 1 timestep to fix - for applications in APPLICATION_TYPES_MAPPING: - assert client_1.software_manager.software.get(applications) is not None - assert client_1.software_manager.software.get(applications).fixing_duration == 1 + # remove test applications from list + applications = set(Application._application_registry) - set(TestApplications) + + for application in applications: + assert client_1.software_manager.software.get(application) is not None + assert client_1.software_manager.software.get(application).fixing_duration == 1 def test_fix_duration_for_one_item(): @@ -80,8 +71,9 @@ def test_fix_duration_for_one_item(): assert client_1.software_manager.software.get(service).fixing_duration == 2 # in config - applications take 1 timestep to fix - applications = copy.copy(APPLICATION_TYPES_MAPPING) - applications.pop("DatabaseClient") + # remove test applications from list + applications = set(Application._application_registry) - set(TestApplications) + applications.remove("DatabaseClient") for applications in applications: assert client_1.software_manager.software.get(applications) is not None assert client_1.software_manager.software.get(applications).fixing_duration == 2 diff --git a/tests/integration_tests/game_layer/actions/test_node_request_permission.py b/tests/integration_tests/game_layer/actions/test_node_request_permission.py new file mode 100644 index 00000000..be6c00e7 --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_node_request_permission.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/integration_tests/network/test_broadcast.py b/tests/integration_tests/network/test_broadcast.py index b89d6db6..bcf7b9b0 100644 --- a/tests/integration_tests/network/test_broadcast.py +++ b/tests/integration_tests/network/test_broadcast.py @@ -14,7 +14,7 @@ from primaite.simulator.system.applications.application import Application from primaite.simulator.system.services.service import Service -class BroadcastService(Service): +class TestBroadcastService(Service): """A service for sending broadcast and unicast messages over a network.""" def __init__(self, **kwargs): @@ -41,14 +41,14 @@ class BroadcastService(Service): super().send(payload="broadcast", dest_ip_address=ip_network, dest_port=Port.HTTP, ip_protocol=self.protocol) -class BroadcastClient(Application, identifier="BroadcastClient"): +class TestBroadcastClient(Application, identifier="TestBroadcastClient"): """A client application to receive broadcast and unicast messages.""" payloads_received: List = [] def __init__(self, **kwargs): # Set default client properties - kwargs["name"] = "BroadcastClient" + kwargs["name"] = "TestBroadcastClient" kwargs["port"] = Port.HTTP kwargs["protocol"] = IPProtocol.TCP super().__init__(**kwargs) @@ -75,8 +75,8 @@ def broadcast_network() -> Network: start_up_duration=0, ) client_1.power_on() - client_1.software_manager.install(BroadcastClient) - application_1 = client_1.software_manager.software["BroadcastClient"] + client_1.software_manager.install(TestBroadcastClient) + application_1 = client_1.software_manager.software["TestBroadcastClient"] application_1.run() client_2 = Computer( @@ -87,8 +87,8 @@ def broadcast_network() -> Network: start_up_duration=0, ) client_2.power_on() - client_2.software_manager.install(BroadcastClient) - application_2 = client_2.software_manager.software["BroadcastClient"] + client_2.software_manager.install(TestBroadcastClient) + application_2 = client_2.software_manager.software["TestBroadcastClient"] application_2.run() server_1 = Server( @@ -100,8 +100,8 @@ def broadcast_network() -> Network: ) server_1.power_on() - server_1.software_manager.install(BroadcastService) - service: BroadcastService = server_1.software_manager.software["BroadcastService"] + server_1.software_manager.install(TestBroadcastService) + service: TestBroadcastService = server_1.software_manager.software["BroadcastService"] service.start() switch_1 = Switch(hostname="switch_1", num_ports=6, start_up_duration=0) @@ -115,14 +115,16 @@ def broadcast_network() -> Network: @pytest.fixture(scope="function") -def broadcast_service_and_clients(broadcast_network) -> Tuple[BroadcastService, BroadcastClient, BroadcastClient]: - client_1: BroadcastClient = broadcast_network.get_node_by_hostname("client_1").software_manager.software[ - "BroadcastClient" +def broadcast_service_and_clients( + broadcast_network, +) -> Tuple[TestBroadcastService, TestBroadcastClient, TestBroadcastClient]: + client_1: TestBroadcastClient = broadcast_network.get_node_by_hostname("client_1").software_manager.software[ + "TestBroadcastClient" ] - client_2: BroadcastClient = broadcast_network.get_node_by_hostname("client_2").software_manager.software[ - "BroadcastClient" + client_2: TestBroadcastClient = broadcast_network.get_node_by_hostname("client_2").software_manager.software[ + "TestBroadcastClient" ] - service: BroadcastService = broadcast_network.get_node_by_hostname("server_1").software_manager.software[ + service: TestBroadcastService = broadcast_network.get_node_by_hostname("server_1").software_manager.software[ "BroadcastService" ] diff --git a/tests/integration_tests/system/test_application_on_node.py b/tests/integration_tests/system/test_application_on_node.py index ffb5cc7f..400ab082 100644 --- a/tests/integration_tests/system/test_application_on_node.py +++ b/tests/integration_tests/system/test_application_on_node.py @@ -21,7 +21,7 @@ def populated_node(application_class) -> Tuple[Application, Computer]: computer.power_on() computer.software_manager.install(application_class) - app = computer.software_manager.software.get("DummyApplication") + app = computer.software_manager.software.get("TestDummyApplication") app.run() return app, computer @@ -39,7 +39,7 @@ def test_application_on_offline_node(application_class): ) computer.software_manager.install(application_class) - app: Application = computer.software_manager.software.get("DummyApplication") + app: Application = computer.software_manager.software.get("TestDummyApplication") computer.power_off() diff --git a/tests/integration_tests/test_simulation/test_request_response.py b/tests/integration_tests/test_simulation/test_request_response.py index a9f0b58d..29c70566 100644 --- a/tests/integration_tests/test_simulation/test_request_response.py +++ b/tests/integration_tests/test_simulation/test_request_response.py @@ -13,7 +13,7 @@ from primaite.simulator.network.hardware.node_operating_state import NodeOperati from primaite.simulator.network.hardware.nodes.host.host_node import HostNode from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router from primaite.simulator.network.transmission.transport_layer import Port -from tests.conftest import DummyApplication, TestService +from tests.conftest import TestDummyApplication, TestService def test_successful_node_file_system_creation_request(example_network): @@ -47,14 +47,14 @@ def test_successful_application_requests(example_network): net = example_network client_1 = net.get_node_by_hostname("client_1") - client_1.software_manager.install(DummyApplication) - client_1.software_manager.software.get("DummyApplication").run() + client_1.software_manager.install(TestDummyApplication) + client_1.software_manager.software.get("TestDummyApplication").run() - resp_1 = net.apply_request(["node", "client_1", "application", "DummyApplication", "scan"]) + resp_1 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "scan"]) assert resp_1 == RequestResponse(status="success", data={}) - resp_2 = net.apply_request(["node", "client_1", "application", "DummyApplication", "fix"]) + resp_2 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "fix"]) assert resp_2 == RequestResponse(status="success", data={}) - resp_3 = net.apply_request(["node", "client_1", "application", "DummyApplication", "compromise"]) + resp_3 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "compromise"]) assert resp_3 == RequestResponse(status="success", data={}) From 4410e05e3ef0cd2758017063d0890a3d688afff2 Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Fri, 5 Jul 2024 16:27:03 +0100 Subject: [PATCH 04/42] #2967 - Updated the DB filesize so that it doesn't fill the 100mbit link. moved the can transmit checks to the network interface to enable frame dropped syslog. narrowed the scope of the NODE_NMAP_PORT_SCAN action in nmap_port_scan_red_agent_config.yaml to select ports and protocols as the link was filling up on the full box scan. --- .../simulator/file_system/file_type.py | 2 +- src/primaite/simulator/network/airspace.py | 23 +++++++++--------- .../simulator/network/hardware/base.py | 24 +++++++++---------- .../network/hardware/nodes/network/switch.py | 16 ++++++++----- .../nmap_port_scan_red_agent_config.yaml | 6 +++++ .../configs/wireless_wan_network_config.yaml | 2 +- tests/conftest.py | 3 +-- 7 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/primaite/simulator/file_system/file_type.py b/src/primaite/simulator/file_system/file_type.py index 8f0cb778..e6e81070 100644 --- a/src/primaite/simulator/file_system/file_type.py +++ b/src/primaite/simulator/file_system/file_type.py @@ -185,5 +185,5 @@ file_type_sizes_bytes = { FileType.ZIP: 1024000, FileType.TAR: 1024000, FileType.GZ: 819200, - FileType.DB: 15360000, + FileType.DB: 5_000_000, } diff --git a/src/primaite/simulator/network/airspace.py b/src/primaite/simulator/network/airspace.py index 6060d969..2ac11a20 100644 --- a/src/primaite/simulator/network/airspace.py +++ b/src/primaite/simulator/network/airspace.py @@ -720,17 +720,18 @@ class WirelessNetworkInterface(NetworkInterface, ABC): :param frame: The network frame to be sent. :return: True if the frame is sent successfully, False if the network interface is disabled. """ - if self.enabled: - frame.set_sent_timestamp() - self.pcap.capture_outbound(frame) - if self.airspace.can_transmit_frame(frame, self): - self.airspace.transmit(frame, self) - return True - else: - # Cannot send Frame as the frequency bandwidth is at capacity - return False - # Cannot send Frame as the network interface is not enabled - return False + if not self.enabled: + return False + if not self.airspace.can_transmit_frame(frame, self): + # Drop frame for now. Queuing will happen here (probably) if it's done in the future. + self._connected_node.sys_log.info(f"{self}: Frame dropped as Link is at capacity") + return False + + super().send_frame(frame) + frame.set_sent_timestamp() + self.pcap.capture_outbound(frame) + self.airspace.transmit(frame, self) + return True def receive_frame(self, frame: Frame) -> bool: """ diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 743b2e76..5ed27658 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -440,14 +440,17 @@ class WiredNetworkInterface(NetworkInterface, ABC): :param frame: The network frame to be sent. :return: True if the frame is sent, False if the Network Interface is disabled or not connected to a link. """ + if not self.enabled: + return False + if not self._connected_link.can_transmit_frame(frame): + # Drop frame for now. Queuing will happen here (probably) if it's done in the future. + self._connected_node.sys_log.info(f"{self}: Frame dropped as Link is at capacity") + return False super().send_frame(frame) - if self.enabled: - frame.set_sent_timestamp() - self.pcap.capture_outbound(frame) - self._connected_link.transmit_frame(sender_nic=self, frame=frame) - return True - # Cannot send Frame as the NIC is not enabled - return False + frame.set_sent_timestamp() + self.pcap.capture_outbound(frame) + self._connected_link.transmit_frame(sender_nic=self, frame=frame) + return True @abstractmethod def receive_frame(self, frame: Frame) -> bool: @@ -678,7 +681,7 @@ class Link(SimComponent): """ return self.endpoint_a.enabled and self.endpoint_b.enabled - def _can_transmit(self, frame: Frame) -> bool: + def can_transmit_frame(self, frame: Frame) -> bool: """ Determines whether a frame can be transmitted considering the current Link load and the Link's bandwidth. @@ -703,11 +706,6 @@ class Link(SimComponent): :param frame: The network frame to be sent. :return: True if the Frame can be sent, otherwise False. """ - can_transmit = self._can_transmit(frame) - if not can_transmit: - _LOGGER.debug(f"Cannot transmit frame as {self} is at capacity") - return False - receiver = self.endpoint_a if receiver == sender_nic: receiver = self.endpoint_b diff --git a/src/primaite/simulator/network/hardware/nodes/network/switch.py b/src/primaite/simulator/network/hardware/nodes/network/switch.py index 6eee0d40..1a7da2e7 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/switch.py +++ b/src/primaite/simulator/network/hardware/nodes/network/switch.py @@ -58,12 +58,16 @@ class SwitchPort(WiredNetworkInterface): :param frame: The network frame to be sent. :return: A boolean indicating whether the frame was successfully sent. """ - if self.enabled: - self.pcap.capture_outbound(frame) - self._connected_link.transmit_frame(sender_nic=self, frame=frame) - return True - # Cannot send Frame as the SwitchPort is not enabled - return False + if not self.enabled: + return False + if not self._connected_link.can_transmit_frame(frame): + # Drop frame for now. Queuing will happen here (probably) if it's done in the future. + self._connected_node.sys_log.info(f"{self}: Frame dropped as Link is at capacity") + return False + + self.pcap.capture_outbound(frame) + self._connected_link.transmit_frame(sender_nic=self, frame=frame) + return True def receive_frame(self, frame: Frame) -> bool: """ diff --git a/tests/assets/configs/nmap_port_scan_red_agent_config.yaml b/tests/assets/configs/nmap_port_scan_red_agent_config.yaml index 08944ee5..8ed715c1 100644 --- a/tests/assets/configs/nmap_port_scan_red_agent_config.yaml +++ b/tests/assets/configs/nmap_port_scan_red_agent_config.yaml @@ -41,6 +41,12 @@ agents: options: source_node: client_1 target_ip_address: 192.168.10.0/24 + target_port: + - 21 + - 53 + - 80 + - 123 + - 219 reward_function: reward_components: diff --git a/tests/assets/configs/wireless_wan_network_config.yaml b/tests/assets/configs/wireless_wan_network_config.yaml index 684acaf7..7172f66d 100644 --- a/tests/assets/configs/wireless_wan_network_config.yaml +++ b/tests/assets/configs/wireless_wan_network_config.yaml @@ -10,7 +10,7 @@ game: simulation: network: airspace: - airspace_environment_type: blocked + airspace_environment_type: urban nodes: - type: computer hostname: pc_a diff --git a/tests/conftest.py b/tests/conftest.py index b8359323..a0117eb6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -252,8 +252,7 @@ def example_network() -> Network: server_2.power_on() network.connect(endpoint_b=server_2.network_interface[1], endpoint_a=switch_1.network_interface[2]) - router_1.acl.add_rule(action=ACLAction.PERMIT, src_port=Port.ARP, dst_port=Port.ARP, position=22) - router_1.acl.add_rule(action=ACLAction.PERMIT, protocol=IPProtocol.ICMP, position=23) + router_1.acl.add_rule(action=ACLAction.PERMIT, position=1) assert all(link.is_up for link in network.links.values()) From 7173c329b09c8ccf95f2d9fe2aedc2ba72bdedb4 Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Fri, 5 Jul 2024 16:56:07 +0100 Subject: [PATCH 05/42] #2739 - Updated azure-benchmark-pipeline.yaml to allow it to run for unlimited time on the Imaginary Yak Pool --- .azure/azure-benchmark-pipeline.yaml | 119 ++++++++++++++------------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 1f7b8ebe..e764c3c1 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -11,74 +11,77 @@ schedules: branches: include: - 'refs/heads/dev' - -pool: - vmImage: ubuntu-latest - variables: VERSION: '' MAJOR_VERSION: '' -steps: -- checkout: self - persistCredentials: true +jobs: +- job: PrimAITE Benchmark + timeoutInMinutes: 0 # Set to unlimited timeout + pool: + name: 'Imaginary Yak Pool' + workspace: + clean: all + steps: + - checkout: self + persistCredentials: true -- script: | - VERSION=$(cat src/primaite/VERSION | tr -d '\n') - if [[ "$(Build.SourceBranch)" == "refs/heads/dev" ]]; then - DATE=$(date +%Y%m%d) - echo "${VERSION}+dev.${DATE}" > src/primaite/VERSION - fi - displayName: 'Update VERSION file for Dev Benchmark' + - script: | + VERSION=$(cat src/primaite/VERSION | tr -d '\n') + if [[ "$(Build.SourceBranch)" == "refs/heads/dev" ]]; then + DATE=$(date +%Y%m%d) + echo "${VERSION}+dev.${DATE}" > src/primaite/VERSION + fi + displayName: 'Update VERSION file for Dev Benchmark' -- script: | - VERSION=$(cat src/primaite/VERSION | tr -d '\n') - MAJOR_VERSION=$(echo $VERSION | cut -d. -f1) - echo "##vso[task.setvariable variable=VERSION]$VERSION" - echo "##vso[task.setvariable variable=MAJOR_VERSION]$MAJOR_VERSION" - displayName: 'Set Version Variables' + - script: | + VERSION=$(cat src/primaite/VERSION | tr -d '\n') + MAJOR_VERSION=$(echo $VERSION | cut -d. -f1) + echo "##vso[task.setvariable variable=VERSION]$VERSION" + echo "##vso[task.setvariable variable=MAJOR_VERSION]$MAJOR_VERSION" + displayName: 'Set Version Variables' -- task: UsePythonVersion@0 - inputs: - versionSpec: '3.11' - addToPath: true + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.11' + addToPath: true -- script: | - python -m pip install --upgrade pip - pip install -e .[dev,rl] - primaite setup - displayName: 'Install Dependencies' + - script: | + python -m pip install --upgrade pip + pip install -e .[dev,rl] + primaite setup + displayName: 'Install Dependencies' -- script: | - cd benchmark - python3 primaite_benchmark.py - cd .. - displayName: 'Run Benchmarking Script' + - script: | + cd benchmark + python3 primaite_benchmark.py + cd .. + displayName: 'Run Benchmarking Script' -- script: | - git config --global user.email "oss@dstl.gov.uk" - git config --global user.name "Defence Science and Technology Laboratory UK" - workingDirectory: $(System.DefaultWorkingDirectory) - displayName: 'Configure Git' - condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release')) + - script: | + git config --global user.email "oss@dstl.gov.uk" + git config --global user.name "Defence Science and Technology Laboratory UK" + workingDirectory: $(System.DefaultWorkingDirectory) + displayName: 'Configure Git' + condition: and(succeeded(), eq(variables['Build.Reason'], 'Manual'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release')) -- script: | - git add benchmark/results/v$(MAJOR_VERSION)/v$(VERSION)/* - git commit -m "Automated benchmark output commit for version $(VERSION)" - git push origin HEAD:refs/heads/$(Build.SourceBranchName) - displayName: 'Commit and Push Benchmark Results' - workingDirectory: $(System.DefaultWorkingDirectory) - env: - GIT_CREDENTIALS: $(System.AccessToken) - condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/release')) + - script: | + git add benchmark/results/v$(MAJOR_VERSION)/v$(VERSION)/* + git commit -m "Automated benchmark output commit for version $(VERSION)" + git push origin HEAD:refs/heads/$(Build.SourceBranchName) + displayName: 'Commit and Push Benchmark Results' + workingDirectory: $(System.DefaultWorkingDirectory) + env: + GIT_CREDENTIALS: $(System.AccessToken) + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/heads/release')) -- script: | - tar czf primaite_v$(VERSION)_benchmark.tar.gz benchmark/results/v$(MAJOR_VERSION)/v$(VERSION) - displayName: 'Prepare Artifacts for Publishing' + - script: | + tar czf primaite_v$(VERSION)_benchmark.tar.gz benchmark/results/v$(MAJOR_VERSION)/v$(VERSION) + displayName: 'Prepare Artifacts for Publishing' -- task: PublishPipelineArtifact@1 - inputs: - targetPath: primaite_v$(VERSION)_benchmark.tar.gz - artifactName: 'benchmark-output' - publishLocation: 'pipeline' - displayName: 'Publish Benchmark Output as Artifact' + - task: PublishPipelineArtifact@1 + inputs: + targetPath: primaite_v$(VERSION)_benchmark.tar.gz + artifactName: 'benchmark-output' + publishLocation: 'pipeline' + displayName: 'Publish Benchmark Output as Artifact' From 5e8343ca9154870b5eb6c5a2f88cd75a64903dd3 Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Fri, 5 Jul 2024 16:57:40 +0100 Subject: [PATCH 06/42] #2739 - update job name in azure-benchmark-pipeline.yaml --- .azure/azure-benchmark-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index e764c3c1..e8e6ec9c 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -16,7 +16,7 @@ variables: MAJOR_VERSION: '' jobs: -- job: PrimAITE Benchmark +- job: PrimAITE_Benchmark timeoutInMinutes: 0 # Set to unlimited timeout pool: name: 'Imaginary Yak Pool' From c14699230714843406e8538f0e0d39bfb7babf7f Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Fri, 5 Jul 2024 17:02:35 +0100 Subject: [PATCH 07/42] #2739 - updated azure-benchmark-pipeline.yaml to run on ubuntu-latest while we wait for authorisation to use the yak pool --- .azure/azure-benchmark-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index e8e6ec9c..350123e5 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -19,7 +19,7 @@ jobs: - job: PrimAITE_Benchmark timeoutInMinutes: 0 # Set to unlimited timeout pool: - name: 'Imaginary Yak Pool' + vmImage: ubuntu-latest workspace: clean: all steps: From 2a003eece9d9845e4cbad1ea5bb6c02f7435af20 Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Mon, 8 Jul 2024 08:25:05 +0000 Subject: [PATCH 08/42] Updated v3.0.0_benchmark_metadata.json so that combined_av_reward_per_episode is now named combined_total_reward_per_episode to match the new script --- benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json b/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json index b6780eac..ed3ea4eb 100644 --- a/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json +++ b/benchmark/results/v3/v3.0.0/v3.0.0_benchmark_metadata.json @@ -26,7 +26,7 @@ "av_s_per_session": 3205.6340542, "av_s_per_step": 0.10017606419375, "av_s_per_100_steps_10_nodes": 10.017606419375, - "combined_av_reward_per_episode": { + "combined_total_reward_per_episode": { "1": -53.42999999999999, "2": -25.18000000000001, "3": -42.00000000000002, From 2d2f2df360d12e1e27c38b3ea8f2baa05090ffb8 Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Mon, 8 Jul 2024 08:26:52 +0000 Subject: [PATCH 09/42] Added set -e to the Run Benchmark Script step in azure-benchmark-pipeline.yaml so that the pipeline fails if the python script fails. --- .azure/azure-benchmark-pipeline.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 350123e5..7eab2114 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -53,6 +53,7 @@ jobs: displayName: 'Install Dependencies' - script: | + set -e cd benchmark python3 primaite_benchmark.py cd .. From 829a6371deb0a0c18b5ce3e97bb8baa15e580e1d Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Mon, 8 Jul 2024 14:39:37 +0100 Subject: [PATCH 10/42] #2688: tests --- .../test_application_request_permission.py | 54 +++++++++ .../actions/test_nic_request_permission.py | 97 ++++++++++++++++ .../actions/test_node_request_permission.py | 93 +++++++++++++++ .../test_service_request_permission.py | 106 ++++++++++++++++++ 4 files changed, 350 insertions(+) create mode 100644 tests/integration_tests/game_layer/actions/test_application_request_permission.py create mode 100644 tests/integration_tests/game_layer/actions/test_nic_request_permission.py create mode 100644 tests/integration_tests/game_layer/actions/test_service_request_permission.py diff --git a/tests/integration_tests/game_layer/actions/test_application_request_permission.py b/tests/integration_tests/game_layer/actions/test_application_request_permission.py new file mode 100644 index 00000000..36a7ae57 --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_application_request_permission.py @@ -0,0 +1,54 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.hardware.nodes.host.computer import Computer +from primaite.simulator.network.hardware.nodes.host.server import Server +from primaite.simulator.system.applications.application import ApplicationOperatingState +from primaite.simulator.system.applications.web_browser import WebBrowser +from primaite.simulator.system.services.service import ServiceOperatingState + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_application_cannot_perform_actions_unless_running(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test the the request permissions prevent any actions unless application is running.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + browser: WebBrowser = client_1.software_manager.software.get("WebBrowser") + + browser.close() + assert browser.operating_state == ApplicationOperatingState.CLOSED + + action = ("NODE_APPLICATION_SCAN", {"node_id": 0, "application_id": 0}) + agent.store_action(action) + game.step() + assert browser.operating_state == ApplicationOperatingState.CLOSED + + action = ("NODE_APPLICATION_CLOSE", {"node_id": 0, "application_id": 0}) + agent.store_action(action) + game.step() + assert browser.operating_state == ApplicationOperatingState.CLOSED + + action = ("NODE_APPLICATION_FIX", {"node_id": 0, "application_id": 0}) + agent.store_action(action) + game.step() + assert browser.operating_state == ApplicationOperatingState.CLOSED + + action = ("NODE_APPLICATION_EXECUTE", {"node_id": 0, "application_id": 0}) + agent.store_action(action) + game.step() + assert browser.operating_state == ApplicationOperatingState.CLOSED diff --git a/tests/integration_tests/game_layer/actions/test_nic_request_permission.py b/tests/integration_tests/game_layer/actions/test_nic_request_permission.py new file mode 100644 index 00000000..4c1619e7 --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_nic_request_permission.py @@ -0,0 +1,97 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.hardware.nodes.host.computer import Computer +from primaite.simulator.network.hardware.nodes.host.server import Server +from primaite.simulator.system.services.service import ServiceOperatingState + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_nic_cannot_be_turned_off_if_not_on(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that a NIC cannot be disabled if it is not enabled.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + nic = client_1.network_interface[1] + nic.disable() + assert nic.enabled is False + + action = ( + "HOST_NIC_DISABLE", + { + "node_id": 0, # client_1 + "nic_id": 0, # the only nic (eth-1) + }, + ) + agent.store_action(action) + game.step() + + assert nic.enabled is False + + +def test_nic_cannot_be_turned_on_if_already_on(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that a NIC cannot be enabled if it is already enabled.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + nic = client_1.network_interface[1] + assert nic.enabled + + action = ( + "HOST_NIC_ENABLE", + { + "node_id": 0, # client_1 + "nic_id": 0, # the only nic (eth-1) + }, + ) + agent.store_action(action) + game.step() + + assert nic.enabled + + +def test_that_a_nic_can_be_enabled_and_disabled(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Tests that a NIC can be enabled and disabled.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + nic = client_1.network_interface[1] + assert nic.enabled + + action = ( + "HOST_NIC_DISABLE", + { + "node_id": 0, # client_1 + "nic_id": 0, # the only nic (eth-1) + }, + ) + agent.store_action(action) + game.step() + + assert nic.enabled is False + + action = ( + "HOST_NIC_ENABLE", + { + "node_id": 0, # client_1 + "nic_id": 0, # the only nic (eth-1) + }, + ) + agent.store_action(action) + game.step() + + assert nic.enabled diff --git a/tests/integration_tests/game_layer/actions/test_node_request_permission.py b/tests/integration_tests/game_layer/actions/test_node_request_permission.py index be6c00e7..fdf04ad5 100644 --- a/tests/integration_tests/game_layer/actions/test_node_request_permission.py +++ b/tests/integration_tests/game_layer/actions/test_node_request_permission.py @@ -1 +1,94 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState +from primaite.simulator.network.hardware.nodes.host.computer import Computer + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_node_startup_shutdown(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the node can be shut down and started up.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + assert client_1.operating_state == NodeOperatingState.ON + + # turn it off + action = ("NODE_SHUTDOWN", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.SHUTTING_DOWN + + for i in range(client_1.shut_down_duration + 1): + action = ("DONOTHING", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.OFF + + # turn it on + action = ("NODE_STARTUP", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.BOOTING + + for i in range(client_1.start_up_duration + 1): + action = ("DONOTHING", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.ON + + +def test_node_cannot_be_started_up_if_node_is_already_on(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that a node cannot be started up if it is already on.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + assert client_1.operating_state == NodeOperatingState.ON + + # turn it on + action = ("NODE_STARTUP", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.ON + + +def test_node_cannot_be_shut_down_if_node_is_already_off(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that a node cannot be shut down if it is already off.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + client_1.power_off() + + for i in range(client_1.shut_down_duration + 1): + action = ("DONOTHING", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.OFF + + # turn it ff + action = ("NODE_SHUTDOWN", {"node_id": 0}) + agent.store_action(action) + game.step() + + assert client_1.operating_state == NodeOperatingState.OFF diff --git a/tests/integration_tests/game_layer/actions/test_service_request_permission.py b/tests/integration_tests/game_layer/actions/test_service_request_permission.py new file mode 100644 index 00000000..3054c73b --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_service_request_permission.py @@ -0,0 +1,106 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.hardware.nodes.host.computer import Computer +from primaite.simulator.network.hardware.nodes.host.server import Server +from primaite.simulator.system.services.service import ServiceOperatingState + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_service_start(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator makes sure that the service is stopped before starting the service.""" + game, agent = game_and_agent_fixture + + server_1: Server = game.simulation.network.get_node_by_hostname("server_1") + dns_server = server_1.software_manager.software.get("DNSServer") + + dns_server.pause() + assert dns_server.operating_state == ServiceOperatingState.PAUSED + + action = ("NODE_SERVICE_START", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.PAUSED + + dns_server.stop() + + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_START", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + + assert dns_server.operating_state == ServiceOperatingState.RUNNING + + +def test_service_resume(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator checks if the service is paused before resuming.""" + game, agent = game_and_agent_fixture + + server_1: Server = game.simulation.network.get_node_by_hostname("server_1") + dns_server = server_1.software_manager.software.get("DNSServer") + + action = ("NODE_SERVICE_RESUME", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.RUNNING + + dns_server.pause() + + assert dns_server.operating_state == ServiceOperatingState.PAUSED + + action = ("NODE_SERVICE_RESUME", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + + assert dns_server.operating_state == ServiceOperatingState.RUNNING + + +def test_service_cannot_perform_actions_unless_running(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test to make sure that the service cannot perform certain actions while not running.""" + game, agent = game_and_agent_fixture + + server_1: Server = game.simulation.network.get_node_by_hostname("server_1") + dns_server = server_1.software_manager.software.get("DNSServer") + + dns_server.stop() + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_SCAN", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_PAUSE", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_RESUME", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_RESTART", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.STOPPED + + action = ("NODE_SERVICE_FIX", {"node_id": 1, "service_id": 0}) + agent.store_action(action) + game.step() + assert dns_server.operating_state == ServiceOperatingState.STOPPED From cbf54d442c37fb774b7e6708b9c2f3404df8bcaa Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Mon, 8 Jul 2024 15:17:35 +0100 Subject: [PATCH 11/42] #2623 Make it possible to view currently valid simulation requests --- src/primaite/simulator/core.py | 31 ++++++++++++++++----- src/primaite/simulator/domain/controller.py | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 8d8425ec..be5eb4b9 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -3,9 +3,10 @@ """Core of the PrimAITE Simulator.""" import warnings from abc import abstractmethod -from typing import Callable, Dict, List, Literal, Optional, Union +from typing import Callable, Dict, List, Literal, Optional, Tuple, Union from uuid import uuid4 +from prettytable import PrettyTable from pydantic import BaseModel, ConfigDict, Field, validate_call from primaite import getLogger @@ -150,18 +151,34 @@ class RequestManager(BaseModel): self.request_types.pop(name) - def get_request_types_recursively(self) -> List[List[str]]: - """Recursively generate request tree for this component.""" + def get_request_types_recursively(self, _parent_valid: bool = True) -> List[Tuple[RequestFormat, bool]]: + """ + Recursively generate request tree for this component. + + :param parent_valid: Whether this sub-request's parent request was valid. This value should not be specified by + users, it is used by the recursive call. + :type parent_valid: bool + :returns: A list of tuples where the first tuple element is the request string and the second is whether that + request is currently possible to execute. + :rtype: List[Tuple[RequestFormat, bool]] + """ requests = [] for req_name, req in self.request_types.items(): + valid = req.validator([], {}) and _parent_valid # if parent is invalid, all children are invalid if isinstance(req.func, RequestManager): - sub_requests = req.func.get_request_types_recursively() - sub_requests = [[req_name] + a for a in sub_requests] + sub_requests = req.func.get_request_types_recursively(valid) # recurse + sub_requests = [([req_name] + a, valid) for a, valid in sub_requests] # prepend parent request to leaf requests.extend(sub_requests) - else: - requests.append([req_name]) + else: # leaf node found + requests.append(([req_name], valid)) return requests + def show(self) -> None: + table = PrettyTable(["request", "valid"]) + table.align = "l" + table.add_rows(self.get_request_types_recursively()) + print(table) + class SimComponent(BaseModel): """Extension of pydantic BaseModel with additional methods that must be defined by all classes in the simulator.""" diff --git a/src/primaite/simulator/domain/controller.py b/src/primaite/simulator/domain/controller.py index 37e60aaa..a264ba24 100644 --- a/src/primaite/simulator/domain/controller.py +++ b/src/primaite/simulator/domain/controller.py @@ -52,6 +52,8 @@ class GroupMembershipValidator(RequestPermissionValidator): def __call__(self, request: List[str], context: Dict) -> bool: """Permit the action if the request comes from an account which belongs to the right group.""" # if context request source is part of any groups mentioned in self.allow_groups, return true, otherwise false + if not context: + return False requestor_groups: List[str] = context["request_source"]["groups"] for allowed_group in self.allowed_groups: if allowed_group.name in requestor_groups: From a3f74087fa27f0830f688cd4adb4837c297759f2 Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Mon, 8 Jul 2024 15:26:30 +0100 Subject: [PATCH 12/42] #2688: refactor test classes --- tests/conftest.py | 12 ++++---- .../test_software_fix_duration.py | 2 +- .../network/test_broadcast.py | 30 +++++++++---------- .../system/test_application_on_node.py | 4 +-- .../test_simulation/test_request_response.py | 12 ++++---- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e36a2460..e3c84e6d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -51,11 +51,11 @@ class TestService(Service): pass -class TestDummyApplication(Application, identifier="TestDummyApplication"): +class DummyApplication(Application, identifier="DummyApplication"): """Test Application class""" def __init__(self, **kwargs): - kwargs["name"] = "TestDummyApplication" + kwargs["name"] = "DummyApplication" kwargs["port"] = Port.HTTP kwargs["protocol"] = IPProtocol.TCP super().__init__(**kwargs) @@ -85,9 +85,9 @@ def service_class(): @pytest.fixture(scope="function") -def application(file_system) -> TestDummyApplication: - return TestDummyApplication( - name="TestDummyApplication", +def application(file_system) -> DummyApplication: + return DummyApplication( + name="DummyApplication", port=Port.ARP, file_system=file_system, sys_log=SysLog(hostname="dummy_application"), @@ -96,7 +96,7 @@ def application(file_system) -> TestDummyApplication: @pytest.fixture(scope="function") def application_class(): - return TestDummyApplication + return DummyApplication @pytest.fixture(scope="function") diff --git a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py b/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py index 04160f8f..ae4825ff 100644 --- a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py +++ b/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py @@ -16,7 +16,7 @@ from tests import TEST_ASSETS_ROOT TEST_CONFIG = TEST_ASSETS_ROOT / "configs/software_fix_duration.yaml" ONE_ITEM_CONFIG = TEST_ASSETS_ROOT / "configs/fix_duration_one_item.yaml" -TestApplications = ["TestDummyApplication", "TestBroadcastClient"] +TestApplications = ["DummyApplication", "BroadcastTestClient"] def load_config(config_path: Union[str, Path]) -> PrimaiteGame: diff --git a/tests/integration_tests/network/test_broadcast.py b/tests/integration_tests/network/test_broadcast.py index bcf7b9b0..80007c46 100644 --- a/tests/integration_tests/network/test_broadcast.py +++ b/tests/integration_tests/network/test_broadcast.py @@ -14,7 +14,7 @@ from primaite.simulator.system.applications.application import Application from primaite.simulator.system.services.service import Service -class TestBroadcastService(Service): +class BroadcastTestService(Service): """A service for sending broadcast and unicast messages over a network.""" def __init__(self, **kwargs): @@ -41,14 +41,14 @@ class TestBroadcastService(Service): super().send(payload="broadcast", dest_ip_address=ip_network, dest_port=Port.HTTP, ip_protocol=self.protocol) -class TestBroadcastClient(Application, identifier="TestBroadcastClient"): +class BroadcastTestClient(Application, identifier="BroadcastTestClient"): """A client application to receive broadcast and unicast messages.""" payloads_received: List = [] def __init__(self, **kwargs): # Set default client properties - kwargs["name"] = "TestBroadcastClient" + kwargs["name"] = "BroadcastTestClient" kwargs["port"] = Port.HTTP kwargs["protocol"] = IPProtocol.TCP super().__init__(**kwargs) @@ -75,8 +75,8 @@ def broadcast_network() -> Network: start_up_duration=0, ) client_1.power_on() - client_1.software_manager.install(TestBroadcastClient) - application_1 = client_1.software_manager.software["TestBroadcastClient"] + client_1.software_manager.install(BroadcastTestClient) + application_1 = client_1.software_manager.software["BroadcastTestClient"] application_1.run() client_2 = Computer( @@ -87,8 +87,8 @@ def broadcast_network() -> Network: start_up_duration=0, ) client_2.power_on() - client_2.software_manager.install(TestBroadcastClient) - application_2 = client_2.software_manager.software["TestBroadcastClient"] + client_2.software_manager.install(BroadcastTestClient) + application_2 = client_2.software_manager.software["BroadcastTestClient"] application_2.run() server_1 = Server( @@ -100,8 +100,8 @@ def broadcast_network() -> Network: ) server_1.power_on() - server_1.software_manager.install(TestBroadcastService) - service: TestBroadcastService = server_1.software_manager.software["BroadcastService"] + server_1.software_manager.install(BroadcastTestService) + service: BroadcastTestService = server_1.software_manager.software["BroadcastService"] service.start() switch_1 = Switch(hostname="switch_1", num_ports=6, start_up_duration=0) @@ -117,14 +117,14 @@ def broadcast_network() -> Network: @pytest.fixture(scope="function") def broadcast_service_and_clients( broadcast_network, -) -> Tuple[TestBroadcastService, TestBroadcastClient, TestBroadcastClient]: - client_1: TestBroadcastClient = broadcast_network.get_node_by_hostname("client_1").software_manager.software[ - "TestBroadcastClient" +) -> Tuple[BroadcastTestService, BroadcastTestClient, BroadcastTestClient]: + client_1: BroadcastTestClient = broadcast_network.get_node_by_hostname("client_1").software_manager.software[ + "BroadcastTestClient" ] - client_2: TestBroadcastClient = broadcast_network.get_node_by_hostname("client_2").software_manager.software[ - "TestBroadcastClient" + client_2: BroadcastTestClient = broadcast_network.get_node_by_hostname("client_2").software_manager.software[ + "BroadcastTestClient" ] - service: TestBroadcastService = broadcast_network.get_node_by_hostname("server_1").software_manager.software[ + service: BroadcastTestService = broadcast_network.get_node_by_hostname("server_1").software_manager.software[ "BroadcastService" ] diff --git a/tests/integration_tests/system/test_application_on_node.py b/tests/integration_tests/system/test_application_on_node.py index 400ab082..ffb5cc7f 100644 --- a/tests/integration_tests/system/test_application_on_node.py +++ b/tests/integration_tests/system/test_application_on_node.py @@ -21,7 +21,7 @@ def populated_node(application_class) -> Tuple[Application, Computer]: computer.power_on() computer.software_manager.install(application_class) - app = computer.software_manager.software.get("TestDummyApplication") + app = computer.software_manager.software.get("DummyApplication") app.run() return app, computer @@ -39,7 +39,7 @@ def test_application_on_offline_node(application_class): ) computer.software_manager.install(application_class) - app: Application = computer.software_manager.software.get("TestDummyApplication") + app: Application = computer.software_manager.software.get("DummyApplication") computer.power_off() diff --git a/tests/integration_tests/test_simulation/test_request_response.py b/tests/integration_tests/test_simulation/test_request_response.py index 29c70566..a9f0b58d 100644 --- a/tests/integration_tests/test_simulation/test_request_response.py +++ b/tests/integration_tests/test_simulation/test_request_response.py @@ -13,7 +13,7 @@ from primaite.simulator.network.hardware.node_operating_state import NodeOperati from primaite.simulator.network.hardware.nodes.host.host_node import HostNode from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router from primaite.simulator.network.transmission.transport_layer import Port -from tests.conftest import TestDummyApplication, TestService +from tests.conftest import DummyApplication, TestService def test_successful_node_file_system_creation_request(example_network): @@ -47,14 +47,14 @@ def test_successful_application_requests(example_network): net = example_network client_1 = net.get_node_by_hostname("client_1") - client_1.software_manager.install(TestDummyApplication) - client_1.software_manager.software.get("TestDummyApplication").run() + client_1.software_manager.install(DummyApplication) + client_1.software_manager.software.get("DummyApplication").run() - resp_1 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "scan"]) + resp_1 = net.apply_request(["node", "client_1", "application", "DummyApplication", "scan"]) assert resp_1 == RequestResponse(status="success", data={}) - resp_2 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "fix"]) + resp_2 = net.apply_request(["node", "client_1", "application", "DummyApplication", "fix"]) assert resp_2 == RequestResponse(status="success", data={}) - resp_3 = net.apply_request(["node", "client_1", "application", "TestDummyApplication", "compromise"]) + resp_3 = net.apply_request(["node", "client_1", "application", "DummyApplication", "compromise"]) assert resp_3 == RequestResponse(status="success", data={}) From 470fa28ee1b38b9596b99af90cd5337018dbb6cf Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Tue, 9 Jul 2024 13:13:13 +0100 Subject: [PATCH 13/42] 2623 Implement basic action masking logic --- src/primaite/game/agent/actions.py | 38 +++++++++++++++-------------- src/primaite/session/environment.py | 23 ++++++++++++++++- src/primaite/simulator/core.py | 19 ++++++++++++++- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/src/primaite/game/agent/actions.py b/src/primaite/game/agent/actions.py index b3b7189c..9a5fedc9 100644 --- a/src/primaite/game/agent/actions.py +++ b/src/primaite/game/agent/actions.py @@ -49,7 +49,7 @@ class AbstractAction(ABC): objects.""" @abstractmethod - def form_request(self) -> List[str]: + def form_request(self) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return [] @@ -67,7 +67,7 @@ class DoNothingAction(AbstractAction): # i.e. a choice between one option. To make enumerating this action easier, we are adding a 'dummy' paramter # with one option. This just aids the Action Manager to enumerate all possibilities. - def form_request(self, **kwargs) -> List[str]: + def form_request(self, **kwargs) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return ["do_nothing"] @@ -86,7 +86,7 @@ class NodeServiceAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes, "service_id": num_services} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int, service_id: int) -> List[str]: + def form_request(self, node_id: int, service_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) service_name = self.manager.get_service_name_by_idx(node_id, service_id) @@ -181,7 +181,7 @@ class NodeApplicationAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes, "application_id": num_applications} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int, application_id: int) -> List[str]: + def form_request(self, node_id: int, application_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) application_name = self.manager.get_application_name_by_idx(node_id, application_id) @@ -229,7 +229,7 @@ class NodeApplicationInstallAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"node_id": num_nodes} - def form_request(self, node_id: int, application_name: str) -> List[str]: + def form_request(self, node_id: int, application_name: str) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None: @@ -324,7 +324,7 @@ class NodeApplicationRemoveAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"node_id": num_nodes} - def form_request(self, node_id: int, application_name: str) -> List[str]: + def form_request(self, node_id: int, application_name: str) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None: @@ -346,7 +346,7 @@ class NodeFolderAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes, "folder_id": num_folders} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int, folder_id: int) -> List[str]: + def form_request(self, node_id: int, folder_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) folder_name = self.manager.get_folder_name_by_idx(node_idx=node_id, folder_idx=folder_id) @@ -394,7 +394,9 @@ class NodeFileCreateAction(AbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs) self.verb: str = "create" - def form_request(self, node_id: int, folder_name: str, file_name: str, force: Optional[bool] = False) -> List[str]: + def form_request( + self, node_id: int, folder_name: str, file_name: str, force: Optional[bool] = False + ) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None or folder_name is None or file_name is None: @@ -409,7 +411,7 @@ class NodeFolderCreateAction(AbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs) self.verb: str = "create" - def form_request(self, node_id: int, folder_name: str) -> List[str]: + def form_request(self, node_id: int, folder_name: str) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None or folder_name is None: @@ -430,7 +432,7 @@ class NodeFileAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes, "folder_id": num_folders, "file_id": num_files} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int, folder_id: int, file_id: int) -> List[str]: + def form_request(self, node_id: int, folder_id: int, file_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) folder_name = self.manager.get_folder_name_by_idx(node_idx=node_id, folder_idx=folder_id) @@ -463,7 +465,7 @@ class NodeFileDeleteAction(NodeFileAbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, num_files=num_files, **kwargs) self.verb: str = "delete" - def form_request(self, node_id: int, folder_id: int, file_id: int) -> List[str]: + def form_request(self, node_id: int, folder_id: int, file_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) folder_name = self.manager.get_folder_name_by_idx(node_idx=node_id, folder_idx=folder_id) @@ -504,7 +506,7 @@ class NodeFileAccessAction(AbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs) self.verb: str = "access" - def form_request(self, node_id: int, folder_name: str, file_name: str) -> List[str]: + def form_request(self, node_id: int, folder_name: str, file_name: str) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None or folder_name is None or file_name is None: @@ -525,7 +527,7 @@ class NodeAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int) -> List[str]: + def form_request(self, node_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) return ["network", "node", node_name, self.verb] @@ -740,7 +742,7 @@ class RouterACLRemoveRuleAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"position": max_acl_rules} - def form_request(self, target_router: str, position: int) -> List[str]: + def form_request(self, target_router: str, position: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return ["network", "node", target_router, "acl", "remove_rule", position] @@ -923,7 +925,7 @@ class HostNICAbstractAction(AbstractAction): self.shape: Dict[str, int] = {"node_id": num_nodes, "nic_id": max_nics_per_node} self.verb: str # define but don't initialise: defends against children classes not defining this - def form_request(self, node_id: int, nic_id: int) -> List[str]: + def form_request(self, node_id: int, nic_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_idx=node_id) nic_num = self.manager.get_nic_num_by_idx(node_idx=node_id, nic_idx=nic_id) @@ -960,7 +962,7 @@ class NetworkPortEnableAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"port_id": max_nics_per_node} - def form_request(self, target_nodename: str, port_id: int) -> List[str]: + def form_request(self, target_nodename: str, port_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" if target_nodename is None or port_id is None: return ["do_nothing"] @@ -979,7 +981,7 @@ class NetworkPortDisableAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"port_id": max_nics_per_node} - def form_request(self, target_nodename: str, port_id: int) -> List[str]: + def form_request(self, target_nodename: str, port_id: int) -> RequestFormat: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" if target_nodename is None or port_id is None: return ["do_nothing"] @@ -1315,7 +1317,7 @@ class ActionManager: act_identifier, act_options = self.action_map[action] return act_identifier, act_options - def form_request(self, action_identifier: str, action_options: Dict) -> List[str]: + def form_request(self, action_identifier: str, action_options: Dict) -> RequestFormat: """Take action in CAOS format and use the execution definition to change it into PrimAITE request format.""" act_obj = self.actions[action_identifier] return act_obj.form_request(**action_options) diff --git a/src/primaite/session/environment.py b/src/primaite/session/environment.py index 6cc1282f..aa2bc308 100644 --- a/src/primaite/session/environment.py +++ b/src/primaite/session/environment.py @@ -1,7 +1,7 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK import json from os import PathLike -from typing import Any, Dict, Optional, SupportsFloat, Tuple, Union +from typing import Any, Dict, List, Optional, SupportsFloat, Tuple, Union import gymnasium from gymnasium.core import ActType, ObsType @@ -40,6 +40,27 @@ class PrimaiteGymEnv(gymnasium.Env): """Current episode number.""" self.total_reward_per_episode: Dict[int, float] = {} """Average rewards of agents per episode.""" + self.action_masking: bool = False + """Whether to use action masking.""" + + def action_masks(self) -> List[bool]: + """ + Return the action mask for the agent. + + This is a boolean list corresponding to the agent's action space. A False entry means this action cannot be + performed during this step. + + :return: Action mask + :rtype: List[bool] + """ + mask = [True] * len(self.agent.action_manager.action_map) + if not self.action_masking: + return mask + + for i, action in self.agent.action_manager.action_map.items(): + request = self.agent.action_manager.form_request(action_identifier=action[0], action_options=action[1]) + mask[i] = self.game.simulation._request_manager.check_valid(request, {}) + return mask @property def agent(self) -> ProxyAgent: diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index be5eb4b9..7653a3ab 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -3,7 +3,7 @@ """Core of the PrimAITE Simulator.""" import warnings from abc import abstractmethod -from typing import Callable, Dict, List, Literal, Optional, Tuple, Union +from typing import Callable, Dict, Iterable, List, Literal, Optional, Tuple, Union from uuid import uuid4 from prettytable import PrettyTable @@ -179,6 +179,23 @@ class RequestManager(BaseModel): table.add_rows(self.get_request_types_recursively()) print(table) + def check_valid(self, request: RequestFormat, context: Dict) -> bool: + """Check if this request would be valid in the current state of the simulation without invoking it.""" + + request_key = request[0] + request_options = request[1:] + + if request_key not in self.request_types: + return False + + request_type = self.request_types[request_key] + + # recurse if we are not at a leaf node + if isinstance(request_type.func, RequestManager): + return request_type.func.check_valid(request_options, context) + + return request_type.validator(request_options, context) + class SimComponent(BaseModel): """Extension of pydantic BaseModel with additional methods that must be defined by all classes in the simulator.""" From 5367f9ad5376241ee40005381652cc13f628c53c Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Tue, 9 Jul 2024 15:27:03 +0100 Subject: [PATCH 14/42] 2623 Ray single agent action masking --- .../_package_data/data_manipulation.yaml | 1 + src/primaite/game/agent/interface.py | 3 + src/primaite/notebooks/Action-masking.ipynb | 184 ++++++++++++++++++ src/primaite/session/environment.py | 11 +- src/primaite/session/ray_envs.py | 31 ++- 5 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 src/primaite/notebooks/Action-masking.ipynb diff --git a/src/primaite/config/_package_data/data_manipulation.yaml b/src/primaite/config/_package_data/data_manipulation.yaml index 6d4ec9b4..97442903 100644 --- a/src/primaite/config/_package_data/data_manipulation.yaml +++ b/src/primaite/config/_package_data/data_manipulation.yaml @@ -741,6 +741,7 @@ agents: agent_settings: flatten_obs: true + action_masking: true diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py index 95468331..01b7fb0a 100644 --- a/src/primaite/game/agent/interface.py +++ b/src/primaite/game/agent/interface.py @@ -69,6 +69,8 @@ class AgentSettings(BaseModel): "Configuration for when an agent begins performing it's actions" flatten_obs: bool = True "Whether to flatten the observation space before passing it to the agent. True by default." + action_masking: bool = True + "Whether to return action masks at each step." @classmethod def from_config(cls, config: Optional[Dict]) -> "AgentSettings": @@ -205,6 +207,7 @@ class ProxyAgent(AbstractAgent): ) self.most_recent_action: ActType self.flatten_obs: bool = agent_settings.flatten_obs if agent_settings else False + self.action_masking: bool = agent_settings.action_masking if agent_settings else False def get_action(self, obs: ObsType, timestep: int = 0) -> Tuple[str, Dict]: """ diff --git a/src/primaite/notebooks/Action-masking.ipynb b/src/primaite/notebooks/Action-masking.ipynb new file mode 100644 index 00000000..822b8451 --- /dev/null +++ b/src/primaite/notebooks/Action-masking.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Action Masking\n", + "\n", + "PrimAITE environments support action masking. The action mask shows which of the agent's actions are applicable with the current environment state. For example, a node can only be turned on if it is currently turned off." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from primaite.session.environment import PrimaiteGymEnv\n", + "from primaite.config.load import data_manipulation_config_path\n", + "from prettytable import PrettyTable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "env = PrimaiteGymEnv(data_manipulation_config_path())\n", + "env.action_masking = True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The action mask is a list of booleans that specifies whether each action in the agent's action map is currently possible. Demonstrated here:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "act_table = PrettyTable((\"number\", \"action\", \"parameters\", \"mask\"))\n", + "mask = env.action_masks()\n", + "actions = env.agent.action_manager.action_map\n", + "max_str_len = 70\n", + "for act,mask in zip(actions.items(), mask):\n", + " act_num, act_data = act\n", + " act_type, act_params = act_data\n", + " act_params = s if len(s:=str(act_params)) List[bool]: + def action_masks(self) -> np.ndarray: """ Return the action mask for the agent. @@ -54,13 +53,13 @@ class PrimaiteGymEnv(gymnasium.Env): :rtype: List[bool] """ mask = [True] * len(self.agent.action_manager.action_map) - if not self.action_masking: + if not self.agent.action_masking: return mask for i, action in self.agent.action_manager.action_map.items(): request = self.agent.action_manager.form_request(action_identifier=action[0], action_options=action[1]) mask[i] = self.game.simulation._request_manager.check_valid(request, {}) - return mask + return np.asarray(mask) @property def agent(self) -> ProxyAgent: diff --git a/src/primaite/session/ray_envs.py b/src/primaite/session/ray_envs.py index fc5d73d8..1fc7624f 100644 --- a/src/primaite/session/ray_envs.py +++ b/src/primaite/session/ray_envs.py @@ -3,6 +3,7 @@ import json from typing import Dict, SupportsFloat, Tuple import gymnasium +from gymnasium import spaces from gymnasium.core import ActType, ObsType from ray.rllib.env.multi_agent_env import MultiAgentEnv @@ -38,15 +39,10 @@ class PrimaiteRayMARLEnv(MultiAgentEnv): self.terminateds = set() self.truncateds = set() - self.observation_space = gymnasium.spaces.Dict( - { - name: gymnasium.spaces.flatten_space(agent.observation_manager.space) - for name, agent in self.agents.items() - } - ) - self.action_space = gymnasium.spaces.Dict( - {name: agent.action_manager.space for name, agent in self.agents.items()} + self.observation_space = spaces.Dict( + {name: spaces.flatten_space(agent.observation_manager.space) for name, agent in self.agents.items()} ) + self.action_space = spaces.Dict({name: agent.action_manager.space for name, agent in self.agents.items()}) self._obs_space_in_preferred_format = True self._action_space_in_preferred_format = True super().__init__() @@ -158,15 +154,30 @@ class PrimaiteRayEnv(gymnasium.Env): self.env = PrimaiteGymEnv(env_config=env_config) # self.env.episode_counter -= 1 self.action_space = self.env.action_space - self.observation_space = self.env.observation_space + if self.env.agent.action_masking: + self.observation_space = spaces.Dict( + {"action_mask": spaces.MultiBinary(self.env.action_space.n), "observations": self.env.observation_space} + ) + else: + self.observation_space = self.env.observation_space def reset(self, *, seed: int = None, options: dict = None) -> Tuple[ObsType, Dict]: """Reset the environment.""" + if self.env.agent.action_masking: + obs, *_ = self.env.reset(seed=seed) + new_obs = {"action_mask": self.env.action_masks(), "observations": obs} + return new_obs, *_ return self.env.reset(seed=seed) def step(self, action: ActType) -> Tuple[ObsType, SupportsFloat, bool, bool, Dict]: """Perform a step in the environment.""" - return self.env.step(action) + # if action masking is enabled, intercept the step method and add action mask to observation + if self.env.agent.action_masking: + obs, *_ = self.env.step(action) + new_obs = {"action_mask": self.env.action_masks(), "observations": obs} + return new_obs, *_ + else: + return self.env.step(action) def close(self): """Close the simulation.""" From faf268a9b9b4fd847bab7f31518b8488dadc169b Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Tue, 9 Jul 2024 15:59:50 +0100 Subject: [PATCH 15/42] 2623 move action mask generation to game and fix MARL masking --- .../_package_data/data_manipulation_marl.yaml | 2 + src/primaite/config/load.py | 15 ++++++ src/primaite/game/game.py | 18 +++++++ src/primaite/notebooks/Action-masking.ipynb | 53 ++++++++++++++++--- src/primaite/session/environment.py | 10 ++-- src/primaite/session/ray_envs.py | 19 +++++-- 6 files changed, 101 insertions(+), 16 deletions(-) diff --git a/src/primaite/config/_package_data/data_manipulation_marl.yaml b/src/primaite/config/_package_data/data_manipulation_marl.yaml index 2e8221a0..ba666781 100644 --- a/src/primaite/config/_package_data/data_manipulation_marl.yaml +++ b/src/primaite/config/_package_data/data_manipulation_marl.yaml @@ -733,6 +733,7 @@ agents: agent_settings: flatten_obs: true + action_masking: true - ref: defender_2 team: BLUE @@ -1316,6 +1317,7 @@ agents: agent_settings: flatten_obs: true + action_masking: true diff --git a/src/primaite/config/load.py b/src/primaite/config/load.py index 3483fc87..144e0733 100644 --- a/src/primaite/config/load.py +++ b/src/primaite/config/load.py @@ -44,3 +44,18 @@ def data_manipulation_config_path() -> Path: _LOGGER.error(msg) raise FileNotFoundError(msg) return path + + +def data_manipulation_marl_config_path() -> Path: + """ + Get the path to the MARL example config. + + :return: Path to yaml config file for the MARL scenario. + :rtype: Path + """ + path = _EXAMPLE_CFG / "data_manipulation_marl.yaml" + if not path.exists(): + msg = f"Example config does not exist: {path}. Have you run `primaite setup`?" + _LOGGER.error(msg) + raise FileNotFoundError(msg) + return path diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 3dc9571f..e7d13061 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -3,6 +3,7 @@ from ipaddress import IPv4Address from typing import Dict, List, Optional +import numpy as np from pydantic import BaseModel, ConfigDict from primaite import DEFAULT_BANDWIDTH, getLogger @@ -192,6 +193,23 @@ class PrimaiteGame: return True return False + def action_mask(self, agent_name: str) -> np.ndarray: + """ + Return the action mask for the agent. + + This is a boolean list corresponding to the agent's action space. A False entry means this action cannot be + performed during this step. + + :return: Action mask + :rtype: List[bool] + """ + agent = self.agents[agent_name] + mask = [True] * len(agent.action_manager.action_map) + for i, action in agent.action_manager.action_map.items(): + request = agent.action_manager.form_request(action_identifier=action[0], action_options=action[1]) + mask[i] = self.simulation._request_manager.check_valid(request, {}) + return np.asarray(mask) + def close(self) -> None: """Close the game, this will close the simulation.""" return NotImplemented diff --git a/src/primaite/notebooks/Action-masking.ipynb b/src/primaite/notebooks/Action-masking.ipynb index 822b8451..8090dacc 100644 --- a/src/primaite/notebooks/Action-masking.ipynb +++ b/src/primaite/notebooks/Action-masking.ipynb @@ -96,7 +96,7 @@ "metadata": {}, "outputs": [], "source": [ - "from primaite.session.ray_envs import PrimaiteRayEnv, PrimaiteRayMARLEnv\n", + "from primaite.session.ray_envs import PrimaiteRayEnv\n", "from ray.rllib.algorithms.ppo import PPOConfig\n", "import yaml\n", "from ray import air, tune\n" @@ -146,18 +146,59 @@ ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], - "source": [] + "source": [ + "## Action masking with MARL in Ray RLLib\n", + "Each agent has their own action mask, this is useful if the agents have different action spaces." + ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], - "source": [] + "source": [ + "from primaite.session.ray_envs import PrimaiteRayMARLEnv\n", + "from primaite.config.load import data_manipulation_marl_config_path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open(data_manipulation_marl_config_path(), 'r') as f:\n", + " cfg = yaml.safe_load(f)\n", + "env_config = cfg\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "config = (\n", + " PPOConfig()\n", + " .multi_agent(\n", + " policies={'defender_1','defender_2'}, # These names are the same as the agents defined in the example config.\n", + " policy_mapping_fn=lambda agent_id, episode, worker, **kw: agent_id,\n", + " )\n", + " .environment(env=PrimaiteRayMARLEnv, env_config=cfg)\n", + " .env_runners(num_env_runners=0)\n", + " .training(train_batch_size=128)\n", + " )\n", + "\n", + "tune.Tuner(\n", + " \"PPO\",\n", + " run_config=air.RunConfig(\n", + " stop={\"timesteps_total\": 5 * 128},\n", + " ),\n", + " param_space=config\n", + ").fit()" + ] } ], "metadata": { diff --git a/src/primaite/session/environment.py b/src/primaite/session/environment.py index 0520cce9..a87f0cde 100644 --- a/src/primaite/session/environment.py +++ b/src/primaite/session/environment.py @@ -52,14 +52,10 @@ class PrimaiteGymEnv(gymnasium.Env): :return: Action mask :rtype: List[bool] """ - mask = [True] * len(self.agent.action_manager.action_map) if not self.agent.action_masking: - return mask - - for i, action in self.agent.action_manager.action_map.items(): - request = self.agent.action_manager.form_request(action_identifier=action[0], action_options=action[1]) - mask[i] = self.game.simulation._request_manager.check_valid(request, {}) - return np.asarray(mask) + return np.asarray([True] * len(self.agent.action_manager.action_map)) + else: + return self.game.action_mask(self._agent_name) @property def agent(self) -> ProxyAgent: diff --git a/src/primaite/session/ray_envs.py b/src/primaite/session/ray_envs.py index 1fc7624f..12167f89 100644 --- a/src/primaite/session/ray_envs.py +++ b/src/primaite/session/ray_envs.py @@ -42,6 +42,15 @@ class PrimaiteRayMARLEnv(MultiAgentEnv): self.observation_space = spaces.Dict( {name: spaces.flatten_space(agent.observation_manager.space) for name, agent in self.agents.items()} ) + for agent_name in self._agent_ids: + agent = self.game.rl_agents[agent_name] + if agent.action_masking: + self.observation_space[agent_name] = spaces.Dict( + { + "action_mask": spaces.MultiBinary(agent.action_manager.space.n), + "observations": self.observation_space[agent_name], + } + ) self.action_space = spaces.Dict({name: agent.action_manager.space for name, agent in self.agents.items()}) self._obs_space_in_preferred_format = True self._action_space_in_preferred_format = True @@ -127,13 +136,17 @@ class PrimaiteRayMARLEnv(MultiAgentEnv): def _get_obs(self) -> Dict[str, ObsType]: """Return the current observation.""" - obs = {} + all_obs = {} for agent_name in self._agent_ids: agent = self.game.rl_agents[agent_name] unflat_space = agent.observation_manager.space unflat_obs = agent.observation_manager.current_observation - obs[agent_name] = gymnasium.spaces.flatten(unflat_space, unflat_obs) - return obs + obs = gymnasium.spaces.flatten(unflat_space, unflat_obs) + if agent.action_masking: + all_obs[agent_name] = {"action_mask": self.game.action_mask(agent_name), "observations": obs} + else: + all_obs[agent_name] = obs + return all_obs def close(self): """Close the simulation.""" From 20b9b61be58b218c59abaa5478bbb3852600361f Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Tue, 9 Jul 2024 16:44:02 +0100 Subject: [PATCH 16/42] #2740: added ability to merge validators + validators for folders --- src/primaite/simulator/core.py | 14 ++ .../simulator/file_system/file_system.py | 83 +++++++++++- src/primaite/simulator/file_system/folder.py | 30 ++++- .../actions/test_file_request_permission.py | 82 ++++++++++++ .../actions/test_folder_request_permission.py | 123 ++++++++++++++++++ .../actions/test_nic_request_permission.py | 2 - 6 files changed, 323 insertions(+), 11 deletions(-) create mode 100644 tests/integration_tests/game_layer/actions/test_file_request_permission.py create mode 100644 tests/integration_tests/game_layer/actions/test_folder_request_permission.py diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 8d8425ec..70485af5 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -34,6 +34,20 @@ class RequestPermissionValidator(BaseModel): """Message that is reported when a request is rejected by this validator.""" return "request rejected" + def __add__(self, other: "RequestPermissionValidator") -> "_CombinedValidator": + return _CombinedValidator(validators=[self, other]) + + +class _CombinedValidator(RequestPermissionValidator): + validators: List[RequestPermissionValidator] = [] + + def __call__(self, request, context) -> bool: + return all(x(request, context) for x in self.validators) + + @property + def fail_message(self): + return f"One of the following conditions are not met: {[v.fail_message for v in self.validators]}" + class AllowAllValidator(RequestPermissionValidator): """Always allows the request.""" diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index 456b800c..42aa0573 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -6,8 +6,8 @@ from typing import Any, Dict, List, Optional from prettytable import MARKDOWN, PrettyTable -from primaite.interface.request import RequestResponse -from primaite.simulator.core import RequestManager, RequestType, SimComponent +from primaite.interface.request import RequestFormat, RequestResponse +from primaite.simulator.core import RequestManager, RequestPermissionValidator, RequestType, SimComponent from primaite.simulator.file_system.file import File from primaite.simulator.file_system.file_type import FileType from primaite.simulator.file_system.folder import Folder @@ -42,6 +42,10 @@ class FileSystem(SimComponent): More information in user guide and docstring for SimComponent._init_request_manager. """ + self._folder_exists = FileSystem._FolderExistsValidator(file_system=self) + self._folder_deleted = FileSystem._FolderNotDeletedValidator(file_system=self) + self._file_exists = FileSystem._FileExistsValidator(file_system=self) + rm = super()._init_request_manager() self._delete_manager = RequestManager() @@ -50,13 +54,15 @@ class FileSystem(SimComponent): request_type=RequestType( func=lambda request, context: RequestResponse.from_bool( self.delete_file(folder_name=request[0], file_name=request[1]) - ) + ), + validator=self._file_exists, ), ) self._delete_manager.add_request( name="folder", request_type=RequestType( - func=lambda request, context: RequestResponse.from_bool(self.delete_folder(folder_name=request[0])) + func=lambda request, context: RequestResponse.from_bool(self.delete_folder(folder_name=request[0])), + validator=self._folder_exists, ), ) rm.add_request( @@ -144,10 +150,13 @@ class FileSystem(SimComponent): ) self._folder_request_manager = RequestManager() - rm.add_request("folder", RequestType(func=self._folder_request_manager)) + rm.add_request( + "folder", + RequestType(func=self._folder_request_manager, validator=self._folder_exists + self._folder_deleted), + ) self._file_request_manager = RequestManager() - rm.add_request("file", RequestType(func=self._file_request_manager)) + rm.add_request("file", RequestType(func=self._file_request_manager, validator=self._file_exists)) return rm @@ -626,3 +635,65 @@ class FileSystem(SimComponent): self.sys_log.error(f"Unable to access file that does not exist. (file name: {file_name})") return False + + class _FolderExistsValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the Folder exists. + + Actions cannot be performed on a non-existent folder. + """ + + file_system: FileSystem + """Save a reference to the FileSystem instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Returns True if folder exists.""" + return self.file_system.get_folder(folder_name=request[0]) is not None + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return "Cannot perform request on folder because it does not exist" + + class _FolderNotDeletedValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the Folder has not been deleted. + + Actions cannot be performed on a deleted folder. + """ + + file_system: FileSystem + """Save a reference to the FileSystem instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Returns True if folder exists and is not deleted.""" + # get folder + folder = self.file_system.get_folder(folder_name=request[0], include_deleted=True) + return folder is not None and not folder.deleted + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return "Cannot perform request on folder because it is deleted." + + class _FileExistsValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the File exists. + + Actions cannot be performed on a non-existent file. + """ + + file_system: FileSystem + """Save a reference to the FileSystem instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Returns True if file exists.""" + return self.file_system.get_file(folder_name=request[0], file_name=request[1]) is not None + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on application '{self.application.name}' because it is not in the " + f"{self.state.name} state." + ) diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index dd2a4c70..af7cc660 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -6,8 +6,8 @@ from typing import Dict, Optional from prettytable import MARKDOWN, PrettyTable -from primaite.interface.request import RequestResponse -from primaite.simulator.core import RequestManager, RequestType +from primaite.interface.request import RequestFormat, RequestResponse +from primaite.simulator.core import RequestManager, RequestPermissionValidator, RequestType from primaite.simulator.file_system.file import File from primaite.simulator.file_system.file_system_item_abc import FileSystemItemABC, FileSystemItemHealthStatus @@ -55,6 +55,8 @@ class Folder(FileSystemItemABC): More information in user guide and docstring for SimComponent._init_request_manager. """ + self._file_exists = Folder._FileExistsValidator(folder=self) + rm = super()._init_request_manager() rm.add_request( name="delete", @@ -65,7 +67,7 @@ class Folder(FileSystemItemABC): self._file_request_manager = RequestManager() rm.add_request( name="file", - request_type=RequestType(func=self._file_request_manager), + request_type=RequestType(func=self._file_request_manager, validator=self._file_exists), ) return rm @@ -469,3 +471,25 @@ class Folder(FileSystemItemABC): self.deleted = True return True + + class _FileExistsValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the File exists. + + Actions cannot be performed on a non-existent file. + """ + + folder: Folder + """Save a reference to the Folder instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Returns True if file exists.""" + return self.folder.get_file(file_name=request[0]) is not None + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return ( + f"Cannot perform request on application '{self.application.name}' because it is not in the " + f"{self.state.name} state." + ) diff --git a/tests/integration_tests/game_layer/actions/test_file_request_permission.py b/tests/integration_tests/game_layer/actions/test_file_request_permission.py new file mode 100644 index 00000000..c422ad43 --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_file_request_permission.py @@ -0,0 +1,82 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import uuid +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus +from primaite.simulator.network.hardware.nodes.host.computer import Computer + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_create_file(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a folder to be created.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + random_folder = str(uuid.uuid4()) + random_file = str(uuid.uuid4()) + + assert client_1.file_system.get_file(folder_name=random_folder, file_name=random_file) is None + + action = ( + "NODE_FILE_CREATE", + {"node_id": 0, "folder_name": random_folder, "file_name": random_file}, + ) + agent.store_action(action) + game.step() + + assert client_1.file_system.get_file(folder_name=random_folder, file_name=random_file) is not None + + +def test_file_delete_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a folder to be created.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + assert file.deleted is False + + action = ( + "NODE_FILE_DELETE", + {"node_id": 0, "folder_id": 0, "file_id": 0}, + ) + agent.store_action(action) + game.step() + + assert file.deleted + + +def test_file_scan_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a folder to be created.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + + file.corrupt() + assert file.health_status == FileSystemItemHealthStatus.CORRUPT + assert file.visible_health_status == FileSystemItemHealthStatus.GOOD + + action = ( + "NODE_FILE_SCAN", + {"node_id": 0, "folder_id": 0, "file_id": 0}, + ) + agent.store_action(action) + game.step() + + assert file.health_status == FileSystemItemHealthStatus.CORRUPT + assert file.visible_health_status == FileSystemItemHealthStatus.CORRUPT diff --git a/tests/integration_tests/game_layer/actions/test_folder_request_permission.py b/tests/integration_tests/game_layer/actions/test_folder_request_permission.py new file mode 100644 index 00000000..e5e0806a --- /dev/null +++ b/tests/integration_tests/game_layer/actions/test_folder_request_permission.py @@ -0,0 +1,123 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import uuid +from typing import Tuple + +import pytest + +from primaite.game.agent.interface import ProxyAgent +from primaite.game.game import PrimaiteGame +from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus +from primaite.simulator.network.hardware.nodes.host.computer import Computer + + +@pytest.fixture +def game_and_agent_fixture(game_and_agent): + """Create a game with a simple agent that can be controlled by the tests.""" + game, agent = game_and_agent + + client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") + client_1.start_up_duration = 3 + + return (game, agent) + + +def test_create_folder(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a folder to be created.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + random_folder = str(uuid.uuid4()) + + assert client_1.file_system.get_folder(folder_name=random_folder) is None + + action = ( + "NODE_FOLDER_CREATE", + { + "node_id": 0, + "folder_name": random_folder, + }, + ) + agent.store_action(action) + game.step() + + assert client_1.file_system.get_folder(folder_name=random_folder) is not None + + +def test_folder_scan_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test to make sure that the validator checks if the folder exists before scanning.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + folder = client_1.file_system.get_folder(folder_name="downloads") + assert folder.health_status == FileSystemItemHealthStatus.GOOD + assert folder.visible_health_status == FileSystemItemHealthStatus.GOOD + + folder.corrupt() + + assert folder.health_status == FileSystemItemHealthStatus.CORRUPT + assert folder.visible_health_status == FileSystemItemHealthStatus.GOOD + + action = ( + "NODE_FOLDER_SCAN", + { + "node_id": 0, # client_1, + "folder_id": 0, # downloads + }, + ) + agent.store_action(action) + game.step() + + for i in range(folder.scan_duration + 1): + game.step() + + assert folder.health_status == FileSystemItemHealthStatus.CORRUPT + assert folder.visible_health_status == FileSystemItemHealthStatus.CORRUPT + + +def test_folder_repair_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test to make sure that the validator checks if the folder exists before repairing.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + folder = client_1.file_system.get_folder(folder_name="downloads") + folder.corrupt() + assert folder.health_status == FileSystemItemHealthStatus.CORRUPT + + action = ( + "NODE_FOLDER_REPAIR", + { + "node_id": 0, # client_1, + "folder_id": 0, # downloads + }, + ) + agent.store_action(action) + game.step() + + assert folder.health_status == FileSystemItemHealthStatus.GOOD + + +def test_folder_restore_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test to make sure that the validator checks if the folder exists before restoring.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + folder = client_1.file_system.get_folder(folder_name="downloads") + folder.corrupt() + + assert folder.health_status == FileSystemItemHealthStatus.CORRUPT + + action = ( + "NODE_FOLDER_RESTORE", + { + "node_id": 0, # client_1, + "folder_id": 0, # downloads + }, + ) + agent.store_action(action) + game.step() + + assert folder.health_status == FileSystemItemHealthStatus.RESTORING diff --git a/tests/integration_tests/game_layer/actions/test_nic_request_permission.py b/tests/integration_tests/game_layer/actions/test_nic_request_permission.py index 4c1619e7..d796b75e 100644 --- a/tests/integration_tests/game_layer/actions/test_nic_request_permission.py +++ b/tests/integration_tests/game_layer/actions/test_nic_request_permission.py @@ -6,8 +6,6 @@ import pytest from primaite.game.agent.interface import ProxyAgent from primaite.game.game import PrimaiteGame from primaite.simulator.network.hardware.nodes.host.computer import Computer -from primaite.simulator.network.hardware.nodes.host.server import Server -from primaite.simulator.system.services.service import ServiceOperatingState @pytest.fixture From 48645d2e72adf0c66a48d8183952c959c02bedae Mon Sep 17 00:00:00 2001 From: "Archer.Bowen" Date: Tue, 9 Jul 2024 16:46:31 +0100 Subject: [PATCH 17/42] #2716 Initial Implementation + Initial Tests and updated changelog and sphinx documentation. --- CHANGELOG.md | 3 +- docs/source/configuration/io_settings.rst | 24 ++- src/primaite/game/agent/agent_log.py | 168 ++++++++++++++++++ src/primaite/game/agent/interface.py | 2 + .../scripted_agents/data_manipulation_bot.py | 4 +- .../scripted_agents/probabilistic_agent.py | 1 + src/primaite/session/io.py | 14 +- src/primaite/simulator/__init__.py | 34 ++++ .../configs/basic_switched_network.yaml | 3 + .../test_io_settings.py | 4 + .../_primaite/_game/_agent/test_agent_log.py | 137 ++++++++++++++ 11 files changed, 387 insertions(+), 7 deletions(-) create mode 100644 src/primaite/game/agent/agent_log.py create mode 100644 tests/unit_tests/_primaite/_game/_agent/test_agent_log.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 17bf3557..beec6d11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,8 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Activating dev-mode will change the location where the sessions will be output - by default will output where the PrimAITE repository is located - Refactored all air-space usage to that a new instance of AirSpace is created for each instance of Network. This 1:1 relationship between network and airspace will allow parallelization. - Added notebook to demonstrate use of SubprocVecEnv from SB3 to vectorise environments to speed up training. - - +- Added a new agent simulation log which are more human friendly than agent action logging. Includes timesteps so that the agent action log can be cross referenced. These Logs are found in simulation_output directory, similar to that of sys_logs and can be enabled in the I/O settings in a yaml configuration file. ## [Unreleased] - Made requests fail to reach their target if the node is off diff --git a/docs/source/configuration/io_settings.rst b/docs/source/configuration/io_settings.rst index 82fd7408..1c9585c9 100644 --- a/docs/source/configuration/io_settings.rst +++ b/docs/source/configuration/io_settings.rst @@ -18,8 +18,11 @@ This section configures how PrimAITE saves data during simulation and training. save_step_metadata: False save_pcap_logs: False save_sys_logs: False + save_agent_logs: False write_sys_log_to_terminal: False + write_agent_log_to_terminal: False sys_log_level: WARNING + agent_log_level: INFO ``save_logs`` @@ -57,6 +60,12 @@ Optional. Default value is ``False``. If ``True``, then the log files which contain all node actions during the simulation will be saved. +``save_agent_logs`` +----------------- + +Optional. Default value is ``False``. + +If ``True``, then the log files which contain all human readable agent behaviour during the simulation will be saved. ``write_sys_log_to_terminal`` ----------------------------- @@ -65,16 +74,25 @@ Optional. Default value is ``False``. If ``True``, PrimAITE will print sys log to the terminal. +``write_agent_log_to_terminal`` +----------------------------- -``sys_log_level`` -------------- +Optional. Default value is ``False``. + +If ``True``, PrimAITE will print all human readable agent behaviour logs to the terminal. + + +``sys_log_level & agent_log_level`` +--------------------------------- Optional. Default value is ``WARNING``. -The level of logging that should be visible in the sys logs or the logs output to the terminal. +The level of logging that should be visible in the syslog, agent logs or the logs output to the terminal. ``save_sys_logs`` or ``write_sys_log_to_terminal`` has to be set to ``True`` for this setting to be used. +This is also true for agent behaviour logging. + Available options are: - ``DEBUG``: Debug level items and the items below diff --git a/src/primaite/game/agent/agent_log.py b/src/primaite/game/agent/agent_log.py new file mode 100644 index 00000000..1e51dcad --- /dev/null +++ b/src/primaite/game/agent/agent_log.py @@ -0,0 +1,168 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import logging +from pathlib import Path + +from prettytable import MARKDOWN, PrettyTable + +from primaite.simulator import LogLevel, SIM_OUTPUT + + +class _NotJSONFilter(logging.Filter): + def filter(self, record: logging.LogRecord) -> bool: + """ + Determines if a log message does not start and end with '{' and '}' (i.e., it is not a JSON-like message). + + :param record: LogRecord object containing all the information pertinent to the event being logged. + :return: True if log message is not JSON-like, False otherwise. + """ + return not record.getMessage().startswith("{") and not record.getMessage().endswith("}") + + +class AgentLog: + """ + A Agent Log class is a simple logger dedicated to managing and writing logging updates and information for an agent. + + Each log message is written to a file located at: /agent/agent_name.log + """ + + def __init__(self, agent_name: str): + """ + Constructs a Agent Log instance for a given hostname. + + :param hostname: The hostname associated with the system logs being recorded. + """ + self.agent_name = agent_name + self.current_episode: int = 1 + self.setup_logger() + + def setup_logger(self): + """ + Configures the logger for this Agent Log instance. + + The logger is set to the DEBUG level, and is equipped with a handler that writes to a file and filters out + JSON-like messages. + """ + if not SIM_OUTPUT.save_agent_logs: + return + + log_path = self._get_log_path() + file_handler = logging.FileHandler(filename=log_path) + file_handler.setLevel(logging.DEBUG) + + log_format = "%(timestep)s::%(levelname)s::%(message)s" + file_handler.setFormatter(logging.Formatter(log_format)) + + self.logger = logging.getLogger(f"{self.agent_name}_log") + for handler in self.logger.handlers: + self.logger.removeHandler(handler) + self.logger.setLevel(logging.DEBUG) + self.logger.addHandler(file_handler) + + def _get_log_path(self) -> Path: + """ + Constructs the path for the log file based on the hostname. + + :return: Path object representing the location of the log file. + """ + root = SIM_OUTPUT.path / f"episode_{self.current_episode}" / "agent_logs" / self.agent_name + root.mkdir(exist_ok=True, parents=True) + return root / f"{self.agent_name}.log" + + def _write_to_terminal(self, msg: str, timestep: int, level: str, to_terminal: bool = False): + if to_terminal or SIM_OUTPUT.write_agent_log_to_terminal: + print(f"{self.agent_name}: ({timestep}) ({level}) {msg}") + + def debug(self, msg: str, time_step: int, to_terminal: bool = False): + """ + Logs a message with the DEBUG level. + + :param msg: The message to be logged. + :param to_terminal: If True, prints to the terminal too. + """ + if SIM_OUTPUT.agent_log_level > LogLevel.DEBUG: + return + + if SIM_OUTPUT.save_agent_logs: + self.logger.debug(msg, extra={"timestep": time_step}) + self._write_to_terminal(msg, "DEBUG", to_terminal) + + def info(self, msg: str, time_step: int, to_terminal: bool = False): + """ + Logs a message with the INFO level. + + :param msg: The message to be logged. + :param timestep: The current timestep. + :param to_terminal: If True, prints to the terminal too. + """ + if SIM_OUTPUT.agent_log_level > LogLevel.INFO: + return + + if SIM_OUTPUT.save_agent_logs: + self.logger.info(msg, extra={"timestep": time_step}) + self._write_to_terminal(msg, "INFO", to_terminal) + + def warning(self, msg: str, time_step: int, to_terminal: bool = False): + """ + Logs a message with the WARNING level. + + :param msg: The message to be logged. + :param timestep: The current timestep. + :param to_terminal: If True, prints to the terminal too. + """ + if SIM_OUTPUT.agent_log_level > LogLevel.WARNING: + return + + if SIM_OUTPUT.save_agent_logs: + self.logger.warning(msg, extra={"timestep": time_step}) + self._write_to_terminal(msg, "WARNING", to_terminal) + + def error(self, msg: str, time_step: int, to_terminal: bool = False): + """ + Logs a message with the ERROR level. + + :param msg: The message to be logged. + :param timestep: The current timestep. + :param to_terminal: If True, prints to the terminal too. + """ + if SIM_OUTPUT.agent_log_level > LogLevel.ERROR: + return + + if SIM_OUTPUT.save_agent_logs: + self.logger.error(msg, extra={"timestep": time_step}) + self._write_to_terminal(msg, "ERROR", to_terminal) + + def critical(self, msg: str, time_step: int, to_terminal: bool = False): + """ + Logs a message with the CRITICAL level. + + :param msg: The message to be logged. + :param timestep: The current timestep. + :param to_terminal: If True, prints to the terminal too. + """ + if LogLevel.CRITICAL < SIM_OUTPUT.agent_log_level: + return + + if SIM_OUTPUT.save_agent_logs: + self.logger.critical(msg, extra={"timestep": time_step}) + self._write_to_terminal(msg, "CRITICAL", to_terminal) + + def show(self, last_n: int = 10, markdown: bool = False): + """ + Print an Agents Log as a table. + + Generate and print PrettyTable instance that shows the agents behaviour log, with columns Time step, + Level and Message. + + :param markdown: Use Markdown style in table output. Defaults to False. + """ + table = PrettyTable(["Time Step", "Level", "Message"]) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"{self.agent_name} Behaviour Log" + if self._get_log_path().exists(): + with open(self._get_log_path()) as file: + lines = file.readlines() + for line in lines[-last_n:]: + table.add_row(line.strip().split("::")) + print(table) diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py index 95468331..c53b1956 100644 --- a/src/primaite/game/agent/interface.py +++ b/src/primaite/game/agent/interface.py @@ -7,6 +7,7 @@ from gymnasium.core import ActType, ObsType from pydantic import BaseModel, model_validator from primaite.game.agent.actions import ActionManager +from primaite.game.agent.agent_log import AgentLog from primaite.game.agent.observations.observation_manager import ObservationManager from primaite.game.agent.rewards import RewardFunction from primaite.interface.request import RequestFormat, RequestResponse @@ -116,6 +117,7 @@ class AbstractAgent(ABC): self.reward_function: Optional[RewardFunction] = reward_function self.agent_settings = agent_settings or AgentSettings() self.history: List[AgentHistoryItem] = [] + self.logger = AgentLog(agent_name) def update_observation(self, state: Dict) -> ObsType: """ diff --git a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py index 3a91f1fe..cd72e001 100644 --- a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py +++ b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py @@ -38,10 +38,11 @@ class DataManipulationAgent(AbstractScriptedAgent): :rtype: Tuple[str, Dict] """ if timestep < self.next_execution_timestep: + self.logger.debug(msg="Performing do NOTHING", time_step=timestep) return "DONOTHING", {} self._set_next_execution_timestep(timestep + self.agent_settings.start_settings.frequency) - + self.logger.info(msg="Performing a data manipulation attack!", time_step=timestep) return "NODE_APPLICATION_EXECUTE", {"node_id": self.starting_node_idx, "application_id": 0} def setup_agent(self) -> None: @@ -54,3 +55,4 @@ class DataManipulationAgent(AbstractScriptedAgent): # we are assuming that every node in the node manager has a data manipulation application at idx 0 num_nodes = len(self.action_manager.node_names) self.starting_node_idx = random.randint(0, num_nodes - 1) + self.logger.debug(msg=f"Select Start Node ID: {self.starting_node_idx}", time_step=0) diff --git a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py index fc168687..e0f41302 100644 --- a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py +++ b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py @@ -85,4 +85,5 @@ class ProbabilisticAgent(AbstractScriptedAgent): :rtype: Tuple[str, Dict] """ choice = self.rng.choice(len(self.action_manager.action_map), p=self.probabilities) + self.logger.info(f"Performing Action: {choice}", time_step=timestep) return self.action_manager.get_action(choice) diff --git a/src/primaite/session/io.py b/src/primaite/session/io.py index 7bfd16f1..05a5ee09 100644 --- a/src/primaite/session/io.py +++ b/src/primaite/session/io.py @@ -35,10 +35,16 @@ class PrimaiteIO: """Whether to save PCAP logs.""" save_sys_logs: bool = True """Whether to save system logs.""" + save_agent_logs: bool = True + """Whether to save agent logs.""" write_sys_log_to_terminal: bool = False """Whether to write the sys log to the terminal.""" + write_agent_log_to_terminal: bool = False + """Whether to write the agent log to the terminal.""" sys_log_level: LogLevel = LogLevel.INFO - """The level of log that should be included in the logfiles/logged into terminal.""" + """The level of sys logs that should be included in the logfiles/logged into terminal.""" + agent_log_level: LogLevel = LogLevel.INFO + """The level of agent logs that should be included in the logfiles/logged into terminal.""" def __init__(self, settings: Optional[Settings] = None) -> None: """ @@ -53,8 +59,11 @@ class PrimaiteIO: SIM_OUTPUT.path = self.session_path / "simulation_output" SIM_OUTPUT.save_pcap_logs = self.settings.save_pcap_logs SIM_OUTPUT.save_sys_logs = self.settings.save_sys_logs + SIM_OUTPUT.save_agent_logs = self.settings.save_agent_logs + SIM_OUTPUT.write_agent_log_to_terminal = self.settings.write_agent_log_to_terminal SIM_OUTPUT.write_sys_log_to_terminal = self.settings.write_sys_log_to_terminal SIM_OUTPUT.sys_log_level = self.settings.sys_log_level + SIM_OUTPUT.agent_log_level = self.settings.agent_log_level def generate_session_path(self, timestamp: Optional[datetime] = None) -> Path: """Create a folder for the session and return the path to it.""" @@ -115,6 +124,9 @@ class PrimaiteIO: if config.get("sys_log_level"): config["sys_log_level"] = LogLevel[config["sys_log_level"].upper()] # convert to enum + if config.get("agent_log_level"): + config["agent_log_level"] = LogLevel[config["agent_log_level"].upper()] # convert to enum + new = cls(settings=cls.Settings(**config)) return new diff --git a/src/primaite/simulator/__init__.py b/src/primaite/simulator/__init__.py index e5fe3cb7..487e7c5e 100644 --- a/src/primaite/simulator/__init__.py +++ b/src/primaite/simulator/__init__.py @@ -36,8 +36,11 @@ class _SimOutput: self._path = path self._save_pcap_logs: bool = False self._save_sys_logs: bool = False + self._save_agent_logs: bool = False self._write_sys_log_to_terminal: bool = False + self._write_agent_log_to_terminal: bool = False self._sys_log_level: LogLevel = LogLevel.WARNING # default log level is at WARNING + self._agent_log_level: LogLevel = LogLevel.WARNING @property def path(self) -> Path: @@ -81,6 +84,16 @@ class _SimOutput: def save_sys_logs(self, save_sys_logs: bool) -> None: self._save_sys_logs = save_sys_logs + @property + def save_agent_logs(self) -> bool: + if is_dev_mode(): + return PRIMAITE_CONFIG.get("developer_mode").get("output_agent_logs") + return self._save_agent_logs + + @save_agent_logs.setter + def save_agent_logs(self, save_agent_logs: bool) -> None: + self._save_agent_logs = save_agent_logs + @property def write_sys_log_to_terminal(self) -> bool: if is_dev_mode(): @@ -91,6 +104,17 @@ class _SimOutput: def write_sys_log_to_terminal(self, write_sys_log_to_terminal: bool) -> None: self._write_sys_log_to_terminal = write_sys_log_to_terminal + # Should this be separate from sys_log? + @property + def write_agent_log_to_terminal(self) -> bool: + if is_dev_mode(): + return PRIMAITE_CONFIG.get("developer_mode").get("output_to_terminal") + return self._write_agent_log_to_terminal + + @write_agent_log_to_terminal.setter + def write_agent_log_to_terminal(self, write_agent_log_to_terminal: bool) -> None: + self._write_agent_log_to_terminal = write_agent_log_to_terminal + @property def sys_log_level(self) -> LogLevel: if is_dev_mode(): @@ -101,5 +125,15 @@ class _SimOutput: def sys_log_level(self, sys_log_level: LogLevel) -> None: self._sys_log_level = sys_log_level + @property + def agent_log_level(self) -> LogLevel: + if is_dev_mode(): + return LogLevel[PRIMAITE_CONFIG.get("developer_mode").get("agent_log_level")] + return self._agent_log_level + + @agent_log_level.setter + def agent_log_level(self, agent_log_level: LogLevel) -> None: + self._agent_log_level = agent_log_level + SIM_OUTPUT = _SimOutput() diff --git a/tests/assets/configs/basic_switched_network.yaml b/tests/assets/configs/basic_switched_network.yaml index 7d40075d..69187fa3 100644 --- a/tests/assets/configs/basic_switched_network.yaml +++ b/tests/assets/configs/basic_switched_network.yaml @@ -9,6 +9,9 @@ io_settings: save_pcap_logs: true save_sys_logs: true sys_log_level: WARNING + agent_log_level: INFO + save_agent_logs: true + write_agent_log_to_terminal: True game: diff --git a/tests/integration_tests/configuration_file_parsing/test_io_settings.py b/tests/integration_tests/configuration_file_parsing/test_io_settings.py index ebaa4956..82977b82 100644 --- a/tests/integration_tests/configuration_file_parsing/test_io_settings.py +++ b/tests/integration_tests/configuration_file_parsing/test_io_settings.py @@ -35,3 +35,7 @@ def test_io_settings(): assert env.io.settings.save_step_metadata is False assert env.io.settings.write_sys_log_to_terminal is False # false by default + + assert env.io.settings.save_agent_logs is True + assert env.io.settings.agent_log_level is LogLevel.INFO + assert env.io.settings.write_agent_log_to_terminal is True # Set to True by the config file. diff --git a/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py b/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py new file mode 100644 index 00000000..a7932cb7 --- /dev/null +++ b/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py @@ -0,0 +1,137 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from uuid import uuid4 + +import pytest + +from primaite import PRIMAITE_CONFIG +from primaite.game.agent.agent_log import AgentLog +from primaite.simulator import LogLevel, SIM_OUTPUT + + +@pytest.fixture(autouse=True) +def override_dev_mode_temporarily(): + """Temporarily turn off dev mode for this test.""" + primaite_dev_mode = PRIMAITE_CONFIG["developer_mode"]["enabled"] + PRIMAITE_CONFIG["developer_mode"]["enabled"] = False + yield # run tests + PRIMAITE_CONFIG["developer_mode"]["enabled"] = primaite_dev_mode + + +@pytest.fixture(scope="function") +def agentlog() -> AgentLog: + return AgentLog(agent_name="test_agent") + + +def test_debug_agent_log_level(agentlog, capsys): + """Test that the debug log level logs debug agent logs and above.""" + SIM_OUTPUT.agent_log_level = LogLevel.DEBUG + SIM_OUTPUT.write_agent_log_to_terminal = True + + test_string = str(uuid4()) + + agentlog.debug(msg=test_string, time_step=0) + agentlog.info(msg=test_string, time_step=0) + agentlog.warning(msg=test_string, time_step=0) + agentlog.error(msg=test_string, time_step=0) + agentlog.critical(msg=test_string, time_step=0) + + captured = "".join(capsys.readouterr()) + + assert test_string in captured + assert "DEBUG" in captured + assert "INFO" in captured + assert "WARNING" in captured + assert "ERROR" in captured + assert "CRITICAL" in captured + + +def test_info_agent_log_level(agentlog, capsys): + """Test that the debug log level logs debug agent logs and above.""" + SIM_OUTPUT.agent_log_level = LogLevel.INFO + SIM_OUTPUT.write_agent_log_to_terminal = True + + test_string = str(uuid4()) + + agentlog.debug(msg=test_string, time_step=0) + agentlog.info(msg=test_string, time_step=0) + agentlog.warning(msg=test_string, time_step=0) + agentlog.error(msg=test_string, time_step=0) + agentlog.critical(msg=test_string, time_step=0) + + captured = "".join(capsys.readouterr()) + + assert test_string in captured + assert "DEBUG" not in captured + assert "INFO" in captured + assert "WARNING" in captured + assert "ERROR" in captured + assert "CRITICAL" in captured + + +def test_warning_agent_log_level(agentlog, capsys): + """Test that the debug log level logs debug agent logs and above.""" + SIM_OUTPUT.agent_log_level = LogLevel.WARNING + SIM_OUTPUT.write_agent_log_to_terminal = True + + test_string = str(uuid4()) + + agentlog.debug(msg=test_string, time_step=0) + agentlog.info(msg=test_string, time_step=0) + agentlog.warning(msg=test_string, time_step=0) + agentlog.error(msg=test_string, time_step=0) + agentlog.critical(msg=test_string, time_step=0) + + captured = "".join(capsys.readouterr()) + + assert test_string in captured + assert "DEBUG" not in captured + assert "INFO" not in captured + assert "WARNING" in captured + assert "ERROR" in captured + assert "CRITICAL" in captured + + +def test_error_agent_log_level(agentlog, capsys): + """Test that the debug log level logs debug agent logs and above.""" + SIM_OUTPUT.agent_log_level = LogLevel.ERROR + SIM_OUTPUT.write_agent_log_to_terminal = True + + test_string = str(uuid4()) + + agentlog.debug(msg=test_string, time_step=0) + agentlog.info(msg=test_string, time_step=0) + agentlog.warning(msg=test_string, time_step=0) + agentlog.error(msg=test_string, time_step=0) + agentlog.critical(msg=test_string, time_step=0) + + captured = "".join(capsys.readouterr()) + + assert test_string in captured + assert "DEBUG" not in captured + assert "INFO" not in captured + assert "WARNING" not in captured + assert "ERROR" in captured + assert "CRITICAL" in captured + + +def test_critical_agent_log_level(agentlog, capsys): + """Test that the debug log level logs debug agent logs and above.""" + SIM_OUTPUT.agent_log_level = LogLevel.CRITICAL + SIM_OUTPUT.write_agent_log_to_terminal = True + + test_string = str(uuid4()) + + agentlog.debug(msg=test_string, time_step=0) + agentlog.info(msg=test_string, time_step=0) + agentlog.warning(msg=test_string, time_step=0) + agentlog.error(msg=test_string, time_step=0) + agentlog.critical(msg=test_string, time_step=0) + + captured = "".join(capsys.readouterr()) + + assert test_string in captured + assert "DEBUG" not in captured + assert "INFO" not in captured + assert "WARNING" not in captured + assert "ERROR" not in captured + assert "CRITICAL" in captured From 2eb9d970bf5a84be9736a11a34c0047392983c36 Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Tue, 9 Jul 2024 19:25:13 +0000 Subject: [PATCH 18/42] Apply suggestions from code review --- .azure/azure-benchmark-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 7eab2114..8bd7d08e 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -17,7 +17,7 @@ variables: jobs: - job: PrimAITE_Benchmark - timeoutInMinutes: 0 # Set to unlimited timeout + timeoutInMinutes: 360 # 6-hour maximum pool: vmImage: ubuntu-latest workspace: From 7201b7b8e096247621eecce69e078a9ebb14a6ed Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Wed, 10 Jul 2024 11:01:42 +0100 Subject: [PATCH 19/42] 2623 Add e2e tests for action masking --- src/primaite/game/game.py | 2 +- src/primaite/notebooks/Action-masking.ipynb | 53 +- src/primaite/session/ray_envs.py | 2 +- tests/assets/configs/multi_agent_session.yaml | 995 +++++++++++++----- .../assets/configs/test_primaite_session.yaml | 1 + .../action_masking/__init__.py | 1 + .../test_agents_use_action_masks.py | 160 +++ .../actions/test_configure_actions.py | 2 +- 8 files changed, 897 insertions(+), 319 deletions(-) create mode 100644 tests/e2e_integration_tests/action_masking/__init__.py create mode 100644 tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index e7d13061..252d1ce2 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -208,7 +208,7 @@ class PrimaiteGame: for i, action in agent.action_manager.action_map.items(): request = agent.action_manager.form_request(action_identifier=action[0], action_options=action[1]) mask[i] = self.simulation._request_manager.check_valid(request, {}) - return np.asarray(mask) + return np.asarray(mask, dtype=np.int8) def close(self) -> None: """Close the game, this will close the simulation.""" diff --git a/src/primaite/notebooks/Action-masking.ipynb b/src/primaite/notebooks/Action-masking.ipynb index 8090dacc..0e067b26 100644 --- a/src/primaite/notebooks/Action-masking.ipynb +++ b/src/primaite/notebooks/Action-masking.ipynb @@ -17,7 +17,7 @@ "source": [ "from primaite.session.environment import PrimaiteGymEnv\n", "from primaite.config.load import data_manipulation_config_path\n", - "from prettytable import PrettyTable" + "from prettytable import PrettyTable\n" ] }, { @@ -99,7 +99,9 @@ "from primaite.session.ray_envs import PrimaiteRayEnv\n", "from ray.rllib.algorithms.ppo import PPOConfig\n", "import yaml\n", - "from ray import air, tune\n" + "from ray import air, tune\n", + "from ray.rllib.examples.rl_modules.classes.action_masking_rlm import ActionMaskingTorchRLModule\n", + "from ray.rllib.core.rl_module.rl_module import SingleAgentRLModuleSpec\n" ] }, { @@ -124,25 +126,15 @@ "source": [ "config = (\n", " PPOConfig()\n", - " .environment(env=PrimaiteRayEnv, env_config=cfg)\n", + " .api_stack(enable_rl_module_and_learner=True, enable_env_runner_and_connector_v2=True)\n", + " .environment(env=PrimaiteRayEnv, env_config=cfg, action_mask_key=\"action_mask\")\n", + " .rl_module(rl_module_spec=SingleAgentRLModuleSpec(module_class = ActionMaskingTorchRLModule))\n", " .env_runners(num_env_runners=0)\n", " .training(train_batch_size=128)\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tune.Tuner(\n", - " \"PPO\",\n", - " run_config=air.RunConfig(\n", - " stop={\"timesteps_total\": 512}\n", - " ),\n", - " param_space=config\n", - ").fit()\n" + ")\n", + "algo = config.build()\n", + "for i in range(2):\n", + " results = algo.train()" ] }, { @@ -159,6 +151,7 @@ "metadata": {}, "outputs": [], "source": [ + "from ray.rllib.core.rl_module.marl_module import MultiAgentRLModuleSpec\n", "from primaite.session.ray_envs import PrimaiteRayMARLEnv\n", "from primaite.config.load import data_manipulation_marl_config_path" ] @@ -184,20 +177,20 @@ " PPOConfig()\n", " .multi_agent(\n", " policies={'defender_1','defender_2'}, # These names are the same as the agents defined in the example config.\n", - " policy_mapping_fn=lambda agent_id, episode, worker, **kw: agent_id,\n", + " policy_mapping_fn=lambda agent_id, *args, **kwargs: agent_id,\n", " )\n", - " .environment(env=PrimaiteRayMARLEnv, env_config=cfg)\n", + " .api_stack(enable_rl_module_and_learner=True, enable_env_runner_and_connector_v2=True)\n", + " .environment(env=PrimaiteRayMARLEnv, env_config=cfg, action_mask_key=\"action_mask\")\n", + " .rl_module(rl_module_spec=MultiAgentRLModuleSpec(module_specs={\n", + " \"defender_1\":SingleAgentRLModuleSpec(module_class=ActionMaskingTorchRLModule),\n", + " \"defender_2\":SingleAgentRLModuleSpec(module_class=ActionMaskingTorchRLModule),\n", + " }))\n", " .env_runners(num_env_runners=0)\n", " .training(train_batch_size=128)\n", - " )\n", - "\n", - "tune.Tuner(\n", - " \"PPO\",\n", - " run_config=air.RunConfig(\n", - " stop={\"timesteps_total\": 5 * 128},\n", - " ),\n", - " param_space=config\n", - ").fit()" + ")\n", + "algo = config.build()\n", + "for i in range(2):\n", + " results = algo.train()" ] } ], diff --git a/src/primaite/session/ray_envs.py b/src/primaite/session/ray_envs.py index 12167f89..1adc324c 100644 --- a/src/primaite/session/ray_envs.py +++ b/src/primaite/session/ray_envs.py @@ -187,7 +187,7 @@ class PrimaiteRayEnv(gymnasium.Env): # if action masking is enabled, intercept the step method and add action mask to observation if self.env.agent.action_masking: obs, *_ = self.env.step(action) - new_obs = {"action_mask": self.env.action_masks(), "observations": obs} + new_obs = {"action_mask": self.game.action_mask(self.env._agent_name), "observations": obs} return new_obs, *_ else: return self.env.step(action) diff --git a/tests/assets/configs/multi_agent_session.yaml b/tests/assets/configs/multi_agent_session.yaml index 971f36f8..a2d64605 100644 --- a/tests/assets/configs/multi_agent_session.yaml +++ b/tests/assets/configs/multi_agent_session.yaml @@ -1,3 +1,10 @@ +io_settings: + save_agent_actions: false + save_step_metadata: false + save_pcap_logs: false + save_sys_logs: false + + game: max_episode_length: 128 ports: @@ -13,31 +20,105 @@ game: agents: - ref: client_2_green_user team: GREEN - type: PeriodicAgent + type: ProbabilisticAgent + agent_settings: + action_probabilities: + 0: 0.3 + 1: 0.6 + 2: 0.1 observation_space: null action_space: action_list: - type: DONOTHING - type: NODE_APPLICATION_EXECUTE - options: nodes: - node_name: client_2 + applications: + - application_name: WebBrowser + - application_name: DatabaseClient max_folders_per_node: 1 max_files_per_folder: 1 max_services_per_node: 1 - max_nics_per_node: 2 - max_acl_rules: 10 + max_applications_per_node: 2 + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 + 2: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 1 reward_function: reward_components: - - type: DUMMY + - type: WEBPAGE_UNAVAILABLE_PENALTY + weight: 0.25 + options: + node_hostname: client_2 + - type: GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY + weight: 0.05 + options: + node_hostname: client_2 + + - ref: client_1_green_user + team: GREEN + type: ProbabilisticAgent + agent_settings: + action_probabilities: + 0: 0.3 + 1: 0.6 + 2: 0.1 + observation_space: null + action_space: + action_list: + - type: DONOTHING + - type: NODE_APPLICATION_EXECUTE + options: + nodes: + - node_name: client_1 + applications: + - application_name: WebBrowser + - application_name: DatabaseClient + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 2 + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 + 2: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 1 + + reward_function: + reward_components: + - type: WEBPAGE_UNAVAILABLE_PENALTY + weight: 0.25 + options: + node_hostname: client_1 + - type: GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY + weight: 0.05 + options: + node_hostname: client_1 + + + - agent_settings: # options specific to this particular agent type, basically args of __init__(self) - start_settings: - start_step: 25 - frequency: 20 - variance: 5 - ref: data_manipulation_attacker team: RED @@ -57,6 +138,9 @@ agents: - node_name: client_1 applications: - application_name: DataManipulationBot + - node_name: client_2 + applications: + - application_name: DataManipulationBot max_folders_per_node: 1 max_files_per_folder: 1 max_services_per_node: 1 @@ -71,7 +155,7 @@ agents: frequency: 20 variance: 5 - - ref: defender1 + - ref: defender_1 team: BLUE type: ProxyAgent @@ -194,318 +278,425 @@ agents: 3: action: "NODE_SERVICE_START" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 4: action: "NODE_SERVICE_PAUSE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 5: action: "NODE_SERVICE_RESUME" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 6: action: "NODE_SERVICE_RESTART" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 7: action: "NODE_SERVICE_DISABLE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 8: action: "NODE_SERVICE_ENABLE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 9: # check database.db file action: "NODE_FILE_SCAN" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 10: - action: "NODE_FILE_CHECKHASH" + action: "NODE_FILE_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 11: action: "NODE_FILE_DELETE" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 12: action: "NODE_FILE_REPAIR" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 13: action: "NODE_SERVICE_FIX" options: - node_id: 2 - service_id: 0 + node_id: 2 + service_id: 0 14: action: "NODE_FOLDER_SCAN" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 15: - action: "NODE_FOLDER_CHECKHASH" + action: "NODE_FOLDER_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 16: action: "NODE_FOLDER_REPAIR" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 17: action: "NODE_FOLDER_RESTORE" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 18: action: "NODE_OS_SCAN" options: - node_id: 2 - 19: # shutdown client 1 + node_id: 0 + 19: action: "NODE_SHUTDOWN" options: - node_id: 5 + node_id: 0 20: - action: "NODE_STARTUP" + action: NODE_STARTUP options: - node_id: 5 + node_id: 0 21: - action: "NODE_RESET" + action: NODE_RESET options: - node_id: 5 - 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "ROUTER_ACL_ADDRULE" + node_id: 0 + 22: + action: "NODE_OS_SCAN" options: - target_router: router_1 - position: 1 - permission: 2 - source_ip_id: 7 # client 1 - dest_ip_id: 1 # ALL - source_port_id: 1 - dest_port_id: 1 - protocol_id: 1 - source_wildcard_id: 0 - dest_wildcard_id: 0 - 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "ROUTER_ACL_ADDRULE" + node_id: 1 + 23: + action: "NODE_SHUTDOWN" options: - target_router: router_1 - position: 2 - permission: 2 - source_ip_id: 8 # client 2 - dest_ip_id: 1 # ALL - source_port_id: 1 - dest_port_id: 1 - protocol_id: 1 - source_wildcard_id: 0 - dest_wildcard_id: 0 - 24: # block tcp traffic from client 1 to web app - action: "ROUTER_ACL_ADDRULE" + node_id: 1 + 24: + action: NODE_STARTUP options: - target_router: router_1 - position: 3 - permission: 2 - source_ip_id: 7 # client 1 - dest_ip_id: 3 # web server - source_port_id: 1 - dest_port_id: 1 - protocol_id: 3 - source_wildcard_id: 0 - dest_wildcard_id: 0 - 25: # block tcp traffic from client 2 to web app - action: "ROUTER_ACL_ADDRULE" + node_id: 1 + 25: + action: NODE_RESET options: - target_router: router_1 - position: 4 - permission: 2 - source_ip_id: 8 # client 2 - dest_ip_id: 3 # web server - source_port_id: 1 - dest_port_id: 1 - protocol_id: 3 - source_wildcard_id: 0 - dest_wildcard_id: 0 - 26: - action: "ROUTER_ACL_ADDRULE" + node_id: 1 + 26: # old action num: 18 + action: "NODE_OS_SCAN" options: - target_router: router_1 - position: 5 - permission: 2 - source_ip_id: 7 # client 1 - dest_ip_id: 4 # database - source_port_id: 1 - dest_port_id: 1 - protocol_id: 3 - source_wildcard_id: 0 - dest_wildcard_id: 0 + node_id: 2 27: - action: "ROUTER_ACL_ADDRULE" + action: "NODE_SHUTDOWN" options: - target_router: router_1 - position: 6 - permission: 2 - source_ip_id: 8 # client 2 - dest_ip_id: 4 # database - source_port_id: 1 - dest_port_id: 1 - protocol_id: 3 - source_wildcard_id: 0 - dest_wildcard_id: 0 + node_id: 2 28: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_STARTUP options: - target_router: router_1 - position: 0 + node_id: 2 29: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_RESET options: - target_router: router_1 - position: 1 + node_id: 2 30: - action: "ROUTER_ACL_REMOVERULE" + action: "NODE_OS_SCAN" options: - target_router: router_1 - position: 2 + node_id: 3 31: - action: "ROUTER_ACL_REMOVERULE" + action: "NODE_SHUTDOWN" options: - target_router: router_1 - position: 3 + node_id: 3 32: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_STARTUP options: - target_router: router_1 - position: 4 + node_id: 3 33: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_RESET options: - target_router: router_1 - position: 5 + node_id: 3 34: - action: "ROUTER_ACL_REMOVERULE" + action: "NODE_OS_SCAN" options: - target_router: router_1 - position: 6 + node_id: 4 35: - action: "ROUTER_ACL_REMOVERULE" + action: "NODE_SHUTDOWN" options: - target_router: router_1 - position: 7 + node_id: 4 36: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_STARTUP options: - target_router: router_1 - position: 8 + node_id: 4 37: - action: "ROUTER_ACL_REMOVERULE" + action: NODE_RESET options: - target_router: router_1 - position: 9 + node_id: 4 38: - action: "HOST_NIC_DISABLE" + action: "NODE_OS_SCAN" options: - node_id: 0 - nic_id: 0 - 39: - action: "HOST_NIC_ENABLE" + node_id: 5 + 39: # old action num: 19 # shutdown client 1 + action: "NODE_SHUTDOWN" options: - node_id: 0 - nic_id: 0 - 40: - action: "HOST_NIC_DISABLE" + node_id: 5 + 40: # old action num: 20 + action: NODE_STARTUP options: - node_id: 1 - nic_id: 0 - 41: - action: "HOST_NIC_ENABLE" + node_id: 5 + 41: # old action num: 21 + action: NODE_RESET options: - node_id: 1 - nic_id: 0 + node_id: 5 42: - action: "HOST_NIC_DISABLE" + action: "NODE_OS_SCAN" options: - node_id: 2 - nic_id: 0 + node_id: 6 43: + action: "NODE_SHUTDOWN" + options: + node_id: 6 + 44: + action: NODE_STARTUP + options: + node_id: 6 + 45: + action: NODE_RESET + options: + node_id: 6 + + 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 1 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 1 # ALL + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 2 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 1 # ALL + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 48: # old action num: 24 # block tcp traffic from client 1 to web app + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 3 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 3 # web server + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 49: # old action num: 25 # block tcp traffic from client 2 to web app + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 4 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 3 # web server + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 50: # old action num: 26 + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 5 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 4 # database + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 51: # old action num: 27 + action: "ROUTER_ACL_ADDRULE" + options: + target_router: router_1 + position: 6 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 4 # database + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + source_wildcard_id: 0 + dest_wildcard_id: 0 + 52: # old action num: 28 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 0 + 53: # old action num: 29 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 1 + 54: # old action num: 30 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 2 + 55: # old action num: 31 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 3 + 56: # old action num: 32 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 4 + 57: # old action num: 33 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 5 + 58: # old action num: 34 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 6 + 59: # old action num: 35 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 7 + 60: # old action num: 36 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 8 + 61: # old action num: 37 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router: router_1 + position: 9 + 62: # old action num: 38 + action: "HOST_NIC_DISABLE" + options: + node_id: 0 + nic_id: 0 + 63: # old action num: 39 + action: "HOST_NIC_ENABLE" + options: + node_id: 0 + nic_id: 0 + 64: # old action num: 40 + action: "HOST_NIC_DISABLE" + options: + node_id: 1 + nic_id: 0 + 65: # old action num: 41 + action: "HOST_NIC_ENABLE" + options: + node_id: 1 + nic_id: 0 + 66: # old action num: 42 + action: "HOST_NIC_DISABLE" + options: + node_id: 2 + nic_id: 0 + 67: # old action num: 43 action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 - 44: + 68: # old action num: 44 action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 - 45: + 69: # old action num: 45 action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 - 46: + 70: # old action num: 46 action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 - 47: + 71: # old action num: 47 action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 - 48: + 72: # old action num: 48 action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 - 49: + 73: # old action num: 49 action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 - 50: + 74: # old action num: 50 action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 - 51: + 75: # old action num: 51 action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 - 52: + 76: # old action num: 52 action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 - 53: + 77: # old action num: 53 action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 - options: nodes: - node_name: domain_controller - node_name: web_server + applications: + - application_name: DatabaseClient + services: + - service_name: WebServer - node_name: database_server + folders: + - folder_name: database + files: + - file_name: database.db + services: + - service_name: DatabaseService - node_name: backup_server - node_name: security_suite - node_name: client_1 - node_name: client_2 + max_folders_per_node: 2 max_files_per_folder: 2 max_services_per_node: 2 @@ -521,27 +712,30 @@ agents: - 192.168.10.22 - 192.168.10.110 + reward_function: reward_components: - type: DATABASE_FILE_INTEGRITY - weight: 0.5 + weight: 0.40 options: node_hostname: database_server folder_name: database file_name: database.db - - - - type: WEB_SERVER_404_PENALTY - weight: 0.5 + - type: SHARED_REWARD + weight: 1.0 options: - node_hostname: web_server - service_name: web_server_web_service + agent_name: client_1_green_user + - type: SHARED_REWARD + weight: 1.0 + options: + agent_name: client_2_green_user agent_settings: - # ... + flatten_obs: true + action_masking: true - - ref: defender2 + - ref: defender_2 team: BLUE type: ProxyAgent @@ -640,7 +834,11 @@ agents: - type: NODE_STARTUP - type: NODE_RESET - type: ROUTER_ACL_ADDRULE + options: + target_router: router_1 - type: ROUTER_ACL_REMOVERULE + options: + target_router: router_1 - type: HOST_NIC_ENABLE - type: HOST_NIC_DISABLE @@ -664,99 +862,196 @@ agents: 3: action: "NODE_SERVICE_START" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 4: action: "NODE_SERVICE_PAUSE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 5: action: "NODE_SERVICE_RESUME" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 6: action: "NODE_SERVICE_RESTART" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 7: action: "NODE_SERVICE_DISABLE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 8: action: "NODE_SERVICE_ENABLE" options: - node_id: 1 - service_id: 0 + node_id: 1 + service_id: 0 9: # check database.db file action: "NODE_FILE_SCAN" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 10: - action: "NODE_FILE_CHECKHASH" + action: "NODE_FILE_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 11: action: "NODE_FILE_DELETE" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 12: action: "NODE_FILE_REPAIR" options: - node_id: 2 - folder_id: 1 - file_id: 0 + node_id: 2 + folder_id: 0 + file_id: 0 13: action: "NODE_SERVICE_FIX" options: - node_id: 2 - service_id: 0 + node_id: 2 + service_id: 0 14: action: "NODE_FOLDER_SCAN" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 15: - action: "NODE_FOLDER_CHECKHASH" + action: "NODE_FOLDER_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 16: action: "NODE_FOLDER_REPAIR" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 17: action: "NODE_FOLDER_RESTORE" options: - node_id: 2 - folder_id: 1 + node_id: 2 + folder_id: 0 18: action: "NODE_OS_SCAN" options: - node_id: 2 - 19: # shutdown client 1 + node_id: 0 + 19: action: "NODE_SHUTDOWN" options: - node_id: 5 + node_id: 0 20: - action: "NODE_STARTUP" + action: NODE_STARTUP options: - node_id: 5 + node_id: 0 21: - action: "NODE_RESET" + action: NODE_RESET options: - node_id: 5 - 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) + node_id: 0 + 22: + action: "NODE_OS_SCAN" + options: + node_id: 1 + 23: + action: "NODE_SHUTDOWN" + options: + node_id: 1 + 24: + action: NODE_STARTUP + options: + node_id: 1 + 25: + action: NODE_RESET + options: + node_id: 1 + 26: # old action num: 18 + action: "NODE_OS_SCAN" + options: + node_id: 2 + 27: + action: "NODE_SHUTDOWN" + options: + node_id: 2 + 28: + action: NODE_STARTUP + options: + node_id: 2 + 29: + action: NODE_RESET + options: + node_id: 2 + 30: + action: "NODE_OS_SCAN" + options: + node_id: 3 + 31: + action: "NODE_SHUTDOWN" + options: + node_id: 3 + 32: + action: NODE_STARTUP + options: + node_id: 3 + 33: + action: NODE_RESET + options: + node_id: 3 + 34: + action: "NODE_OS_SCAN" + options: + node_id: 4 + 35: + action: "NODE_SHUTDOWN" + options: + node_id: 4 + 36: + action: NODE_STARTUP + options: + node_id: 4 + 37: + action: NODE_RESET + options: + node_id: 4 + 38: + action: "NODE_OS_SCAN" + options: + node_id: 5 + 39: # old action num: 19 # shutdown client 1 + action: "NODE_SHUTDOWN" + options: + node_id: 5 + 40: # old action num: 20 + action: NODE_STARTUP + options: + node_id: 5 + 41: # old action num: 21 + action: NODE_RESET + options: + node_id: 5 + 42: + action: "NODE_OS_SCAN" + options: + node_id: 6 + 43: + action: "NODE_SHUTDOWN" + options: + node_id: 6 + 44: + action: NODE_STARTUP + options: + node_id: 6 + 45: + action: NODE_RESET + options: + node_id: 6 + + 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -769,7 +1064,7 @@ agents: protocol_id: 1 source_wildcard_id: 0 dest_wildcard_id: 0 - 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) + 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -782,7 +1077,7 @@ agents: protocol_id: 1 source_wildcard_id: 0 dest_wildcard_id: 0 - 24: # block tcp traffic from client 1 to web app + 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -795,7 +1090,7 @@ agents: protocol_id: 3 source_wildcard_id: 0 dest_wildcard_id: 0 - 25: # block tcp traffic from client 2 to web app + 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -808,7 +1103,7 @@ agents: protocol_id: 3 source_wildcard_id: 0 dest_wildcard_id: 0 - 26: + 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -821,7 +1116,7 @@ agents: protocol_id: 3 source_wildcard_id: 0 dest_wildcard_id: 0 - 27: + 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: target_router: router_1 @@ -834,67 +1129,159 @@ agents: protocol_id: 3 source_wildcard_id: 0 dest_wildcard_id: 0 - 28: + 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 0 - 29: + 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 1 - 30: + 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 2 - 31: + 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 3 - 32: + 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 4 - 33: + 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 5 - 34: + 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 6 - 35: + 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 7 - 36: + 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 8 - 37: + 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: target_router: router_1 position: 9 + 62: # old action num: 38 + action: "HOST_NIC_DISABLE" + options: + node_id: 0 + nic_id: 0 + 63: # old action num: 39 + action: "HOST_NIC_ENABLE" + options: + node_id: 0 + nic_id: 0 + 64: # old action num: 40 + action: "HOST_NIC_DISABLE" + options: + node_id: 1 + nic_id: 0 + 65: # old action num: 41 + action: "HOST_NIC_ENABLE" + options: + node_id: 1 + nic_id: 0 + 66: # old action num: 42 + action: "HOST_NIC_DISABLE" + options: + node_id: 2 + nic_id: 0 + 67: # old action num: 43 + action: "HOST_NIC_ENABLE" + options: + node_id: 2 + nic_id: 0 + 68: # old action num: 44 + action: "HOST_NIC_DISABLE" + options: + node_id: 3 + nic_id: 0 + 69: # old action num: 45 + action: "HOST_NIC_ENABLE" + options: + node_id: 3 + nic_id: 0 + 70: # old action num: 46 + action: "HOST_NIC_DISABLE" + options: + node_id: 4 + nic_id: 0 + 71: # old action num: 47 + action: "HOST_NIC_ENABLE" + options: + node_id: 4 + nic_id: 0 + 72: # old action num: 48 + action: "HOST_NIC_DISABLE" + options: + node_id: 4 + nic_id: 1 + 73: # old action num: 49 + action: "HOST_NIC_ENABLE" + options: + node_id: 4 + nic_id: 1 + 74: # old action num: 50 + action: "HOST_NIC_DISABLE" + options: + node_id: 5 + nic_id: 0 + 75: # old action num: 51 + action: "HOST_NIC_ENABLE" + options: + node_id: 5 + nic_id: 0 + 76: # old action num: 52 + action: "HOST_NIC_DISABLE" + options: + node_id: 6 + nic_id: 0 + 77: # old action num: 53 + action: "HOST_NIC_ENABLE" + options: + node_id: 6 + nic_id: 0 + options: nodes: - node_name: domain_controller - node_name: web_server + applications: + - application_name: DatabaseClient + services: + - service_name: WebServer - node_name: database_server + folders: + - folder_name: database + files: + - file_name: database.db + services: + - service_name: DatabaseService - node_name: backup_server - node_name: security_suite - node_name: client_1 - node_name: client_2 + max_folders_per_node: 2 max_files_per_folder: 2 max_services_per_node: 2 @@ -913,50 +1300,63 @@ agents: reward_function: reward_components: - type: DATABASE_FILE_INTEGRITY - weight: 0.5 + weight: 0.40 options: node_hostname: database_server folder_name: database file_name: database.db - - - - type: WEB_SERVER_404_PENALTY - weight: 0.5 + - type: SHARED_REWARD + weight: 1.0 options: - node_hostname: web_server - service_name: web_server_web_service + agent_name: client_1_green_user + - type: SHARED_REWARD + weight: 1.0 + options: + agent_name: client_2_green_user agent_settings: - # ... - + flatten_obs: true + action_masking: true simulation: network: + nmne_config: + capture_nmne: true + nmne_capture_keywords: + - DELETE nodes: - - type: router - hostname: router_1 + - hostname: router_1 + type: router num_ports: 5 ports: 1: ip_address: 192.168.1.1 subnet_mask: 255.255.255.0 2: - ip_address: 192.168.1.1 + ip_address: 192.168.10.1 subnet_mask: 255.255.255.0 acl: - 0: + 18: action: PERMIT src_port: POSTGRES_SERVER dst_port: POSTGRES_SERVER - 1: + 19: action: PERMIT src_port: DNS dst_port: DNS + 20: + action: PERMIT + src_port: FTP + dst_port: FTP + 21: + action: PERMIT + src_port: HTTP + dst_port: HTTP 22: action: PERMIT src_port: ARP @@ -965,16 +1365,16 @@ simulation: action: PERMIT protocol: ICMP - - type: switch - hostname: switch_1 + - hostname: switch_1 + type: switch num_ports: 8 - - type: switch - hostname: switch_2 + - hostname: switch_2 + type: switch num_ports: 8 - - type: server - hostname: domain_controller + - hostname: domain_controller + type: server ip_address: 192.168.1.10 subnet_mask: 255.255.255.0 default_gateway: 192.168.1.1 @@ -984,8 +1384,8 @@ simulation: domain_mapping: arcd.com: 192.168.1.12 # web server - - type: server - hostname: web_server + - hostname: web_server + type: server ip_address: 192.168.1.12 subnet_mask: 255.255.255.0 default_gateway: 192.168.1.1 @@ -997,17 +1397,21 @@ simulation: options: db_server_ip: 192.168.1.14 - - type: server - hostname: database_server + + - hostname: database_server + type: server ip_address: 192.168.1.14 subnet_mask: 255.255.255.0 default_gateway: 192.168.1.1 dns_server: 192.168.1.10 services: - type: DatabaseService + options: + backup_server_ip: 192.168.1.16 + - type: FTPClient - - type: server - hostname: backup_server + - hostname: backup_server + type: server ip_address: 192.168.1.16 subnet_mask: 255.255.255.0 default_gateway: 192.168.1.1 @@ -1015,8 +1419,8 @@ simulation: services: - type: FTPServer - - type: server - hostname: security_suite + - hostname: security_suite + type: server ip_address: 192.168.1.110 subnet_mask: 255.255.255.0 default_gateway: 192.168.1.1 @@ -1026,8 +1430,8 @@ simulation: ip_address: 192.168.10.110 subnet_mask: 255.255.255.0 - - type: computer - hostname: client_1 + - hostname: client_1 + type: computer ip_address: 192.168.10.21 subnet_mask: 255.255.255.0 default_gateway: 192.168.10.1 @@ -1035,24 +1439,43 @@ simulation: applications: - type: DataManipulationBot options: - port_scan_p_of_success: 0.1 - data_manipulation_p_of_success: 0.1 + port_scan_p_of_success: 0.8 + data_manipulation_p_of_success: 0.8 payload: "DELETE" server_ip: 192.168.1.14 + - type: WebBrowser + options: + target_url: http://arcd.com/users/ + - type: DatabaseClient + options: + db_server_ip: 192.168.1.14 services: - type: DNSClient - - type: computer - hostname: client_2 + - hostname: client_2 + type: computer ip_address: 192.168.10.22 subnet_mask: 255.255.255.0 default_gateway: 192.168.10.1 dns_server: 192.168.1.10 applications: - type: WebBrowser + options: + target_url: http://arcd.com/users/ + - type: DataManipulationBot + options: + port_scan_p_of_success: 0.8 + data_manipulation_p_of_success: 0.8 + payload: "DELETE" + server_ip: 192.168.1.14 + - type: DatabaseClient + options: + db_server_ip: 192.168.1.14 services: - type: DNSClient + + links: - endpoint_a_hostname: router_1 endpoint_a_port: 1 diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index 54143af0..7c894ba0 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -557,6 +557,7 @@ agents: agent_settings: flatten_obs: true + action_masking: true diff --git a/tests/e2e_integration_tests/action_masking/__init__.py b/tests/e2e_integration_tests/action_masking/__init__.py new file mode 100644 index 00000000..be6c00e7 --- /dev/null +++ b/tests/e2e_integration_tests/action_masking/__init__.py @@ -0,0 +1 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK diff --git a/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py new file mode 100644 index 00000000..3efda71a --- /dev/null +++ b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py @@ -0,0 +1,160 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import importlib +from typing import Dict + +import yaml +from ray import air, init, tune +from ray.rllib.algorithms.ppo import PPOConfig +from ray.rllib.core.rl_module.marl_module import MultiAgentRLModuleSpec +from ray.rllib.core.rl_module.rl_module import SingleAgentRLModuleSpec +from ray.rllib.examples.rl_modules.classes.action_masking_rlm import ActionMaskingTorchRLModule +from sb3_contrib import MaskablePPO + +from primaite.game.game import PrimaiteGame +from primaite.session.environment import PrimaiteGymEnv +from primaite.session.ray_envs import PrimaiteRayEnv, PrimaiteRayMARLEnv +from tests import TEST_ASSETS_ROOT + +init(local_mode=True) + +CFG_PATH = TEST_ASSETS_ROOT / "configs/test_primaite_session.yaml" +MARL_PATH = TEST_ASSETS_ROOT / "configs/multi_agent_session.yaml" + + +def test_sb3_action_masking(monkeypatch): + # There's no simple way of capturing what the action mask was at every step, therefore we are mocking the action + # mask function here to save the output of the action mask method and pass through the result back to the agent. + old_action_mask_method = PrimaiteGame.action_mask + mask_history = [] + + def cache_action_mask(obj, agent_name): + mask = old_action_mask_method(obj, agent_name) + mask_history.append(mask) + return mask + + # Even though it's easy to know which CAOS action the agent took by looking at agent history, we don't know which + # action map action integer that was, therefore we cache it by using monkeypatch + action_num_history = [] + + def cache_step(env, action: int): + action_num_history.append(action) + return PrimaiteGymEnv.step(env, action) + + monkeypatch.setattr(PrimaiteGame, "action_mask", cache_action_mask) + env = PrimaiteGymEnv(CFG_PATH) + monkeypatch.setattr(env, "step", lambda action: cache_step(env, action)) + + model = MaskablePPO("MlpPolicy", env, gamma=0.4, seed=32, batch_size=32) + model.learn(512) + + assert len(action_num_history) == len(mask_history) > 0 + # Make sure the masks had at least some False entries, if it was all True then the mask was disabled + assert any([not all(x) for x in mask_history]) + # When the agent takes action N from its action map, we need to have a look at the action mask and make sure that + # the N-th entry was True, meaning that it was a valid action at that step. + # This plucks out the mask history at step i, and at action entry a and checks that it's set to True, and this + # happens for all steps i in the episode + assert all(mask_history[i][a] for i, a in enumerate(action_num_history)) + monkeypatch.undo() + + +def test_ray_single_agent_action_masking(monkeypatch): + """Check that a Ray agent uses the action mask and never chooses invalid actions.""" + with open(CFG_PATH, "r") as f: + cfg = yaml.safe_load(f) + for agent in cfg["agents"]: + if agent["ref"] == "defender": + agent["agent_settings"]["flatten_obs"] = True + + # There's no simple way of capturing what the action mask was at every step, therefore we are mocking the step + # function to save the action mask and the agent's chosen action to a local variable. + old_step_method = PrimaiteRayEnv.step + action_num_history = [] + mask_history = [] + + def cache_step(self, action: int): + action_num_history.append(action) + obs, *_ = old_step_method(self, action) + action_mask = obs["action_mask"] + mask_history.append(action_mask) + return obs, *_ + + monkeypatch.setattr(PrimaiteRayEnv, "step", lambda *args, **kwargs: cache_step(*args, **kwargs)) + + # Configure Ray PPO to use action masking by using the ActionMaskingTorchRLModule + config = ( + PPOConfig() + .api_stack(enable_rl_module_and_learner=True, enable_env_runner_and_connector_v2=True) + .environment(env=PrimaiteRayEnv, env_config=cfg, action_mask_key="action_mask") + .rl_module(rl_module_spec=SingleAgentRLModuleSpec(module_class=ActionMaskingTorchRLModule)) + .env_runners(num_env_runners=0) + .training(train_batch_size=128) + ) + algo = config.build() + algo.train() + + assert len(action_num_history) == len(mask_history) > 0 + # Make sure the masks had at least some False entries, if it was all True then the mask was disabled + assert any([not all(x) for x in mask_history]) + # When the agent takes action N from its action map, we need to have a look at the action mask and make sure that + # the N-th action was valid. + # The first step uses the action mask provided by the reset method, so we are only checking from the second step + # onward, that's why we need to use mask_history[:-1] and action_num_history[1:] + assert all(mask_history[:-1][i][a] for i, a in enumerate(action_num_history[1:])) + monkeypatch.undo() + + +def test_ray_multi_agent_action_masking(monkeypatch): + """Check that Ray agents never take invalid actions when using MARL.""" + with open(MARL_PATH, "r") as f: + cfg = yaml.safe_load(f) + + old_step_method = PrimaiteRayMARLEnv.step + action_num_history = {"defender_1": [], "defender_2": []} + mask_history = {"defender_1": [], "defender_2": []} + + def cache_step(self, actions: Dict[str, int]): + for agent_name, action in actions.items(): + action_num_history[agent_name].append(action) + obs, *_ = old_step_method(self, actions) + for ( + agent_name, + o, + ) in obs.items(): + mask_history[agent_name].append(o["action_mask"]) + return obs, *_ + + monkeypatch.setattr(PrimaiteRayMARLEnv, "step", lambda *args, **kwargs: cache_step(*args, **kwargs)) + + config = ( + PPOConfig() + .multi_agent( + policies={ + "defender_1", + "defender_2", + }, # These names are the same as the agents defined in the example config. + policy_mapping_fn=lambda agent_id, *args, **kwargs: agent_id, + ) + .api_stack(enable_rl_module_and_learner=True, enable_env_runner_and_connector_v2=True) + .environment(env=PrimaiteRayMARLEnv, env_config=cfg, action_mask_key="action_mask") + .rl_module( + rl_module_spec=MultiAgentRLModuleSpec( + module_specs={ + "defender_1": SingleAgentRLModuleSpec(module_class=ActionMaskingTorchRLModule), + "defender_2": SingleAgentRLModuleSpec(module_class=ActionMaskingTorchRLModule), + } + ) + ) + .env_runners(num_env_runners=0) + .training(train_batch_size=128) + ) + algo = config.build() + algo.train() + + for agent_name in ["defender_1", "defender_2"]: + act_hist = action_num_history[agent_name] + mask_hist = mask_history[agent_name] + assert len(act_hist) == len(mask_hist) > 0 + assert any([not all(x) for x in mask_hist]) + assert all(mask_hist[:-1][i][a] for i, a in enumerate(act_hist[1:])) + monkeypatch.undo() diff --git a/tests/integration_tests/game_layer/actions/test_configure_actions.py b/tests/integration_tests/game_layer/actions/test_configure_actions.py index b7acc8a8..0c9ec6f0 100644 --- a/tests/integration_tests/game_layer/actions/test_configure_actions.py +++ b/tests/integration_tests/game_layer/actions/test_configure_actions.py @@ -99,7 +99,7 @@ class TestConfigureDatabaseAction: game.step() assert db_client.server_ip_address == old_ip - assert db_client.server_password is "admin123" + assert db_client.server_password == "admin123" class TestConfigureRansomwareScriptAction: From caa6a4809c724bc1cecec90c3b1afd57dd900243 Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Wed, 10 Jul 2024 13:14:22 +0100 Subject: [PATCH 20/42] #2740: tests + implement file request validators --- .../simulator/file_system/file_system.py | 5 +- src/primaite/simulator/file_system/folder.py | 5 +- .../actions/test_file_request_permission.py | 83 ++++++++++++++++++- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index 42aa0573..bcb0334e 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -693,7 +693,4 @@ class FileSystem(SimComponent): @property def fail_message(self) -> str: """Message that is reported when a request is rejected by this validator.""" - return ( - f"Cannot perform request on application '{self.application.name}' because it is not in the " - f"{self.state.name} state." - ) + return "Cannot perform request on file that does not exist." diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index af7cc660..d891641e 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -489,7 +489,4 @@ class Folder(FileSystemItemABC): @property def fail_message(self) -> str: """Message that is reported when a request is rejected by this validator.""" - return ( - f"Cannot perform request on application '{self.application.name}' because it is not in the " - f"{self.state.name} state." - ) + return "Cannot perform request on file that does not exist." diff --git a/tests/integration_tests/game_layer/actions/test_file_request_permission.py b/tests/integration_tests/game_layer/actions/test_file_request_permission.py index c422ad43..1c143aed 100644 --- a/tests/integration_tests/game_layer/actions/test_file_request_permission.py +++ b/tests/integration_tests/game_layer/actions/test_file_request_permission.py @@ -22,7 +22,7 @@ def game_and_agent_fixture(game_and_agent): def test_create_file(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the validator allows a folder to be created.""" + """Test that the validator allows a files to be created.""" game, agent = game_and_agent_fixture client_1 = game.simulation.network.get_node_by_hostname("client_1") @@ -43,7 +43,7 @@ def test_create_file(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): def test_file_delete_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the validator allows a folder to be created.""" + """Test that the validator allows a file to be deleted.""" game, agent = game_and_agent_fixture client_1 = game.simulation.network.get_node_by_hostname("client_1") @@ -61,7 +61,7 @@ def test_file_delete_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAge def test_file_scan_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the validator allows a folder to be created.""" + """Test that the validator allows a file to be scanned.""" game, agent = game_and_agent_fixture client_1 = game.simulation.network.get_node_by_hostname("client_1") @@ -80,3 +80,80 @@ def test_file_scan_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent assert file.health_status == FileSystemItemHealthStatus.CORRUPT assert file.visible_health_status == FileSystemItemHealthStatus.CORRUPT + + +def test_file_repair_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a folder to be created.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + + file.corrupt() + assert file.health_status == FileSystemItemHealthStatus.CORRUPT + + action = ( + "NODE_FILE_REPAIR", + {"node_id": 0, "folder_id": 0, "file_id": 0}, + ) + agent.store_action(action) + game.step() + + assert file.health_status == FileSystemItemHealthStatus.GOOD + + +def test_file_restore_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a file to be restored.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + + file.corrupt() + assert file.health_status == FileSystemItemHealthStatus.CORRUPT + + action = ( + "NODE_FILE_RESTORE", + {"node_id": 0, "folder_id": 0, "file_id": 0}, + ) + agent.store_action(action) + game.step() + + assert file.health_status == FileSystemItemHealthStatus.GOOD + + +def test_file_corrupt_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a file to be corrupted.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + + assert file.health_status == FileSystemItemHealthStatus.GOOD + + action = ( + "NODE_FILE_CORRUPT", + {"node_id": 0, "folder_id": 0, "file_id": 0}, + ) + agent.store_action(action) + game.step() + + assert file.health_status == FileSystemItemHealthStatus.CORRUPT + + +def test_file_access_action(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the validator allows a file to be accessed.""" + game, agent = game_and_agent_fixture + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + file = client_1.file_system.get_file(folder_name="downloads", file_name="cat.png") + assert file.num_access == 0 + + action = ( + "NODE_FILE_ACCESS", + {"node_id": 0, "folder_name": file.folder_name, "file_name": file.name}, + ) + agent.store_action(action) + game.step() + + assert file.num_access == 1 From 239f5b86c0fd33744b693f332038267ba6615fb5 Mon Sep 17 00:00:00 2001 From: "Archer.Bowen" Date: Wed, 10 Jul 2024 13:36:37 +0100 Subject: [PATCH 21/42] #2716 Agent logging now sits outside of the simulation output log directory, updated dev-mode CLI to include agent logging and added additional tests. --- CHANGELOG.md | 2 +- src/primaite/game/agent/agent_log.py | 50 +++++++++++------ .../scripted_agents/data_manipulation_bot.py | 6 +-- .../scripted_agents/probabilistic_agent.py | 2 +- src/primaite/game/game.py | 9 ++++ src/primaite/session/io.py | 17 +++--- .../setup/_package_data/primaite_config.yaml | 2 + src/primaite/simulator/__init__.py | 23 ++++++++ src/primaite/utils/cli/dev_cli.py | 27 ++++++++++ tests/integration_tests/cli/test_dev_cli.py | 54 ++++++++++++++++++- .../_primaite/_game/_agent/test_agent_log.py | 50 ++++++++--------- 11 files changed, 187 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index beec6d11..63a4bfe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Activating dev-mode will change the location where the sessions will be output - by default will output where the PrimAITE repository is located - Refactored all air-space usage to that a new instance of AirSpace is created for each instance of Network. This 1:1 relationship between network and airspace will allow parallelization. - Added notebook to demonstrate use of SubprocVecEnv from SB3 to vectorise environments to speed up training. -- Added a new agent simulation log which are more human friendly than agent action logging. Includes timesteps so that the agent action log can be cross referenced. These Logs are found in simulation_output directory, similar to that of sys_logs and can be enabled in the I/O settings in a yaml configuration file. +- Added a new agent behaviour log which are more human friendly than agent history. These Logs are found in session log directory and can be enabled in the I/O settings in a yaml configuration file. ## [Unreleased] - Made requests fail to reach their target if the node is off diff --git a/src/primaite/game/agent/agent_log.py b/src/primaite/game/agent/agent_log.py index 1e51dcad..62ef4884 100644 --- a/src/primaite/game/agent/agent_log.py +++ b/src/primaite/game/agent/agent_log.py @@ -22,7 +22,7 @@ class AgentLog: """ A Agent Log class is a simple logger dedicated to managing and writing logging updates and information for an agent. - Each log message is written to a file located at: /agent/agent_name.log + Each log message is written to a file located at: /agent_name/agent_name.log """ def __init__(self, agent_name: str): @@ -33,8 +33,28 @@ class AgentLog: """ self.agent_name = agent_name self.current_episode: int = 1 + self.current_timestep: int = 0 self.setup_logger() + @property + def timestep(self) -> int: + """Returns the current timestep. Used for log indexing. + + :return: The current timestep as an Int. + """ + return self.current_timestep + + def update_timestep(self, new_timestep: int): + """ + Updates the self.current_timestep attribute with the given parameter. + + This method is called within .step() to ensure that all instances of Agent Logs + are in sync with one another. + + :param new_timestep: The new timestep. + """ + self.current_timestep = new_timestep + def setup_logger(self): """ Configures the logger for this Agent Log instance. @@ -60,19 +80,19 @@ class AgentLog: def _get_log_path(self) -> Path: """ - Constructs the path for the log file based on the hostname. + Constructs the path for the log file based on the agent name. :return: Path object representing the location of the log file. """ - root = SIM_OUTPUT.path / f"episode_{self.current_episode}" / "agent_logs" / self.agent_name + root = SIM_OUTPUT.agent_behaviour_path / f"episode_{self.current_episode}" / self.agent_name root.mkdir(exist_ok=True, parents=True) return root / f"{self.agent_name}.log" - def _write_to_terminal(self, msg: str, timestep: int, level: str, to_terminal: bool = False): + def _write_to_terminal(self, msg: str, level: str, to_terminal: bool = False): if to_terminal or SIM_OUTPUT.write_agent_log_to_terminal: - print(f"{self.agent_name}: ({timestep}) ({level}) {msg}") + print(f"{self.agent_name}: ({ self.timestep}) ({level}) {msg}") - def debug(self, msg: str, time_step: int, to_terminal: bool = False): + def debug(self, msg: str, to_terminal: bool = False): """ Logs a message with the DEBUG level. @@ -83,10 +103,10 @@ class AgentLog: return if SIM_OUTPUT.save_agent_logs: - self.logger.debug(msg, extra={"timestep": time_step}) + self.logger.debug(msg, extra={"timestep": self.timestep}) self._write_to_terminal(msg, "DEBUG", to_terminal) - def info(self, msg: str, time_step: int, to_terminal: bool = False): + def info(self, msg: str, to_terminal: bool = False): """ Logs a message with the INFO level. @@ -98,10 +118,10 @@ class AgentLog: return if SIM_OUTPUT.save_agent_logs: - self.logger.info(msg, extra={"timestep": time_step}) + self.logger.info(msg, extra={"timestep": self.timestep}) self._write_to_terminal(msg, "INFO", to_terminal) - def warning(self, msg: str, time_step: int, to_terminal: bool = False): + def warning(self, msg: str, to_terminal: bool = False): """ Logs a message with the WARNING level. @@ -113,10 +133,10 @@ class AgentLog: return if SIM_OUTPUT.save_agent_logs: - self.logger.warning(msg, extra={"timestep": time_step}) + self.logger.warning(msg, extra={"timestep": self.timestep}) self._write_to_terminal(msg, "WARNING", to_terminal) - def error(self, msg: str, time_step: int, to_terminal: bool = False): + def error(self, msg: str, to_terminal: bool = False): """ Logs a message with the ERROR level. @@ -128,10 +148,10 @@ class AgentLog: return if SIM_OUTPUT.save_agent_logs: - self.logger.error(msg, extra={"timestep": time_step}) + self.logger.error(msg, extra={"timestep": self.timestep}) self._write_to_terminal(msg, "ERROR", to_terminal) - def critical(self, msg: str, time_step: int, to_terminal: bool = False): + def critical(self, msg: str, to_terminal: bool = False): """ Logs a message with the CRITICAL level. @@ -143,7 +163,7 @@ class AgentLog: return if SIM_OUTPUT.save_agent_logs: - self.logger.critical(msg, extra={"timestep": time_step}) + self.logger.critical(msg, extra={"timestep": self.timestep}) self._write_to_terminal(msg, "CRITICAL", to_terminal) def show(self, last_n: int = 10, markdown: bool = False): diff --git a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py index cd72e001..129fac1a 100644 --- a/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py +++ b/src/primaite/game/agent/scripted_agents/data_manipulation_bot.py @@ -38,11 +38,11 @@ class DataManipulationAgent(AbstractScriptedAgent): :rtype: Tuple[str, Dict] """ if timestep < self.next_execution_timestep: - self.logger.debug(msg="Performing do NOTHING", time_step=timestep) + self.logger.debug(msg="Performing do NOTHING") return "DONOTHING", {} self._set_next_execution_timestep(timestep + self.agent_settings.start_settings.frequency) - self.logger.info(msg="Performing a data manipulation attack!", time_step=timestep) + self.logger.info(msg="Performing a data manipulation attack!") return "NODE_APPLICATION_EXECUTE", {"node_id": self.starting_node_idx, "application_id": 0} def setup_agent(self) -> None: @@ -55,4 +55,4 @@ class DataManipulationAgent(AbstractScriptedAgent): # we are assuming that every node in the node manager has a data manipulation application at idx 0 num_nodes = len(self.action_manager.node_names) self.starting_node_idx = random.randint(0, num_nodes - 1) - self.logger.debug(msg=f"Select Start Node ID: {self.starting_node_idx}", time_step=0) + self.logger.debug(msg=f"Select Start Node ID: {self.starting_node_idx}") diff --git a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py index e0f41302..f5905ad0 100644 --- a/src/primaite/game/agent/scripted_agents/probabilistic_agent.py +++ b/src/primaite/game/agent/scripted_agents/probabilistic_agent.py @@ -85,5 +85,5 @@ class ProbabilisticAgent(AbstractScriptedAgent): :rtype: Tuple[str, Dict] """ choice = self.rng.choice(len(self.action_manager.action_map), p=self.probabilities) - self.logger.info(f"Performing Action: {choice}", time_step=timestep) + self.logger.info(f"Performing Action: {choice}") return self.action_manager.get_action(choice) diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 3dc9571f..cb787e68 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -15,6 +15,7 @@ from primaite.game.agent.scripted_agents.probabilistic_agent import Probabilisti from primaite.game.agent.scripted_agents.random_agent import PeriodicAgent from primaite.game.agent.scripted_agents.tap001 import TAP001 from primaite.game.science import graph_has_cycle, topological_sort +from primaite.simulator import SIM_OUTPUT from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC @@ -164,6 +165,8 @@ class PrimaiteGame: for _, agent in self.agents.items(): obs = agent.observation_manager.current_observation action_choice, parameters = agent.get_action(obs, timestep=self.step_counter) + if SIM_OUTPUT.save_agent_logs: + agent.logger.debug(f"Chosen Action: {action_choice}") request = agent.format_request(action_choice, parameters) response = self.simulation.apply_request(request) agent.process_action_response( @@ -182,8 +185,14 @@ class PrimaiteGame: """Advance timestep.""" self.step_counter += 1 _LOGGER.debug(f"Advancing timestep to {self.step_counter} ") + self.update_agent_loggers() self.simulation.apply_timestep(self.step_counter) + def update_agent_loggers(self) -> None: + """Updates Agent Loggers with new timestep.""" + for agent in self.agents.values(): + agent.logger.update_timestep(self.step_counter) + def calculate_truncated(self) -> bool: """Calculate whether the episode is truncated.""" current_step = self.step_counter diff --git a/src/primaite/session/io.py b/src/primaite/session/io.py index 05a5ee09..78d7cb3c 100644 --- a/src/primaite/session/io.py +++ b/src/primaite/session/io.py @@ -57,6 +57,7 @@ class PrimaiteIO: self.session_path: Path = self.generate_session_path() # set global SIM_OUTPUT path SIM_OUTPUT.path = self.session_path / "simulation_output" + SIM_OUTPUT.agent_behaviour_path = self.session_path / "agent_behaviour" SIM_OUTPUT.save_pcap_logs = self.settings.save_pcap_logs SIM_OUTPUT.save_sys_logs = self.settings.save_sys_logs SIM_OUTPUT.save_agent_logs = self.settings.save_agent_logs @@ -67,20 +68,20 @@ class PrimaiteIO: def generate_session_path(self, timestamp: Optional[datetime] = None) -> Path: """Create a folder for the session and return the path to it.""" - if timestamp is None: - timestamp = datetime.now() - date_str = timestamp.strftime("%Y-%m-%d") - time_str = timestamp.strftime("%H-%M-%S") - - session_path = PRIMAITE_PATHS.user_sessions_path / date_str / time_str + session_path = PRIMAITE_PATHS.user_sessions_path / SIM_OUTPUT.date_str / SIM_OUTPUT.time_str # check if running in dev mode if is_dev_mode(): - session_path = _PRIMAITE_ROOT.parent.parent / "sessions" / date_str / time_str + session_path = _PRIMAITE_ROOT.parent.parent / "sessions" / SIM_OUTPUT.date_str / SIM_OUTPUT.time_str # check if there is an output directory set in config if PRIMAITE_CONFIG["developer_mode"]["output_dir"]: - session_path = Path(PRIMAITE_CONFIG["developer_mode"]["output_dir"]) / "sessions" / date_str / time_str + session_path = ( + Path(PRIMAITE_CONFIG["developer_mode"]["output_dir"]) + / "sessions" + / SIM_OUTPUT.date_str + / SIM_OUTPUT.time_str + ) session_path.mkdir(exist_ok=True, parents=True) return session_path diff --git a/src/primaite/setup/_package_data/primaite_config.yaml b/src/primaite/setup/_package_data/primaite_config.yaml index c1caf1f4..e08d951e 100644 --- a/src/primaite/setup/_package_data/primaite_config.yaml +++ b/src/primaite/setup/_package_data/primaite_config.yaml @@ -3,6 +3,8 @@ developer_mode: enabled: False # not enabled by default sys_log_level: DEBUG # level of output for system logs, DEBUG by default + agent_log_level: DEBUG # level of output for agent logs, DEBUG by default + output_agent_logs: False # level of output for system logs, DEBUG by default output_sys_logs: False # system logs not output by default output_pcap_logs: False # pcap logs not output by default output_to_terminal: False # do not output to terminal by default diff --git a/src/primaite/simulator/__init__.py b/src/primaite/simulator/__init__.py index 487e7c5e..ade1a73b 100644 --- a/src/primaite/simulator/__init__.py +++ b/src/primaite/simulator/__init__.py @@ -34,6 +34,7 @@ class _SimOutput: path = PRIMAITE_PATHS.user_sessions_path / self.date_str / self.time_str self._path = path + self._agent_behaviour_path = path self._save_pcap_logs: bool = False self._save_sys_logs: bool = False self._save_agent_logs: bool = False @@ -64,6 +65,28 @@ class _SimOutput: self._path = new_path self._path.mkdir(exist_ok=True, parents=True) + @property + def agent_behaviour_path(self) -> Path: + if is_dev_mode(): + # if dev mode is enabled, if output dir is not set, print to primaite repo root + path: Path = _PRIMAITE_ROOT.parent.parent / "sessions" / self.date_str / self.time_str / "agent_behaviour" + # otherwise print to output dir + if PRIMAITE_CONFIG["developer_mode"]["output_dir"]: + path: Path = ( + Path(PRIMAITE_CONFIG["developer_mode"]["output_dir"]) + / "sessions" + / self.date_str + / self.time_str + / "agent_behaviour" + ) + self._agent_behaviour_path = path + return self._agent_behaviour_path + + @agent_behaviour_path.setter + def agent_behaviour_path(self, new_path: Path) -> None: + self._agent_behaviour_path = new_path + self._agent_behaviour_path.mkdir(exist_ok=True, parents=True) + @property def save_pcap_logs(self) -> bool: if is_dev_mode(): diff --git a/src/primaite/utils/cli/dev_cli.py b/src/primaite/utils/cli/dev_cli.py index 15adacb3..0dd9f9cc 100644 --- a/src/primaite/utils/cli/dev_cli.py +++ b/src/primaite/utils/cli/dev_cli.py @@ -82,12 +82,31 @@ def config_callback( show_default=False, ), ] = None, + agent_log_level: Annotated[ + LogLevel, + typer.Option( + "--agent-log-level", + "-level", + click_type=click.Choice(LogLevel._member_names_, case_sensitive=False), + help="The level of agent behaviour logs to output.", + show_default=False, + ), + ] = None, output_sys_logs: Annotated[ bool, typer.Option( "--output-sys-logs/--no-sys-logs", "-sys/-nsys", help="Output system logs to file.", show_default=False ), ] = None, + output_agent_logs: Annotated[ + bool, + typer.Option( + "--output-agent-logs/--no-agent-logs", + "-agent/-nagent", + help="Output agent logs to file.", + show_default=False, + ), + ] = None, output_pcap_logs: Annotated[ bool, typer.Option( @@ -109,10 +128,18 @@ def config_callback( PRIMAITE_CONFIG["developer_mode"]["sys_log_level"] = ctx.params.get("sys_log_level") print(f"PrimAITE dev-mode config updated sys_log_level={ctx.params.get('sys_log_level')}") + if ctx.params.get("agent_log_level") is not None: + PRIMAITE_CONFIG["developer_mode"]["agent_log_level"] = ctx.params.get("agent_log_level") + print(f"PrimAITE dev-mode config updated agent_log_level={ctx.params.get('agent_log_level')}") + if output_sys_logs is not None: PRIMAITE_CONFIG["developer_mode"]["output_sys_logs"] = output_sys_logs print(f"PrimAITE dev-mode config updated {output_sys_logs=}") + if output_agent_logs is not None: + PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] = output_agent_logs + print(f"PrimAITE dev-mode config updated {output_agent_logs=}") + if output_pcap_logs is not None: PRIMAITE_CONFIG["developer_mode"]["output_pcap_logs"] = output_pcap_logs print(f"PrimAITE dev-mode config updated {output_pcap_logs=}") diff --git a/tests/integration_tests/cli/test_dev_cli.py b/tests/integration_tests/cli/test_dev_cli.py index 43f623a5..19559e7c 100644 --- a/tests/integration_tests/cli/test_dev_cli.py +++ b/tests/integration_tests/cli/test_dev_cli.py @@ -67,7 +67,7 @@ def test_dev_mode_config_sys_log_level(): # check defaults assert PRIMAITE_CONFIG["developer_mode"]["sys_log_level"] == "DEBUG" # DEBUG by default - result = cli(["dev-mode", "config", "-level", "WARNING"]) + result = cli(["dev-mode", "config", "--sys-log-level", "WARNING"]) assert "sys_log_level=WARNING" in result.output # should print correct value @@ -78,10 +78,30 @@ def test_dev_mode_config_sys_log_level(): assert "sys_log_level=INFO" in result.output # should print correct value - # config should reflect that log level is WARNING + # config should reflect that log level is INFO assert PRIMAITE_CONFIG["developer_mode"]["sys_log_level"] == "INFO" +def test_dev_mode_config_agent_log_level(): + """Check that the agent log level can be changed via CLI.""" + # check defaults + assert PRIMAITE_CONFIG["developer_mode"]["agent_log_level"] == "DEBUG" # DEBUG by default + + result = cli(["dev-mode", "config", "-level", "WARNING"]) + + assert "agent_log_level=WARNING" in result.output # should print correct value + + # config should reflect that log level is WARNING + assert PRIMAITE_CONFIG["developer_mode"]["agent_log_level"] == "WARNING" + + result = cli(["dev-mode", "config", "--agent-log-level", "INFO"]) + + assert "agent_log_level=INFO" in result.output # should print correct value + + # config should reflect that log level is INFO + assert PRIMAITE_CONFIG["developer_mode"]["agent_log_level"] == "INFO" + + def test_dev_mode_config_sys_logs_enable_disable(): """Test that the system logs output can be enabled or disabled.""" # check defaults @@ -112,6 +132,36 @@ def test_dev_mode_config_sys_logs_enable_disable(): assert PRIMAITE_CONFIG["developer_mode"]["output_sys_logs"] is False +def test_dev_mode_config_agent_logs_enable_disable(): + """Test that the agent logs output can be enabled or disabled.""" + # check defaults + assert PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] is False # False by default + + result = cli(["dev-mode", "config", "--output-agent-logs"]) + assert "output_agent_logs=True" in result.output # should print correct value + + # config should reflect that output_agent_logs is True + assert PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] + + result = cli(["dev-mode", "config", "--no-agent-logs"]) + assert "output_agent_logs=False" in result.output # should print correct value + + # config should reflect that output_agent_logs is True + assert PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] is False + + result = cli(["dev-mode", "config", "-agent"]) + assert "output_agent_logs=True" in result.output # should print correct value + + # config should reflect that output_agent_logs is True + assert PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] + + result = cli(["dev-mode", "config", "-nagent"]) + assert "output_agent_logs=False" in result.output # should print correct value + + # config should reflect that output_agent_logs is True + assert PRIMAITE_CONFIG["developer_mode"]["output_agent_logs"] is False + + def test_dev_mode_config_pcap_logs_enable_disable(): """Test that the pcap logs output can be enabled or disabled.""" # check defaults diff --git a/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py b/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py index a7932cb7..d61e1a23 100644 --- a/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py +++ b/tests/unit_tests/_primaite/_game/_agent/test_agent_log.py @@ -29,11 +29,11 @@ def test_debug_agent_log_level(agentlog, capsys): test_string = str(uuid4()) - agentlog.debug(msg=test_string, time_step=0) - agentlog.info(msg=test_string, time_step=0) - agentlog.warning(msg=test_string, time_step=0) - agentlog.error(msg=test_string, time_step=0) - agentlog.critical(msg=test_string, time_step=0) + agentlog.debug(msg=test_string) + agentlog.info(msg=test_string) + agentlog.warning(msg=test_string) + agentlog.error(msg=test_string) + agentlog.critical(msg=test_string) captured = "".join(capsys.readouterr()) @@ -52,11 +52,11 @@ def test_info_agent_log_level(agentlog, capsys): test_string = str(uuid4()) - agentlog.debug(msg=test_string, time_step=0) - agentlog.info(msg=test_string, time_step=0) - agentlog.warning(msg=test_string, time_step=0) - agentlog.error(msg=test_string, time_step=0) - agentlog.critical(msg=test_string, time_step=0) + agentlog.debug(msg=test_string) + agentlog.info(msg=test_string) + agentlog.warning(msg=test_string) + agentlog.error(msg=test_string) + agentlog.critical(msg=test_string) captured = "".join(capsys.readouterr()) @@ -75,11 +75,11 @@ def test_warning_agent_log_level(agentlog, capsys): test_string = str(uuid4()) - agentlog.debug(msg=test_string, time_step=0) - agentlog.info(msg=test_string, time_step=0) - agentlog.warning(msg=test_string, time_step=0) - agentlog.error(msg=test_string, time_step=0) - agentlog.critical(msg=test_string, time_step=0) + agentlog.debug(msg=test_string) + agentlog.info(msg=test_string) + agentlog.warning(msg=test_string) + agentlog.error(msg=test_string) + agentlog.critical(msg=test_string) captured = "".join(capsys.readouterr()) @@ -98,11 +98,11 @@ def test_error_agent_log_level(agentlog, capsys): test_string = str(uuid4()) - agentlog.debug(msg=test_string, time_step=0) - agentlog.info(msg=test_string, time_step=0) - agentlog.warning(msg=test_string, time_step=0) - agentlog.error(msg=test_string, time_step=0) - agentlog.critical(msg=test_string, time_step=0) + agentlog.debug(msg=test_string) + agentlog.info(msg=test_string) + agentlog.warning(msg=test_string) + agentlog.error(msg=test_string) + agentlog.critical(msg=test_string) captured = "".join(capsys.readouterr()) @@ -121,11 +121,11 @@ def test_critical_agent_log_level(agentlog, capsys): test_string = str(uuid4()) - agentlog.debug(msg=test_string, time_step=0) - agentlog.info(msg=test_string, time_step=0) - agentlog.warning(msg=test_string, time_step=0) - agentlog.error(msg=test_string, time_step=0) - agentlog.critical(msg=test_string, time_step=0) + agentlog.debug(msg=test_string) + agentlog.info(msg=test_string) + agentlog.warning(msg=test_string) + agentlog.error(msg=test_string) + agentlog.critical(msg=test_string) captured = "".join(capsys.readouterr()) From 0c58c3969a901a8d508b2a429080905a311811ee Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Wed, 10 Jul 2024 13:46:30 +0100 Subject: [PATCH 22/42] 2623 - finish testing action mask --- .../simulator/system/services/service.py | 8 +- .../assets/configs/test_primaite_session.yaml | 27 ++- tests/conftest.py | 2 + .../test_agents_use_action_masks.py | 2 - .../test_rllib_multi_agent_environment.py | 3 - .../test_rllib_single_agent_environment.py | 4 - .../e2e_integration_tests/test_environment.py | 18 +- .../game_layer/test_action_mask.py | 161 ++++++++++++++++++ 8 files changed, 198 insertions(+), 27 deletions(-) create mode 100644 tests/integration_tests/game_layer/test_action_mask.py diff --git a/src/primaite/simulator/system/services/service.py b/src/primaite/simulator/system/services/service.py index 8167a8a9..5adea6e7 100644 --- a/src/primaite/simulator/system/services/service.py +++ b/src/primaite/simulator/system/services/service.py @@ -92,6 +92,7 @@ class Service(IOSoftware): _is_service_running = Service._StateValidator(service=self, state=ServiceOperatingState.RUNNING) _is_service_stopped = Service._StateValidator(service=self, state=ServiceOperatingState.STOPPED) _is_service_paused = Service._StateValidator(service=self, state=ServiceOperatingState.PAUSED) + _is_service_disabled = Service._StateValidator(service=self, state=ServiceOperatingState.DISABLED) rm = super()._init_request_manager() rm.add_request( @@ -131,7 +132,12 @@ class Service(IOSoftware): ), ) rm.add_request("disable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.disable()))) - rm.add_request("enable", RequestType(func=lambda request, context: RequestResponse.from_bool(self.enable()))) + rm.add_request( + "enable", + RequestType( + func=lambda request, context: RequestResponse.from_bool(self.enable()), validator=_is_service_disabled + ), + ) rm.add_request( "fix", RequestType( diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index 7c894ba0..c435fe44 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -243,25 +243,25 @@ agents: action: "NODE_FILE_SCAN" options: node_id: 2 - folder_id: 1 + folder_id: 0 file_id: 0 10: action: "NODE_FILE_CHECKHASH" options: node_id: 2 - folder_id: 1 + folder_id: 0 file_id: 0 11: action: "NODE_FILE_DELETE" options: node_id: 2 - folder_id: 1 + folder_id: 0 file_id: 0 12: action: "NODE_FILE_REPAIR" options: node_id: 2 - folder_id: 1 + folder_id: 0 file_id: 0 13: action: "NODE_SERVICE_FIX" @@ -272,22 +272,22 @@ agents: action: "NODE_FOLDER_SCAN" options: node_id: 2 - folder_id: 1 + folder_id: 0 15: action: "NODE_FOLDER_CHECKHASH" options: node_id: 2 - folder_id: 1 + folder_id: 0 16: action: "NODE_FOLDER_REPAIR" options: node_id: 2 - folder_id: 1 + folder_id: 0 17: action: "NODE_FOLDER_RESTORE" options: node_id: 2 - folder_id: 1 + folder_id: 0 18: action: "NODE_OS_SCAN" options: @@ -518,11 +518,22 @@ agents: nodes: - node_name: domain_controller - node_name: web_server + applications: + - application_name: DatabaseClient + services: + - service_name: WebServer - node_name: database_server + folders: + - folder_name: database + files: + - file_name: database.db + services: + - service_name: DatabaseService - node_name: backup_server - node_name: security_suite - node_name: client_1 - node_name: client_2 + max_folders_per_node: 2 max_files_per_folder: 2 max_services_per_node: 2 diff --git a/tests/conftest.py b/tests/conftest.py index e36a2460..adfa7724 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ from typing import Any, Dict, Tuple import pytest +import ray import yaml from primaite import getLogger, PRIMAITE_PATHS @@ -29,6 +30,7 @@ from primaite.simulator.system.services.service import Service from primaite.simulator.system.services.web_server.web_server import WebServer from tests import TEST_ASSETS_ROOT +ray.init(local_mode=True) ACTION_SPACE_NODE_VALUES = 1 ACTION_SPACE_NODE_ACTION_VALUES = 1 diff --git a/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py index 3efda71a..a299b913 100644 --- a/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py +++ b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py @@ -15,8 +15,6 @@ from primaite.session.environment import PrimaiteGymEnv from primaite.session.ray_envs import PrimaiteRayEnv, PrimaiteRayMARLEnv from tests import TEST_ASSETS_ROOT -init(local_mode=True) - CFG_PATH = TEST_ASSETS_ROOT / "configs/test_primaite_session.yaml" MARL_PATH = TEST_ASSETS_ROOT / "configs/multi_agent_session.yaml" diff --git a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py index 96ec799c..e015c33c 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py @@ -16,8 +16,6 @@ def test_rllib_multi_agent_compatibility(): with open(MULTI_AGENT_PATH, "r") as f: cfg = yaml.safe_load(f) - ray.init() - config = ( PPOConfig() .environment(env=PrimaiteRayMARLEnv, env_config=cfg) @@ -39,4 +37,3 @@ def test_rllib_multi_agent_compatibility(): ), param_space=config, ).fit() - ray.shutdown() diff --git a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py index d6cacfd2..a02a078c 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py @@ -20,9 +20,6 @@ def test_rllib_single_agent_compatibility(): game = PrimaiteGame.from_config(cfg) - ray.shutdown() - ray.init() - env_config = {"game": game} config = { "env": PrimaiteRayEnv, @@ -41,4 +38,3 @@ def test_rllib_single_agent_compatibility(): assert save_file.exists() save_file.unlink() # clean up - ray.shutdown() diff --git a/tests/e2e_integration_tests/test_environment.py b/tests/e2e_integration_tests/test_environment.py index c8238aba..253bd396 100644 --- a/tests/e2e_integration_tests/test_environment.py +++ b/tests/e2e_integration_tests/test_environment.py @@ -65,25 +65,25 @@ class TestPrimaiteEnvironment: cfg = yaml.safe_load(f) env = PrimaiteRayMARLEnv(env_config=cfg) - assert set(env._agent_ids) == {"defender1", "defender2"} + assert set(env._agent_ids) == {"defender_1", "defender_2"} assert len(env.agents) == 2 - defender1 = env.agents["defender1"] - defender2 = env.agents["defender2"] - assert (num_actions_1 := len(defender1.action_manager.action_map)) == 54 - assert (num_actions_2 := len(defender2.action_manager.action_map)) == 38 + defender_1 = env.agents["defender_1"] + defender_2 = env.agents["defender_2"] + assert (num_actions_1 := len(defender_1.action_manager.action_map)) == 74 + assert (num_actions_2 := len(defender_2.action_manager.action_map)) == 74 # ensure we can run all valid actions without error for act_1 in range(num_actions_1): - env.step({"defender1": act_1, "defender2": 0}) + env.step({"defender_1": act_1, "defender_2": 0}) for act_2 in range(num_actions_2): - env.step({"defender1": 0, "defender2": act_2}) + env.step({"defender_1": 0, "defender_2": act_2}) # ensure we get error when taking an invalid action with pytest.raises(KeyError): - env.step({"defender1": num_actions_1, "defender2": 0}) + env.step({"defender_1": num_actions_1, "defender_2": 0}) with pytest.raises(KeyError): - env.step({"defender1": 0, "defender2": num_actions_2}) + env.step({"defender_1": 0, "defender_2": num_actions_2}) def test_error_thrown_on_bad_configuration(self): """Make sure we throw an error when the config is bad.""" diff --git a/tests/integration_tests/game_layer/test_action_mask.py b/tests/integration_tests/game_layer/test_action_mask.py new file mode 100644 index 00000000..64464724 --- /dev/null +++ b/tests/integration_tests/game_layer/test_action_mask.py @@ -0,0 +1,161 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from primaite.session.environment import PrimaiteGymEnv +from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState +from primaite.simulator.network.hardware.nodes.host.host_node import HostNode +from primaite.simulator.system.services.service import ServiceOperatingState +from tests.conftest import TEST_ASSETS_ROOT + +CFG_PATH = TEST_ASSETS_ROOT / "configs/test_primaite_session.yaml" + + +def test_mask_contents_correct(): + env = PrimaiteGymEnv(CFG_PATH) + game = env.game + sim = game.simulation + net = sim.network + mask = game.action_mask("defender") + agent = env.agent + node_list = agent.action_manager.node_names + action_map = agent.action_manager.action_map + + # CHECK NIC ENABLE/DISABLE ACTIONS + for action_num, action in action_map.items(): + mask = game.action_mask("defender") + act_type, act_params = action + + if act_type == "NODE_NIC_ENABLE": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + nic_obj = node_obj.network_interface[act_params["nic_id"] + 1] + assert nic_obj.enabled + assert not mask[action_num] + nic_obj.disable() + mask = game.action_mask("defender") + assert mask[action_num] + nic_obj.enable() + + if act_type == "NODE_NIC_DISABLE": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + nic_obj = node_obj.network_interface[act_params["nic_id"] + 1] + assert nic_obj.enabled + assert mask[action_num] + nic_obj.disable() + mask = game.action_mask("defender") + assert not mask[action_num] + nic_obj.enable() + + if act_type == "ROUTER_ACL_ADDRULE": + assert mask[action_num] + + if act_type == "ROUTER_ACL_REMOVERULE": + assert mask[action_num] + + if act_type == "NODE_RESET": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + assert node_obj.operating_state is NodeOperatingState.ON + assert mask[action_num] + node_obj.operating_state = NodeOperatingState.OFF + mask = game.action_mask("defender") + assert not mask[action_num] + node_obj.operating_state = NodeOperatingState.ON + + if act_type == "NODE_SHUTDOWN": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + assert node_obj.operating_state is NodeOperatingState.ON + assert mask[action_num] + node_obj.operating_state = NodeOperatingState.OFF + mask = game.action_mask("defender") + assert not mask[action_num] + node_obj.operating_state = NodeOperatingState.ON + + if act_type == "NODE_OS_SCAN": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + assert node_obj.operating_state is NodeOperatingState.ON + assert mask[action_num] + node_obj.operating_state = NodeOperatingState.OFF + mask = game.action_mask("defender") + assert not mask[action_num] + node_obj.operating_state = NodeOperatingState.ON + + if act_type == "NODE_STARTUP": + node_name = node_list[act_params["node_id"]] + node_obj = net.get_node_by_hostname(node_name) + assert node_obj.operating_state is NodeOperatingState.ON + assert not mask[action_num] + node_obj.operating_state = NodeOperatingState.OFF + mask = game.action_mask("defender") + assert mask[action_num] + node_obj.operating_state = NodeOperatingState.ON + + if act_type == "DONOTHING": + assert mask[action_num] + + if act_type == "NODE_SERVICE_DISABLE": + assert mask[action_num] + + if act_type in ["NODE_SERVICE_SCAN", "NODE_SERVICE_STOP", "NODE_SERVICE_PAUSE"]: + node_name = node_list[act_params["node_id"]] + service_name = agent.action_manager.service_names[act_params["node_id"]][act_params["service_id"]] + node_obj = net.get_node_by_hostname(node_name) + service_obj = node_obj.software_manager.software.get(service_name) + assert service_obj.operating_state is ServiceOperatingState.RUNNING + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.DISABLED + mask = game.action_mask("defender") + assert not mask[action_num] + service_obj.operating_state = ServiceOperatingState.RUNNING + + if act_type == "NODE_SERVICE_RESUME": + node_name = node_list[act_params["node_id"]] + service_name = agent.action_manager.service_names[act_params["node_id"]][act_params["service_id"]] + node_obj = net.get_node_by_hostname(node_name) + service_obj = node_obj.software_manager.software.get(service_name) + assert service_obj.operating_state is ServiceOperatingState.RUNNING + assert not mask[action_num] + service_obj.operating_state = ServiceOperatingState.PAUSED + mask = game.action_mask("defender") + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.RUNNING + + if act_type == "NODE_SERVICE_START": + node_name = node_list[act_params["node_id"]] + service_name = agent.action_manager.service_names[act_params["node_id"]][act_params["service_id"]] + node_obj = net.get_node_by_hostname(node_name) + service_obj = node_obj.software_manager.software.get(service_name) + assert service_obj.operating_state is ServiceOperatingState.RUNNING + assert not mask[action_num] + service_obj.operating_state = ServiceOperatingState.STOPPED + mask = game.action_mask("defender") + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.RUNNING + + if act_type == "NODE_SERVICE_ENABLE": + node_name = node_list[act_params["node_id"]] + service_name = agent.action_manager.service_names[act_params["node_id"]][act_params["service_id"]] + node_obj = net.get_node_by_hostname(node_name) + service_obj = node_obj.software_manager.software.get(service_name) + assert service_obj.operating_state is ServiceOperatingState.RUNNING + assert not mask[action_num] + service_obj.operating_state = ServiceOperatingState.DISABLED + mask = game.action_mask("defender") + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.RUNNING + + if act_type in ["NODE_FILE_SCAN", "NODE_FILE_CHECKHASH", "NODE_FILE_DELETE"]: + node_name = node_list[act_params["node_id"]] + folder_name = agent.action_manager.get_folder_name_by_idx(act_params["node_id"], act_params["folder_id"]) + file_name = agent.action_manager.get_file_name_by_idx( + act_params["node_id"], act_params["folder_id"], act_params["file_id"] + ) + node_obj = net.get_node_by_hostname(node_name) + file_obj = node_obj.file_system.get_file(folder_name, file_name, include_deleted=True) + assert not file_obj.deleted + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.DISABLED + mask = game.action_mask("defender") + assert mask[action_num] + service_obj.operating_state = ServiceOperatingState.RUNNING From 2bedf0c36301cd07a22267065703fedff02ebf37 Mon Sep 17 00:00:00 2001 From: "Archer.Bowen" Date: Wed, 10 Jul 2024 13:56:33 +0100 Subject: [PATCH 23/42] Updated changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5418bdf..2d9aed82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Bandwidth Tracking**: Tracks data transmission across each frequency/channel width pairing. - **Configuration Support for Wireless Routers**: `channel_width` can now be configured in the config file under `wireless_access_point`. - **New Tests**: Added to validate the respect of bandwidth capacities and the correct parsing of airspace configurations from YAML files. +- **New Logging**: Added a new agent behaviour log which are more human friendly than agent history. These Logs are found in session log directory and can be enabled in the I/O settings in a yaml configuration file. ### Changed @@ -58,7 +59,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Activating dev-mode will change the location where the sessions will be output - by default will output where the PrimAITE repository is located - Refactored all air-space usage to that a new instance of AirSpace is created for each instance of Network. This 1:1 relationship between network and airspace will allow parallelization. - Added notebook to demonstrate use of SubprocVecEnv from SB3 to vectorise environments to speed up training. -- Added a new agent behaviour log which are more human friendly than agent history. These Logs are found in session log directory and can be enabled in the I/O settings in a yaml configuration file. ## [Unreleased] - Made requests fail to reach their target if the node is off From 9e7fd017df0944f52c8103f0b9e85eb5bc5665a1 Mon Sep 17 00:00:00 2001 From: "Archer.Bowen" Date: Wed, 10 Jul 2024 14:04:52 +0100 Subject: [PATCH 24/42] #2716 Fixed game.py pre-commit issue. --- src/primaite/game/game.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index ec59a784..1e6aeae0 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -15,8 +15,8 @@ from primaite.game.agent.scripted_agents.probabilistic_agent import Probabilisti from primaite.game.agent.scripted_agents.random_agent import PeriodicAgent from primaite.game.agent.scripted_agents.tap001 import TAP001 from primaite.game.science import graph_has_cycle, topological_sort -from primaite.simulator.network.airspace import AirspaceEnvironmentType from primaite.simulator import SIM_OUTPUT +from primaite.simulator.network.airspace import AirspaceEnvironmentType from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC From aa425a528443d14529f0873843d7138042023fe2 Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Wed, 10 Jul 2024 14:40:25 +0100 Subject: [PATCH 25/42] #2740: fix tests affected by request permissions --- .../_simulator/_file_system/test_file_actions.py | 14 +++++++------- .../_simulator/_file_system/test_folder_actions.py | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py index 295bca08..594c7afe 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py @@ -26,7 +26,7 @@ def test_file_scan_request(populated_file_system): assert file.health_status == FileSystemItemHealthStatus.CORRUPT assert file.visible_health_status == FileSystemItemHealthStatus.GOOD - fs.apply_request(request=["file", file.name, "scan"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "scan"]) assert file.health_status == FileSystemItemHealthStatus.CORRUPT assert file.visible_health_status == FileSystemItemHealthStatus.CORRUPT @@ -37,12 +37,12 @@ def test_file_checkhash_request(populated_file_system): """Test that an agent can request a file hash check.""" fs, folder, file = populated_file_system - fs.apply_request(request=["file", file.name, "checkhash"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "checkhash"]) assert file.health_status == FileSystemItemHealthStatus.GOOD file.sim_size = 0 - fs.apply_request(request=["file", file.name, "checkhash"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "checkhash"]) assert file.health_status == FileSystemItemHealthStatus.CORRUPT @@ -54,7 +54,7 @@ def test_file_repair_request(populated_file_system): file.corrupt() assert file.health_status == FileSystemItemHealthStatus.CORRUPT - fs.apply_request(request=["file", file.name, "repair"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "repair"]) assert file.health_status == FileSystemItemHealthStatus.GOOD @@ -71,7 +71,7 @@ def test_file_restore_request(populated_file_system): assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None assert fs.get_file(folder_name=folder.name, file_name=file.name).deleted is False - fs.apply_request(request=["file", file.name, "corrupt"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"]) assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT fs.apply_request(request=["restore", "file", folder.name, file.name]) @@ -81,7 +81,7 @@ def test_file_restore_request(populated_file_system): def test_file_corrupt_request(populated_file_system): """Test that an agent can request a file corruption.""" fs, folder, file = populated_file_system - fs.apply_request(request=["file", file.name, "corrupt"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"]) assert file.health_status == FileSystemItemHealthStatus.CORRUPT @@ -90,7 +90,7 @@ def test_deleted_file_cannot_be_interacted_with(populated_file_system): fs, folder, file = populated_file_system assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - fs.apply_request(request=["file", file.name, "corrupt"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"]) assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT assert ( fs.get_file(folder_name=folder.name, file_name=file.name).visible_health_status diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py index 40f1e78b..00148311 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py @@ -166,13 +166,13 @@ def test_deleted_folder_and_its_files_cannot_be_interacted_with(populated_file_s fs, folder, file = populated_file_system assert fs.get_file(folder_name=folder.name, file_name=file.name) is not None - fs.apply_request(request=["file", file.name, "corrupt"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "corrupt"]) assert fs.get_file(folder_name=folder.name, file_name=file.name).health_status == FileSystemItemHealthStatus.CORRUPT fs.apply_request(request=["delete", "folder", folder.name]) assert fs.get_file(folder_name=folder.name, file_name=file.name) is None - fs.apply_request(request=["file", file.name, "repair"]) + fs.apply_request(request=["folder", folder.name, "file", file.name, "repair"]) deleted_folder = fs.deleted_folders.get(folder.uuid) deleted_file = deleted_folder.deleted_files.get(file.uuid) From bdf5ff21671a5799c894f04c5db7361f045a56e1 Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Thu, 11 Jul 2024 10:01:33 +0100 Subject: [PATCH 26/42] 2623 Add docs for action masking --- docs/index.rst | 1 + docs/source/action_masking.rst | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 docs/source/action_masking.rst diff --git a/docs/index.rst b/docs/index.rst index 5749ad56..431dea28 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -123,6 +123,7 @@ Head over to the :ref:`getting-started` page to install and setup PrimAITE! source/environment source/customising_scenarios source/varying_config_files + source/action_masking .. toctree:: :caption: Notebooks: diff --git a/docs/source/action_masking.rst b/docs/source/action_masking.rst new file mode 100644 index 00000000..3e5b967b --- /dev/null +++ b/docs/source/action_masking.rst @@ -0,0 +1,80 @@ +.. only:: comment + + © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK + +Action Masking +************** +The PrimAITE simulation is able to provide action masks in the environment output. These action masks let the agents know +about which actions are invalid based on the current environment state. For instance, it's not possible to install +software on a node that is turned off. Therefore, if an agent has a NODE_SOFTWARE_INSTALL in it's action map for that node, +the action mask will show `0` in the corresponding entry. + +Configuration +============= +Action masking is supported for agents that use the `ProxyAgent` class (the class used for connecting to RL algorithms). +In order to use action masking, set the agent_settings.action_masking parameter to True in the config file. + +Masking Logic +============= +The following logic is applied: + +* **DONOTHING** : Always possible +* **NODE_HOST_SERVICE_SCAN** : Node is on. Service is running. +* **NODE_HOST_SERVICE_STOP** : Node is on. Service is running. +* **NODE_HOST_SERVICE_START** : Node is on. Service is stopped. +* **NODE_HOST_SERVICE_PAUSE** : Node is on. Service is running. +* **NODE_HOST_SERVICE_RESUME** : Node is on. Service is paused. +* **NODE_HOST_SERVICE_RESTART** : Node is on. Service is running. +* **NODE_HOST_SERVICE_DISABLE** : Node is on. +* **NODE_HOST_SERVICE_ENABLE** : Node is on. Service is disabled. +* **NODE_HOST_SERVICE_FIX** : Node is on. Service is running. +* **NODE_HOST_APPLICATION_EXECUTE** : Node is on. +* **NODE_HOST_APPLICATION_SCAN** : Node is on. Application is running. +* **NODE_HOST_APPLICATION_CLOSE** : Node is on. Application is running. +* **NODE_HOST_APPLICATION_FIX** : Node is on. Application is running. +* **NODE_HOST_APPLICATION_INSTALL** : Node is on. +* **NODE_HOST_APPLICATION_REMOVE** : Node is on. +* **NODE_HOST_FILE_SCAN** : Node is on. File exists. File not deleted. +* **NODE_HOST_FILE_CREATE** : Node is on. +* **NODE_HOST_FILE_CHECKHASH** : Node is on. File exists. File not deleted. +* **NODE_HOST_FILE_DELETE** : Node is on. File exists. +* **NODE_HOST_FILE_REPAIR** : Node is on. File exists. File not deleted. +* **NODE_HOST_FILE_RESTORE** : Node is on. File exists. File is deleted. +* **NODE_HOST_FILE_CORRUPT** : Node is on. File exists. File not deleted. +* **NODE_HOST_FILE_ACCESS** : Node is on. File exists. File not deleted. +* **NODE_HOST_FOLDER_CREATE** : Node is on. +* **NODE_HOST_FOLDER_SCAN** : Node is on. Folder exists. Folder not deleted. +* **NODE_HOST_FOLDER_CHECKHASH** : Node is on. Folder exists. Folder not deleted. +* **NODE_HOST_FOLDER_REPAIR** : Node is on. Folder exists. Folder not deleted. +* **NODE_HOST_FOLDER_RESTORE** : Node is on. Folder exists. Folder is deleted. +* **NODE_HOST_OS_SCAN** : Node is on. +* **NODE_HOST_NIC_ENABLE** : NIC is disabled. Node is on. +* **NODE_HOST_NIC_DISABLE** : NIC is enabled. Node is on. +* **NODE_HOST_SHUTDOWN** : Node is on. +* **NODE_HOST_STARTUP** : Node is off. +* **NODE_HOST_RESET** : Node is on. +* **NODE_HOST_NMAP_PING_SCAN** : Node is on. +* **NODE_HOST_NMAP_PORT_SCAN** : Node is on. +* **NODE_HOST_NMAP_NETWORK_SERVICE_RECON** : Node is on. +* **NODE_ROUTER_PORT_ENABLE** : Router is on. +* **NODE_ROUTER_PORT_DISABLE** : Router is on. +* **NODE_ROUTER_ACL_ADDRULE** : Router is on. +* **NODE_ROUTER_ACL_REMOVERULE** : Router is on. +* **NODE_FIREWALL_PORT_ENABLE** : Firewall is on. +* **NODE_FIREWALL_PORT_DISABLE** : Firewall is on. +* **NODE_FIREWALL_ACL_ADDRULE** : Firewall is on. +* **NODE_FIREWALL_ACL_REMOVERULE** : Firewall is on. + + +Mechanism +========= +The environment iterates over the RL agent's ``action_map`` and generates the corresponding simulator request string. +It uses the ``RequestManager.check_valid()`` method to invoke the relevant ``RequestPermissionValidator`` without +actually running the request on the simulation. + +Current Limitations +=================== +Currently, action masking only considers whether the action as a whole is possible, it doesn't verify that the exact +parameter combination passed to the action make sense in the current context. For instance, if ACL rule 3 on router_1 is +already populated, the action for adding another rule at position 3 will be available regardless, as long as that router +is turned on. This will never block valid actions. It will just occasionally allow invalid actions. From 579469d1c3fc30af8484e192f7f0c17724e96aee Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Thu, 11 Jul 2024 11:25:38 +0100 Subject: [PATCH 27/42] 2623 add sb3 contrib dependency --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index a0c2e3eb..9e919604 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,7 @@ rl = [ "ray[rllib] >= 2.20.0, < 3", "tensorflow==2.12.0", "stable-baselines3[extra]==2.1.0", + "sb3-contrib==2.1.0", ] dev = [ "build==0.10.0", From b8c62386104ff5dc2169abe5cb29a9d2e87ec9a9 Mon Sep 17 00:00:00 2001 From: "Archer.Bowen" Date: Thu, 11 Jul 2024 11:55:03 +0100 Subject: [PATCH 28/42] #2740 Fixed Nmap Test Failure. --- tests/integration_tests/system/test_nmap.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration_tests/system/test_nmap.py b/tests/integration_tests/system/test_nmap.py index bbfa4f43..2b8691cc 100644 --- a/tests/integration_tests/system/test_nmap.py +++ b/tests/integration_tests/system/test_nmap.py @@ -101,6 +101,7 @@ def test_port_scan_full_subnet_all_ports_and_protocols(example_network): actual_result = client_1_nmap.port_scan( target_ip_address=IPv4Network("192.168.10.0/24"), + target_port=[Port.ARP, Port.HTTP, Port.FTP, Port.DNS, Port.NTP], ) expected_result = { From 1d466d6807f7bab422316c719d5a977e9fb12ac0 Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Thu, 11 Jul 2024 12:19:27 +0100 Subject: [PATCH 29/42] #2740: unit tests + a minor fix to nic test --- .../simulator/file_system/file_system.py | 4 +-- src/primaite/simulator/file_system/folder.py | 27 ++++++++++++-- .../observations/test_nic_observations.py | 4 +-- .../_file_system/test_file_system_actions.py | 36 +++++++++++++++++++ .../_file_system/test_folder_actions.py | 25 +++++++++++++ .../test_network_interface_actions.py | 34 ++++++++++++++++++ .../_network/_hardware/test_node_actions.py | 36 +++++++++++++++++++ .../_applications/test_application_actions.py | 14 ++++++++ .../_system/_services/test_service_actions.py | 20 ++++++++++- 9 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 tests/unit_tests/_primaite/_simulator/_network/_hardware/test_network_interface_actions.py diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index bcb0334e..ba72e1ac 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -653,7 +653,7 @@ class FileSystem(SimComponent): @property def fail_message(self) -> str: """Message that is reported when a request is rejected by this validator.""" - return "Cannot perform request on folder because it does not exist" + return "Cannot perform request on folder because it does not exist." class _FolderNotDeletedValidator(RequestPermissionValidator): """ @@ -693,4 +693,4 @@ class FileSystem(SimComponent): @property def fail_message(self) -> str: """Message that is reported when a request is rejected by this validator.""" - return "Cannot perform request on file that does not exist." + return "Cannot perform request on a file that does not exist." diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index d891641e..c98e4492 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -56,6 +56,7 @@ class Folder(FileSystemItemABC): More information in user guide and docstring for SimComponent._init_request_manager. """ self._file_exists = Folder._FileExistsValidator(folder=self) + self._file_not_deleted = Folder._FileNotDeletedValidator(folder=self) rm = super()._init_request_manager() rm.add_request( @@ -67,7 +68,9 @@ class Folder(FileSystemItemABC): self._file_request_manager = RequestManager() rm.add_request( name="file", - request_type=RequestType(func=self._file_request_manager, validator=self._file_exists), + request_type=RequestType( + func=self._file_request_manager, validator=self._file_exists + self._file_not_deleted + ), ) return rm @@ -489,4 +492,24 @@ class Folder(FileSystemItemABC): @property def fail_message(self) -> str: """Message that is reported when a request is rejected by this validator.""" - return "Cannot perform request on file that does not exist." + return "Cannot perform request on a file that does not exist." + + class _FileNotDeletedValidator(RequestPermissionValidator): + """ + When requests come in, this validator will only let them through if the File is not deleted. + + Actions cannot be performed on a deleted file. + """ + + folder: Folder + """Save a reference to the Folder instance.""" + + def __call__(self, request: RequestFormat, context: Dict) -> bool: + """Returns True if file exists and is not deleted.""" + file = self.folder.get_file(file_name=request[0]) + return file is not None and not file.deleted + + @property + def fail_message(self) -> str: + """Message that is reported when a request is rejected by this validator.""" + return "Cannot perform request on a file that is deleted." diff --git a/tests/integration_tests/game_layer/observations/test_nic_observations.py b/tests/integration_tests/game_layer/observations/test_nic_observations.py index f1a8ea92..88dd2bd5 100644 --- a/tests/integration_tests/game_layer/observations/test_nic_observations.py +++ b/tests/integration_tests/game_layer/observations/test_nic_observations.py @@ -155,7 +155,7 @@ def test_nic_monitored_traffic(simulation): assert traffic_obs["icmp"]["outbound"] == 0 # send a ping - pc.ping(target_ip_address=pc2.network_interface[1].ip_address) + assert pc.ping(target_ip_address=pc2.network_interface[1].ip_address) traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") assert traffic_obs["icmp"]["inbound"] == 1 @@ -178,7 +178,7 @@ def test_nic_monitored_traffic(simulation): traffic_obs = nic_obs.observe(simulation.describe_state()).get("TRAFFIC") assert traffic_obs["icmp"]["inbound"] == 0 assert traffic_obs["icmp"]["outbound"] == 0 - assert traffic_obs["tcp"][53]["inbound"] == 0 + assert traffic_obs["tcp"][53]["inbound"] == 1 assert traffic_obs["tcp"][53]["outbound"] == 1 # getting a webpage sent a dns request out simulation.pre_timestep(2) # apply timestep to whole sim diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py index 209668c4..7d022ea4 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system_actions.py @@ -39,3 +39,39 @@ def test_folder_delete_request(populated_file_system): assert fs.get_file_by_id(folder_uuid=folder.uuid, file_uuid=file.uuid) is None fs.show(full=True) + + +def test_folder_exists_request_validator(populated_file_system): + """Tests that the _FolderExistsValidator works as intended.""" + fs, folder, file = populated_file_system + validator = FileSystem._FolderExistsValidator(file_system=fs) + + assert validator(request=["test_folder"], context={}) # test_folder exists + assert validator(request=["fake_folder"], context={}) is False # fake_folder does not exist + + assert validator.fail_message == "Cannot perform request on folder because it does not exist." + + +def test_file_exists_request_validator(populated_file_system): + """Tests that the _FolderExistsValidator works as intended.""" + fs, folder, file = populated_file_system + validator = FileSystem._FileExistsValidator(file_system=fs) + + assert validator(request=["test_folder", "test_file.txt"], context={}) # test_file.txt exists + assert validator(request=["test_folder", "fake_file.txt"], context={}) is False # fake_file.txt does not exist + + assert validator.fail_message == "Cannot perform request on a file that does not exist." + + +def test_folder_not_deleted_request_validator(populated_file_system): + """Tests that the _FolderExistsValidator works as intended.""" + fs, folder, file = populated_file_system + validator = FileSystem._FolderNotDeletedValidator(file_system=fs) + + assert validator(request=["test_folder"], context={}) # test_folder is not deleted + + fs.delete_folder(folder_name="test_folder") + + assert validator(request=["test_folder"], context={}) is False # test_folder is deleted + + assert validator.fail_message == "Cannot perform request on folder because it is deleted." diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py index 00148311..4a561b97 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py @@ -178,3 +178,28 @@ def test_deleted_folder_and_its_files_cannot_be_interacted_with(populated_file_s deleted_file = deleted_folder.deleted_files.get(file.uuid) assert deleted_file.health_status is not FileSystemItemHealthStatus.GOOD + + +def test_file_exists_request_validator(populated_file_system): + """Tests that the _FolderExistsValidator works as intended.""" + fs, folder, file = populated_file_system + validator = Folder._FileExistsValidator(folder=folder) + + assert validator(request=["test_file.txt"], context={}) # test_file.txt exists + assert validator(request=["fake_file.txt"], context={}) is False # fake_file.txt does not exist + + assert validator.fail_message == "Cannot perform request on a file that does not exist." + + +def test_file_not_deleted_request_validator(populated_file_system): + """Tests that the _FolderExistsValidator works as intended.""" + fs, folder, file = populated_file_system + validator = Folder._FileNotDeletedValidator(folder=folder) + + assert validator(request=["test_file.txt"], context={}) # test_file.txt is not deleted + + fs.delete_file(folder_name="test_folder", file_name="test_file.txt") + + assert validator(request=["fake_file.txt"], context={}) is False # test_file.txt is deleted + + assert validator.fail_message == "Cannot perform request on a file that is deleted." diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_network_interface_actions.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_network_interface_actions.py new file mode 100644 index 00000000..f35cf171 --- /dev/null +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_network_interface_actions.py @@ -0,0 +1,34 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import pytest + +from primaite.simulator.network.hardware.base import NetworkInterface, Node +from primaite.simulator.network.hardware.nodes.host.computer import Computer + + +@pytest.fixture +def node() -> Node: + return Computer(hostname="test", ip_address="192.168.1.2", subnet_mask="255.255.255.0") + + +def test_nic_enabled_validator(node): + """Test the NetworkInterface enabled validator.""" + network_interface = node.network_interface[1] + validator = NetworkInterface._EnabledValidator(network_interface=network_interface) + + assert validator(request=[], context={}) is False # not enabled + + network_interface.enabled = True + + assert validator(request=[], context={}) # enabled + + +def test_nic_disabled_validator(node): + """Test the NetworkInterface enabled validator.""" + network_interface = node.network_interface[1] + validator = NetworkInterface._DisabledValidator(network_interface=network_interface) + + assert validator(request=[], context={}) # not enabled + + network_interface.enabled = True + + assert validator(request=[], context={}) is False # enabled diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py index 57d6cecb..9b37ac80 100644 --- a/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/test_node_actions.py @@ -155,3 +155,39 @@ def test_reset_node(node): assert node.operating_state == NodeOperatingState.BOOTING assert node.operating_state == NodeOperatingState.ON + + +def test_node_is_on_validator(node): + """Test that the node is on validator.""" + node.power_on() + + for i in range(node.start_up_duration + 1): + node.apply_timestep(i) + + validator = Node._NodeIsOnValidator(node=node) + + assert validator(request=[], context={}) + + node.power_off() + for i in range(node.shut_down_duration + 1): + node.apply_timestep(i) + + assert validator(request=[], context={}) is False + + +def test_node_is_off_validator(node): + """Test that the node is on validator.""" + node.power_on() + + for i in range(node.start_up_duration + 1): + node.apply_timestep(i) + + validator = Node._NodeIsOffValidator(node=node) + + assert validator(request=[], context={}) is False + + node.power_off() + for i in range(node.shut_down_duration + 1): + node.apply_timestep(i) + + assert validator(request=[], context={}) diff --git a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py index be6c00e7..0e9c536c 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_applications/test_application_actions.py @@ -1 +1,15 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +from primaite.simulator.system.applications.application import Application, ApplicationOperatingState + + +def test_application_state_validator(application): + """Test the application state validator.""" + validator = Application._StateValidator(application=application, state=ApplicationOperatingState.CLOSED) + assert validator(request=[], context={}) # application is closed + application.run() + assert validator(request=[], context={}) is False # application is running - expecting closed + + validator = Application._StateValidator(application=application, state=ApplicationOperatingState.RUNNING) + assert validator(request=[], context={}) # application is running + application.close() + assert validator(request=[], context={}) is False # application is closed - expecting running diff --git a/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py b/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py index 2d9a6c52..537beb8b 100644 --- a/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_system/_services/test_service_actions.py @@ -1,5 +1,5 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK -from primaite.simulator.system.services.service import ServiceOperatingState +from primaite.simulator.system.services.service import Service, ServiceOperatingState from primaite.simulator.system.software import SoftwareHealthState @@ -92,3 +92,21 @@ def test_service_fix(service): assert service.health_state_actual == SoftwareHealthState.FIXING service.apply_timestep(2) assert service.health_state_actual == SoftwareHealthState.GOOD + + +def test_service_state_validator(service): + """Test the service state validator.""" + validator = Service._StateValidator(service=service, state=ServiceOperatingState.STOPPED) + assert validator(request=[], context={}) # service is stopped + service.start() + assert validator(request=[], context={}) is False # service is running - expecting stopped + + validator = Service._StateValidator(service=service, state=ServiceOperatingState.RUNNING) + assert validator(request=[], context={}) # service is running + service.pause() + assert validator(request=[], context={}) is False # service is paused - expecting running + + validator = Service._StateValidator(service=service, state=ServiceOperatingState.PAUSED) + assert validator(request=[], context={}) # service is paused + service.resume() + assert validator(request=[], context={}) is False # service is running - expecting paused From 9636882ed1de0e392f80671d021a9dfab46b02fa Mon Sep 17 00:00:00 2001 From: Czar Echavez Date: Thu, 11 Jul 2024 13:57:23 +0100 Subject: [PATCH 30/42] #2740: refactor variable --- src/primaite/simulator/file_system/file_system.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index ba72e1ac..2162915f 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -43,7 +43,7 @@ class FileSystem(SimComponent): More information in user guide and docstring for SimComponent._init_request_manager. """ self._folder_exists = FileSystem._FolderExistsValidator(file_system=self) - self._folder_deleted = FileSystem._FolderNotDeletedValidator(file_system=self) + self._folder_not_deleted = FileSystem._FolderNotDeletedValidator(file_system=self) self._file_exists = FileSystem._FileExistsValidator(file_system=self) rm = super()._init_request_manager() @@ -152,7 +152,7 @@ class FileSystem(SimComponent): self._folder_request_manager = RequestManager() rm.add_request( "folder", - RequestType(func=self._folder_request_manager, validator=self._folder_exists + self._folder_deleted), + RequestType(func=self._folder_request_manager, validator=self._folder_exists + self._folder_not_deleted), ) self._file_request_manager = RequestManager() From cf563149ec54e10b00a66a3562474bb7b058744f Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Thu, 11 Jul 2024 15:07:58 +0100 Subject: [PATCH 31/42] #2745 carried over changes from internal that backtracked on the complex channel width stuff for now and focussed on getting a stable data rate baked in for each frequency --- CHANGELOG.md | 16 +- .../network/airspace.rst | 68 +-- .../network/nodes/wireless_router.rst | 3 - src/primaite/game/game.py | 5 - src/primaite/simulator/network/airspace.py | 495 ++---------------- .../hardware/nodes/network/wireless_router.py | 11 +- ...s_wan_wifi_5_80_channel_width_blocked.yaml | 2 - ...ess_wan_wifi_5_80_channel_width_urban.yaml | 2 - .../test_airspace_capacity_configuration.py | 106 ---- ...ndwidth_load_checks_before_transmission.py | 24 - 10 files changed, 61 insertions(+), 671 deletions(-) delete mode 100644 tests/integration_tests/network/test_airspace_capacity_configuration.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d9aed82..515be435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,17 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- **AirSpaceEnvironmentType Enum Class**: Introduced in `airspace.py` to define different environmental settings affecting wireless network behavior. -- **ChannelWidth Enum Class**: Added in `airspace.py` to specify channel width options for wireless network interfaces. -- **Channel Width Attribute**: Incorporated into the `WirelessNetworkInterface` class to allow dynamic setting based on `AirSpaceFrequency` and `AirSpaceEnvironmentType`. -- **SNR and Capacity Calculation Functions**: Functions `estimate_snr` and `calculate_total_channel_capacity` added to `airspace.py` for computing signal-to-noise ratio and capacity based on frequency and channel width. -- **Dynamic Speed Setting**: WirelessInterface speed attribute now dynamically adjusts based on the operational environment, frequency, and channel width. -- **airspace_key Attribute**: Added to `WirelessNetworkInterface` as a tuple of frequency and channel width, serving as a key for bandwidth/channel management. -- **airspace_environment_type Attribute**: Determines the environmental type for the airspace, influencing data rate calculations and capacity sharing. -- **show_bandwidth_load Function**: Displays current bandwidth load for each frequency and channel width in the airspace. -- **Configuration Schema Update**: The `simulation.network` config file now includes settings for the `airspace_environment_type`. -- **Bandwidth Tracking**: Tracks data transmission across each frequency/channel width pairing. -- **Configuration Support for Wireless Routers**: `channel_width` can now be configured in the config file under `wireless_access_point`. +- **show_bandwidth_load Function**: Displays current bandwidth load for each frequency in the airspace. +- **Bandwidth Tracking**: Tracks data transmission across each frequency. - **New Tests**: Added to validate the respect of bandwidth capacities and the correct parsing of airspace configurations from YAML files. - **New Logging**: Added a new agent behaviour log which are more human friendly than agent history. These Logs are found in session log directory and can be enabled in the I/O settings in a yaml configuration file. @@ -27,9 +18,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **NetworkInterface Speed Type**: The `speed` attribute of `NetworkInterface` has been changed from `int` to `float`. - **Transmission Feasibility Check**: Updated `_can_transmit` function in `Link` to account for current load and total bandwidth capacity, ensuring transmissions do not exceed limits. - **Frame Size Details**: Frame `size` attribute now includes both core size and payload size in bytes. -- **WirelessRouter Configuration Function**: `configure_wireless_access_point` function now accepts `channel_width` as a parameter. -- **Interface Grouping**: `WirelessNetworkInterfaces` are now grouped by both `AirSpaceFrequency` and `ChannelWidth`. -- **Interface Frequency/Channel Width Adjustment**: Changing an interface's settings now involves removal from the airspace, recalculation of its data rate, and re-addition under new settings. - **Transmission Blocking**: Enhanced `AirSpace` logic to block transmissions that would exceed the available capacity. ### Fixed diff --git a/docs/source/simulation_components/network/airspace.rst b/docs/source/simulation_components/network/airspace.rst index dcd762d4..06a884a7 100644 --- a/docs/source/simulation_components/network/airspace.rst +++ b/docs/source/simulation_components/network/airspace.rst @@ -22,79 +22,21 @@ The AirSpace is a virtual representation of a physical wireless environment, man ^^^^^^^^^^^^^^^^^^ - **Wireless Network Interfaces**: Representations of network interfaces connected physical devices like routers, computers, or IoT devices that can send and receive data wirelessly. -- **Environmental Settings**: Different types of environments (e.g., urban, rural) that affect signal propagation and interference. -- **Channel Management**: Handles channels and their widths (e.g., 20 MHz, 40 MHz) to determine data transmission over different frequencies. -- **Bandwidth Management**: Tracks data transmission over channels to prevent overloading and simulate real-world network congestion. +- **Bandwidth Management**: Tracks data transmission over frequencies to prevent overloading and simulate real-world network congestion. -3. AirSpace Environment Types ------------------------------ -The AirspaceEnvironmentType is a critical component that simulates different physical environments: - -- Urban, Suburban, Rural, etc. -- Each type simulates different levels of electromagnetic interference and signal propagation characteristics. -- Changing the AirspaceEnvironmentType impacts data rates by affecting the signal-to-noise ratio (SNR). - -4. Simulation of Environment Changes ------------------------------------- - -When an AirspaceEnvironmentType is set or changed, the AirSpace: - -1. Recalculates the maximum data transmission capacities for all managed frequencies and channel widths. -2. Updates all wireless interfaces to reflect new capacities. - -5. Managing Wireless Network Interfaces +3. Managing Wireless Network Interfaces --------------------------------------- - Interfaces can be dynamically added or removed. - Configurations can be changed in real-time. -- The AirSpace handles data transmissions, ensuring data sent by an interface is received by all other interfaces on the same frequency and channel. +- The AirSpace handles data transmissions, ensuring data sent by an interface is received by all other interfaces on the same frequency. -6. Signal-to-Noise Ratio (SNR) Calculation ------------------------------------------- -SNR is crucial in determining the quality of a wireless communication channel: - -.. math:: - - SNR = \frac{\text{Signal Power}}{\text{Noise Power}} - -- Impacted by environment type, frequency, and channel width -- Higher SNR indicates a clearer signal, leading to higher data transmission rates - -7. Total Channel Capacity Calculation -------------------------------------- - -Channel capacity is calculated using the Shannon-Hartley theorem: - -.. math:: - - C = B \cdot \log_2(1 + SNR) - -Where: - -- C: channel capacity in bits per second (bps) -- B: bandwidth of the channel in hertz (Hz) -- SNR: signal-to-noise ratio - -Implementation in AirSpace: - -1. Convert channel width from MHz to Hz. -2. Recalculate SNR based on new environment or interface settings. -3. Apply Shannon-Hartley theorem to determine new maximum channel capacity in Mbps. - -8. Shared Maximum Capacity Across Devices ------------------------------------------ - -While individual devices have theoretical maximum data rates, the actual achievable rate is often less due to: - -- Shared wireless medium among all devices on the same frequency and channel width -- Interference and congestion from multiple devices transmitting simultaneously - -9. AirSpace Inspection +4. AirSpace Inspection ---------------------- The AirSpace class provides methods for visualizing network behavior: - ``show_wireless_interfaces()``: Displays current state of all interfaces -- ``show_bandwidth_load()``: Shows channel loads and bandwidth utilization +- ``show_bandwidth_load()``: Shows bandwidth utilisation diff --git a/docs/source/simulation_components/network/nodes/wireless_router.rst b/docs/source/simulation_components/network/nodes/wireless_router.rst index eb7f95e3..c78c8419 100644 --- a/docs/source/simulation_components/network/nodes/wireless_router.rst +++ b/docs/source/simulation_components/network/nodes/wireless_router.rst @@ -50,7 +50,6 @@ additional steps to configure wireless settings: port=1, ip_address="192.168.2.1", subnet_mask="255.255.255.0", frequency=AirSpaceFrequency.WIFI_2_4, - channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) @@ -132,14 +131,12 @@ ICMP traffic, ensuring basic network connectivity and ping functionality. ip_address="192.168.1.1", subnet_mask="255.255.255.0", frequency=AirSpaceFrequency.WIFI_2_4, - channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) router_2.configure_wireless_access_point( port=1, ip_address="192.168.1.2", subnet_mask="255.255.255.0", frequency=AirSpaceFrequency.WIFI_2_4, - channel_width=ChannelWidth.ChannelWidth.WIDTH_40_MHZ ) # Configure routes for inter-router communication diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 1e6aeae0..b976e55f 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -16,7 +16,6 @@ from primaite.game.agent.scripted_agents.random_agent import PeriodicAgent from primaite.game.agent.scripted_agents.tap001 import TAP001 from primaite.game.science import graph_has_cycle, topological_sort from primaite.simulator import SIM_OUTPUT -from primaite.simulator.network.airspace import AirspaceEnvironmentType from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC @@ -238,10 +237,6 @@ class PrimaiteGame: simulation_config = cfg.get("simulation", {}) network_config = simulation_config.get("network", {}) airspace_cfg = network_config.get("airspace", {}) - airspace_environment_type_str = airspace_cfg.get("airspace_environment_type", "urban") - - airspace_environment_type: AirspaceEnvironmentType = AirspaceEnvironmentType(airspace_environment_type_str) - net.airspace.airspace_environment_type = airspace_environment_type nodes_cfg = network_config.get("nodes", []) links_cfg = network_config.get("links", []) diff --git a/src/primaite/simulator/network/airspace.py b/src/primaite/simulator/network/airspace.py index 2ac11a20..5019385a 100644 --- a/src/primaite/simulator/network/airspace.py +++ b/src/primaite/simulator/network/airspace.py @@ -3,11 +3,10 @@ from __future__ import annotations from abc import ABC, abstractmethod from enum import Enum -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Optional -import numpy as np from prettytable import MARKDOWN, PrettyTable -from pydantic import BaseModel, computed_field, Field, model_validator +from pydantic import BaseModel, Field from primaite import getLogger from primaite.simulator.network.hardware.base import Layer3Interface, NetworkInterface, WiredNetworkInterface @@ -58,228 +57,17 @@ class AirSpaceFrequency(Enum): return f"WiFi {hertz_str}" return "Unknown Frequency" - -class ChannelWidth(Enum): - """ - Enumeration representing the available channel widths in MHz for wireless communications. - - This enum facilitates standardising and validating channel width configurations. - - Attributes: - WIDTH_20_MHZ (int): Represents a channel width of 20 MHz, commonly used for basic - Wi-Fi connectivity with standard range and interference resistance. - WIDTH_40_MHZ (int): Represents a channel width of 40 MHz, offering higher data - throughput at the expense of potentially increased interference. - WIDTH_80_MHZ (int): Represents a channel width of 80 MHz, typically used in modern - Wi-Fi setups for high data rate applications but with higher susceptibility to interference. - WIDTH_160_MHZ (int): Represents a channel width of 160 MHz, used for ultra-high-speed - network applications, providing maximum data throughput with significant - requirements on the spectral environment to minimize interference. - """ - - WIDTH_20_MHZ = 20 - """ - Represents a channel width of 20 MHz, commonly used for basic Wi-Fi connectivity with standard range and - interference resistance - """ - - WIDTH_40_MHZ = 40 - """ - Represents a channel width of 40 MHz, offering higher data throughput at the expense of potentially increased - interference. - """ - - WIDTH_80_MHZ = 80 - """ - Represents a channel width of 80 MHz, typically used in modern Wi-Fi setups for high data rate applications but - with higher susceptibility to interference. - """ - - WIDTH_160_MHZ = 160 - """ - Represents a channel width of 160 MHz, used for ultra-high-speed network applications, providing maximum data - throughput with significant requirements on the spectral environment to minimize interference. - """ - - def __str__(self) -> str: - """ - Returns a string representation of the channel width. - - :return: String in the format of " MHz" indicating the channel width. - """ - return f"{self.value} MHz" - - -AirSpaceKeyType = Tuple[AirSpaceFrequency, ChannelWidth] - - -class AirspaceEnvironmentType(Enum): - """Enum representing different types of airspace environments which affect wireless communication signals.""" - - RURAL = "rural" - """ - A rural environment offers clear channel conditions due to low population density and minimal electronic device - presence. - """ - - OUTDOOR = "outdoor" - """ - Outdoor environments like parks or fields have minimal electronic interference. - """ - - SUBURBAN = "suburban" - """ - Suburban environments strike a balance with fewer electronic interferences than urban but more than rural. - """ - - OFFICE = "office" - """ - Office environments have moderate interference from numerous electronic devices and overlapping networks. - """ - - URBAN = "urban" - """ - Urban environments are characterized by tall buildings and a high density of electronic devices, leading to - significant interference. - """ - - INDUSTRIAL = "industrial" - """ - Industrial areas face high interference from heavy machinery and numerous electronic devices. - """ - - TRANSPORT = "transport" - """ - Environments such as subways and buses where metal structures and high mobility create complex interference - patterns. - """ - - DENSE_URBAN = "dense_urban" - """ - Dense urban areas like city centers have the highest level of signal interference due to the very high density of - buildings and devices. - """ - - JAMMING_ZONE = "jamming_zone" - """ - A jamming zone environment where signals are actively interfered with, typically through the use of signal jammers - or scrambling devices. This represents the environment with the highest level of interference. - """ - - BLOCKED = "blocked" - """ - A jamming zone environment with total levels of interference. Airspace is completely blocked. - """ + @property + def maximum_data_rate_bps(self) -> float: + if self == AirSpaceFrequency.WIFI_2_4: + return 100_000_000.0 # 100 Megabits per second + if self == AirSpaceFrequency.WIFI_5: + return 500_000_000.0 # 500 Megabits per second + return 0.0 @property - def snr_impact(self) -> int: - """ - Returns the SNR impact associated with the environment. - - :return: SNR impact in dB. - """ - impacts = { - AirspaceEnvironmentType.RURAL: 0, - AirspaceEnvironmentType.OUTDOOR: 1, - AirspaceEnvironmentType.SUBURBAN: -5, - AirspaceEnvironmentType.OFFICE: -7, - AirspaceEnvironmentType.URBAN: -10, - AirspaceEnvironmentType.INDUSTRIAL: -15, - AirspaceEnvironmentType.TRANSPORT: -12, - AirspaceEnvironmentType.DENSE_URBAN: -20, - AirspaceEnvironmentType.JAMMING_ZONE: -40, - AirspaceEnvironmentType.BLOCKED: -100, - } - return impacts[self] - - def __str__(self) -> str: - return f"{self.value.title()} Environment (SNR Impact: {self.snr_impact})" - - -def estimate_snr( - frequency: AirSpaceFrequency, environment_type: AirspaceEnvironmentType, channel_width: ChannelWidth -) -> float: - """ - Estimate the Signal-to-Noise Ratio (SNR) based on the communication frequency, environment, and channel width. - - This function considers both the base SNR value dependent on the frequency and the impact of environmental - factors and channel width on the SNR. - - The SNR is adjusted by reducing it for wider channels, reflecting the increased noise floor from a broader - frequency range. - - :param frequency: The operating frequency as defined by AirSpaceFrequency enum, influencing the base SNR. Higher - frequencies like 5 GHz generally start with a higher base SNR due to less noise. - :param environment_type: The type of environment from AirspaceEnvironmentType enum, which adjusts the SNR based on - expected environmental noise and interference levels. - :param channel_width: The channel width from ChannelWidth enum, where wider channels (80 MHz and 160 MHz) decrease - the SNR slightly due to an increased noise floor. - :return: Estimated SNR in dB, calculated as the base SNR modified by environmental and channel width impacts. - """ - base_snr = 40 if frequency == AirSpaceFrequency.WIFI_5 else 30 - snr_impact = environment_type.snr_impact - - # Adjust SNR impact based on channel width - if channel_width == ChannelWidth.WIDTH_80_MHZ or channel_width == ChannelWidth.WIDTH_160_MHZ: - snr_impact -= 3 # Assume wider channels have slightly lower SNR due to increased noise floor - - return base_snr + snr_impact - - -def calculate_total_channel_capacity( - channel_width: ChannelWidth, frequency: AirSpaceFrequency, environment_type: AirspaceEnvironmentType -) -> float: - """ - Calculate the total theoretical data rate for the channel using the Shannon-Hartley theorem. - - This function determines the channel's capacity by considering the bandwidth (derived from channel width), - and the signal-to-noise ratio (SNR) adjusted by frequency and environmental conditions. - - The Shannon-Hartley theorem states that channel capacity C (in bits per second) can be calculated as: - ``C = B * log2(1 + SNR)`` where B is the bandwidth in Hertz and SNR is the signal-to-noise ratio. - - :param channel_width: The width of the channel as defined by ChannelWidth enum, converted to Hz for calculation. - :param frequency: The operating frequency as defined by AirSpaceFrequency enum, influencing the base SNR and part - of the SNR estimation. - :param environment_type: The type of environment as defined by AirspaceEnvironmentType enum, used in SNR estimation. - :return: Theoretical total data rate in Mbps for the entire channel. - """ - bandwidth_hz = channel_width.value * 1_000_000 # Convert MHz to Hz - snr_db = estimate_snr(frequency, environment_type, channel_width) - snr_linear = 10 ** (snr_db / 10) - - total_capacity_bps = bandwidth_hz * np.log2(1 + snr_linear) - total_capacity_mbps = total_capacity_bps / 1_000_000 - - return total_capacity_mbps - - -def calculate_individual_device_rate( - channel_width: ChannelWidth, - frequency: AirSpaceFrequency, - environment_type: AirspaceEnvironmentType, - device_count: int, -) -> float: - """ - Calculate the theoretical data rate available to each individual device on the channel. - - This function first calculates the total channel capacity and then divides this capacity by the number - of active devices to estimate each device's share of the bandwidth. This reflects the practical limitation - that multiple devices must share the same channel resources. - - :param channel_width: The channel width as defined by ChannelWidth enum, used in total capacity calculation. - :param frequency: The operating frequency as defined by AirSpaceFrequency enum, used in total capacity calculation. - :param environment_type: The environment type as defined by AirspaceEnvironmentType enum, impacting SNR and - capacity. - :param device_count: The number of devices sharing the channel. If zero, returns zero to avoid division by zero. - :return: Theoretical data rate in Mbps available per device, based on shared channel capacity. - """ - total_capacity_mbps = calculate_total_channel_capacity(channel_width, frequency, environment_type) - if device_count == 0: - return 0 # Avoid division by zero - individual_device_rate_mbps = total_capacity_mbps / device_count - - return individual_device_rate_mbps + def maximum_data_rate_mbps(self) -> float: + return self.maximum_data_rate_bps / 1_000_000.0 class AirSpace(BaseModel): @@ -287,105 +75,62 @@ class AirSpace(BaseModel): Represents a wireless airspace, managing wireless network interfaces and handling wireless transmission. This class provides functionalities to manage a collection of wireless network interfaces, each associated with - specific frequencies and channel widths. It includes methods to calculate and manage bandwidth loads, add and - remove wireless interfaces, and handle data transmission across these interfaces. + specific frequencies. It includes methods to add and remove wireless interfaces, and handle data transmission + across these interfaces. """ - airspace_environment_type_: AirspaceEnvironmentType = AirspaceEnvironmentType.URBAN wireless_interfaces: Dict[str, WirelessNetworkInterface] = Field(default_factory=lambda: {}) - wireless_interfaces_by_frequency_channel_width: Dict[AirSpaceKeyType, List[WirelessNetworkInterface]] = Field( + wireless_interfaces_by_frequency: Dict[AirSpaceFrequency, List[WirelessNetworkInterface]] = Field( default_factory=lambda: {} ) - bandwidth_load: Dict[AirSpaceKeyType, float] = Field(default_factory=lambda: {}) - frequency_channel_width_max_capacity_mbps: Dict[AirSpaceKeyType, float] = Field(default_factory=lambda: {}) + bandwidth_load: Dict[AirSpaceFrequency, float] = Field(default_factory=lambda: {}) + frequency_max_capacity_mbps: Dict[AirSpaceFrequency, float] = Field(default_factory=lambda: {}) def model_post_init(self, __context: Any) -> None: """ Initialize the airspace metadata after instantiation. - This method is called to set up initial configurations like the maximum capacity of each channel width and - frequency based on the current environment setting. + This method is called to set up initial configurations like the maximum capacity of each frequency. :param __context: Contextual data or settings, typically used for further initializations beyond the basic constructor. """ - self._set_frequency_channel_width_max_capacity_mbps() + self.set_frequency_max_capacity_mbps() - def _set_frequency_channel_width_max_capacity_mbps(self): + def set_frequency_max_capacity_mbps(self, capacity_config: Optional[Dict[AirSpaceFrequency, float]] = None): """ - Private method to compute and set the maximum channel capacity in Mbps for each frequency and channel width. - - Based on the airspace environment type, this method calculates the maximum possible data transmission - capacity for each combination of frequency and channel width available and stores these values. - These capacities are critical for managing and limiting bandwidth load during operations. + Set the maximum channel capacity in Mbps for each frequency. """ - print( - f"Rebuilding the frequency channel width maximum capacity dictionary based on " - f"airspace environment type {self.airspace_environment_type_}" - ) + if capacity_config is None: + capacity_config = {} for frequency in AirSpaceFrequency: - for channel_width in ChannelWidth: - max_capacity = calculate_total_channel_capacity( - frequency=frequency, channel_width=channel_width, environment_type=self.airspace_environment_type - ) - self.frequency_channel_width_max_capacity_mbps[frequency, channel_width] = max_capacity - - @computed_field - @property - def airspace_environment_type(self) -> AirspaceEnvironmentType: - """ - Gets the current environment type of the airspace. - - :return: The AirspaceEnvironmentType representing the current environment type. - """ - return self.airspace_environment_type_ - - @airspace_environment_type.setter - def airspace_environment_type(self, value: AirspaceEnvironmentType) -> None: - """ - Sets a new environment type for the airspace and updates related configurations. - - Changing the environment type triggers a re-calculation of the maximum channel capacities and - adjustments to the current setup of wireless interfaces to ensure they are aligned with the - new environment settings. - - :param value: The new environment type as an AirspaceEnvironmentType. - """ - if value != self.airspace_environment_type_: - print(f"Setting airspace_environment_type to {value}") - self.airspace_environment_type_ = value - self._set_frequency_channel_width_max_capacity_mbps() - wireless_interface_keys = list(self.wireless_interfaces.keys()) - for wireless_interface_key in wireless_interface_keys: - wireless_interface = self.wireless_interfaces[wireless_interface_key] - self.remove_wireless_interface(wireless_interface) - self.add_wireless_interface(wireless_interface) + max_capacity = capacity_config.get(frequency, frequency.maximum_data_rate_mbps) + self.frequency_max_capacity_mbps[frequency] = max_capacity def show_bandwidth_load(self, markdown: bool = False): """ - Prints a table of the current bandwidth load for each frequency and channel width combination on the airspace. + Prints a table of the current bandwidth load for each frequency on the airspace. - This method prints a tabulated view showing the utilisation of available bandwidth capacities for all configured - frequency and channel width pairings. The table includes the current capacity usage as a percentage of the - maximum capacity, alongside the absolute maximum capacity values in Mbps. + This method prints a tabulated view showing the utilisation of available bandwidth capacities for all + frequencies. The table includes the current capacity usage as a percentage of the maximum capacity, alongside + the absolute maximum capacity values in Mbps. :param markdown: Flag indicating if output should be in markdown format. """ - headers = ["Frequency", "Channel Width", "Current Capacity (%)", "Maximum Capacity (Mbit)"] + if not self.frequency_max_capacity_mbps: + self.set_frequency_max_capacity_mbps() + headers = ["Frequency", "Current Capacity (%)", "Maximum Capacity (Mbit)"] table = PrettyTable(headers) if markdown: table.set_style(MARKDOWN) table.align = "l" table.title = "Airspace Frequency Channel Loads" - for key, load in self.bandwidth_load.items(): - frequency, channel_width = key - maximum_capacity = self.frequency_channel_width_max_capacity_mbps[key] + for frequency, load in self.bandwidth_load.items(): + maximum_capacity = self.frequency_max_capacity_mbps[frequency] load_percent = load / maximum_capacity if load_percent > 1.0: load_percent = 1.0 - table.add_row( - [format_hertz(frequency.value), str(channel_width), f"{load_percent:.0%}", f"{maximum_capacity:.3f}"] - ) + table.add_row([format_hertz(frequency.value), f"{load_percent:.0%}", f"{maximum_capacity:.3f}"]) print(table) def show_wireless_interfaces(self, markdown: bool = False): @@ -400,7 +145,6 @@ class AirSpace(BaseModel): "IP Address", "Subnet Mask", "Frequency", - "Channel Width", "Speed (Mbps)", "Status", ] @@ -408,7 +152,7 @@ class AirSpace(BaseModel): if markdown: table.set_style(MARKDOWN) table.align = "l" - table.title = f"Devices on Air Space - {self.airspace_environment_type}" + table.title = f"Devices on Air Space" for interface in self.wireless_interfaces.values(): status = "Enabled" if interface.enabled else "Disabled" @@ -419,7 +163,6 @@ class AirSpace(BaseModel): interface.ip_address if hasattr(interface, "ip_address") else None, interface.subnet_mask if hasattr(interface, "subnet_mask") else None, format_hertz(interface.frequency.value), - str(interface.channel_width), f"{interface.speed:.3f}", status, ] @@ -431,8 +174,8 @@ class AirSpace(BaseModel): Prints a summary of the current state of the airspace, including both wireless interfaces and bandwidth loads. This method is a convenient wrapper that calls two separate methods to display detailed tables: one for - wireless interfaces and another for bandwidth load across all frequencies and channel widths managed within the - airspace. It provides a holistic view of the operational status and performance metrics of the airspace. + wireless interfaces and another for bandwidth load across all frequencies managed within the airspace. It + provides a holistic view of the operational status and performance metrics of the airspace. :param markdown: Flag indicating if output should be in markdown format. """ @@ -447,15 +190,9 @@ class AirSpace(BaseModel): """ if wireless_interface.mac_address not in self.wireless_interfaces: self.wireless_interfaces[wireless_interface.mac_address] = wireless_interface - if wireless_interface.airspace_key not in self.wireless_interfaces_by_frequency_channel_width: - self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key] = [] - self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key].append( - wireless_interface - ) - speed = calculate_total_channel_capacity( - wireless_interface.channel_width, wireless_interface.frequency, self.airspace_environment_type - ) - wireless_interface.set_speed(speed) + if wireless_interface.frequency not in self.wireless_interfaces_by_frequency: + self.wireless_interfaces_by_frequency[wireless_interface.frequency] = [] + self.wireless_interfaces_by_frequency[wireless_interface.frequency].append(wireless_interface) def remove_wireless_interface(self, wireless_interface: WirelessNetworkInterface): """ @@ -465,9 +202,7 @@ class AirSpace(BaseModel): """ if wireless_interface.mac_address in self.wireless_interfaces: self.wireless_interfaces.pop(wireless_interface.mac_address) - self.wireless_interfaces_by_frequency_channel_width[wireless_interface.airspace_key].remove( - wireless_interface - ) + self.wireless_interfaces_by_frequency[wireless_interface.frequency].remove(wireless_interface) def clear(self): """ @@ -477,7 +212,7 @@ class AirSpace(BaseModel): occur until new interfaces are added again. """ self.wireless_interfaces.clear() - self.wireless_interfaces_by_frequency_channel_width.clear() + self.wireless_interfaces_by_frequency.clear() def reset_bandwidth_load(self): """ @@ -500,11 +235,13 @@ class AirSpace(BaseModel): relevant frequency and its current bandwidth load. :return: True if the frame can be transmitted within the bandwidth limit, False if it would exceed the limit. """ - if sender_network_interface.airspace_key not in self.bandwidth_load: - self.bandwidth_load[sender_network_interface.airspace_key] = 0.0 + if not self.frequency_max_capacity_mbps: + self.set_frequency_max_capacity_mbps() + if sender_network_interface.frequency not in self.bandwidth_load: + self.bandwidth_load[sender_network_interface.frequency] = 0.0 return ( - self.bandwidth_load[sender_network_interface.airspace_key] + frame.size_Mbits - <= self.frequency_channel_width_max_capacity_mbps[sender_network_interface.airspace_key] + self.bandwidth_load[sender_network_interface.frequency] + frame.size_Mbits + <= self.frequency_max_capacity_mbps[sender_network_interface.frequency] ) def transmit(self, frame: Frame, sender_network_interface: WirelessNetworkInterface): @@ -517,9 +254,9 @@ class AirSpace(BaseModel): :param sender_network_interface: The wireless network interface sending the frame. This interface will be excluded from the list of receivers to prevent it from receiving its own transmission. """ - self.bandwidth_load[sender_network_interface.airspace_key] += frame.size_Mbits - for wireless_interface in self.wireless_interfaces_by_frequency_channel_width.get( - sender_network_interface.airspace_key, [] + self.bandwidth_load[sender_network_interface.frequency] += frame.size_Mbits + for wireless_interface in self.wireless_interfaces_by_frequency.get( + sender_network_interface.frequency, [] ): if wireless_interface != sender_network_interface and wireless_interface.enabled: wireless_interface.receive_frame(frame) @@ -546,135 +283,7 @@ class WirelessNetworkInterface(NetworkInterface, ABC): """ airspace: AirSpace - frequency_: AirSpaceFrequency = AirSpaceFrequency.WIFI_2_4 - channel_width_: ChannelWidth = ChannelWidth.WIDTH_40_MHZ - - @model_validator(mode="after") # noqa - def validate_channel_width_for_2_4_ghz(self) -> "WirelessNetworkInterface": - """ - Validate the wireless interface's channel width settings after model changes. - - This method serves as a model validator to ensure that the channel width settings for the 2.4 GHz frequency - comply with accepted standards (either 20 MHz or 40 MHz). It's triggered after model instantiation. - - Ensures that the channel width is appropriate for the current frequency setting, particularly checking - and adjusting the settings for the 2.4 GHz frequency band to not exceed 40 MHz. This is crucial for - avoiding interference and ensuring optimal performance in densely populated wireless environments. - """ - self._check_wifi_24_channel_width() - return self - - def model_post_init(self, __context: Any) -> None: - """Initialise the model after its creation, setting the speed based on the calculated channel capacity.""" - speed = calculate_total_channel_capacity( - channel_width=self.channel_width, - frequency=self.frequency, - environment_type=self.airspace.airspace_environment_type, - ) - self.set_speed(speed) - - def _check_wifi_24_channel_width(self) -> None: - """ - Ensures that the channel width for 2.4 GHz frequency does not exceed 40 MHz. - - This method checks the current frequency and channel width settings and adjusts the channel width - to 40 MHz if the frequency is set to 2.4 GHz and the channel width exceeds 40 MHz. This is done to - comply with typical Wi-Fi standards for 2.4 GHz frequencies, which commonly support up to 40 MHz. - - Logs a SysLog warning if the channel width had to be adjusted, logging this change either to the connected - node's system log or the global logger, depending on whether the interface is connected to a node. - """ - if self.frequency_ == AirSpaceFrequency.WIFI_2_4 and self.channel_width_.value > 40: - self.channel_width_ = ChannelWidth.WIDTH_40_MHZ - msg = ( - f"Channel width must be either 20 Mhz or 40 Mhz when using {AirSpaceFrequency.WIFI_2_4}. " - f"Overriding value to use {ChannelWidth.WIDTH_40_MHZ}." - ) - if self._connected_node: - self._connected_node.sys_log.warning(f"Wireless Interface {self.port_num}: {msg}") - else: - _LOGGER.warning(msg) - - @computed_field - @property - def frequency(self) -> AirSpaceFrequency: - """ - Get the current operating frequency of the wireless interface. - - :return: The current frequency as an AirSpaceFrequency enum value. - """ - return self.frequency_ - - @frequency.setter - def frequency(self, value: AirSpaceFrequency) -> None: - """ - Set the operating frequency of the wireless interface and update the network configuration. - - This setter updates the frequency of the wireless interface if the new value differs from the current setting. - It handles the update by first removing the interface from the current airspace management to avoid conflicts, - setting the new frequency, ensuring the channel width remains compliant, and then re-adding the interface - to the airspace with the new settings. - - :param value: The new frequency to set, as an AirSpaceFrequency enum value. - """ - if value != self.frequency_: - self.airspace.remove_wireless_interface(self) - self.frequency_ = value - self._check_wifi_24_channel_width() - self.airspace.add_wireless_interface(self) - - @computed_field - @property - def channel_width(self) -> ChannelWidth: - """ - Get the current channel width setting of the wireless interface. - - :return: The current channel width as a ChannelWidth enum value. - """ - return self.channel_width_ - - @channel_width.setter - def channel_width(self, value: ChannelWidth) -> None: - """ - Set the channel width of the wireless interface and manage configuration compliance. - - Updates the channel width of the wireless interface. If the new channel width is different from the existing - one, it first removes the interface from the airspace to prevent configuration conflicts, sets the new channel - width, checks and adjusts it if necessary (especially for 2.4 GHz frequency to comply with typical standards), - and then re-registers the interface in the airspace with updated settings. - - :param value: The new channel width to set, as a ChannelWidth enum value. - """ - if value != self.channel_width_: - self.airspace.remove_wireless_interface(self) - self.channel_width_ = value - self._check_wifi_24_channel_width() - self.airspace.add_wireless_interface(self) - - @property - def airspace_key(self) -> tuple: - """ - The airspace bandwidth/channel identifier for the wireless interface based on its frequency and channel width. - - :return: A tuple containing the frequency and channel width, serving as a bandwidth/channel key. - """ - return self.frequency_, self.channel_width_ - - def set_speed(self, speed: float): - """ - Sets the network interface speed to the specified value and logs this action. - - This method updates the speed attribute of the network interface to the given value, reflecting - the theoretical maximum data rate that the interface can support based on the current settings. - It logs the new speed to the system log of the connected node if available. - - :param speed: The speed in Mbps to be set for the network interface. - """ - self.speed = speed - if self._connected_node: - self._connected_node.sys_log.info( - f"Wireless Interface {self.port_num}: Setting theoretical maximum data rate to {speed:.3f} Mbps." - ) + frequency: AirSpaceFrequency = AirSpaceFrequency.WIFI_2_4 def enable(self): """Attempt to enable the network interface.""" diff --git a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py index dda9e4f8..5ded993e 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py @@ -4,7 +4,7 @@ from typing import Any, Dict, Optional, Union from pydantic import validate_call -from primaite.simulator.network.airspace import AirSpace, AirSpaceFrequency, ChannelWidth, IPWirelessNetworkInterface +from primaite.simulator.network.airspace import AirSpace, AirSpaceFrequency, IPWirelessNetworkInterface from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router, RouterInterface from primaite.simulator.network.transmission.data_link_layer import Frame @@ -154,7 +154,6 @@ class WirelessRouter(Router): ip_address: IPV4Address, subnet_mask: IPV4Address, frequency: Optional[AirSpaceFrequency] = AirSpaceFrequency.WIFI_2_4, - channel_width: Optional[ChannelWidth] = ChannelWidth.WIDTH_40_MHZ, ): """ Configures a wireless access point (WAP). @@ -173,8 +172,6 @@ class WirelessRouter(Router): """ if not frequency: frequency = AirSpaceFrequency.WIFI_2_4 - if not channel_width: - channel_width = ChannelWidth.WIDTH_40_MHZ self.sys_log.info("Configuring wireless access point") self.wireless_access_point.disable() # Temporarily disable the WAP for reconfiguration @@ -185,7 +182,6 @@ class WirelessRouter(Router): network_interface.subnet_mask = subnet_mask self.wireless_access_point.frequency = frequency # Set operating frequency - self.wireless_access_point.channel_width = channel_width self.wireless_access_point.enable() # Re-enable the WAP with new settings self.sys_log.info(f"Configured WAP {network_interface}") @@ -269,11 +265,8 @@ class WirelessRouter(Router): ip_address = cfg["wireless_access_point"]["ip_address"] subnet_mask = cfg["wireless_access_point"]["subnet_mask"] frequency = AirSpaceFrequency[cfg["wireless_access_point"]["frequency"]] - channel_width = cfg["wireless_access_point"].get("channel_width") - if channel_width: - channel_width = ChannelWidth(channel_width) router.configure_wireless_access_point( - ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency, channel_width=channel_width + ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency ) if "acl" in cfg: diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml index 21b0fe5e..5aed49cb 100644 --- a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml +++ b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml @@ -38,7 +38,6 @@ simulation: ip_address: 192.168.1.1 subnet_mask: 255.255.255.0 frequency: WIFI_5 - channel_width: 80 acl: 1: action: PERMIT @@ -60,7 +59,6 @@ simulation: ip_address: 192.168.1.2 subnet_mask: 255.255.255.0 frequency: WIFI_5 - channel_width: 80 acl: 1: action: PERMIT diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml index ed27cd35..d2e64720 100644 --- a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml +++ b/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml @@ -38,7 +38,6 @@ simulation: ip_address: 192.168.1.1 subnet_mask: 255.255.255.0 frequency: WIFI_5 - channel_width: 80 acl: 1: action: PERMIT @@ -60,7 +59,6 @@ simulation: ip_address: 192.168.1.2 subnet_mask: 255.255.255.0 frequency: WIFI_5 - channel_width: 80 acl: 1: action: PERMIT diff --git a/tests/integration_tests/network/test_airspace_capacity_configuration.py b/tests/integration_tests/network/test_airspace_capacity_configuration.py deleted file mode 100644 index f91f1290..00000000 --- a/tests/integration_tests/network/test_airspace_capacity_configuration.py +++ /dev/null @@ -1,106 +0,0 @@ -# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK -import yaml - -from primaite.game.game import PrimaiteGame -from primaite.simulator.network.airspace import ( - AirspaceEnvironmentType, - AirSpaceFrequency, - calculate_total_channel_capacity, - ChannelWidth, -) -from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter -from tests import TEST_ASSETS_ROOT - - -def test_wireless_wan_wifi_5_80_channel_width_urban(): - config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_urban.yaml" - - with open(config_path, "r") as f: - config_dict = yaml.safe_load(f) - network = PrimaiteGame.from_config(cfg=config_dict).simulation.network - - airspace = network.airspace - - assert airspace.airspace_environment_type == AirspaceEnvironmentType.URBAN - - router_1: WirelessRouter = network.get_node_by_hostname("router_1") - router_2: WirelessRouter = network.get_node_by_hostname("router_2") - - expected_speed = calculate_total_channel_capacity( - channel_width=ChannelWidth.WIDTH_80_MHZ, - frequency=AirSpaceFrequency.WIFI_5, - environment_type=AirspaceEnvironmentType.URBAN, - ) - - assert router_1.wireless_access_point.speed == expected_speed - assert router_2.wireless_access_point.speed == expected_speed - - pc_a = network.get_node_by_hostname("pc_a") - pc_b = network.get_node_by_hostname("pc_b") - - assert pc_a.ping(pc_a.default_gateway), "PC A should ping its default gateway successfully." - assert pc_b.ping(pc_b.default_gateway), "PC B should ping its default gateway successfully." - - assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." - assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." - - -def test_wireless_wan_wifi_5_80_channel_width_blocked(): - config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_blocked.yaml" - - with open(config_path, "r") as f: - config_dict = yaml.safe_load(f) - network = PrimaiteGame.from_config(cfg=config_dict).simulation.network - - airspace = network.airspace - - assert airspace.airspace_environment_type == AirspaceEnvironmentType.BLOCKED - - router_1: WirelessRouter = network.get_node_by_hostname("router_1") - router_2: WirelessRouter = network.get_node_by_hostname("router_2") - - expected_speed = calculate_total_channel_capacity( - channel_width=ChannelWidth.WIDTH_80_MHZ, - frequency=AirSpaceFrequency.WIFI_5, - environment_type=AirspaceEnvironmentType.BLOCKED, - ) - - assert router_1.wireless_access_point.speed == expected_speed - assert router_2.wireless_access_point.speed == expected_speed - - pc_a = network.get_node_by_hostname("pc_a") - pc_b = network.get_node_by_hostname("pc_b") - - assert pc_a.ping(pc_a.default_gateway), "PC A should ping its default gateway successfully." - assert pc_b.ping(pc_b.default_gateway), "PC B should ping its default gateway successfully." - - assert not pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers unsuccessfully." - assert not pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers unsuccessfully." - - -def test_wireless_wan_blocking_and_unblocking_airspace(): - config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_wifi_5_80_channel_width_urban.yaml" - - with open(config_path, "r") as f: - config_dict = yaml.safe_load(f) - network = PrimaiteGame.from_config(cfg=config_dict).simulation.network - - airspace = network.airspace - - assert airspace.airspace_environment_type == AirspaceEnvironmentType.URBAN - - pc_a = network.get_node_by_hostname("pc_a") - pc_b = network.get_node_by_hostname("pc_b") - - assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." - assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." - - airspace.airspace_environment_type = AirspaceEnvironmentType.BLOCKED - - assert not pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers unsuccessfully." - assert not pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers unsuccessfully." - - airspace.airspace_environment_type = AirspaceEnvironmentType.URBAN - - assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should ping PC B across routers successfully." - assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should ping PC A across routers successfully." diff --git a/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py b/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py index cf03ea8e..b7317c3d 100644 --- a/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py +++ b/tests/integration_tests/network/test_bandwidth_load_checks_before_transmission.py @@ -40,30 +40,6 @@ def test_wireless_link_loading(wireless_wan_network): client.network_interface[1]._connected_link.pre_timestep(1) server.network_interface[1]._connected_link.pre_timestep(1) - assert ftp_client.send_file( - src_file_name="mixtape.mp3", - src_folder_name="music", - dest_ip_address=server.network_interface[1].ip_address, - dest_file_name="mixtape1.mp3", - dest_folder_name="music", - ) - - # Reset the physical links between the host nodes and the routers - client.network_interface[1]._connected_link.pre_timestep(1) - server.network_interface[1]._connected_link.pre_timestep(1) - - assert ftp_client.send_file( - src_file_name="mixtape.mp3", - src_folder_name="music", - dest_ip_address=server.network_interface[1].ip_address, - dest_file_name="mixtape2.mp3", - dest_folder_name="music", - ) - - # Reset the physical links between the host nodes and the routers - client.network_interface[1]._connected_link.pre_timestep(1) - server.network_interface[1]._connected_link.pre_timestep(1) - assert not ftp_client.send_file( src_file_name="mixtape.mp3", src_folder_name="music", From abbfc869425bdcde77a432372299c939879f9335 Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Thu, 11 Jul 2024 15:50:35 +0100 Subject: [PATCH 32/42] 2623 update defaults --- src/primaite/game/agent/interface.py | 2 +- src/primaite/simulator/core.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py index 01b7fb0a..c00fd9d4 100644 --- a/src/primaite/game/agent/interface.py +++ b/src/primaite/game/agent/interface.py @@ -69,7 +69,7 @@ class AgentSettings(BaseModel): "Configuration for when an agent begins performing it's actions" flatten_obs: bool = True "Whether to flatten the observation space before passing it to the agent. True by default." - action_masking: bool = True + action_masking: bool = False "Whether to return action masks at each step." @classmethod diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 7653a3ab..574fcc19 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -174,6 +174,7 @@ class RequestManager(BaseModel): return requests def show(self) -> None: + """Display all currently available requests and whether they are valid.""" table = PrettyTable(["request", "valid"]) table.align = "l" table.add_rows(self.get_request_types_recursively()) From e759ae59904725695e31eb20095a2b1de3daf0e9 Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Thu, 11 Jul 2024 17:44:31 +0100 Subject: [PATCH 33/42] 2623 fix issues with tests and revert request show method --- src/primaite/simulator/core.py | 11 +++++------ tests/assets/configs/test_primaite_session.yaml | 2 ++ tests/e2e_integration_tests/test_environment.py | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 67108d5d..a5e39cc8 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -165,7 +165,7 @@ class RequestManager(BaseModel): self.request_types.pop(name) - def get_request_types_recursively(self, _parent_valid: bool = True) -> List[Tuple[RequestFormat, bool]]: + def get_request_types_recursively(self) -> List[RequestFormat]: """ Recursively generate request tree for this component. @@ -178,18 +178,17 @@ class RequestManager(BaseModel): """ requests = [] for req_name, req in self.request_types.items(): - valid = req.validator([], {}) and _parent_valid # if parent is invalid, all children are invalid if isinstance(req.func, RequestManager): - sub_requests = req.func.get_request_types_recursively(valid) # recurse - sub_requests = [([req_name] + a, valid) for a, valid in sub_requests] # prepend parent request to leaf + sub_requests = req.func.get_request_types_recursively() # recurse + sub_requests = [([req_name] + a) for a in sub_requests] # prepend parent request to leaf requests.extend(sub_requests) else: # leaf node found - requests.append(([req_name], valid)) + requests.append(req_name) return requests def show(self) -> None: """Display all currently available requests and whether they are valid.""" - table = PrettyTable(["request", "valid"]) + table = PrettyTable(["request"]) table.align = "l" table.add_rows(self.get_request_types_recursively()) print(table) diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index c435fe44..eb8103e8 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -646,6 +646,8 @@ simulation: dns_server: 192.168.1.10 services: - type: DatabaseService + options: + backup_server_ip: 192.168.1.16 - type: server hostname: backup_server diff --git a/tests/e2e_integration_tests/test_environment.py b/tests/e2e_integration_tests/test_environment.py index 253bd396..dcd51193 100644 --- a/tests/e2e_integration_tests/test_environment.py +++ b/tests/e2e_integration_tests/test_environment.py @@ -70,8 +70,8 @@ class TestPrimaiteEnvironment: assert len(env.agents) == 2 defender_1 = env.agents["defender_1"] defender_2 = env.agents["defender_2"] - assert (num_actions_1 := len(defender_1.action_manager.action_map)) == 74 - assert (num_actions_2 := len(defender_2.action_manager.action_map)) == 74 + assert (num_actions_1 := len(defender_1.action_manager.action_map)) == 78 + assert (num_actions_2 := len(defender_2.action_manager.action_map)) == 78 # ensure we can run all valid actions without error for act_1 in range(num_actions_1): From cde632066cf262c2e17b7705362bb9fd1530b50a Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Thu, 11 Jul 2024 21:11:27 +0100 Subject: [PATCH 34/42] #2745 implemented overriding of frequency max capacities on the airspace. updated documentation to reflect the changes in airspace.py. --- docs/source/configuration/simulation.rst | 36 ++++----- src/primaite/game/game.py | 6 ++ src/primaite/simulator/network/airspace.py | 75 +++++++++++-------- .../hardware/nodes/network/wireless_router.py | 4 +- .../configs/wireless_wan_network_config.yaml | 2 - ...wan_network_config_freq_max_override.yaml} | 8 +- ...ork_config_freq_max_override_blocked.yaml} | 8 +- .../network/test_airspace_config.py | 44 +++++++++++ 8 files changed, 120 insertions(+), 63 deletions(-) rename tests/assets/configs/{wireless_wan_wifi_5_80_channel_width_urban.yaml => wireless_wan_network_config_freq_max_override.yaml} (92%) rename tests/assets/configs/{wireless_wan_wifi_5_80_channel_width_blocked.yaml => wireless_wan_network_config_freq_max_override_blocked.yaml} (92%) create mode 100644 tests/integration_tests/network/test_airspace_config.py diff --git a/docs/source/configuration/simulation.rst b/docs/source/configuration/simulation.rst index bd66914d..48b857d9 100644 --- a/docs/source/configuration/simulation.rst +++ b/docs/source/configuration/simulation.rst @@ -108,31 +108,23 @@ This is an integer value specifying the allowed bandwidth across the connection. ``airspace`` ------------ -This section configures settings specific to the wireless network's virtual airspace. It defines how wireless interfaces within the simulation will interact and perform under various environmental conditions. +This section configures settings specific to the wireless network's virtual airspace. -``airspace_environment_type`` +``frequency_max_capacity_mbps`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This setting specifies the environmental conditions of the airspace which affect the propagation and interference characteristics of wireless signals. Changing this environment type impacts how signal noise and interference are calculated, thus affecting the overall network performance, including data transmission rates and signal quality. +This setting allows the user to override the default maximum bandwidth capacity set for each frequency. The key should +be the AirSpaceFrequency name and the value be the desired maximum bandwidth capacity in mbps (megabits per second) for +a single timestep. -**Configurable Options** +The below example would permit 123.45 megabits to be transmit across the WiFi 2.4 GHz frequency in a single timestep. +Setting a frequencies max capacity to 0.0 blocks that frequency on the airspace. -- **rural**: A rural environment offers clear channel conditions due to low population density and minimal electronic device presence. +.. code-block:: yaml -- **outdoor**: Outdoor environments like parks or fields have minimal electronic interference. - -- **suburban**: Suburban environments strike a balance with fewer electronic interferences than urban but more than rural. - -- **office**: Office environments have moderate interference from numerous electronic devices and overlapping networks. - -- **urban**: Urban environments are characterized by tall buildings and a high density of electronic devices, leading to significant interference. - -- **industrial**: Industrial areas face high interference from heavy machinery and numerous electronic devices. - -- **transport**: Environments such as subways and buses where metal structures and high mobility create complex interference patterns. - -- **dense_urban**: Dense urban areas like city centers have the highest level of signal interference due to the very high density of buildings and devices. - -- **jamming_zone**: A jamming zone environment where signals are actively interfered with, typically through the use of signal jammers or scrambling devices. This represents the environment with the highest level of interference. - -- **blocked**: A jamming zone environment with total levels of interference. Airspace is completely blocked. + simulation: + network: + airspace: + frequency_max_capacity_mbps: + WIFI_2_4: 123.45 + WIFI_5: 0.0 diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index b976e55f..9eadc360 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -16,6 +16,7 @@ from primaite.game.agent.scripted_agents.random_agent import PeriodicAgent from primaite.game.agent.scripted_agents.tap001 import TAP001 from primaite.game.science import graph_has_cycle, topological_sort from primaite.simulator import SIM_OUTPUT +from primaite.simulator.network.airspace import AirSpaceFrequency from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC @@ -237,6 +238,11 @@ class PrimaiteGame: simulation_config = cfg.get("simulation", {}) network_config = simulation_config.get("network", {}) airspace_cfg = network_config.get("airspace", {}) + frequency_max_capacity_mbps_cfg = airspace_cfg.get("frequency_max_capacity_mbps", {}) + + frequency_max_capacity_mbps_cfg = {AirSpaceFrequency[k]: v for k, v in frequency_max_capacity_mbps_cfg.items()} + + net.airspace.frequency_max_capacity_mbps_ = frequency_max_capacity_mbps_cfg nodes_cfg = network_config.get("nodes", []) links_cfg = network_config.get("links", []) diff --git a/src/primaite/simulator/network/airspace.py b/src/primaite/simulator/network/airspace.py index 5019385a..9c736383 100644 --- a/src/primaite/simulator/network/airspace.py +++ b/src/primaite/simulator/network/airspace.py @@ -3,7 +3,7 @@ from __future__ import annotations from abc import ABC, abstractmethod from enum import Enum -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List from prettytable import MARKDOWN, PrettyTable from pydantic import BaseModel, Field @@ -59,6 +59,15 @@ class AirSpaceFrequency(Enum): @property def maximum_data_rate_bps(self) -> float: + """ + Retrieves the maximum data transmission rate in bits per second (bps) for the frequency. + + The maximum rates are predefined for known frequencies: + - For WIFI_2_4, it returns 100,000,000 bps (100 Mbps). + - For WIFI_5, it returns 500,000,000 bps (500 Mbps). + + :return: The maximum data rate in bits per second. If the frequency is not recognized, returns 0.0. + """ if self == AirSpaceFrequency.WIFI_2_4: return 100_000_000.0 # 100 Megabits per second if self == AirSpaceFrequency.WIFI_5: @@ -67,6 +76,14 @@ class AirSpaceFrequency(Enum): @property def maximum_data_rate_mbps(self) -> float: + """ + Retrieves the maximum data transmission rate in megabits per second (Mbps). + + This is derived by converting the maximum data rate from bits per second, as defined + in `maximum_data_rate_bps`, to megabits per second. + + :return: The maximum data rate in megabits per second. + """ return self.maximum_data_rate_bps / 1_000_000.0 @@ -84,28 +101,33 @@ class AirSpace(BaseModel): default_factory=lambda: {} ) bandwidth_load: Dict[AirSpaceFrequency, float] = Field(default_factory=lambda: {}) - frequency_max_capacity_mbps: Dict[AirSpaceFrequency, float] = Field(default_factory=lambda: {}) + frequency_max_capacity_mbps_: Dict[AirSpaceFrequency, float] = Field(default_factory=lambda: {}) - def model_post_init(self, __context: Any) -> None: + def get_frequency_max_capacity_mbps(self, frequency: AirSpaceFrequency) -> float: """ - Initialize the airspace metadata after instantiation. + Retrieves the maximum data transmission capacity for a specified frequency. - This method is called to set up initial configurations like the maximum capacity of each frequency. + This method checks a dictionary holding custom maximum capacities. If the frequency is found, it returns the + custom set maximum capacity. If the frequency is not found in the dictionary, it defaults to the standard + maximum data rate associated with that frequency. - :param __context: Contextual data or settings, typically used for further initializations beyond - the basic constructor. - """ - self.set_frequency_max_capacity_mbps() + :param frequency: The frequency for which the maximum capacity is queried. - def set_frequency_max_capacity_mbps(self, capacity_config: Optional[Dict[AirSpaceFrequency, float]] = None): + :return: The maximum capacity in Mbps for the specified frequency. """ - Set the maximum channel capacity in Mbps for each frequency. + if frequency in self.frequency_max_capacity_mbps_: + return self.frequency_max_capacity_mbps_[frequency] + return frequency.maximum_data_rate_mbps + + def set_frequency_max_capacity_mbps(self, cfg: Dict[AirSpaceFrequency, float]): """ - if capacity_config is None: - capacity_config = {} - for frequency in AirSpaceFrequency: - max_capacity = capacity_config.get(frequency, frequency.maximum_data_rate_mbps) - self.frequency_max_capacity_mbps[frequency] = max_capacity + Sets custom maximum data transmission capacities for multiple frequencies. + + :param cfg: A dictionary mapping frequencies to their new maximum capacities in Mbps. + """ + self.frequency_max_capacity_mbps_ = cfg + for freq, mbps in cfg.items(): + print(f"Overriding {freq} max capacity as {mbps:.3f} mbps") def show_bandwidth_load(self, markdown: bool = False): """ @@ -117,8 +139,6 @@ class AirSpace(BaseModel): :param markdown: Flag indicating if output should be in markdown format. """ - if not self.frequency_max_capacity_mbps: - self.set_frequency_max_capacity_mbps() headers = ["Frequency", "Current Capacity (%)", "Maximum Capacity (Mbit)"] table = PrettyTable(headers) if markdown: @@ -126,8 +146,8 @@ class AirSpace(BaseModel): table.align = "l" table.title = "Airspace Frequency Channel Loads" for frequency, load in self.bandwidth_load.items(): - maximum_capacity = self.frequency_max_capacity_mbps[frequency] - load_percent = load / maximum_capacity + maximum_capacity = self.get_frequency_max_capacity_mbps(frequency) + load_percent = load / maximum_capacity if maximum_capacity > 0 else 0.0 if load_percent > 1.0: load_percent = 1.0 table.add_row([format_hertz(frequency.value), f"{load_percent:.0%}", f"{maximum_capacity:.3f}"]) @@ -152,7 +172,7 @@ class AirSpace(BaseModel): if markdown: table.set_style(MARKDOWN) table.align = "l" - table.title = f"Devices on Air Space" + table.title = "Devices on Air Space" for interface in self.wireless_interfaces.values(): status = "Enabled" if interface.enabled else "Disabled" @@ -235,14 +255,11 @@ class AirSpace(BaseModel): relevant frequency and its current bandwidth load. :return: True if the frame can be transmitted within the bandwidth limit, False if it would exceed the limit. """ - if not self.frequency_max_capacity_mbps: - self.set_frequency_max_capacity_mbps() if sender_network_interface.frequency not in self.bandwidth_load: self.bandwidth_load[sender_network_interface.frequency] = 0.0 - return ( - self.bandwidth_load[sender_network_interface.frequency] + frame.size_Mbits - <= self.frequency_max_capacity_mbps[sender_network_interface.frequency] - ) + return self.bandwidth_load[ + sender_network_interface.frequency + ] + frame.size_Mbits <= self.get_frequency_max_capacity_mbps(sender_network_interface.frequency) def transmit(self, frame: Frame, sender_network_interface: WirelessNetworkInterface): """ @@ -255,9 +272,7 @@ class AirSpace(BaseModel): excluded from the list of receivers to prevent it from receiving its own transmission. """ self.bandwidth_load[sender_network_interface.frequency] += frame.size_Mbits - for wireless_interface in self.wireless_interfaces_by_frequency.get( - sender_network_interface.frequency, [] - ): + for wireless_interface in self.wireless_interfaces_by_frequency.get(sender_network_interface.frequency, []): if wireless_interface != sender_network_interface and wireless_interface.enabled: wireless_interface.receive_frame(frame) diff --git a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py index 5ded993e..3cb4c515 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py @@ -265,9 +265,7 @@ class WirelessRouter(Router): ip_address = cfg["wireless_access_point"]["ip_address"] subnet_mask = cfg["wireless_access_point"]["subnet_mask"] frequency = AirSpaceFrequency[cfg["wireless_access_point"]["frequency"]] - router.configure_wireless_access_point( - ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency - ) + router.configure_wireless_access_point(ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency) if "acl" in cfg: for r_num, r_cfg in cfg["acl"].items(): diff --git a/tests/assets/configs/wireless_wan_network_config.yaml b/tests/assets/configs/wireless_wan_network_config.yaml index 7172f66d..c8f61bad 100644 --- a/tests/assets/configs/wireless_wan_network_config.yaml +++ b/tests/assets/configs/wireless_wan_network_config.yaml @@ -9,8 +9,6 @@ game: simulation: network: - airspace: - airspace_environment_type: urban nodes: - type: computer hostname: pc_a diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml b/tests/assets/configs/wireless_wan_network_config_freq_max_override.yaml similarity index 92% rename from tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml rename to tests/assets/configs/wireless_wan_network_config_freq_max_override.yaml index d2e64720..a327b0f5 100644 --- a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_urban.yaml +++ b/tests/assets/configs/wireless_wan_network_config_freq_max_override.yaml @@ -10,7 +10,9 @@ game: simulation: network: airspace: - airspace_environment_type: urban + frequency_max_capacity_mbps: + WIFI_2_4: 123.45 + WIFI_5: 0.0 nodes: - type: computer hostname: pc_a @@ -37,7 +39,7 @@ simulation: wireless_access_point: ip_address: 192.168.1.1 subnet_mask: 255.255.255.0 - frequency: WIFI_5 + frequency: WIFI_2_4 acl: 1: action: PERMIT @@ -58,7 +60,7 @@ simulation: wireless_access_point: ip_address: 192.168.1.2 subnet_mask: 255.255.255.0 - frequency: WIFI_5 + frequency: WIFI_2_4 acl: 1: action: PERMIT diff --git a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml b/tests/assets/configs/wireless_wan_network_config_freq_max_override_blocked.yaml similarity index 92% rename from tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml rename to tests/assets/configs/wireless_wan_network_config_freq_max_override_blocked.yaml index 5aed49cb..ff048c92 100644 --- a/tests/assets/configs/wireless_wan_wifi_5_80_channel_width_blocked.yaml +++ b/tests/assets/configs/wireless_wan_network_config_freq_max_override_blocked.yaml @@ -10,7 +10,9 @@ game: simulation: network: airspace: - airspace_environment_type: blocked + frequency_max_capacity_mbps: + WIFI_2_4: 0.0 + WIFI_5: 0.0 nodes: - type: computer hostname: pc_a @@ -37,7 +39,7 @@ simulation: wireless_access_point: ip_address: 192.168.1.1 subnet_mask: 255.255.255.0 - frequency: WIFI_5 + frequency: WIFI_2_4 acl: 1: action: PERMIT @@ -58,7 +60,7 @@ simulation: wireless_access_point: ip_address: 192.168.1.2 subnet_mask: 255.255.255.0 - frequency: WIFI_5 + frequency: WIFI_2_4 acl: 1: action: PERMIT diff --git a/tests/integration_tests/network/test_airspace_config.py b/tests/integration_tests/network/test_airspace_config.py new file mode 100644 index 00000000..78d00b47 --- /dev/null +++ b/tests/integration_tests/network/test_airspace_config.py @@ -0,0 +1,44 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK +import yaml + +from primaite.game.game import PrimaiteGame +from primaite.simulator.network.airspace import AirSpaceFrequency +from tests import TEST_ASSETS_ROOT + + +def test_override_freq_max_capacity_mbps(): + config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_network_config_freq_max_override.yaml" + + with open(config_path, "r") as f: + config_dict = yaml.safe_load(f) + network = PrimaiteGame.from_config(cfg=config_dict).simulation.network + + assert network.airspace.get_frequency_max_capacity_mbps(AirSpaceFrequency.WIFI_2_4) == 123.45 + assert network.airspace.get_frequency_max_capacity_mbps(AirSpaceFrequency.WIFI_5) == 0.0 + + pc_a = network.get_node_by_hostname("pc_a") + pc_b = network.get_node_by_hostname("pc_b") + + assert pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should be able to ping PC B" + assert pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should be able to ping PC A" + + network.airspace.show() + + +def test_override_freq_max_capacity_mbps_blocked(): + config_path = TEST_ASSETS_ROOT / "configs" / "wireless_wan_network_config_freq_max_override_blocked.yaml" + + with open(config_path, "r") as f: + config_dict = yaml.safe_load(f) + network = PrimaiteGame.from_config(cfg=config_dict).simulation.network + + assert network.airspace.get_frequency_max_capacity_mbps(AirSpaceFrequency.WIFI_2_4) == 0.0 + assert network.airspace.get_frequency_max_capacity_mbps(AirSpaceFrequency.WIFI_5) == 0.0 + + pc_a = network.get_node_by_hostname("pc_a") + pc_b = network.get_node_by_hostname("pc_b") + + assert not pc_a.ping(pc_b.network_interface[1].ip_address), "PC A should not be able to ping PC B" + assert not pc_b.ping(pc_a.network_interface[1].ip_address), "PC B should not be able to ping PC A" + + network.airspace.show() From 199cd0d9dfe2ae40310491b07aa3fba2b169f5bc Mon Sep 17 00:00:00 2001 From: Marek Wolan Date: Fri, 12 Jul 2024 11:23:41 +0100 Subject: [PATCH 35/42] fix test problems and slowness --- src/primaite/simulator/core.py | 14 +++++++------- tests/conftest.py | 4 ++-- .../test_agents_use_action_masks.py | 4 +--- .../test_rllib_multi_agent_environment.py | 16 ++-------------- .../test_rllib_single_agent_environment.py | 1 - .../environments/test_sb3_environment.py | 2 +- 6 files changed, 13 insertions(+), 28 deletions(-) diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index a5e39cc8..848570fe 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -179,18 +179,18 @@ class RequestManager(BaseModel): requests = [] for req_name, req in self.request_types.items(): if isinstance(req.func, RequestManager): - sub_requests = req.func.get_request_types_recursively() # recurse - sub_requests = [([req_name] + a) for a in sub_requests] # prepend parent request to leaf + sub_requests = req.func.get_request_types_recursively() + sub_requests = [[req_name] + a for a in sub_requests] requests.extend(sub_requests) - else: # leaf node found - requests.append(req_name) + else: + requests.append([req_name]) return requests def show(self) -> None: - """Display all currently available requests and whether they are valid.""" - table = PrettyTable(["request"]) + """Display all currently available requests.""" + table = PrettyTable(["requests"]) table.align = "l" - table.add_rows(self.get_request_types_recursively()) + table.add_rows([[x] for x in self.get_request_types_recursively()]) print(table) def check_valid(self, request: RequestFormat, context: Dict) -> bool: diff --git a/tests/conftest.py b/tests/conftest.py index b8b50182..54519e2b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,8 +2,8 @@ from typing import Any, Dict, Tuple import pytest -import ray import yaml +from ray import init as rayinit from primaite import getLogger, PRIMAITE_PATHS from primaite.game.agent.actions import ActionManager @@ -30,7 +30,7 @@ from primaite.simulator.system.services.service import Service from primaite.simulator.system.services.web_server.web_server import WebServer from tests import TEST_ASSETS_ROOT -ray.init(local_mode=True) +rayinit(local_mode=True) ACTION_SPACE_NODE_VALUES = 1 ACTION_SPACE_NODE_ACTION_VALUES = 1 diff --git a/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py index a299b913..745e280b 100644 --- a/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py +++ b/tests/e2e_integration_tests/action_masking/test_agents_use_action_masks.py @@ -1,9 +1,7 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK -import importlib from typing import Dict import yaml -from ray import air, init, tune from ray.rllib.algorithms.ppo import PPOConfig from ray.rllib.core.rl_module.marl_module import MultiAgentRLModuleSpec from ray.rllib.core.rl_module.rl_module import SingleAgentRLModuleSpec @@ -43,7 +41,7 @@ def test_sb3_action_masking(monkeypatch): monkeypatch.setattr(env, "step", lambda action: cache_step(env, action)) model = MaskablePPO("MlpPolicy", env, gamma=0.4, seed=32, batch_size=32) - model.learn(512) + model.learn(256) assert len(action_num_history) == len(mask_history) > 0 # Make sure the masks had at least some False entries, if it was all True then the mask was disabled diff --git a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py index e015c33c..26e690d0 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py @@ -1,7 +1,5 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK -import ray import yaml -from ray import air, tune from ray.rllib.algorithms.ppo import PPOConfig from primaite.session.ray_envs import PrimaiteRayMARLEnv @@ -12,7 +10,6 @@ MULTI_AGENT_PATH = TEST_ASSETS_ROOT / "configs/multi_agent_session.yaml" def test_rllib_multi_agent_compatibility(): """Test that the PrimaiteRayEnv class can be used with a multi agent RLLIB system.""" - with open(MULTI_AGENT_PATH, "r") as f: cfg = yaml.safe_load(f) @@ -26,14 +23,5 @@ def test_rllib_multi_agent_compatibility(): ) .training(train_batch_size=128) ) - - tune.Tuner( - "PPO", - run_config=air.RunConfig( - stop={"training_iteration": 128}, - checkpoint_config=air.CheckpointConfig( - checkpoint_frequency=10, - ), - ), - param_space=config, - ).fit() + algo = config.build() + algo.train() diff --git a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py index a02a078c..265257e4 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py @@ -3,7 +3,6 @@ import tempfile from pathlib import Path import pytest -import ray import yaml from ray.rllib.algorithms import ppo diff --git a/tests/e2e_integration_tests/environments/test_sb3_environment.py b/tests/e2e_integration_tests/environments/test_sb3_environment.py index 27fb134b..a07d5d2e 100644 --- a/tests/e2e_integration_tests/environments/test_sb3_environment.py +++ b/tests/e2e_integration_tests/environments/test_sb3_environment.py @@ -20,7 +20,7 @@ def test_sb3_compatibility(): gym = PrimaiteGymEnv(env_config=cfg) model = PPO("MlpPolicy", gym) - model.learn(total_timesteps=1000) + model.learn(total_timesteps=256) save_path = Path(tempfile.gettempdir()) / "model.zip" model.save(save_path) From 951fd30e03e91b96261d84898082f916680e213c Mon Sep 17 00:00:00 2001 From: Chris McCarthy Date: Sat, 13 Jul 2024 19:58:41 +0100 Subject: [PATCH 36/42] retrospectively added the 3.1.0 benchmark results --- .../PrimAITE v3.1.0 Learning Benchmark.pdf | Bin 0 -> 387130 bytes .../PrimAITE v3.1.0 Learning Benchmark.png | Bin 0 -> 329770 bytes .../v3/v3.1.0/v3.1.0_benchmark_metadata.json | 7444 +++++++++++++++++ 3 files changed, 7444 insertions(+) create mode 100644 benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.pdf create mode 100644 benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png create mode 100644 benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json diff --git a/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.pdf b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.pdf new file mode 100644 index 0000000000000000000000000000000000000000..880fd8dec071c09d40ad7da217e648d10515b3a8 GIT binary patch literal 387130 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�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

IT@O!wHlHmkJDmc3 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

=e*%vW+FSB3CV5Q0^h#cjznSmY00ql9i|lh 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 z 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 z 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®3Lak<6Hnif8_GEic~bK?UbFc=^6p)MSr8N- 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 DS{2P; literal 0 HcmV?d00001 diff --git a/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png b/benchmark/results/v3/v3.1.0/PrimAITE v3.1.0 Learning Benchmark.png new file mode 100644 index 0000000000000000000000000000000000000000..2771745d89b94248e2caceae0d64f7a4ea8adc11 GIT binary patch literal 329770 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

AS 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

gj&utt8%K#~s*|+ooIsgdn!)hj#73&2;tA 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 literal 0 HcmV?d00001 diff --git a/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json b/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json new file mode 100644 index 00000000..fcd2d610 --- /dev/null +++ b/benchmark/results/v3/v3.1.0/v3.1.0_benchmark_metadata.json @@ -0,0 +1,7444 @@ +{ + "start_timestamp": "2024-07-13T13:15:57.915794", + "end_datetime": "2024-07-13T17:23:50.622036", + "primaite_version": "3.1.0", + "system_info": { + "System": { + "OS": "Windows", + "OS Version": "10.0.22631", + "Machine": "AMD64", + "Processor": "Intel64 Family 6 Model 142 Stepping 12, GenuineIntel" + }, + "CPU": { + "Physical Cores": 4, + "Total Cores": 8, + "Max Frequency": "2304.00Mhz" + }, + "Memory": { + "Total": "15.68GB", + "Swap Total": "15.68GB" + }, + "GPU": [] + }, + "total_sessions": 5, + "total_episodes": 5005, + "total_time_steps": 640000, + "av_s_per_session": 2974.2557622, + "av_s_per_step": 0.09294549256875, + "av_s_per_100_steps_10_nodes": 9.294549256875001, + "combined_total_reward_per_episode": { + "1": -50.19000000000003, + "2": -37.08, + "3": -39.42000000000002, + "4": -32.90000000000003, + "5": -29.1, + "6": -21.420000000000005, + "7": -24.229999999999997, + "8": -32.010000000000026, + "9": -41.95000000000006, + "10": -33.46000000000002, + "11": -22.999999999999986, + "12": -27.81000000000002, + "13": -37.719999999999985, + "14": -31.21999999999998, + "15": -35.62000000000003, + "16": -20.88999999999998, + "17": -31.059999999999995, + "18": -39.09000000000004, + "19": -47.99999999999998, + "20": -50.209999999999994, + "21": -31.219999999999978, + "22": -27.05, + "23": -42.66000000000001, + "24": -28.89999999999997, + "25": -30.089999999999964, + "26": -58.25, + "27": -23.779999999999987, + "28": -23.189999999999994, + "29": -35.39000000000003, + "30": -26.810000000000013, + "31": -50.27999999999999, + "32": -14.059999999999999, + "33": -27.82000000000003, + "34": -34.619999999999976, + "35": -19.749999999999986, + "36": -18.659999999999986, + "37": -39.81000000000003, + "38": -21.5, + "39": -52.24000000000002, + "40": -35.65000000000005, + "41": -33.48999999999999, + "42": -36.70999999999999, + "43": -23.019999999999992, + "44": -44.96, + "45": -17.969999999999974, + "46": -29.44999999999998, + "47": -17.76999999999997, + "48": -22.339999999999986, + "49": -36.18999999999999, + "50": -28.01, + "51": -44.8, + "52": -35.59, + "53": -36.69000000000001, + "54": -53.0, + "55": -23.449999999999978, + "56": -32.06999999999999, + "57": -17.409999999999982, + "58": -29.610000000000003, + "59": -13.339999999999984, + "60": -36.94000000000002, + "61": -15.64999999999998, + "62": -21.539999999999992, + "63": -41.82999999999999, + "64": -8.18999999999999, + "65": -33.300000000000004, + "66": -34.66000000000004, + "67": -22.839999999999986, + "68": -23.839999999999996, + "69": -18.14999999999997, + "70": -17.339999999999982, + "71": -56.26000000000001, + "72": -37.179999999999986, + "73": -32.870000000000026, + "74": -15.09999999999997, + "75": -37.679999999999986, + "76": -13.569999999999983, + "77": -11.789999999999981, + "78": -46.869999999999976, + "79": -29.45999999999998, + "80": -39.99, + "81": -22.599999999999977, + "82": -35.64000000000001, + "83": -19.20999999999996, + "84": -10.239999999999995, + "85": -10.409999999999982, + "86": -25.14999999999997, + "87": -13.70000000000002, + "88": -46.37999999999999, + "89": -25.379999999999992, + "90": -43.129999999999974, + "91": -26.359999999999975, + "92": -28.9, + "93": -52.14, + "94": -14.389999999999981, + "95": -17.739999999999995, + "96": -15.079999999999984, + "97": -18.75999999999997, + "98": -10.959999999999985, + "99": -23.189999999999984, + "100": -26.79, + "101": -13.209999999999997, + "102": -15.759999999999994, + "103": -28.50999999999998, + "104": -28.499999999999993, + "105": -50.37000000000003, + "106": -23.359999999999985, + "107": -17.990000000000016, + "108": -13.849999999999998, + "109": -22.820000000000014, + "110": -19.509999999999973, + "111": -21.719999999999978, + "112": -11.379999999999981, + "113": -27.03999999999998, + "114": -16.50000000000003, + "115": 0.5000000000000108, + "116": -38.779999999999994, + "117": -21.609999999999967, + "118": -33.17, + "119": -42.91999999999999, + "120": -6.389999999999989, + "121": -35.57, + "122": -10.479999999999993, + "123": -28.919999999999977, + "124": -29.24999999999998, + "125": -45.599999999999966, + "126": -33.97999999999998, + "127": -6.819999999999976, + "128": -25.44999999999999, + "129": -10.839999999999979, + "130": -7.3699999999999735, + "131": -13.14999999999998, + "132": -5.600000000000014, + "133": -38.18999999999996, + "134": -22.839999999999975, + "135": -28.01999999999996, + "136": -18.46, + "137": -17.769999999999975, + "138": -17.860000000000007, + "139": -24.69, + "140": -19.99999999999998, + "141": -29.120000000000005, + "142": -23.93999999999998, + "143": -13.999999999999996, + "144": -13.179999999999973, + "145": -33.58, + "146": -3.7899999999999983, + "147": -11.520000000000035, + "148": -38.609999999999985, + "149": -7.090000000000018, + "150": 14.609999999999932, + "151": -37.13999999999997, + "152": 3.390000000000023, + "153": -7.829999999999981, + "154": -29.940000000000026, + "155": -36.17999999999999, + "156": -10.690000000000005, + "157": -49.84000000000001, + "158": -11.899999999999986, + "159": -27.940000000000005, + "160": -51.04999999999998, + "161": -49.46999999999998, + "162": -0.6199999999999779, + "163": 2.9800000000000164, + "164": -19.80999999999998, + "165": -34.34999999999999, + "166": -14.520000000000039, + "167": -56.739999999999974, + "168": -37.59, + "169": -11.200000000000017, + "170": -39.030000000000044, + "171": 0.34000000000003683, + "172": -3.690000000000004, + "173": -38.34000000000001, + "174": 0.27999999999997627, + "175": -9.659999999999988, + "176": -21.130000000000052, + "177": -17.179999999999975, + "178": -29.15999999999999, + "179": -19.709999999999972, + "180": -27.849999999999987, + "181": -17.36000000000006, + "182": -30.92000000000001, + "183": -31.849999999999984, + "184": 18.66999999999998, + "185": -14.780000000000005, + "186": -28.70999999999999, + "187": 1.4300000000000146, + "188": -16.180000000000042, + "189": -6.440000000000012, + "190": -7.770000000000017, + "191": 8.599999999999909, + "192": -35.13999999999999, + "193": -8.440000000000008, + "194": -33.03999999999999, + "195": -20.320000000000014, + "196": -22.949999999999992, + "197": -10.810000000000024, + "198": -9.95999999999997, + "199": -14.459999999999997, + "200": 6.80000000000004, + "201": -10.139999999999999, + "202": -29.719999999999978, + "203": 4.839999999999988, + "204": -45.51999999999996, + "205": 9.359999999999967, + "206": -15.060000000000011, + "207": -11.120000000000001, + "208": -10.230000000000018, + "209": -4.810000000000011, + "210": -24.110000000000003, + "211": -10.809999999999965, + "212": -22.969999999999995, + "213": -32.93000000000001, + "214": -44.849999999999966, + "215": -7.409999999999971, + "216": -55.249999999999986, + "217": -11.000000000000039, + "218": -13.789999999999987, + "219": 6.780000000000013, + "220": -36.989999999999995, + "221": 0.05999999999995964, + "222": -23.66999999999999, + "223": 4.489999999999997, + "224": -32.989999999999995, + "225": -30.080000000000005, + "226": -25.13999999999997, + "227": 21.37999999999991, + "228": -25.430000000000042, + "229": -11.67999999999999, + "230": -0.8, + "231": -16.230000000000054, + "232": 19.34999999999995, + "233": -16.190000000000037, + "234": -39.27999999999999, + "235": -32.65999999999999, + "236": -24.819999999999993, + "237": -13.209999999999974, + "238": -12.51, + "239": 14.51, + "240": -11.750000000000018, + "241": -11.279999999999976, + "242": -3.460000000000045, + "243": -1.5800000000000438, + "244": -9.049999999999997, + "245": -10.840000000000021, + "246": -12.060000000000025, + "247": -10.719999999999988, + "248": -4.250000000000009, + "249": -15.509999999999977, + "250": -20.600000000000044, + "251": -16.36000000000002, + "252": 26.319999999999972, + "253": 30.57000000000004, + "254": -66.94000000000001, + "255": -33.81999999999997, + "256": 3.1900000000000075, + "257": -9.36000000000001, + "258": 15.4799999999999, + "259": 25.349999999999987, + "260": -19.860000000000014, + "261": 23.169999999999977, + "262": 10.279999999999967, + "263": 41.609999999999886, + "264": -16.279999999999994, + "265": 19.81999999999998, + "266": 4.179999999999954, + "267": 12.709999999999997, + "268": -5.1600000000000135, + "269": -7.580000000000041, + "270": 0.38999999999994517, + "271": 12.130000000000017, + "272": 17.339999999999982, + "273": -2.52000000000002, + "274": -39.070000000000036, + "275": 6.959999999999923, + "276": -8.35000000000006, + "277": 19.52999999999997, + "278": 48.72, + "279": 27.119999999999926, + "280": 19.370000000000076, + "281": 31.73999999999997, + "282": 26.65999999999993, + "283": -6.270000000000027, + "284": -29.76999999999997, + "285": 17.299999999999923, + "286": -7.230000000000004, + "287": 22.819999999999983, + "288": 8.859999999999992, + "289": 12.009999999999954, + "290": 9.480000000000015, + "291": 28.48999999999996, + "292": 22.72999999999994, + "293": 9.759999999999996, + "294": 16.889999999999993, + "295": 47.449999999999974, + "296": 29.229999999999972, + "297": 33.959999999999965, + "298": 34.949999999999896, + "299": 39.8799999999999, + "300": 22.319999999999915, + "301": 9.599999999999955, + "302": -1.3099999999999739, + "303": 23.930000000000003, + "304": 28.26999999999997, + "305": 21.609999999999946, + "306": 54.81999999999996, + "307": 17.859999999999978, + "308": -0.8900000000000119, + "309": 27.900000000000006, + "310": 15.899999999999991, + "311": 59.06999999999997, + "312": 12.529999999999916, + "313": 33.330000000000005, + "314": 46.78999999999993, + "315": 42.32000000000001, + "316": 39.19999999999994, + "317": 19.399999999999984, + "318": 10.940000000000007, + "319": 4.799999999999926, + "320": 53.97999999999992, + "321": 15.399999999999983, + "322": 33.55999999999995, + "323": 35.370000000000005, + "324": 56.52999999999997, + "325": -19.31000000000006, + "326": 59.559999999999945, + "327": 64.26000000000002, + "328": 61.64, + "329": 31.54000000000003, + "330": 25.21999999999994, + "331": 4.900000000000077, + "332": 43.93, + "333": 58.64000000000003, + "334": 45.10999999999995, + "335": 7.880000000000015, + "336": 21.56000000000001, + "337": 28.059999999999967, + "338": 62.60999999999992, + "339": 35.860000000000014, + "340": 47.01999999999995, + "341": 38.5, + "342": 29.940000000000026, + "343": 38.869999999999955, + "344": 54.18000000000002, + "345": 52.470000000000006, + "346": 77.61999999999992, + "347": 91.96000000000005, + "348": 45.899999999999885, + "349": 61.289999999999964, + "350": 66.13999999999994, + "351": 41.21999999999996, + "352": 60.00999999999999, + "353": 76.99999999999996, + "354": 38.95999999999991, + "355": 54.65999999999991, + "356": 53.92999999999999, + "357": 21.990000000000048, + "358": 44.9, + "359": 2.220000000000013, + "360": 16.209999999999972, + "361": 49.140000000000036, + "362": 77.32999999999998, + "363": 36.98000000000001, + "364": 32.62999999999999, + "365": 18.11999999999994, + "366": 60.84999999999995, + "367": 32.38999999999997, + "368": 40.66999999999997, + "369": 56.98999999999995, + "370": 43.18000000000003, + "371": 67.46999999999996, + "372": 38.04000000000004, + "373": 36.599999999999945, + "374": 56.759999999999955, + "375": 86.07999999999996, + "376": 67.81999999999996, + "377": 43.750000000000036, + "378": 66.75999999999993, + "379": 81.25000000000009, + "380": 35.030000000000015, + "381": 84.4399999999999, + "382": 46.96999999999992, + "383": 52.759999999999934, + "384": 42.72000000000001, + "385": 72.69999999999999, + "386": 20.10000000000006, + "387": 61.92999999999988, + "388": 40.89999999999995, + "389": 50.309999999999924, + "390": 83.08999999999997, + "391": 45.04999999999994, + "392": 92.0100000000001, + "393": 72.51999999999995, + "394": 82.71000000000001, + "395": 67.56, + "396": 43.689999999999955, + "397": 64.49999999999994, + "398": 56.60000000000006, + "399": 87.21, + "400": 69.86999999999998, + "401": 73.04000000000009, + "402": 77.73999999999997, + "403": 70.53999999999996, + "404": 38.960000000000065, + "405": 53.639999999999944, + "406": 36.68999999999998, + "407": 70.75000000000003, + "408": 32.63999999999994, + "409": 82.27999999999992, + "410": 83.77000000000002, + "411": 80.82999999999984, + "412": 50.33, + "413": 56.04000000000004, + "414": 29.680000000000085, + "415": 43.84, + "416": 66.66000000000004, + "417": 68.80999999999997, + "418": 67.46999999999997, + "419": 40.41999999999993, + "420": 69.02000000000001, + "421": 79.35999999999993, + "422": 64.07, + "423": 41.07000000000001, + "424": 84.76999999999997, + "425": 80.94999999999993, + "426": 70.64000000000007, + "427": 53.80999999999997, + "428": 72.94999999999996, + "429": 94.79999999999998, + "430": 106.06999999999987, + "431": 98.68999999999994, + "432": 101.55000000000007, + "433": 96.01000000000008, + "434": 83.60999999999999, + "435": 68.25999999999996, + "436": 70.89, + "437": 97.38999999999993, + "438": 70.83000000000001, + "439": 90.90999999999994, + "440": 106.93999999999998, + "441": 94.95999999999998, + "442": 101.21000000000004, + "443": 76.48999999999998, + "444": 103.21000000000011, + "445": 79.66999999999989, + "446": 63.64000000000003, + "447": 83.44999999999993, + "448": 49.78999999999999, + "449": 90.65999999999997, + "450": 61.13000000000005, + "451": 100.85000000000002, + "452": 60.54, + "453": 85.21999999999998, + "454": 87.20000000000007, + "455": 93.86, + "456": 60.91000000000001, + "457": 89.71000000000008, + "458": 84.68000000000004, + "459": 99.51999999999997, + "460": 77.16, + "461": 92.71999999999989, + "462": 96.67999999999998, + "463": 93.40000000000006, + "464": 79.86000000000004, + "465": 103.88999999999987, + "466": 54.62000000000008, + "467": 54.690000000000055, + "468": 92.58999999999992, + "469": 59.19999999999995, + "470": 63.47999999999996, + "471": 78.86999999999989, + "472": 60.120000000000026, + "473": 85.85999999999999, + "474": 98.70000000000007, + "475": 67.90999999999994, + "476": 66.67000000000007, + "477": 102.28000000000003, + "478": 104.27000000000002, + "479": 104.14000000000003, + "480": 97.9599999999999, + "481": 92.68999999999998, + "482": 92.87999999999995, + "483": 89.50999999999995, + "484": 85.83999999999995, + "485": 83.54999999999998, + "486": 102.29000000000003, + "487": 99.46999999999991, + "488": 100.30999999999997, + "489": 84.05999999999993, + "490": 76.88999999999999, + "491": 106.40000000000006, + "492": 93.4799999999999, + "493": 103.57999999999997, + "494": 88.19999999999992, + "495": 92.16999999999987, + "496": 88.89999999999995, + "497": 104.15999999999994, + "498": 98.28, + "499": 107.52999999999997, + "500": 78.07000000000001, + "501": 103.88000000000002, + "502": 99.37000000000003, + "503": 94.39999999999998, + "504": 108.35999999999999, + "505": 100.99, + "506": 78.42, + "507": 93.80999999999997, + "508": 108.90000000000002, + "509": 89.64999999999998, + "510": 108.55999999999999, + "511": 81.81999999999996, + "512": 90.56999999999995, + "513": 94.83000000000004, + "514": 99.62000000000002, + "515": 110.9200000000001, + "516": 104.24000000000005, + "517": 110.09000000000007, + "518": 83.50999999999999, + "519": 99.98000000000002, + "520": 108.48999999999985, + "521": 105.34999999999994, + "522": 96.30999999999997, + "523": 106.87999999999997, + "524": 104.03999999999996, + "525": 98.23999999999998, + "526": 106.78000000000002, + "527": 75.90999999999995, + "528": 104.52999999999993, + "529": 101.9799999999999, + "530": 99.07999999999991, + "531": 102.55999999999995, + "532": 107.69999999999993, + "533": 92.12999999999997, + "534": 110.20000000000002, + "535": 93.24999999999994, + "536": 100.79999999999991, + "537": 102.19000000000005, + "538": 91.01000000000003, + "539": 104.14000000000003, + "540": 104.32000000000001, + "541": 75.87999999999997, + "542": 72.13999999999994, + "543": 102.33000000000001, + "544": 102.02999999999993, + "545": 93.53999999999989, + "546": 97.08999999999997, + "547": 95.48, + "548": 95.15999999999988, + "549": 97.62999999999991, + "550": 94.71999999999998, + "551": 96.79, + "552": 109.08999999999999, + "553": 99.15999999999995, + "554": 105.43999999999997, + "555": 99.43000000000002, + "556": 99.44999999999996, + "557": 102.26999999999994, + "558": 108.96999999999998, + "559": 102.85999999999999, + "560": 101.80999999999997, + "561": 99.13000000000004, + "562": 96.28999999999981, + "563": 97.94000000000004, + "564": 110.34, + "565": 106.42999999999998, + "566": 106.78000000000002, + "567": 111.13000000000014, + "568": 104.49999999999997, + "569": 108.21999999999996, + "570": 78.12999999999991, + "571": 101.58, + "572": 100.57000000000001, + "573": 74.57999999999993, + "574": 50.72000000000006, + "575": 109.27999999999997, + "576": 86.68000000000006, + "577": 109.28999999999996, + "578": 86.58000000000004, + "579": 98.42000000000004, + "580": 83.32999999999996, + "581": 76.26999999999997, + "582": 108.31999999999998, + "583": 99.02000000000008, + "584": 99.43999999999997, + "585": 93.69999999999999, + "586": 92.58999999999996, + "587": 99.98000000000005, + "588": 98.03999999999992, + "589": 82.60000000000002, + "590": 105.47999999999999, + "591": 80.39999999999989, + "592": 93.51999999999992, + "593": 69.4299999999999, + "594": 76.12999999999988, + "595": 80.21000000000005, + "596": 73.21000000000001, + "597": 88.74999999999993, + "598": 80.70999999999997, + "599": 90.69999999999997, + "600": 81.02999999999993, + "601": 60.57999999999991, + "602": 97.92999999999994, + "603": 73.92999999999998, + "604": 83.46000000000008, + "605": 82.54999999999995, + "606": 85.26999999999998, + "607": 69.3299999999999, + "608": 60.17999999999999, + "609": 87.09999999999994, + "610": 106.67000000000007, + "611": 93.97999999999988, + "612": 73.37999999999998, + "613": 64.58999999999993, + "614": 80.5599999999999, + "615": 99.38000000000002, + "616": 88.98999999999997, + "617": 75.57999999999991, + "618": 76.00000000000006, + "619": 58.75999999999999, + "620": 63.21999999999993, + "621": 62.07999999999995, + "622": 70.83999999999997, + "623": 60.44000000000003, + "624": 86.45000000000002, + "625": 69.58999999999997, + "626": 82.05999999999995, + "627": 77.79, + "628": 65.22999999999998, + "629": 71.94999999999995, + "630": 65.83000000000001, + "631": 70.28999999999996, + "632": 62.65, + "633": 72.90999999999991, + "634": 83.25999999999996, + "635": 64.75999999999996, + "636": 52.02000000000005, + "637": 73.73000000000006, + "638": 75.53999999999994, + "639": 86.05999999999997, + "640": 63.08, + "641": 84.82000000000001, + "642": 64.18999999999993, + "643": 60.64999999999999, + "644": 71.23999999999992, + "645": 58.85000000000002, + "646": 78.13999999999994, + "647": 88.07999999999994, + "648": 85.05999999999999, + "649": 80.97999999999999, + "650": 59.919999999999945, + "651": 66.49999999999987, + "652": 74.45, + "653": 66.74000000000012, + "654": 93.63999999999997, + "655": 89.36999999999995, + "656": 88.47, + "657": 93.96000000000001, + "658": 80.02999999999999, + "659": 71.99000000000002, + "660": 70.56000000000003, + "661": 102.16999999999999, + "662": 82.48999999999995, + "663": 81.85999999999999, + "664": 67.88999999999999, + "665": 78.07999999999998, + "666": 51.479999999999926, + "667": 74.87000000000008, + "668": 82.04, + "669": 56.53999999999992, + "670": 96.64000000000003, + "671": 90.94999999999995, + "672": 90.45, + "673": 66.54000000000005, + "674": 84.67, + "675": 107.12999999999992, + "676": 98.6700000000001, + "677": 92.9500000000001, + "678": 76.47000000000003, + "679": 80.52999999999997, + "680": 70.38000000000004, + "681": 84.00000000000011, + "682": 104.79000000000008, + "683": 99.92999999999998, + "684": 94.68999999999998, + "685": 99.95000000000002, + "686": 92.61000000000006, + "687": 82.13999999999996, + "688": 101.60999999999994, + "689": 99.07000000000006, + "690": 84.57999999999996, + "691": 95.8600000000001, + "692": 88.60000000000002, + "693": 83.73000000000008, + "694": 73.83, + "695": 108.27000000000001, + "696": 100.87000000000008, + "697": 105.27000000000012, + "698": 96.77000000000001, + "699": 89.7300000000001, + "700": 93.39000000000001, + "701": 94.54, + "702": 88.72000000000003, + "703": 84.92000000000009, + "704": 106.47999999999999, + "705": 95.74999999999997, + "706": 83.50999999999996, + "707": 90.57000000000004, + "708": 100.48999999999994, + "709": 103.41000000000001, + "710": 91.1600000000001, + "711": 104.74000000000005, + "712": 91.21000000000001, + "713": 79.26, + "714": 105.12000000000003, + "715": 86.2300000000001, + "716": 98.3600000000001, + "717": 92.7900000000001, + "718": 95.51000000000009, + "719": 109.90000000000013, + "720": 104.70000000000009, + "721": 87.9900000000001, + "722": 89.44000000000005, + "723": 101.9599999999999, + "724": 102.55999999999999, + "725": 83.79000000000005, + "726": 79.24999999999997, + "727": 107.15000000000005, + "728": 80.05000000000008, + "729": 107.49000000000017, + "730": 96.63, + "731": 105.88000000000008, + "732": 107.70000000000009, + "733": 89.3500000000001, + "734": 83.90000000000013, + "735": 82.75, + "736": 99.63000000000002, + "737": 104.5400000000001, + "738": 105.10999999999999, + "739": 95.79000000000009, + "740": 106.92000000000007, + "741": 97.0600000000001, + "742": 101.53000000000007, + "743": 103.48000000000002, + "744": 85.27000000000007, + "745": 75.59999999999998, + "746": 105.17000000000012, + "747": 100.48000000000002, + "748": 83.61000000000008, + "749": 107.25000000000004, + "750": 56.840000000000074, + "751": 99.72999999999995, + "752": 72.87000000000005, + "753": 87.5700000000001, + "754": 108.24000000000001, + "755": 107.35999999999999, + "756": 99.72000000000004, + "757": 100.24, + "758": 112.08000000000011, + "759": 94.98, + "760": 107.14000000000007, + "761": 110.20000000000009, + "762": 104.11000000000004, + "763": 109.82000000000014, + "764": 87.53000000000013, + "765": 85.35000000000001, + "766": 106.84000000000006, + "767": 110.1900000000001, + "768": 68.91, + "769": 103.63999999999999, + "770": 86.44000000000013, + "771": 94.47999999999999, + "772": 93.81000000000004, + "773": 114.15000000000018, + "774": 106.29000000000005, + "775": 110.21000000000008, + "776": 104.8500000000001, + "777": 106.29000000000008, + "778": 94.86000000000006, + "779": 97.29000000000005, + "780": 100.36000000000006, + "781": 96.86000000000007, + "782": 115.45000000000009, + "783": 105.95000000000002, + "784": 91.35000000000002, + "785": 96.51000000000003, + "786": 108.47000000000006, + "787": 112.44000000000005, + "788": 113.40000000000009, + "789": 106.47999999999999, + "790": 110.37000000000009, + "791": 71.37000000000006, + "792": 99.78000000000009, + "793": 56.160000000000046, + "794": 96.18999999999998, + "795": 95.39000000000003, + "796": 99.30000000000004, + "797": 112.14000000000006, + "798": 104.70000000000002, + "799": 91.49, + "800": 106.93999999999997, + "801": 84.84999999999998, + "802": 76.02000000000002, + "803": 106.90999999999993, + "804": 101.50000000000009, + "805": 95.89000000000003, + "806": 93.28, + "807": 82.80000000000003, + "808": 94.57000000000002, + "809": 106.33999999999999, + "810": 87.66000000000011, + "811": 97.2, + "812": 98.35, + "813": 111.22000000000011, + "814": 79.20000000000009, + "815": 96.70000000000009, + "816": 109.2300000000001, + "817": 107.96000000000001, + "818": 106.08000000000011, + "819": 78.23, + "820": 109.59000000000003, + "821": 112.76000000000013, + "822": 105.44000000000005, + "823": 106.04000000000005, + "824": 107.45000000000012, + "825": 85.59999999999992, + "826": 86.8499999999999, + "827": 102.86000000000008, + "828": 96.86000000000003, + "829": 92.24999999999997, + "830": 96.45, + "831": 104.06000000000006, + "832": 98.92000000000003, + "833": 98.90000000000009, + "834": 106.53000000000013, + "835": 85.58999999999997, + "836": 106.08000000000004, + "837": 104.14000000000013, + "838": 88.97000000000011, + "839": 102.71000000000004, + "840": 108.82000000000002, + "841": 108.32000000000012, + "842": 104.55000000000004, + "843": 100.3700000000001, + "844": 108.65000000000013, + "845": 109.07000000000008, + "846": 105.22000000000011, + "847": 112.66000000000017, + "848": 106.72000000000007, + "849": 108.38999999999999, + "850": 101.06000000000003, + "851": 97.02000000000007, + "852": 93.6700000000001, + "853": 109.68000000000013, + "854": 106.59000000000007, + "855": 100.99000000000007, + "856": 109.50000000000007, + "857": 92.62999999999997, + "858": 107.44000000000005, + "859": 108.06999999999998, + "860": 100.76000000000013, + "861": 95.26000000000003, + "862": 101.02, + "863": 88.91000000000003, + "864": 112.1000000000001, + "865": 65.08000000000001, + "866": 112.20000000000009, + "867": 101.91000000000001, + "868": 111.21000000000008, + "869": 106.36000000000006, + "870": 110.57000000000005, + "871": 110.53000000000016, + "872": 63.220000000000084, + "873": 108.88000000000015, + "874": 107.58000000000007, + "875": 100.64000000000004, + "876": 109.90000000000006, + "877": 112.52000000000018, + "878": 108.60000000000007, + "879": 110.27000000000002, + "880": 89.95000000000003, + "881": 81.24000000000001, + "882": 105.15000000000006, + "883": 107.81000000000013, + "884": 65.77, + "885": 108.19000000000008, + "886": 113.3400000000001, + "887": 102.62000000000005, + "888": 112.37000000000012, + "889": 102.68000000000004, + "890": 105.24000000000012, + "891": 106.27000000000002, + "892": 97.48000000000005, + "893": 105.95000000000005, + "894": 99.50000000000001, + "895": 108.3500000000001, + "896": 109.97000000000011, + "897": 98.68000000000004, + "898": 108.95000000000009, + "899": 107.53000000000004, + "900": 110.14000000000013, + "901": 104.47, + "902": 111.57000000000009, + "903": 99.88000000000002, + "904": 109.98000000000006, + "905": 111.31000000000009, + "906": 109.68000000000013, + "907": 98.51000000000003, + "908": 79.69000000000003, + "909": 98.15, + "910": 92.56000000000002, + "911": 96.29000000000005, + "912": 102.84000000000003, + "913": 95.44, + "914": 112.39000000000013, + "915": 101.91000000000001, + "916": 88.87000000000003, + "917": 110.44000000000013, + "918": 102.96000000000008, + "919": 107.64000000000003, + "920": 102.58000000000011, + "921": 102.22000000000006, + "922": 111.8600000000001, + "923": 104.65000000000006, + "924": 111.16999999999999, + "925": 99.11000000000013, + "926": 107.14999999999998, + "927": 104.17000000000003, + "928": 110.23000000000006, + "929": 99.83000000000001, + "930": 105.15000000000009, + "931": 111.58000000000001, + "932": 108.78000000000011, + "933": 101.24999999999997, + "934": 109.0600000000001, + "935": 69.79000000000005, + "936": 101.37000000000003, + "937": 108.06000000000009, + "938": 96.2400000000001, + "939": 107.15000000000009, + "940": 107.59000000000003, + "941": 100.72, + "942": 91.73000000000005, + "943": 104.58000000000004, + "944": 109.4900000000001, + "945": 104.87000000000003, + "946": 98.48000000000012, + "947": 107.53000000000011, + "948": 108.7400000000001, + "949": 96.33000000000007, + "950": 109.82000000000009, + "951": 99.71000000000004, + "952": 100.64000000000011, + "953": 107.84000000000012, + "954": 104.81000000000009, + "955": 109.61000000000013, + "956": 107.86000000000008, + "957": 102.35000000000005, + "958": 107.70000000000013, + "959": 100.60000000000001, + "960": 110.30000000000003, + "961": 110.25000000000004, + "962": 87.39000000000007, + "963": 109.01000000000003, + "964": 113.37000000000012, + "965": 101.08000000000001, + "966": 108.4800000000001, + "967": 103.98000000000002, + "968": 102.89000000000001, + "969": 101.12000000000009, + "970": 108.16000000000012, + "971": 104.08000000000001, + "972": 111.71000000000006, + "973": 72.61000000000004, + "974": 104.61999999999998, + "975": 105.24000000000005, + "976": 100.28000000000003, + "977": 82.39999999999998, + "978": 111.73000000000013, + "979": 111.9900000000001, + "980": 108.42000000000007, + "981": 99.59000000000007, + "982": 104.66000000000012, + "983": 107.31000000000006, + "984": 107.61000000000008, + "985": 110.38000000000007, + "986": 111.51000000000008, + "987": 107.72000000000006, + "988": 110.40000000000006, + "989": 108.0900000000001, + "990": 110.33000000000011, + "991": 100.7100000000001, + "992": 105.92000000000007, + "993": 98.41000000000001, + "994": 100.67999999999998, + "995": 104.59000000000006, + "996": 106.10000000000007, + "997": 107.17000000000007, + "998": 110.26000000000006, + "999": 99.21, + "1000": 107.41999999999999 + }, + "session_av_reward_per_episode": { + "1": { + "1": -11.54999999999999, + "2": -21.849999999999955, + "3": -34.29999999999997, + "4": -19.199999999999964, + "5": -40.300000000000075, + "6": -36.800000000000026, + "7": -28.300000000000008, + "8": -64.4000000000001, + "9": -52.80000000000019, + "10": -60.25000000000009, + "11": -22.249999999999954, + "12": -19.299999999999965, + "13": -22.99999999999995, + "14": -89.85000000000001, + "15": -10.500000000000004, + "16": -36.90000000000003, + "17": -35.85000000000003, + "18": -19.199999999999978, + "19": -21.499999999999957, + "20": -40.350000000000115, + "21": -75.8499999999999, + "22": -90.3, + "23": -96.15, + "24": -16.999999999999986, + "25": -16.699999999999967, + "26": -23.55000000000001, + "27": -14.199999999999983, + "28": -44.10000000000005, + "29": -99.85000000000005, + "30": -15.849999999999975, + "31": -103.45, + "32": -13.04999999999998, + "33": -44.850000000000136, + "34": -20.799999999999976, + "35": -18.749999999999968, + "36": -21.54999999999995, + "37": -35.95000000000001, + "38": -16.94999999999997, + "39": -71.55000000000004, + "40": -19.34999999999997, + "41": -33.19999999999998, + "42": -80.95, + "43": -15.64999999999997, + "44": -22.85, + "45": -16.79999999999998, + "46": -78.55000000000004, + "47": -13.399999999999979, + "48": -10.749999999999986, + "49": -20.24999999999996, + "50": -94.25000000000009, + "51": -56.900000000000034, + "52": -21.249999999999957, + "53": -19.799999999999965, + "54": -19.299999999999965, + "55": -16.999999999999964, + "56": -11.599999999999985, + "57": -35.15000000000002, + "58": -59.8000000000001, + "59": -8.650000000000002, + "60": -49.95000000000017, + "61": -17.54999999999997, + "62": -41.90000000000005, + "63": -2.099999999999989, + "64": -6.850000000000007, + "65": -45.599999999999994, + "66": -15.449999999999973, + "67": -22.449999999999992, + "68": -22.449999999999953, + "69": -22.299999999999955, + "70": -20.649999999999956, + "71": -9.59999999999999, + "72": -20.44999999999996, + "73": -49.10000000000011, + "74": -20.74999999999997, + "75": -18.499999999999964, + "76": -8.099999999999987, + "77": -19.199999999999967, + "78": -13.349999999999968, + "79": -30.900000000000013, + "80": -12.999999999999986, + "81": -13.949999999999987, + "82": -11.449999999999985, + "83": -19.899999999999963, + "84": -8.949999999999987, + "85": -14.39999999999998, + "86": -27.59999999999997, + "87": -62.599999999999994, + "88": -93.95, + "89": -96.7, + "90": -76.1, + "91": -8.199999999999982, + "92": -23.19999999999995, + "93": -20.14999999999996, + "94": -20.69999999999996, + "95": -21.09999999999996, + "96": -20.79999999999996, + "97": -19.249999999999968, + "98": -16.74999999999997, + "99": -9.749999999999995, + "100": -22.499999999999954, + "101": 2.40000000000002, + "102": 2.3499999999999615, + "103": -10.749999999999991, + "104": -29.750000000000007, + "105": -59.75000000000014, + "106": -86.25, + "107": -1.2499999999999865, + "108": -18.099999999999966, + "109": -48.0500000000001, + "110": -19.999999999999964, + "111": -16.449999999999974, + "112": -18.199999999999967, + "113": -18.70000000000001, + "114": 13.049999999999937, + "115": -15.599999999999973, + "116": -7.950000000000006, + "117": -20.64999999999996, + "118": -60.80000000000007, + "119": -15.799999999999969, + "120": 8.950000000000006, + "121": 7.800000000000014, + "122": 1.0500000000000098, + "123": -12.89999999999997, + "124": -79.15, + "125": -76.85, + "126": -5.199999999999989, + "127": -23.949999999999964, + "128": -14.099999999999984, + "129": 16.60000000000001, + "130": 0.8500000000000276, + "131": -11.499999999999993, + "132": -7.8000000000000025, + "133": -19.949999999999964, + "134": -77.99999999999997, + "135": -16.449999999999967, + "136": 1.4500000000000257, + "137": -16.34999999999997, + "138": -23.29999999999995, + "139": -14.649999999999977, + "140": 2.800000000000015, + "141": -10.399999999999993, + "142": -27.599999999999945, + "143": -30.399999999999967, + "144": -19.849999999999948, + "145": -4.4499999999999815, + "146": -15.549999999999976, + "147": -54.20000000000001, + "148": 6.650000000000046, + "149": 16.89999999999998, + "150": 8.550000000000026, + "151": -7.999999999999995, + "152": 6.650000000000028, + "153": 1.7000000000000353, + "154": -0.6499999999999777, + "155": -17.399999999999977, + "156": -49.950000000000045, + "157": -10.499999999999995, + "158": 12.700000000000035, + "159": -94.54999999999998, + "160": -27.99999999999995, + "161": -103.69999999999999, + "162": -1.1999999999999869, + "163": 9.850000000000001, + "164": -11.399999999999993, + "165": -13.499999999999988, + "166": -81.5, + "167": -86.14999999999999, + "168": -25.800000000000008, + "169": -21.899999999999956, + "170": -96.19999999999996, + "171": 28.600000000000076, + "172": -6.199999999999996, + "173": 20.800000000000008, + "174": -13.799999999999985, + "175": -20.249999999999964, + "176": -28.49999999999998, + "177": -15.099999999999968, + "178": -16.849999999999977, + "179": -21.199999999999957, + "180": -1.799999999999969, + "181": 20.400000000000063, + "182": 0.4500000000000153, + "183": -5.599999999999983, + "184": 13.70000000000007, + "185": 41.59999999999995, + "186": -4.349999999999988, + "187": 0.8500000000000101, + "188": -4.399999999999994, + "189": 10.900000000000043, + "190": -9.5, + "191": 31.899999999999746, + "192": 19.60000000000008, + "193": -17.04999999999999, + "194": 14.350000000000017, + "195": -8.50000000000001, + "196": 12.350000000000026, + "197": 18.800000000000036, + "198": 30.35000000000007, + "199": -1.3999999999999637, + "200": -19.799999999999997, + "201": 6.950000000000027, + "202": -25.04999999999999, + "203": 5.000000000000051, + "204": -77.09999999999998, + "205": -34.400000000000034, + "206": 4.050000000000061, + "207": 37.899999999999956, + "208": -67.00000000000003, + "209": 19.650000000000073, + "210": 6.800000000000031, + "211": 14.40000000000008, + "212": -19.34999999999997, + "213": 11.450000000000003, + "214": -26.499999999999957, + "215": 6.300000000000046, + "216": -38.35000000000004, + "217": 18.000000000000078, + "218": -7.499999999999994, + "219": 18.80000000000003, + "220": 22.450000000000024, + "221": 19.200000000000053, + "222": 9.050000000000061, + "223": 20.650000000000066, + "224": -5.549999999999993, + "225": 31.29999999999996, + "226": -18.849999999999962, + "227": 32.249999999999986, + "228": -34.10000000000001, + "229": 9.100000000000005, + "230": 2.1500000000000146, + "231": -42.65000000000009, + "232": 49.04999999999976, + "233": 21.099999999999977, + "234": -1.7999999999999867, + "235": -5.699999999999985, + "236": -54.15000000000003, + "237": 10.550000000000072, + "238": -0.6999999999999889, + "239": 26.700000000000077, + "240": 10.999999999999998, + "241": -9.600000000000005, + "242": 19.099999999999998, + "243": 1.6000000000000463, + "244": 1.100000000000019, + "245": -19.699999999999978, + "246": 19.199999999999985, + "247": 5.50000000000003, + "248": 0.8499999999999992, + "249": -69.84999999999998, + "250": -33.35000000000008, + "251": -54.1000000000001, + "252": 51.949999999999974, + "253": 31.200000000000053, + "254": -79.05, + "255": 6.050000000000049, + "256": 17.800000000000075, + "257": 8.950000000000063, + "258": 45.849999999999866, + "259": 21.05000000000004, + "260": 9.999999999999957, + "261": 27.049999999999994, + "262": 21.650000000000038, + "263": 0.45000000000000995, + "264": 14.650000000000045, + "265": 5.9500000000000055, + "266": 4.199999999999993, + "267": 38.39999999999983, + "268": 15.700000000000017, + "269": -22.399999999999977, + "270": -52.050000000000104, + "271": 49.89999999999983, + "272": 11.400000000000023, + "273": 57.29999999999981, + "274": 38.6999999999999, + "275": 41.44999999999997, + "276": 20.550000000000065, + "277": 55.04999999999984, + "278": 2.550000000000031, + "279": 50.349999999999746, + "280": 33.05000000000005, + "281": 80.45, + "282": 7.1000000000000005, + "283": 26.650000000000052, + "284": 6.850000000000049, + "285": 32.34999999999997, + "286": -35.65000000000002, + "287": 24.850000000000005, + "288": 49.59999999999978, + "289": 82.34999999999977, + "290": 18.70000000000005, + "291": -4.2000000000000055, + "292": -41.50000000000013, + "293": 21.15000000000001, + "294": -12.499999999999998, + "295": 60.09999999999976, + "296": -20.25, + "297": 52.64999999999983, + "298": 51.999999999999744, + "299": -2.6999999999999873, + "300": 61.79999999999981, + "301": 72.2499999999998, + "302": 44.999999999999964, + "303": 74.69999999999999, + "304": 61.29999999999977, + "305": 44.299999999999855, + "306": 32.499999999999964, + "307": 51.25000000000005, + "308": -18.400000000000016, + "309": 105.6000000000001, + "310": 80.80000000000008, + "311": 77.64999999999979, + "312": 38.799999999999805, + "313": 82.70000000000002, + "314": 62.79999999999974, + "315": 39.84999999999993, + "316": -82.29999999999998, + "317": -16.049999999999972, + "318": 67.59999999999994, + "319": 70.14999999999984, + "320": 80.79999999999978, + "321": 57.94999999999992, + "322": 72.69999999999995, + "323": 100.30000000000003, + "324": 36.449999999999996, + "325": 69.29999999999986, + "326": 93.6500000000001, + "327": 91.00000000000016, + "328": 87.64999999999995, + "329": 99.69999999999996, + "330": 22.549999999999926, + "331": -46.89999999999998, + "332": 98.35000000000011, + "333": 61.2999999999999, + "334": 89.90000000000003, + "335": 92.95000000000007, + "336": 54.849999999999845, + "337": 48.999999999999964, + "338": 60.499999999999815, + "339": 110.90000000000008, + "340": 84.69999999999999, + "341": 3.900000000000027, + "342": 107.10000000000015, + "343": 74.59999999999987, + "344": 99.30000000000007, + "345": 102.55000000000018, + "346": 70.69999999999987, + "347": 110.65000000000016, + "348": 44.89999999999975, + "349": 34.04999999999978, + "350": 100.04999999999997, + "351": 58.599999999999824, + "352": 90.75000000000003, + "353": 106.64999999999978, + "354": 37.94999999999972, + "355": 71.14999999999975, + "356": 87.74999999999994, + "357": 101.80000000000018, + "358": 98.29999999999978, + "359": 117.90000000000006, + "360": 69.54999999999986, + "361": 35.89999999999984, + "362": 101.29999999999998, + "363": 105.54999999999995, + "364": 96.30000000000014, + "365": 50.1499999999998, + "366": 40.0, + "367": 103.34999999999977, + "368": 90.99999999999974, + "369": 87.99999999999999, + "370": 115.60000000000025, + "371": 79.09999999999992, + "372": 112.10000000000018, + "373": 49.09999999999975, + "374": 84.60000000000007, + "375": 108.80000000000004, + "376": 69.64999999999979, + "377": 115.10000000000024, + "378": 64.7499999999999, + "379": 83.0, + "380": -11.149999999999991, + "381": 67.99999999999986, + "382": 82.79999999999981, + "383": 102.39999999999978, + "384": 47.99999999999983, + "385": 83.64999999999984, + "386": 96.10000000000004, + "387": -80.55000000000005, + "388": 72.0999999999999, + "389": 85.60000000000007, + "390": 112.75000000000007, + "391": 56.04999999999982, + "392": 99.10000000000015, + "393": 101.24999999999994, + "394": 112.6000000000002, + "395": 98.7, + "396": 100.79999999999987, + "397": 84.0000000000001, + "398": 111.74999999999994, + "399": 72.24999999999999, + "400": 108.00000000000013, + "401": 111.20000000000012, + "402": 107.39999999999979, + "403": 108.20000000000019, + "404": 109.35000000000008, + "405": 88.65000000000009, + "406": 106.14999999999975, + "407": 112.25000000000016, + "408": 76.14999999999986, + "409": 48.64999999999982, + "410": 105.70000000000019, + "411": 82.14999999999982, + "412": 90.79999999999998, + "413": 114.30000000000004, + "414": -0.39999999999998037, + "415": 84.64999999999999, + "416": 94.45000000000017, + "417": 112.80000000000008, + "418": 90.59999999999998, + "419": 92.04999999999974, + "420": 103.80000000000017, + "421": 102.64999999999989, + "422": -3.250000000000009, + "423": 108.60000000000016, + "424": 109.89999999999989, + "425": 111.80000000000003, + "426": 112.50000000000011, + "427": 22.049999999999976, + "428": 111.50000000000003, + "429": 109.65000000000026, + "430": 99.74999999999979, + "431": 110.65000000000009, + "432": 109.99999999999989, + "433": 94.70000000000009, + "434": 112.30000000000017, + "435": 110.50000000000006, + "436": 111.75000000000014, + "437": 101.05000000000003, + "438": 107.3500000000002, + "439": 107.3499999999999, + "440": 112.85000000000015, + "441": 106.15000000000006, + "442": 80.29999999999995, + "443": 100.3000000000001, + "444": 115.5500000000003, + "445": 110.29999999999977, + "446": 100.7, + "447": 90.50000000000011, + "448": 93.8500000000001, + "449": 82.09999999999995, + "450": 111.0500000000002, + "451": 103.95000000000013, + "452": 106.59999999999998, + "453": 104.30000000000007, + "454": 110.8000000000002, + "455": 112.8500000000001, + "456": 102.64999999999979, + "457": 104.70000000000014, + "458": 92.34999999999988, + "459": 99.80000000000003, + "460": 113.85000000000002, + "461": 106.0499999999999, + "462": 111.8500000000001, + "463": 106.40000000000012, + "464": 110.30000000000004, + "465": 105.29999999999976, + "466": 104.90000000000013, + "467": 41.599999999999945, + "468": 87.1499999999999, + "469": 108.44999999999987, + "470": 91.75000000000011, + "471": 113.10000000000008, + "472": 105.25000000000013, + "473": 106.25000000000009, + "474": 107.75000000000013, + "475": 57.09999999999995, + "476": 111.45000000000024, + "477": 103.70000000000009, + "478": 114.3000000000001, + "479": 102.3000000000001, + "480": 100.49999999999974, + "481": 47.09999999999997, + "482": 112.00000000000016, + "483": 118.6500000000002, + "484": 83.45, + "485": 115.45000000000024, + "486": 107.25000000000013, + "487": 107.85000000000011, + "488": 109.14999999999989, + "489": 98.89999999999988, + "490": 29.699999999999832, + "491": 116.25000000000027, + "492": 90.44999999999993, + "493": 100.94999999999996, + "494": 94.10000000000007, + "495": 89.04999999999993, + "496": 112.30000000000004, + "497": 116.35000000000029, + "498": 93.10000000000001, + "499": 106.70000000000012, + "500": 92.45000000000009, + "501": 108.25000000000006, + "502": 112.25000000000017, + "503": 109.10000000000025, + "504": 113.95000000000012, + "505": 101.30000000000011, + "506": 100.49999999999982, + "507": 111.29999999999997, + "508": 107.75000000000007, + "509": 84.75000000000004, + "510": 113.05000000000013, + "511": 104.8, + "512": 108.99999999999983, + "513": 115.85000000000026, + "514": 82.64999999999993, + "515": 111.50000000000017, + "516": 108.45000000000009, + "517": 118.00000000000026, + "518": 109.50000000000006, + "519": 115.20000000000024, + "520": 110.29999999999988, + "521": 110.55000000000015, + "522": 105.7999999999998, + "523": 113.75000000000018, + "524": 98.10000000000002, + "525": 108.10000000000005, + "526": 99.60000000000011, + "527": 88.50000000000007, + "528": 87.39999999999999, + "529": 108.14999999999992, + "530": 69.89999999999984, + "531": 104.35000000000018, + "532": 110.94999999999995, + "533": 117.00000000000028, + "534": 114.80000000000025, + "535": 84.70000000000006, + "536": 75.59999999999997, + "537": 113.30000000000004, + "538": 113.40000000000005, + "539": 115.00000000000013, + "540": 114.25000000000011, + "541": 110.99999999999999, + "542": -2.3999999999999826, + "543": 102.7500000000001, + "544": 108.59999999999987, + "545": 106.05000000000004, + "546": 114.10000000000004, + "547": 95.15000000000005, + "548": 102.79999999999983, + "549": 84.24999999999997, + "550": 99.19999999999987, + "551": 90.59999999999998, + "552": 111.30000000000022, + "553": 110.74999999999999, + "554": 114.85000000000015, + "555": 109.94999999999999, + "556": 97.69999999999993, + "557": 81.8, + "558": 104.99999999999991, + "559": 112.05000000000022, + "560": 112.30000000000011, + "561": 111.90000000000015, + "562": 110.04999999999976, + "563": 76.05000000000003, + "564": 114.35000000000011, + "565": 112.10000000000008, + "566": 113.4500000000001, + "567": 115.60000000000025, + "568": 91.09999999999995, + "569": 106.6000000000002, + "570": 35.999999999999766, + "571": 84.25000000000004, + "572": 116.05000000000024, + "573": 19.99999999999998, + "574": 104.0000000000002, + "575": 114.55000000000003, + "576": 112.25000000000018, + "577": 109.65000000000018, + "578": 116.35000000000026, + "579": 85.10000000000012, + "580": 94.75000000000004, + "581": 114.00000000000007, + "582": 111.24999999999999, + "583": 105.75000000000009, + "584": 105.34999999999984, + "585": 112.75000000000013, + "586": 95.90000000000006, + "587": 105.90000000000012, + "588": 102.35000000000002, + "589": 58.94999999999994, + "590": 110.69999999999993, + "591": 92.74999999999993, + "592": 111.75000000000016, + "593": 89.99999999999983, + "594": 65.89999999999993, + "595": 95.3000000000001, + "596": 101.20000000000014, + "597": 104.50000000000001, + "598": 109.60000000000014, + "599": 109.49999999999997, + "600": 98.40000000000012, + "601": 107.8499999999999, + "602": 109.05, + "603": 107.35000000000008, + "604": 105.75000000000011, + "605": 101.40000000000009, + "606": 107.90000000000002, + "607": 112.75000000000014, + "608": 99.59999999999988, + "609": 112.90000000000018, + "610": 107.24999999999993, + "611": 100.84999999999988, + "612": 105.90000000000002, + "613": 101.7500000000001, + "614": 95.8499999999999, + "615": 108.09999999999997, + "616": 104.44999999999976, + "617": 110.65000000000012, + "618": 111.20000000000013, + "619": 101.90000000000003, + "620": 98.19999999999997, + "621": 104.20000000000007, + "622": 110.60000000000015, + "623": 110.40000000000015, + "624": 115.35000000000025, + "625": 107.70000000000009, + "626": 96.10000000000005, + "627": 108.8000000000002, + "628": 108.74999999999994, + "629": 106.19999999999996, + "630": 109.85000000000004, + "631": 109.50000000000013, + "632": 113.95000000000024, + "633": 100.54999999999993, + "634": 109.90000000000005, + "635": 107.90000000000019, + "636": 105.75000000000014, + "637": 85.64999999999995, + "638": 114.95000000000014, + "639": 107.94999999999999, + "640": 113.85000000000018, + "641": 99.44999999999987, + "642": 103.24999999999991, + "643": 111.80000000000014, + "644": 91.64999999999989, + "645": 104.35000000000014, + "646": 111.25000000000004, + "647": 112.75000000000004, + "648": 114.10000000000022, + "649": 108.69999999999989, + "650": 103.84999999999987, + "651": 103.39999999999982, + "652": 74.64999999999984, + "653": 105.7500000000002, + "654": 110.39999999999998, + "655": 111.15000000000023, + "656": 109.90000000000006, + "657": 110.84999999999998, + "658": 94.09999999999991, + "659": 108.85000000000002, + "660": 108.44999999999997, + "661": 111.40000000000002, + "662": 107.35000000000005, + "663": 86.05000000000004, + "664": 25.500000000000014, + "665": 111.05000000000008, + "666": 93.99999999999999, + "667": 112.90000000000015, + "668": 105.75000000000007, + "669": 95.7999999999999, + "670": 110.80000000000013, + "671": 89.74999999999982, + "672": 113.80000000000011, + "673": 110.40000000000002, + "674": 112.30000000000007, + "675": 108.39999999999999, + "676": 113.4500000000002, + "677": 114.05000000000022, + "678": 112.80000000000007, + "679": 109.04999999999983, + "680": 110.65000000000009, + "681": 111.75000000000009, + "682": 109.20000000000005, + "683": 111.95000000000007, + "684": 112.75000000000013, + "685": 114.20000000000022, + "686": 111.79999999999997, + "687": 108.90000000000008, + "688": 104.50000000000011, + "689": 112.6500000000001, + "690": 95.84999999999981, + "691": 102.39999999999998, + "692": 110.09999999999998, + "693": 102.95000000000006, + "694": 106.10000000000005, + "695": 104.39999999999996, + "696": 110.45000000000017, + "697": 109.05000000000013, + "698": 105.70000000000012, + "699": 110.90000000000022, + "700": 106.70000000000002, + "701": 114.25000000000003, + "702": 113.00000000000011, + "703": 99.50000000000009, + "704": 110.50000000000004, + "705": 93.1499999999998, + "706": 113.45000000000019, + "707": 101.25000000000013, + "708": 113.20000000000016, + "709": 114.35000000000021, + "710": 114.75000000000023, + "711": 98.15, + "712": 96.20000000000009, + "713": 105.54999999999971, + "714": 114.70000000000024, + "715": 111.09999999999998, + "716": 107.35000000000014, + "717": 107.05000000000017, + "718": 113.20000000000026, + "719": 113.40000000000008, + "720": 88.94999999999995, + "721": 112.6000000000001, + "722": 35.699999999999974, + "723": 108.9499999999998, + "724": 106.9, + "725": 107.9499999999998, + "726": 86.30000000000001, + "727": 108.79999999999997, + "728": 107.69999999999999, + "729": 109.80000000000018, + "730": 112.90000000000015, + "731": 111.20000000000007, + "732": 111.85000000000008, + "733": 113.70000000000024, + "734": 113.10000000000018, + "735": 88.14999999999993, + "736": 102.90000000000009, + "737": 107.9, + "738": 111.05000000000011, + "739": 115.00000000000024, + "740": 105.74999999999996, + "741": 111.35000000000021, + "742": 100.60000000000007, + "743": 101.2999999999999, + "744": 107.25000000000007, + "745": 98.39999999999989, + "746": 107.70000000000014, + "747": 110.90000000000009, + "748": 109.85000000000008, + "749": 110.50000000000006, + "750": 111.85000000000016, + "751": 109.99999999999979, + "752": -17.299999999999997, + "753": 93.00000000000011, + "754": 113.80000000000011, + "755": 111.04999999999993, + "756": 63.69999999999992, + "757": 97.79999999999977, + "758": 112.85000000000004, + "759": 109.85, + "760": 96.49999999999999, + "761": 112.90000000000028, + "762": 87.54999999999995, + "763": 113.35000000000015, + "764": -3.5499999999999683, + "765": 103.79999999999994, + "766": 96.99999999999984, + "767": 113.95000000000027, + "768": -65.89999999999998, + "769": 94.65, + "770": 111.2000000000001, + "771": 112.70000000000009, + "772": 100.5500000000001, + "773": 112.00000000000021, + "774": 111.10000000000012, + "775": 117.15000000000028, + "776": 112.64999999999999, + "777": 107.69999999999995, + "778": 49.99999999999994, + "779": 103.04999999999988, + "780": 108.50000000000003, + "781": 73.99999999999986, + "782": 114.25000000000013, + "783": 115.40000000000025, + "784": 86.69999999999997, + "785": 113.35000000000015, + "786": 86.34999999999998, + "787": 108.00000000000003, + "788": 111.75000000000026, + "789": 108.45, + "790": 96.20000000000009, + "791": 90.75000000000009, + "792": 112.85000000000002, + "793": -5.299999999999993, + "794": 95.19999999999989, + "795": 103.9, + "796": 86.40000000000003, + "797": 112.65000000000005, + "798": 105.25000000000004, + "799": 115.75000000000023, + "800": 107.49999999999999, + "801": 109.80000000000005, + "802": -1.7499999999999785, + "803": 110.34999999999984, + "804": 115.55000000000017, + "805": 92.7500000000001, + "806": 109.1499999999999, + "807": 114.6000000000002, + "808": 112.10000000000004, + "809": 101.99999999999976, + "810": 112.15000000000022, + "811": 113.65000000000022, + "812": 114.55000000000003, + "813": 113.60000000000029, + "814": 105.80000000000018, + "815": 112.55000000000022, + "816": 113.00000000000018, + "817": 108.94999999999996, + "818": 116.65000000000026, + "819": 88.29999999999997, + "820": 111.80000000000004, + "821": 115.15000000000025, + "822": 112.90000000000019, + "823": 113.90000000000012, + "824": 94.50000000000013, + "825": 106.29999999999991, + "826": 98.39999999999998, + "827": 101.55, + "828": 98.09999999999981, + "829": 99.45000000000012, + "830": 92.54999999999977, + "831": 63.3499999999999, + "832": 114.90000000000023, + "833": 89.65000000000003, + "834": 114.35000000000016, + "835": -10.999999999999986, + "836": 113.00000000000007, + "837": 93.10000000000001, + "838": 110.65000000000022, + "839": 112.70000000000009, + "840": 100.59999999999977, + "841": 91.59999999999992, + "842": 110.5500000000001, + "843": 84.60000000000008, + "844": 112.75000000000017, + "845": 112.95000000000019, + "846": 106.90000000000009, + "847": 111.25000000000007, + "848": 113.55000000000025, + "849": 112.0500000000001, + "850": 80.79999999999991, + "851": 113.3000000000002, + "852": 105.75000000000013, + "853": 116.70000000000022, + "854": 103.0, + "855": 110.15000000000022, + "856": 112.55000000000004, + "857": 91.09999999999991, + "858": 114.65000000000023, + "859": 100.54999999999994, + "860": 75.8, + "861": 87.85000000000007, + "862": 102.49999999999979, + "863": 102.4, + "864": 110.05000000000018, + "865": -36.5, + "866": 113.45000000000017, + "867": 111.24999999999991, + "868": 108.7000000000002, + "869": 113.35000000000024, + "870": 113.85000000000016, + "871": 113.35000000000022, + "872": -44.799999999999955, + "873": 112.14999999999999, + "874": 113.40000000000013, + "875": 111.55000000000021, + "876": 115.60000000000025, + "877": 119.30000000000032, + "878": 97.45000000000013, + "879": 108.70000000000003, + "880": 113.75000000000018, + "881": 95.04999999999984, + "882": 90.45, + "883": 102.20000000000012, + "884": -76.15, + "885": 99.65000000000016, + "886": 109.65000000000016, + "887": 79.44999999999985, + "888": 114.50000000000026, + "889": 101.35000000000008, + "890": 111.5500000000002, + "891": 88.89999999999995, + "892": 98.60000000000014, + "893": 111.4500000000001, + "894": 100.70000000000003, + "895": 108.25, + "896": 115.45000000000026, + "897": 94.19999999999996, + "898": 89.80000000000005, + "899": 86.1999999999999, + "900": 118.9500000000003, + "901": 99.79999999999994, + "902": 115.20000000000024, + "903": 84.34999999999992, + "904": 114.00000000000017, + "905": 98.6500000000001, + "906": 111.50000000000017, + "907": 101.4500000000001, + "908": -20.749999999999986, + "909": 93.54999999999997, + "910": 85.10000000000007, + "911": 96.15, + "912": 110.79999999999991, + "913": 104.79999999999976, + "914": 105.00000000000016, + "915": 96.04999999999995, + "916": 110.19999999999996, + "917": 113.35000000000002, + "918": 102.85000000000004, + "919": 109.75000000000009, + "920": 113.10000000000026, + "921": 90.15000000000005, + "922": 113.15000000000013, + "923": 91.55000000000005, + "924": 101.80000000000004, + "925": 81.90000000000005, + "926": 110.14999999999986, + "927": 93.2500000000001, + "928": 99.89999999999985, + "929": 95.70000000000013, + "930": 90.9000000000001, + "931": 112.75000000000006, + "932": 112.9000000000002, + "933": 115.95000000000003, + "934": 109.95000000000002, + "935": 115.10000000000016, + "936": 95.5500000000001, + "937": 109.00000000000026, + "938": 39.49999999999998, + "939": 114.35000000000024, + "940": 110.65000000000019, + "941": 107.85000000000004, + "942": 80.14999999999999, + "943": 113.25000000000013, + "944": 99.10000000000005, + "945": 105.75, + "946": 104.4500000000002, + "947": 111.70000000000007, + "948": 97.10000000000012, + "949": 112.64999999999999, + "950": 113.50000000000016, + "951": 91.85000000000011, + "952": 114.00000000000027, + "953": 115.00000000000023, + "954": 97.65000000000006, + "955": 104.45000000000022, + "956": 102.44999999999996, + "957": 112.80000000000008, + "958": 87.2000000000001, + "959": 70.6499999999999, + "960": 108.04999999999974, + "961": 105.8499999999998, + "962": 81.15000000000005, + "963": 105.09999999999991, + "964": 107.10000000000016, + "965": 112.30000000000017, + "966": 101.60000000000014, + "967": 93.84999999999982, + "968": 103.25000000000001, + "969": 101.05000000000017, + "970": 107.45000000000016, + "971": 103.59999999999985, + "972": 113.79999999999988, + "973": -63.24999999999998, + "974": 107.2499999999999, + "975": 113.20000000000022, + "976": 107.35, + "977": 100.14999999999993, + "978": 114.70000000000013, + "979": 113.2000000000002, + "980": 112.10000000000016, + "981": 112.20000000000013, + "982": 88.85000000000005, + "983": 95.09999999999988, + "984": 92.95000000000002, + "985": 109.49999999999993, + "986": 104.0500000000002, + "987": 106.74999999999994, + "988": 101.55000000000011, + "989": 102.35000000000007, + "990": 101.80000000000003, + "991": 113.90000000000018, + "992": 99.04999999999984, + "993": 108.19999999999995, + "994": 80.74999999999994, + "995": 99.55000000000005, + "996": 101.90000000000018, + "997": 92.49999999999991, + "998": 114.15000000000012, + "999": 55.2499999999998, + "1000": 107.04999999999977 + }, + "2": { + "1": -6.399999999999982, + "2": -13.049999999999981, + "3": -2.949999999999971, + "4": -59.450000000000095, + "5": -22.54999999999998, + "6": -7.65, + "7": -27.64999999999999, + "8": -8.399999999999988, + "9": -50.45000000000013, + "10": -19.64999999999997, + "11": -15.499999999999973, + "12": -41.40000000000003, + "13": -20.949999999999957, + "14": -21.899999999999956, + "15": -33.40000000000003, + "16": -3.699999999999987, + "17": -29.499999999999922, + "18": -24.95, + "19": -82.79999999999995, + "20": -13.899999999999995, + "21": -13.999999999999982, + "22": 23.64999999999994, + "23": -36.85000000000005, + "24": -16.349999999999977, + "25": -76.39999999999992, + "26": -101.80000000000001, + "27": -75.75, + "28": -31.649999999999977, + "29": -1.6500000000000088, + "30": -37.349999999999994, + "31": -20.199999999999964, + "32": -7.050000000000009, + "33": -15.499999999999966, + "34": -12.649999999999988, + "35": -38.500000000000014, + "36": -5.3499999999999925, + "37": -16.549999999999955, + "38": -64.05000000000004, + "39": -66.10000000000008, + "40": -35.500000000000014, + "41": -10.999999999999993, + "42": -10.849999999999989, + "43": -36.00000000000004, + "44": -9.449999999999966, + "45": -21.34999999999996, + "46": -19.199999999999964, + "47": -19.09999999999997, + "48": -14.499999999999984, + "49": -42.60000000000006, + "50": -14.94999999999998, + "51": -86.65, + "52": -51.30000000000011, + "53": -35.650000000000006, + "54": -10.199999999999992, + "55": -19.249999999999964, + "56": -38.90000000000003, + "57": -21.599999999999955, + "58": -13.249999999999982, + "59": -17.649999999999974, + "60": -18.599999999999966, + "61": -15.099999999999984, + "62": -9.999999999999996, + "63": -83.85000000000004, + "64": -10.299999999999994, + "65": -13.14999999999999, + "66": -47.90000000000019, + "67": -50.8, + "68": -56.950000000000095, + "69": -16.299999999999976, + "70": -40.450000000000045, + "71": -91.85, + "72": -20.64999999999996, + "73": -9.749999999999991, + "74": -0.7499999999999669, + "75": -67.64999999999999, + "76": -13.799999999999988, + "77": -6.449999999999992, + "78": -20.44999999999996, + "79": -18.14999999999997, + "80": -2.2499999999999867, + "81": -18.14999999999997, + "82": -64.94999999999999, + "83": -19.94999999999996, + "84": -9.849999999999996, + "85": -1.699999999999971, + "86": -16.349999999999977, + "87": -20.899999999999974, + "88": -29.6, + "89": 1.950000000000004, + "90": -13.599999999999994, + "91": -3.099999999999965, + "92": -11.199999999999985, + "93": -97.29999999999998, + "94": -12.999999999999988, + "95": -10.199999999999992, + "96": -7.2499999999999964, + "97": -15.399999999999974, + "98": -18.14999999999997, + "99": -71.4, + "100": -66.20000000000005, + "101": 9.25000000000005, + "102": -19.199999999999967, + "103": 3.5500000000000536, + "104": -66.70000000000002, + "105": -92.95, + "106": -12.84999999999999, + "107": -6.749999999999985, + "108": -17.74999999999997, + "109": -2.249999999999985, + "110": -6.099999999999991, + "111": -63.54999999999996, + "112": 3.249999999999993, + "113": -64.44999999999999, + "114": -18.999999999999964, + "115": 23.249999999999954, + "116": -3.4000000000000075, + "117": -16.749999999999975, + "118": -15.149999999999975, + "119": -86.25, + "120": -7.499999999999985, + "121": -0.799999999999994, + "122": 0.49999999999999645, + "123": -16.24999999999998, + "124": -3.6999999999999797, + "125": 14.30000000000004, + "126": -26.049999999999937, + "127": 14.600000000000012, + "128": -14.549999999999988, + "129": -22.84999999999995, + "130": -28.79999999999994, + "131": -4.1, + "132": -78.79999999999998, + "133": -78.54999999999987, + "134": 7.8000000000000425, + "135": -23.54999999999995, + "136": -37.64999999999999, + "137": -18.04999999999997, + "138": 1.9999999999999984, + "139": -62.3500000000001, + "140": -20.349999999999962, + "141": -3.4499999999999718, + "142": -6.04999999999999, + "143": 13.750000000000053, + "144": -15.899999999999974, + "145": -19.749999999999986, + "146": -14.449999999999974, + "147": -13.699999999999958, + "148": -87.99999999999997, + "149": -10.99999999999999, + "150": 47.199999999999825, + "151": -13.049999999999985, + "152": 3.550000000000023, + "153": -18.799999999999965, + "154": -51.95000000000017, + "155": -90.15, + "156": -11.599999999999987, + "157": -57.700000000000095, + "158": 14.15000000000003, + "159": -73.35, + "160": -29.150000000000016, + "161": -53.6, + "162": 20.34999999999999, + "163": 2.3500000000000183, + "164": 6.450000000000037, + "165": -46.45, + "166": -65.5000000000001, + "167": -19.399999999999963, + "168": -5.749999999999993, + "169": 28.449999999999825, + "170": -86.45, + "171": -11.399999999999983, + "172": -4.550000000000002, + "173": -102.95, + "174": 14.800000000000082, + "175": 14.899999999999988, + "176": 27.74999999999988, + "177": 12.050000000000065, + "178": -81.35, + "179": -9.549999999999988, + "180": -55.7, + "181": 51.899999999999785, + "182": -102.2, + "183": -60.34999999999997, + "184": 38.04999999999984, + "185": -91.35000000000002, + "186": -30.599999999999998, + "187": -12.200000000000001, + "188": 38.84999999999976, + "189": 12.449999999999964, + "190": 22.599999999999923, + "191": -8.299999999999995, + "192": -69.19999999999995, + "193": 41.04999999999996, + "194": -30.199999999999967, + "195": 27.249999999999886, + "196": -20.44999999999996, + "197": 28.649999999999824, + "198": -80.70000000000002, + "199": -82.5, + "200": 3.1000000000000503, + "201": -36.900000000000055, + "202": -67.54999999999998, + "203": 14.700000000000063, + "204": -82.34999999999995, + "205": 19.899999999999913, + "206": -80.00000000000001, + "207": 0.6500000000000454, + "208": 2.2500000000000435, + "209": 31.349999999999753, + "210": -82.65, + "211": -78.09999999999997, + "212": -34.0, + "213": -45.349999999999994, + "214": -14.899999999999984, + "215": 7.050000000000028, + "216": -90.8, + "217": 43.7999999999998, + "218": -3.3499999999999757, + "219": 5.800000000000023, + "220": -4.899999999999984, + "221": 23.14999999999988, + "222": -8.349999999999994, + "223": 24.799999999999866, + "224": -85.80000000000001, + "225": -17.049999999999976, + "226": -2.150000000000013, + "227": 61.79999999999973, + "228": -65.1, + "229": 13.850000000000026, + "230": 3.2000000000000384, + "231": -30.399999999999984, + "232": 24.349999999999884, + "233": -15.149999999999988, + "234": 9.20000000000001, + "235": -20.349999999999962, + "236": 2.4000000000000394, + "237": 16.700000000000028, + "238": -18.59999999999996, + "239": 12.850000000000051, + "240": -2.399999999999972, + "241": 0.9000000000000248, + "242": 52.34999999999981, + "243": -64.15, + "244": -5.950000000000009, + "245": 6.300000000000021, + "246": 39.049999999999756, + "247": 2.4000000000000377, + "248": -21.29999999999995, + "249": -15.049999999999978, + "250": -74.35, + "251": -29.05000000000004, + "252": 4.1500000000000625, + "253": -17.999999999999968, + "254": -84.05, + "255": -22.749999999999947, + "256": -78.49999999999999, + "257": 0.649999999999993, + "258": 30.39999999999979, + "259": 71.44999999999986, + "260": -14.949999999999989, + "261": 24.30000000000006, + "262": 4.800000000000029, + "263": 58.749999999999815, + "264": -48.70000000000003, + "265": -1.0499999999999634, + "266": 37.19999999999998, + "267": 14.65000000000008, + "268": -29.999999999999968, + "269": 57.64999999999978, + "270": 17.40000000000003, + "271": -72.49999999999999, + "272": 83.10000000000008, + "273": -62.150000000000055, + "274": -81.75000000000009, + "275": 41.29999999999977, + "276": -48.949999999999996, + "277": -4.199999999999985, + "278": 6.850000000000071, + "279": 11.80000000000004, + "280": -0.24999999999997802, + "281": 41.699999999999925, + "282": 58.64999999999977, + "283": -72.14999999999998, + "284": -84.65, + "285": 42.9499999999998, + "286": -6.349999999999988, + "287": 52.749999999999886, + "288": -54.799999999999926, + "289": -29.90000000000001, + "290": 4.600000000000045, + "291": 43.4999999999999, + "292": 0.10000000000002762, + "293": 9.75000000000005, + "294": 29.100000000000005, + "295": -66.65, + "296": -6.549999999999944, + "297": 13.95000000000002, + "298": 58.79999999999974, + "299": 65.69999999999986, + "300": 76.29999999999976, + "301": -14.349999999999973, + "302": -7.650000000000009, + "303": 8.150000000000011, + "304": 84.74999999999999, + "305": -53.19999999999999, + "306": 65.54999999999993, + "307": -91.39999999999998, + "308": -16.549999999999965, + "309": -44.44999999999998, + "310": -34.95000000000003, + "311": 29.299999999999834, + "312": -61.20000000000003, + "313": -12.900000000000055, + "314": 65.29999999999987, + "315": 13.300000000000079, + "316": 73.99999999999994, + "317": -53.900000000000105, + "318": 10.350000000000014, + "319": 44.94999999999996, + "320": 48.7999999999998, + "321": -73.30000000000001, + "322": 40.9999999999998, + "323": -9.99999999999999, + "324": 30.10000000000005, + "325": -39.75000000000014, + "326": 70.64999999999993, + "327": 89.44999999999997, + "328": 44.74999999999988, + "329": -13.549999999999969, + "330": -38.300000000000075, + "331": -44.699999999999946, + "332": 82.59999999999981, + "333": 86.55000000000001, + "334": 73.89999999999984, + "335": -70.1, + "336": 4.750000000000067, + "337": 69.69999999999983, + "338": 45.44999999999983, + "339": 13.249999999999915, + "340": 90.34999999999974, + "341": 92.34999999999981, + "342": -83.00000000000007, + "343": 2.499999999999984, + "344": -53.49999999999997, + "345": 86.44999999999978, + "346": 71.24999999999977, + "347": 62.19999999999985, + "348": 39.39999999999982, + "349": 28.700000000000074, + "350": 63.29999999999988, + "351": 16.2499999999998, + "352": 57.49999999999982, + "353": 77.64999999999976, + "354": 70.29999999999994, + "355": 76.64999999999988, + "356": 1.5000000000000495, + "357": 88.6, + "358": -10.449999999999978, + "359": -9.249999999999998, + "360": -69.69999999999996, + "361": -57.64999999999997, + "362": 103.10000000000001, + "363": 22.64999999999991, + "364": -43.30000000000015, + "365": -30.050000000000058, + "366": 66.69999999999985, + "367": 46.89999999999986, + "368": 17.749999999999975, + "369": 10.150000000000025, + "370": 3.949999999999926, + "371": 66.29999999999978, + "372": 19.400000000000016, + "373": 42.549999999999905, + "374": 13.649999999999972, + "375": 102.2999999999998, + "376": 13.250000000000039, + "377": -30.49999999999997, + "378": 63.4999999999998, + "379": 108.4000000000002, + "380": -78.79999999999998, + "381": 93.14999999999976, + "382": 50.49999999999977, + "383": -30.74999999999998, + "384": 96.70000000000016, + "385": 77.84999999999987, + "386": 32.79999999999999, + "387": 99.89999999999978, + "388": -23.850000000000033, + "389": -65.30000000000001, + "390": 103.59999999999974, + "391": -45.84999999999997, + "392": 111.95000000000027, + "393": -17.20000000000004, + "394": 43.899999999999814, + "395": 81.5999999999998, + "396": 21.04999999999997, + "397": -25.349999999999987, + "398": 111.10000000000025, + "399": 88.19999999999989, + "400": 48.84999999999974, + "401": 98.25000000000026, + "402": 15.000000000000018, + "403": 78.5999999999998, + "404": -13.099999999999959, + "405": 77.39999999999979, + "406": 4.450000000000009, + "407": 40.99999999999988, + "408": -20.99999999999998, + "409": 103.54999999999974, + "410": 75.99999999999986, + "411": 93.19999999999978, + "412": 50.09999999999988, + "413": -32.39999999999997, + "414": -72.1, + "415": -26.10000000000001, + "416": 93.24999999999997, + "417": -49.74999999999996, + "418": 57.64999999999984, + "419": 4.049999999999951, + "420": -2.6499999999999835, + "421": 83.09999999999975, + "422": 107.89999999999988, + "423": -73.90000000000002, + "424": 50.2, + "425": 59.599999999999795, + "426": -30.20000000000003, + "427": -35.250000000000014, + "428": 18.899999999999945, + "429": 105.20000000000016, + "430": 105.79999999999991, + "431": 64.49999999999977, + "432": 113.85000000000018, + "433": 105.95000000000009, + "434": 35.99999999999978, + "435": 11.000000000000027, + "436": 107.04999999999973, + "437": 105.54999999999987, + "438": 99.94999999999979, + "439": 67.79999999999987, + "440": 107.40000000000009, + "441": 50.049999999999756, + "442": 114.15000000000012, + "443": 91.04999999999978, + "444": 90.20000000000006, + "445": 104.49999999999977, + "446": 14.499999999999996, + "447": 82.30000000000003, + "448": -0.3500000000000014, + "449": 83.05000000000003, + "450": -75.39999999999999, + "451": 108.79999999999976, + "452": -10.95000000000001, + "453": 38.299999999999976, + "454": 101.40000000000015, + "455": 33.74999999999989, + "456": 76.15000000000015, + "457": 98.95000000000009, + "458": 105.9, + "459": 87.2500000000001, + "460": 105.19999999999976, + "461": 78.94999999999976, + "462": 71.39999999999988, + "463": 95.70000000000002, + "464": 99.30000000000005, + "465": 105.74999999999986, + "466": -26.79999999999999, + "467": 2.95000000000001, + "468": 87.59999999999977, + "469": -63.69999999999996, + "470": -72.9, + "471": 105.09999999999977, + "472": 38.449999999999946, + "473": 21.499999999999964, + "474": 109.75000000000021, + "475": -36.09999999999997, + "476": 8.399999999999947, + "477": 90.45000000000022, + "478": 108.75000000000013, + "479": 105.75000000000017, + "480": 84.24999999999984, + "481": 98.89999999999989, + "482": 79.29999999999983, + "483": 77.14999999999976, + "484": 35.54999999999984, + "485": 60.04999999999994, + "486": 70.09999999999997, + "487": 99.59999999999977, + "488": 69.19999999999995, + "489": 102.74999999999979, + "490": 26.799999999999994, + "491": 107.05000000000001, + "492": 104.34999999999994, + "493": 112.70000000000016, + "494": 110.1999999999998, + "495": 97.59999999999974, + "496": 70.64999999999993, + "497": 101.49999999999976, + "498": 108.00000000000021, + "499": 104.54999999999974, + "500": 34.499999999999964, + "501": 84.99999999999997, + "502": 68.19999999999995, + "503": 63.499999999999794, + "504": 105.14999999999995, + "505": 107.39999999999974, + "506": 73.39999999999999, + "507": 52.84999999999995, + "508": 105.94999999999997, + "509": 56.59999999999975, + "510": 108.74999999999996, + "511": 38.699999999999946, + "512": 38.35, + "513": 73.95000000000019, + "514": 107.09999999999972, + "515": 117.30000000000028, + "516": 111.35000000000024, + "517": 111.69999999999997, + "518": 38.9499999999999, + "519": 74.54999999999995, + "520": 111.64999999999989, + "521": 102.5999999999998, + "522": 38.34999999999992, + "523": 105.34999999999984, + "524": 108.94999999999976, + "525": 86.09999999999984, + "526": 111.19999999999987, + "527": 66.79999999999987, + "528": 110.89999999999988, + "529": 108.79999999999991, + "530": 104.64999999999972, + "531": 101.99999999999973, + "532": 106.74999999999983, + "533": 28.299999999999915, + "534": 101.89999999999976, + "535": 104.34999999999975, + "536": 110.64999999999976, + "537": 111.60000000000015, + "538": 80.00000000000003, + "539": 102.84999999999977, + "540": 91.85000000000012, + "541": 100.29999999999978, + "542": 66.94999999999989, + "543": 96.14999999999988, + "544": 110.19999999999987, + "545": 74.89999999999995, + "546": 46.999999999999865, + "547": 89.19999999999982, + "548": 72.54999999999984, + "549": 79.7499999999998, + "550": 102.65000000000002, + "551": 80.10000000000007, + "552": 107.59999999999974, + "553": 63.79999999999991, + "554": 99.34999999999977, + "555": 60.99999999999995, + "556": 91.54999999999991, + "557": 103.84999999999974, + "558": 109.8499999999998, + "559": 91.59999999999981, + "560": 82.89999999999975, + "561": 101.25000000000003, + "562": 103.34999999999977, + "563": 87.49999999999982, + "564": 105.99999999999979, + "565": 103.64999999999984, + "566": 108.54999999999995, + "567": 110.15000000000003, + "568": 104.24999999999999, + "569": 107.84999999999972, + "570": 109.09999999999975, + "571": 95.24999999999976, + "572": 101.54999999999997, + "573": 86.64999999999979, + "574": -66.35000000000007, + "575": 106.24999999999986, + "576": 105.69999999999975, + "577": 104.74999999999977, + "578": 95.59999999999988, + "579": 111.15000000000026, + "580": 27.09999999999997, + "581": 5.250000000000066, + "582": 102.19999999999976, + "583": 47.849999999999746, + "584": 96.19999999999995, + "585": 77.54999999999978, + "586": 38.64999999999988, + "587": 74.29999999999973, + "588": 98.99999999999993, + "589": 31.099999999999813, + "590": 76.94999999999976, + "591": 92.84999999999982, + "592": 93.54999999999976, + "593": 34.49999999999976, + "594": 96.9999999999999, + "595": 95.80000000000021, + "596": 82.19999999999976, + "597": 111.04999999999993, + "598": 91.09999999999974, + "599": 82.55000000000014, + "600": 87.04999999999977, + "601": 29.349999999999866, + "602": 95.04999999999986, + "603": -7.5499999999999945, + "604": 109.90000000000008, + "605": 100.39999999999972, + "606": 104.64999999999974, + "607": 104.64999999999972, + "608": 17.300000000000086, + "609": 106.59999999999975, + "610": 109.35000000000012, + "611": 104.79999999999976, + "612": 116.90000000000019, + "613": 77.89999999999986, + "614": 86.15000000000005, + "615": 111.14999999999996, + "616": 109.89999999999984, + "617": 84.94999999999973, + "618": 117.05000000000025, + "619": -31.700000000000003, + "620": 40.99999999999973, + "621": 100.19999999999997, + "622": 98.44999999999979, + "623": 82.70000000000003, + "624": 94.35000000000011, + "625": 101.90000000000012, + "626": 103.04999999999974, + "627": 74.29999999999993, + "628": 99.94999999999999, + "629": 102.54999999999991, + "630": 36.699999999999996, + "631": 92.14999999999998, + "632": 86.00000000000004, + "633": 92.69999999999978, + "634": 79.59999999999981, + "635": 55.09999999999986, + "636": 52.00000000000002, + "637": 102.95000000000017, + "638": 72.8499999999999, + "639": 105.40000000000015, + "640": 101.70000000000006, + "641": 104.05000000000017, + "642": 103.95000000000009, + "643": -16.20000000000005, + "644": 110.04999999999998, + "645": 107.75000000000013, + "646": 36.04999999999999, + "647": 108.74999999999976, + "648": 102.2999999999999, + "649": 107.74999999999974, + "650": 90.19999999999979, + "651": 102.19999999999986, + "652": 95.84999999999987, + "653": 113.85000000000015, + "654": 99.19999999999975, + "655": 98.44999999999973, + "656": 102.64999999999976, + "657": 102.89999999999995, + "658": 93.75000000000001, + "659": 93.55, + "660": 96.44999999999997, + "661": 104.69999999999973, + "662": 104.49999999999982, + "663": 62.39999999999992, + "664": 81.55000000000001, + "665": 80.20000000000002, + "666": 43.5999999999998, + "667": 106.8500000000002, + "668": 111.30000000000014, + "669": 66.44999999999995, + "670": 95.45000000000005, + "671": 99.15000000000015, + "672": 103.04999999999977, + "673": 118.3500000000003, + "674": 114.70000000000024, + "675": 107.94999999999982, + "676": 97.70000000000014, + "677": 116.25000000000023, + "678": 110.45000000000002, + "679": 114.7500000000002, + "680": -3.7499999999999662, + "681": 113.90000000000023, + "682": 105.10000000000015, + "683": 93.79999999999978, + "684": 108.25000000000021, + "685": 106.14999999999985, + "686": 120.05000000000034, + "687": 83.89999999999988, + "688": 97.89999999999993, + "689": 112.85000000000018, + "690": 112.2000000000001, + "691": 98.25000000000017, + "692": 48.94999999999988, + "693": 117.30000000000022, + "694": 100.25000000000007, + "695": 106.8999999999998, + "696": 74.70000000000005, + "697": 78.60000000000001, + "698": 113.10000000000002, + "699": 84.25000000000003, + "700": 116.65000000000019, + "701": 112.60000000000016, + "702": 84.95000000000003, + "703": 117.05000000000025, + "704": 104.69999999999973, + "705": 113.95000000000016, + "706": 98.49999999999977, + "707": 103.34999999999978, + "708": 105.49999999999972, + "709": 88.59999999999984, + "710": 111.25000000000004, + "711": 112.74999999999999, + "712": 80.70000000000005, + "713": 112.60000000000011, + "714": 81.99999999999994, + "715": 100.60000000000015, + "716": 82.15000000000005, + "717": 63.19999999999997, + "718": 64.04999999999988, + "719": 114.75000000000027, + "720": 117.15000000000023, + "721": 91.30000000000005, + "722": 95.45000000000003, + "723": 109.84999999999995, + "724": 114.1499999999999, + "725": 70.25000000000026, + "726": 71.10000000000008, + "727": 95.69999999999997, + "728": 64.30000000000004, + "729": 94.95000000000009, + "730": 63.09999999999995, + "731": 88.69999999999989, + "732": 92.04999999999993, + "733": 73.95, + "734": 4.449999999999994, + "735": 107.44999999999986, + "736": 104.00000000000007, + "737": 102.55000000000018, + "738": 105.04999999999974, + "739": 55.64999999999993, + "740": 117.85000000000026, + "741": 28.799999999999834, + "742": 116.15000000000026, + "743": 103.49999999999999, + "744": 85.19999999999996, + "745": 113.15000000000006, + "746": 101.05000000000014, + "747": 112.95000000000006, + "748": 17.45000000000006, + "749": 112.59999999999992, + "750": 43.10000000000004, + "751": 82.15000000000003, + "752": 100.04999999999974, + "753": 112.15000000000018, + "754": 103.84999999999978, + "755": 108.9999999999998, + "756": 94.64999999999995, + "757": 82.75000000000006, + "758": 111.50000000000007, + "759": 100.3999999999998, + "760": 114.70000000000024, + "761": 113.70000000000006, + "762": 110.0500000000002, + "763": 110.35000000000018, + "764": 113.45000000000019, + "765": 51.999999999999915, + "766": 113.55000000000025, + "767": 110.19999999999979, + "768": 90.59999999999992, + "769": 97.54999999999993, + "770": 105.10000000000016, + "771": 78.29999999999993, + "772": 82.70000000000006, + "773": 118.50000000000023, + "774": 84.29999999999997, + "775": 111.75000000000007, + "776": 101.05000000000008, + "777": 110.94999999999999, + "778": 103.75000000000014, + "779": 114.70000000000012, + "780": 76.00000000000004, + "781": 87.35000000000008, + "782": 115.65000000000026, + "783": 106.04999999999974, + "784": 108.80000000000011, + "785": 94.14999999999988, + "786": 112.30000000000007, + "787": 106.75000000000007, + "788": 111.49999999999994, + "789": 98.70000000000005, + "790": 115.30000000000027, + "791": 49.34999999999987, + "792": 98.00000000000016, + "793": 79.20000000000003, + "794": 110.05000000000001, + "795": 82.30000000000011, + "796": 90.89999999999989, + "797": 117.15000000000028, + "798": 88.29999999999995, + "799": 79.7499999999999, + "800": 112.39999999999993, + "801": 110.60000000000001, + "802": 95.85000000000007, + "803": 105.99999999999972, + "804": 102.05000000000017, + "805": 113.40000000000008, + "806": 41.99999999999995, + "807": 91.09999999999994, + "808": 72.64999999999993, + "809": 105.59999999999995, + "810": 33.50000000000001, + "811": 88.89999999999999, + "812": 108.04999999999997, + "813": 103.95000000000007, + "814": 106.35000000000007, + "815": 45.99999999999995, + "816": 114.50000000000021, + "817": 112.1500000000001, + "818": 109.50000000000003, + "819": 106.10000000000007, + "820": 95.29999999999998, + "821": 115.05000000000025, + "822": 94.19999999999992, + "823": 105.4499999999999, + "824": 115.3000000000002, + "825": 108.84999999999998, + "826": 107.54999999999986, + "827": 113.85000000000007, + "828": 92.00000000000014, + "829": 108.69999999999979, + "830": 110.2000000000001, + "831": 113.55000000000021, + "832": 113.70000000000014, + "833": 90.20000000000019, + "834": 115.20000000000022, + "835": 109.89999999999993, + "836": 115.05000000000018, + "837": 116.25000000000024, + "838": 11.550000000000006, + "839": 71.39999999999995, + "840": 114.2000000000002, + "841": 112.40000000000023, + "842": 92.60000000000005, + "843": 114.40000000000022, + "844": 113.85000000000024, + "845": 104.0000000000001, + "846": 96.20000000000002, + "847": 108.60000000000016, + "848": 92.45000000000005, + "849": 101.94999999999985, + "850": 111.60000000000018, + "851": 112.80000000000024, + "852": 93.45000000000007, + "853": 113.55000000000008, + "854": 100.80000000000018, + "855": 80.69999999999999, + "856": 110.65000000000022, + "857": 99.59999999999992, + "858": 81.89999999999996, + "859": 105.8499999999998, + "860": 115.15000000000025, + "861": 78.1500000000001, + "862": 92.3, + "863": 73.24999999999997, + "864": 113.15000000000005, + "865": 27.449999999999992, + "866": 115.00000000000023, + "867": 86.60000000000002, + "868": 113.90000000000025, + "869": 70.24999999999983, + "870": 101.59999999999994, + "871": 102.25000000000016, + "872": 115.85000000000025, + "873": 109.10000000000025, + "874": 108.30000000000021, + "875": 58.99999999999993, + "876": 110.84999999999991, + "877": 115.00000000000024, + "878": 110.45000000000006, + "879": 89.65000000000009, + "880": 72.64999999999998, + "881": 60.099999999999895, + "882": 112.30000000000011, + "883": 115.50000000000017, + "884": 70.54999999999993, + "885": 111.44999999999996, + "886": 107.50000000000018, + "887": 95.70000000000012, + "888": 116.40000000000025, + "889": 93.05000000000003, + "890": 113.40000000000012, + "891": 111.7, + "892": 107.55000000000004, + "893": 92.69999999999982, + "894": 72.94999999999997, + "895": 109.05000000000013, + "896": 97.10000000000014, + "897": 60.09999999999993, + "898": 114.35000000000022, + "899": 114.60000000000012, + "900": 91.70000000000007, + "901": 80.99999999999996, + "902": 99.75000000000006, + "903": 87.1, + "904": 93.65, + "905": 113.45000000000014, + "906": 108.20000000000013, + "907": 93.8500000000001, + "908": 72.44999999999985, + "909": 61.899999999999935, + "910": 110.7500000000001, + "911": 93.50000000000009, + "912": 113.50000000000003, + "913": 80.35000000000025, + "914": 113.25000000000014, + "915": 99.0, + "916": 104.85000000000016, + "917": 115.60000000000026, + "918": 101.25000000000011, + "919": 97.80000000000007, + "920": 77.39999999999998, + "921": 111.40000000000023, + "922": 114.05000000000024, + "923": 116.60000000000028, + "924": 106.44999999999973, + "925": 107.90000000000018, + "926": 87.4, + "927": 113.7500000000002, + "928": 114.5000000000002, + "929": 89.90000000000008, + "930": 112.95000000000016, + "931": 104.89999999999985, + "932": 107.45000000000005, + "933": 81.64999999999985, + "934": 114.35000000000021, + "935": 31.199999999999974, + "936": 71.99999999999999, + "937": 104.3500000000002, + "938": 118.85000000000015, + "939": 115.10000000000015, + "940": 113.0999999999999, + "941": 111.15000000000005, + "942": 101.95000000000019, + "943": 111.80000000000005, + "944": 115.45000000000024, + "945": 92.1500000000001, + "946": 52.54999999999997, + "947": 103.30000000000018, + "948": 108.40000000000022, + "949": 37.39999999999997, + "950": 92.20000000000017, + "951": 94.00000000000006, + "952": 113.50000000000009, + "953": 115.80000000000025, + "954": 110.95000000000023, + "955": 112.4500000000002, + "956": 114.40000000000025, + "957": 80.15000000000005, + "958": 116.65000000000023, + "959": 104.60000000000018, + "960": 115.60000000000024, + "961": 113.90000000000019, + "962": 113.25000000000014, + "963": 110.95000000000006, + "964": 113.80000000000022, + "965": 64.64999999999992, + "966": 114.40000000000023, + "967": 98.65000000000006, + "968": 80.64999999999998, + "969": 73.05000000000001, + "970": 86.80000000000011, + "971": 90.40000000000008, + "972": 112.95000000000017, + "973": 84.34999999999985, + "974": 73.14999999999998, + "975": 91.9999999999999, + "976": 74.15000000000002, + "977": 68.34999999999994, + "978": 105.45000000000006, + "979": 114.00000000000016, + "980": 115.10000000000025, + "981": 111.00000000000006, + "982": 102.45000000000012, + "983": 99.00000000000016, + "984": 112.80000000000011, + "985": 113.45000000000012, + "986": 112.0, + "987": 111.6500000000001, + "988": 114.50000000000001, + "989": 108.6000000000002, + "990": 116.05000000000018, + "991": 73.75, + "992": 116.35000000000026, + "993": 45.64999999999986, + "994": 104.74999999999976, + "995": 89.35000000000004, + "996": 90.15000000000008, + "997": 107.40000000000019, + "998": 99.1999999999999, + "999": 107.45000000000007, + "1000": 111.90000000000013 + }, + "3": { + "1": -53.550000000000075, + "2": -20.14999999999996, + "3": -35.59999999999995, + "4": -57.150000000000084, + "5": -28.14999999999997, + "6": -4.350000000000001, + "7": -19.74999999999996, + "8": -18.84999999999997, + "9": -17.199999999999985, + "10": -11.59999999999999, + "11": -2.149999999999972, + "12": -42.650000000000176, + "13": -15.249999999999966, + "14": -12.549999999999978, + "15": -54.75, + "16": -19.649999999999963, + "17": -57.65000000000006, + "18": -52.050000000000075, + "19": -14.949999999999982, + "20": -81.44999999999982, + "21": -15.399999999999979, + "22": -20.099999999999962, + "23": -43.95000000000005, + "24": -83.29999999999993, + "25": -23.599999999999977, + "26": -20.59999999999997, + "27": -0.949999999999972, + "28": -17.14999999999997, + "29": -3.2499999999999787, + "30": -10.849999999999998, + "31": -11.34999999999999, + "32": -24.950000000000035, + "33": -11.799999999999992, + "34": -86.99999999999994, + "35": -17.499999999999968, + "36": -13.549999999999981, + "37": -53.10000000000008, + "38": -14.849999999999984, + "39": -10.99999999999999, + "40": -44.30000000000016, + "41": -17.8, + "42": -21.39999999999995, + "43": -29.700000000000017, + "44": -13.69999999999999, + "45": -14.099999999999987, + "46": -22.049999999999955, + "47": -17.249999999999975, + "48": -15.299999999999986, + "49": -19.549999999999965, + "50": -1.2499999999999953, + "51": -23.44999999999995, + "52": -17.249999999999954, + "53": -45.250000000000185, + "54": -77.59999999999997, + "55": -46.95, + "56": -77.7, + "57": -12.949999999999985, + "58": -46.89999999999995, + "59": -7.849999999999997, + "60": -41.199999999999974, + "61": -9.000000000000007, + "62": -20.649999999999956, + "63": -13.999999999999972, + "64": -2.8499999999999837, + "65": -6.049999999999981, + "66": -52.10000000000007, + "67": -16.099999999999977, + "68": -18.399999999999967, + "69": -20.999999999999957, + "70": 12.600000000000046, + "71": -16.499999999999975, + "72": -38.150000000000006, + "73": -17.74999999999997, + "74": -12.64999999999999, + "75": -68.99999999999994, + "76": -19.99999999999996, + "77": -5.149999999999989, + "78": -101.79999999999998, + "79": 4.350000000000045, + "80": -87.85000000000001, + "81": -44.49999999999999, + "82": -46.5, + "83": -19.99999999999996, + "84": -6.700000000000016, + "85": -10.949999999999992, + "86": 7.9500000000000535, + "87": -8.700000000000001, + "88": -77.29999999999998, + "89": 0.25000000000000466, + "90": -89.59999999999994, + "91": -83.45, + "92": -8.700000000000001, + "93": -91.20000000000002, + "94": -13.899999999999983, + "95": -69.45000000000006, + "96": -7.9499999999999975, + "97": -21.549999999999958, + "98": -7.999999999999985, + "99": -15.599999999999978, + "100": -52.89999999999998, + "101": -42.95000000000012, + "102": -13.949999999999983, + "103": -62.89999999999999, + "104": 2.9000000000000288, + "105": -79.65, + "106": 4.55000000000002, + "107": -35.60000000000007, + "108": -10.049999999999988, + "109": -68.25000000000003, + "110": -1.1999999999999844, + "111": -0.7999999999999656, + "112": -20.549999999999955, + "113": -19.79999999999996, + "114": -11.399999999999993, + "115": 11.500000000000021, + "116": -18.44999999999997, + "117": -26.44999999999998, + "118": 2.3500000000000147, + "119": -0.2499999999999707, + "120": -13.09999999999998, + "121": -93.8, + "122": -34.90000000000002, + "123": -73.30000000000001, + "124": -19.69999999999996, + "125": -98.69999999999999, + "126": -67.85000000000001, + "127": -19.09999999999997, + "128": -70.14999999999998, + "129": -10.450000000000003, + "130": -5.6999999999999975, + "131": -14.79999999999997, + "132": 40.94999999999987, + "133": -6.749999999999996, + "134": -13.299999999999988, + "135": -20.549999999999955, + "136": -12.849999999999987, + "137": -26.14999999999998, + "138": -4.9999999999999805, + "139": 3.7500000000000444, + "140": -18.09999999999997, + "141": -3.34999999999998, + "142": -8.399999999999988, + "143": -1.7499999999999825, + "144": -7.99999999999999, + "145": -92.65, + "146": 28.699999999999925, + "147": 32.649999999999764, + "148": -22.350000000000023, + "149": -72.85, + "150": 40.84999999999977, + "151": -55.249999999999964, + "152": 17.95000000000005, + "153": 4.500000000000005, + "154": -26.999999999999982, + "155": -5.649999999999988, + "156": 23.549999999999976, + "157": -2.4499999999999433, + "158": -12.249999999999988, + "159": -19.29999999999997, + "160": -31.249999999999996, + "161": 5.600000000000037, + "162": -20.899999999999956, + "163": -12.149999999999991, + "164": -2.399999999999962, + "165": -17.69999999999997, + "166": 51.1499999999999, + "167": -68.9, + "168": -24.700000000000003, + "169": -42.05, + "170": 58.249999999999815, + "171": -7.999999999999994, + "172": 0.8500000000000347, + "173": 0.5499999999999936, + "174": 52.94999999999982, + "175": -1.950000000000001, + "176": -83.05, + "177": -68.65000000000002, + "178": -52.09999999999995, + "179": -25.04999999999999, + "180": 13.950000000000019, + "181": -64.8000000000001, + "182": 25.899999999999892, + "183": 12.50000000000006, + "184": 18.750000000000032, + "185": -12.45000000000004, + "186": -83.85, + "187": 24.15000000000003, + "188": -32.70000000000004, + "189": -55.05000000000005, + "190": -78.85, + "191": -0.6999999999999784, + "192": -14.399999999999991, + "193": -13.199999999999985, + "194": -31.899999999999988, + "195": -17.99999999999997, + "196": -32.10000000000001, + "197": -9.150000000000002, + "198": 5.15000000000006, + "199": 10.850000000000016, + "200": -2.4499999999999673, + "201": 4.850000000000048, + "202": -15.399999999999983, + "203": -39.10000000000001, + "204": -28.24999999999994, + "205": 68.84999999999992, + "206": 33.09999999999985, + "207": -21.69999999999999, + "208": -4.04999999999999, + "209": -6.6499999999999915, + "210": -11.69999999999999, + "211": 18.950000000000003, + "212": -28.25000000000001, + "213": -67.94999999999999, + "214": -40.05, + "215": 22.800000000000047, + "216": -70.75, + "217": -8.949999999999996, + "218": 19.05, + "219": 0.05000000000001714, + "220": -52.25000000000001, + "221": -77.89999999999998, + "222": -74.89999999999998, + "223": -75.94999999999999, + "224": 2.00000000000003, + "225": -6.250000000000014, + "226": 20.74999999999999, + "227": 34.299999999999876, + "228": -0.19999999999999063, + "229": -13.899999999999984, + "230": -32.900000000000006, + "231": 62.999999999999886, + "232": 91.1000000000001, + "233": 44.04999999999978, + "234": -73.54999999999997, + "235": 11.14999999999999, + "236": 7.200000000000019, + "237": -82.75000000000001, + "238": 0.2000000000000306, + "239": 9.250000000000053, + "240": -21.299999999999986, + "241": -58.39999999999999, + "242": -6.349999999999995, + "243": 60.79999999999984, + "244": -8.649999999999995, + "245": 35.999999999999794, + "246": -63.99999999999995, + "247": 67.49999999999999, + "248": 60.499999999999986, + "249": 15.800000000000033, + "250": 24.649999999999896, + "251": 23.30000000000001, + "252": 51.749999999999794, + "253": 94.15000000000012, + "254": -45.50000000000002, + "255": -74.7, + "256": 64.94999999999992, + "257": -83.44999999999999, + "258": 8.500000000000018, + "259": 14.150000000000059, + "260": -22.49999999999995, + "261": 80.95, + "262": -48.10000000000007, + "263": 86.49999999999986, + "264": -96.99999999999997, + "265": 99.79999999999984, + "266": 24.79999999999985, + "267": -16.24999999999997, + "268": 31.69999999999989, + "269": 22.949999999999942, + "270": 87.09999999999987, + "271": 78.40000000000006, + "272": -60.49999999999996, + "273": 7.650000000000068, + "274": -63.35000000000004, + "275": 28.399999999999853, + "276": 30.04999999999987, + "277": 19.699999999999953, + "278": 103.05000000000018, + "279": 72.1499999999998, + "280": 98.15000000000028, + "281": -2.4499999999999815, + "282": 40.299999999999805, + "283": -6.800000000000008, + "284": 4.800000000000047, + "285": -15.00000000000006, + "286": 6.90000000000002, + "287": 9.199999999999982, + "288": 81.35000000000008, + "289": 45.999999999999986, + "290": 48.10000000000001, + "291": 63.599999999999824, + "292": 33.69999999999979, + "293": 43.09999999999996, + "294": 41.00000000000003, + "295": 97.65000000000006, + "296": 69.24999999999987, + "297": 50.100000000000016, + "298": 34.40000000000001, + "299": 4.849999999999987, + "300": 44.89999999999994, + "301": 82.09999999999994, + "302": 74.6500000000001, + "303": 79.85000000000002, + "304": 33.999999999999986, + "305": 89.39999999999999, + "306": 67.84999999999992, + "307": 105.19999999999999, + "308": 75.49999999999996, + "309": 96.49999999999983, + "310": 53.89999999999983, + "311": 90.25000000000009, + "312": 104.45, + "313": 114.6000000000001, + "314": 72.94999999999997, + "315": 91.75000000000004, + "316": 109.70000000000006, + "317": 104.24999999999982, + "318": 94.70000000000009, + "319": 80.79999999999997, + "320": 80.90000000000016, + "321": 90.4500000000001, + "322": 104.75000000000003, + "323": 112.00000000000021, + "324": 88.7500000000001, + "325": -26.700000000000028, + "326": 84.2499999999998, + "327": 92.0, + "328": 105.85000000000015, + "329": 83.8500000000001, + "330": 81.14999999999996, + "331": 72.85000000000002, + "332": 97.20000000000005, + "333": 99.80000000000008, + "334": 6.599999999999982, + "335": 94.99999999999997, + "336": 22.749999999999947, + "337": 102.95, + "338": 91.55000000000004, + "339": 87.95, + "340": 99.15000000000012, + "341": 100.05000000000004, + "342": 106.9000000000001, + "343": 94.64999999999998, + "344": 87.85000000000014, + "345": 101.95000000000003, + "346": 92.05000000000001, + "347": 84.55000000000008, + "348": 102.95, + "349": 100.7000000000002, + "350": 106.89999999999993, + "351": 111.75000000000023, + "352": 108.75000000000014, + "353": 103.4000000000001, + "354": 24.199999999999935, + "355": 94.60000000000001, + "356": 113.10000000000002, + "357": -46.949999999999974, + "358": 83.95000000000007, + "359": 9.500000000000039, + "360": 113.0000000000001, + "361": 111.0000000000002, + "362": 98.5500000000001, + "363": 117.7500000000001, + "364": 64.09999999999997, + "365": 86.45000000000005, + "366": 77.00000000000006, + "367": 112.15000000000012, + "368": 98.35000000000001, + "369": 100.70000000000003, + "370": 100.85000000000011, + "371": 114.85000000000005, + "372": 101.19999999999999, + "373": 105.85000000000005, + "374": 109.94999999999999, + "375": 108.50000000000007, + "376": 109.35000000000018, + "377": 115.55000000000007, + "378": 108.15000000000006, + "379": 78.30000000000011, + "380": 106.50000000000004, + "381": 93.90000000000006, + "382": 82.45000000000002, + "383": 91.20000000000003, + "384": 101.35000000000021, + "385": 93.55000000000003, + "386": 111.15, + "387": 106.10000000000002, + "388": 99.75000000000013, + "389": 60.99999999999983, + "390": 105.35000000000014, + "391": 122.20000000000012, + "392": 105.80000000000001, + "393": 102.10000000000012, + "394": 104.20000000000014, + "395": 105.60000000000022, + "396": 104.79999999999993, + "397": 111.45, + "398": 109.85000000000011, + "399": 113.15000000000003, + "400": 84.19999999999997, + "401": 112.0, + "402": 117.55000000000004, + "403": 103.25000000000011, + "404": 111.2000000000002, + "405": 16.950000000000035, + "406": 81.15000000000013, + "407": 112.30000000000004, + "408": 106.5500000000001, + "409": 118.55000000000007, + "410": 95.30000000000017, + "411": 79.64999999999998, + "412": 97.2000000000001, + "413": 108.25000000000013, + "414": 107.55000000000022, + "415": 108.00000000000011, + "416": 99.15000000000006, + "417": 111.85000000000008, + "418": 114.1500000000002, + "419": 118.05, + "420": 104.55000000000003, + "421": 109.84999999999997, + "422": 114.55000000000015, + "423": 99.8, + "424": 110.30000000000001, + "425": 106.30000000000011, + "426": 112.65000000000023, + "427": 109.15000000000009, + "428": 100.55000000000013, + "429": 110.19999999999996, + "430": 107.84999999999998, + "431": 108.69999999999997, + "432": 111.80000000000018, + "433": 110.9000000000001, + "434": 106.30000000000001, + "435": 56.899999999999835, + "436": 115.1000000000002, + "437": 110.85000000000005, + "438": 105.80000000000008, + "439": 106.65000000000005, + "440": 111.34999999999987, + "441": 112.65000000000016, + "442": 116.40000000000018, + "443": 110.00000000000017, + "444": 110.65000000000002, + "445": 105.20000000000002, + "446": 98.70000000000003, + "447": 101.09999999999992, + "448": 98.55000000000007, + "449": 114.75000000000011, + "450": 109.95000000000009, + "451": 123.15000000000002, + "452": 110.75000000000016, + "453": 97.15000000000019, + "454": 109.70000000000017, + "455": 110.85000000000014, + "456": 118.20000000000009, + "457": 104.2500000000001, + "458": 120.05000000000015, + "459": 105.10000000000002, + "460": 114.80000000000005, + "461": 111.70000000000006, + "462": 115.45, + "463": 112.05000000000005, + "464": 107.30000000000008, + "465": 111.09999999999998, + "466": 122.70000000000013, + "467": 117.10000000000004, + "468": 96.45000000000005, + "469": 118.10000000000002, + "470": 109.15000000000003, + "471": 35.94999999999987, + "472": 105.10000000000016, + "473": 114.34999999999995, + "474": 116.55000000000011, + "475": 105.50000000000013, + "476": 113.80000000000001, + "477": 117.30000000000007, + "478": 112.1, + "479": 95.85000000000008, + "480": 116.2500000000001, + "481": 113.15000000000013, + "482": 101.15, + "483": 96.40000000000015, + "484": 117.65000000000012, + "485": 108.95000000000007, + "486": 114.3500000000001, + "487": 88.24999999999994, + "488": 107.40000000000005, + "489": 105.80000000000008, + "490": 121.55000000000001, + "491": 115.05000000000013, + "492": 101.14999999999993, + "493": 112.00000000000004, + "494": 115.15000000000015, + "495": 117.04999999999997, + "496": 45.54999999999983, + "497": 111.64999999999995, + "498": 116.50000000000004, + "499": 110.05000000000003, + "500": 106.4000000000001, + "501": 118.35000000000014, + "502": 106.19999999999997, + "503": 101.75000000000009, + "504": 114.85000000000007, + "505": 113.00000000000014, + "506": 69.84999999999997, + "507": 98.64999999999995, + "508": 112.25000000000004, + "509": 97.50000000000018, + "510": 103.65000000000003, + "511": 94.55000000000011, + "512": 110.95000000000014, + "513": 105.2, + "514": 106.05000000000017, + "515": 112.30000000000014, + "516": 114.15000000000002, + "517": 107.50000000000011, + "518": 96.80000000000013, + "519": 108.7000000000001, + "520": 108.44999999999999, + "521": 108.30000000000014, + "522": 115.55000000000022, + "523": 118.80000000000004, + "524": 102.00000000000007, + "525": 106.70000000000014, + "526": 106.35000000000015, + "527": 111.45000000000003, + "528": 106.39999999999995, + "529": 104.30000000000005, + "530": 105.90000000000013, + "531": 106.89999999999999, + "532": 108.25, + "533": 107.29999999999997, + "534": 114.80000000000008, + "535": 113.05000000000008, + "536": 110.70000000000016, + "537": 92.00000000000001, + "538": 118.85000000000001, + "539": 115.50000000000004, + "540": 116.64999999999996, + "541": 117.60000000000011, + "542": 102.15000000000003, + "543": 113.85000000000008, + "544": 109.30000000000014, + "545": 100.79999999999995, + "546": 119.40000000000009, + "547": 112.15000000000018, + "548": 115.40000000000005, + "549": 114.30000000000007, + "550": 115.25000000000014, + "551": 107.80000000000005, + "552": 113.65000000000016, + "553": 102.20000000000014, + "554": 108.74999999999999, + "555": 109.00000000000013, + "556": 110.60000000000012, + "557": 111.95000000000012, + "558": 107.29999999999995, + "559": 112.65000000000008, + "560": 105.10000000000002, + "561": 109.55000000000014, + "562": 113.19999999999989, + "563": 115.3000000000001, + "564": 108.35000000000011, + "565": 104.95000000000003, + "566": 109.70000000000005, + "567": 111.80000000000008, + "568": 106.05000000000008, + "569": 116.70000000000003, + "570": 67.69999999999993, + "571": 114.10000000000021, + "572": 108.9, + "573": 100.60000000000002, + "574": 84.54999999999997, + "575": 113.30000000000004, + "576": 101.90000000000013, + "577": 115.29999999999995, + "578": 106.54999999999984, + "579": 109.45000000000005, + "580": 105.35000000000007, + "581": 56.299999999999855, + "582": 119.75000000000004, + "583": 117.95000000000014, + "584": 121.90000000000002, + "585": 55.59999999999996, + "586": 109.10000000000007, + "587": 101.65, + "588": 99.85000000000001, + "589": 114.4500000000001, + "590": 114.2000000000001, + "591": 7.550000000000013, + "592": 45.199999999999825, + "593": 11.499999999999938, + "594": 7.550000000000017, + "595": -6.349999999999991, + "596": 0.8500000000000087, + "597": 30.149999999999935, + "598": -7.799999999999986, + "599": 43.99999999999995, + "600": 6.649999999999995, + "601": -0.8499999999999986, + "602": 78.4500000000001, + "603": 56.14999999999995, + "604": 3.3500000000000036, + "605": -2.59999999999999, + "606": 1.049999999999999, + "607": 16.049999999999912, + "608": -3.25000000000001, + "609": 7.999999999999995, + "610": 107.85000000000011, + "611": 101.4, + "612": 42.84999999999995, + "613": 38.549999999999905, + "614": 55.44999999999999, + "615": 59.499999999999986, + "616": 16.450000000000017, + "617": 14.149999999999933, + "618": 31.599999999999923, + "619": 55.799999999999926, + "620": 41.14999999999994, + "621": 9.900000000000004, + "622": 45.499999999999986, + "623": -4.599999999999982, + "624": 118.75000000000001, + "625": 25.349999999999888, + "626": 106.85, + "627": 82.49999999999996, + "628": 38.79999999999987, + "629": 7.599999999999958, + "630": 98.75000000000014, + "631": 37.399999999999906, + "632": 21.499999999999936, + "633": 69.80000000000008, + "634": 107.90000000000022, + "635": 52.09999999999994, + "636": 6.349999999999993, + "637": 75.75000000000004, + "638": 101.09999999999988, + "639": 115.05000000000008, + "640": -1.6542323066914832e-14, + "641": 116.00000000000013, + "642": 32.64999999999988, + "643": 109.15000000000003, + "644": 60.199999999999925, + "645": -3.199999999999987, + "646": 87.80000000000003, + "647": 114.25000000000003, + "648": 112.40000000000008, + "649": 103.50000000000006, + "650": 5.44999999999999, + "651": 32.59999999999995, + "652": 113.25000000000026, + "653": 108.85000000000007, + "654": 110.75000000000011, + "655": 111.55000000000004, + "656": 111.40000000000003, + "657": 107.55000000000007, + "658": 94.50000000000016, + "659": 57.25, + "660": 29.34999999999989, + "661": 118.30000000000011, + "662": 100.70000000000022, + "663": 115.64999999999993, + "664": 112.75000000000004, + "665": 111.90000000000003, + "666": -2.4999999999999973, + "667": 91.10000000000008, + "668": 79.74999999999994, + "669": 1.7000000000000086, + "670": 112.70000000000007, + "671": 114.80000000000014, + "672": 70.25000000000006, + "673": 17.999999999999943, + "674": 109.25000000000009, + "675": 110.44999999999999, + "676": 113.75000000000011, + "677": 111.85000000000012, + "678": 102.95000000000012, + "679": 110.85000000000007, + "680": 110.15000000000015, + "681": 80.5000000000002, + "682": 105.70000000000007, + "683": 111.8500000000002, + "684": 110.0499999999999, + "685": 112.10000000000002, + "686": 111.3000000000001, + "687": 102.14999999999998, + "688": 99.70000000000002, + "689": 113.40000000000013, + "690": 76.29999999999997, + "691": 100.55000000000004, + "692": 116.85000000000012, + "693": 98.15000000000006, + "694": 107.44999999999999, + "695": 104.05000000000007, + "696": 110.20000000000024, + "697": 111.15000000000012, + "698": 111.00000000000011, + "699": 99.95000000000017, + "700": 102.60000000000008, + "701": 102.90000000000006, + "702": 108.9500000000001, + "703": 113.04999999999997, + "704": 107.4000000000002, + "705": 106.85000000000004, + "706": 113.50000000000003, + "707": 111.20000000000019, + "708": 120.10000000000004, + "709": 116.55000000000008, + "710": 115.0, + "711": 115.30000000000013, + "712": 109.35000000000011, + "713": 65.55000000000004, + "714": 112.6, + "715": 111.90000000000018, + "716": 104.45000000000007, + "717": 105.9500000000001, + "718": 99.30000000000005, + "719": 116.65000000000002, + "720": 114.40000000000002, + "721": 112.60000000000025, + "722": 113.44999999999999, + "723": 117.3499999999999, + "724": 68.85000000000007, + "725": 119.35000000000014, + "726": 92.50000000000006, + "727": 108.80000000000001, + "728": 112.90000000000013, + "729": 115.45000000000029, + "730": 114.35000000000001, + "731": 113.70000000000014, + "732": 114.50000000000028, + "733": 110.45000000000014, + "734": 113.60000000000026, + "735": 109.65000000000005, + "736": 111.69999999999997, + "737": 100.70000000000013, + "738": 110.80000000000001, + "739": 102.50000000000006, + "740": 112.20000000000007, + "741": 117.85000000000014, + "742": 106.85000000000004, + "743": 118.15000000000003, + "744": 104.40000000000019, + "745": 20.749999999999943, + "746": 112.25, + "747": 109.75000000000006, + "748": 98.79999999999997, + "749": 111.34999999999997, + "750": 104.59999999999995, + "751": 102.95, + "752": 106.3500000000002, + "753": 11.650000000000034, + "754": 116.75000000000003, + "755": 101.20000000000019, + "756": 111.6000000000001, + "757": 106.30000000000015, + "758": 113.95000000000007, + "759": 106.60000000000012, + "760": 104.55000000000005, + "761": 107.70000000000006, + "762": 112.95000000000016, + "763": 110.05000000000003, + "764": 113.20000000000014, + "765": 47.599999999999945, + "766": 114.30000000000008, + "767": 111.10000000000011, + "768": 112.55000000000007, + "769": 111.50000000000003, + "770": 91.80000000000018, + "771": 119.40000000000003, + "772": 76.39999999999989, + "773": 118.85000000000012, + "774": 116.45, + "775": 109.59999999999998, + "776": 116.55000000000001, + "777": 112.60000000000015, + "778": 105.64999999999995, + "779": 69.94999999999993, + "780": 109.85000000000005, + "781": 111.75000000000014, + "782": 116.14999999999996, + "783": 101.80000000000001, + "784": 49.04999999999993, + "785": 62.25, + "786": 114.50000000000001, + "787": 112.05, + "788": 108.85000000000002, + "789": 118.45000000000006, + "790": 117.30000000000007, + "791": 112.90000000000013, + "792": 108.90000000000008, + "793": 110.55000000000008, + "794": 114.60000000000007, + "795": 114.30000000000003, + "796": 113.50000000000016, + "797": 114.84999999999994, + "798": 116.50000000000004, + "799": 111.04999999999994, + "800": 113.25000000000007, + "801": 112.05000000000024, + "802": 115.55, + "803": 108.50000000000006, + "804": 116.55000000000008, + "805": 109.2500000000001, + "806": 100.95000000000003, + "807": 112.60000000000008, + "808": 114.15000000000012, + "809": 111.80000000000008, + "810": 83.30000000000001, + "811": 111.75000000000004, + "812": 107.55000000000013, + "813": 112.05000000000008, + "814": 17.350000000000037, + "815": 110.55000000000001, + "816": 111.20000000000014, + "817": 112.00000000000003, + "818": 110.1000000000002, + "819": 106.00000000000001, + "820": 114.30000000000004, + "821": 105.54999999999995, + "822": 101.95000000000013, + "823": 96.69999999999996, + "824": 113.40000000000012, + "825": 52.699999999999854, + "826": 41.34999999999981, + "827": 101.90000000000012, + "828": 105.35000000000012, + "829": 111.29999999999995, + "830": 111.8, + "831": 112.85, + "832": 67.69999999999975, + "833": 112.85000000000005, + "834": 105.40000000000012, + "835": 112.85, + "836": 95.84999999999998, + "837": 95.95000000000006, + "838": 100.40000000000013, + "839": 107.00000000000001, + "840": 111.00000000000004, + "841": 114.95000000000027, + "842": 107.65000000000003, + "843": 111.65000000000009, + "844": 105.15000000000008, + "845": 106.30000000000004, + "846": 107.65000000000013, + "847": 113.90000000000019, + "848": 120.30000000000007, + "849": 108.80000000000003, + "850": 105.74999999999999, + "851": 86.49999999999994, + "852": 115.50000000000011, + "853": 116.00000000000016, + "854": 122.55000000000011, + "855": 112.6500000000001, + "856": 108.15, + "857": 83.30000000000001, + "858": 114.8000000000001, + "859": 116.40000000000005, + "860": 108.70000000000009, + "861": 116.45000000000003, + "862": 102.40000000000002, + "863": 113.60000000000011, + "864": 112.15000000000009, + "865": 110.20000000000002, + "866": 113.19999999999993, + "867": 113.00000000000003, + "868": 111.55000000000015, + "869": 117.75000000000006, + "870": 116.8000000000001, + "871": 110.45000000000017, + "872": 114.00000000000013, + "873": 118.70000000000026, + "874": 113.95000000000012, + "875": 113.00000000000001, + "876": 112.60000000000014, + "877": 107.50000000000009, + "878": 112.49999999999999, + "879": 116.94999999999999, + "880": 107.10000000000014, + "881": 106.70000000000013, + "882": 106.05000000000015, + "883": 111.7000000000001, + "884": 112.85000000000015, + "885": 112.7500000000001, + "886": 109.8500000000001, + "887": 111.55000000000008, + "888": 112.30000000000005, + "889": 110.10000000000001, + "890": 110.60000000000024, + "891": 114.55, + "892": 49.55000000000004, + "893": 115.2500000000001, + "894": 104.69999999999996, + "895": 109.15000000000008, + "896": 119.15000000000003, + "897": 100.55000000000003, + "898": 119.84999999999998, + "899": 116.70000000000003, + "900": 112.85000000000007, + "901": 115.74999999999997, + "902": 118.5500000000001, + "903": 106.89999999999996, + "904": 110.29999999999997, + "905": 115.04999999999998, + "906": 112.35000000000011, + "907": 80.84999999999994, + "908": 109.55000000000008, + "909": 109.49999999999994, + "910": 102.29999999999998, + "911": 108.25000000000001, + "912": 104.90000000000008, + "913": 109.20000000000009, + "914": 118.90000000000015, + "915": 108.95000000000014, + "916": 109.24999999999994, + "917": 104.50000000000018, + "918": 100.55000000000015, + "919": 111.64999999999998, + "920": 112.80000000000014, + "921": 97.7, + "922": 114.40000000000013, + "923": 110.60000000000001, + "924": 118.20000000000009, + "925": 108.90000000000005, + "926": 110.24999999999999, + "927": 102.64999999999982, + "928": 110.95000000000002, + "929": 110.20000000000005, + "930": 97.55, + "931": 114.70000000000006, + "932": 96.09999999999998, + "933": 88.59999999999991, + "934": 110.6000000000001, + "935": -8.149999999999997, + "936": 112.25, + "937": 114.44999999999995, + "938": 111.9500000000001, + "939": 115.40000000000006, + "940": 117.05000000000015, + "941": 70.84999999999978, + "942": 121.45000000000014, + "943": 72.14999999999992, + "944": 110.30000000000011, + "945": 109.19999999999995, + "946": 109.3000000000001, + "947": 105.3500000000001, + "948": 118.29999999999998, + "949": 116.50000000000018, + "950": 111.85, + "951": 106.59999999999994, + "952": 66.55000000000011, + "953": 109.50000000000007, + "954": 89.90000000000006, + "955": 108.9000000000001, + "956": 108.95000000000017, + "957": 99.69999999999996, + "958": 104.95000000000014, + "959": 109.55000000000017, + "960": 107.94999999999999, + "961": 111.85000000000016, + "962": 96.05000000000004, + "963": 114.35, + "964": 119.25000000000007, + "965": 115.3, + "966": 108.30000000000018, + "967": 108.85000000000015, + "968": 114.40000000000003, + "969": 109.8, + "970": 111.40000000000009, + "971": 102.10000000000011, + "972": 111.75000000000013, + "973": 112.60000000000014, + "974": 113.00000000000009, + "975": 110.10000000000011, + "976": 100.70000000000005, + "977": 27.900000000000002, + "978": 120.10000000000014, + "979": 113.35000000000008, + "980": 113.19999999999993, + "981": 51.39999999999995, + "982": 111.25000000000017, + "983": 114.05000000000007, + "984": 112.95000000000016, + "985": 105.80000000000007, + "986": 118.20000000000012, + "987": 110.4, + "988": 113.35000000000004, + "989": 108.35000000000005, + "990": 118.95000000000014, + "991": 107.3500000000002, + "992": 102.2000000000001, + "993": 112.35000000000005, + "994": 95.69999999999989, + "995": 106.35000000000015, + "996": 113.55, + "997": 117.9500000000001, + "998": 112.35000000000011, + "999": 115.20000000000002, + "1000": 102.64999999999988 + }, + "4": { + "1": -88.3, + "2": -78.44999999999999, + "3": -61.60000000000013, + "4": -17.999999999999968, + "5": -21.299999999999958, + "6": -21.499999999999957, + "7": -6.500000000000002, + "8": -50.60000000000009, + "9": -20.799999999999958, + "10": -52.50000000000008, + "11": -54.60000000000007, + "12": -17.84999999999996, + "13": -79.69999999999996, + "14": -24.249999999999947, + "15": -57.80000000000017, + "16": -23.14999999999996, + "17": -16.99999999999997, + "18": -52.100000000000115, + "19": -88.49999999999997, + "20": -15.949999999999974, + "21": -14.149999999999984, + "22": -24.14999999999995, + "23": -17.89999999999998, + "24": -8.249999999999972, + "25": -11.549999999999986, + "26": -97.44999999999996, + "27": -16.699999999999978, + "28": -8.849999999999987, + "29": -16.449999999999974, + "30": -8.900000000000004, + "31": -16.24999999999999, + "32": -8.849999999999998, + "33": -55.550000000000075, + "34": -19.79999999999996, + "35": -11.799999999999988, + "36": -32.45000000000004, + "37": -63.150000000000105, + "38": -6.25000000000001, + "39": -97.9, + "40": -17.59999999999997, + "41": -23.49999999999995, + "42": -3.9499999999999806, + "43": -18.799999999999965, + "44": -99.0, + "45": -21.249999999999957, + "46": -17.599999999999973, + "47": -20.94999999999996, + "48": -55.05, + "49": -93.09999999999998, + "50": -17.899999999999963, + "51": -46.900000000000006, + "52": -73.60000000000002, + "53": -61.09999999999998, + "54": -94.55, + "55": -19.649999999999963, + "56": -19.949999999999967, + "57": -4.849999999999982, + "58": -9.449999999999992, + "59": -17.049999999999972, + "60": -25.69999999999994, + "61": -21.049999999999958, + "62": -17.74999999999997, + "63": -91.25, + "64": -18.54999999999997, + "65": -71.75000000000003, + "66": -23.49999999999995, + "67": -8.799999999999985, + "68": -14.549999999999978, + "69": -19.699999999999964, + "70": -20.149999999999988, + "71": -95.95000000000006, + "72": -60.55, + "73": -22.649999999999952, + "74": -21.949999999999957, + "75": 1.0000000000000002, + "76": -13.749999999999986, + "77": -9.049999999999994, + "78": -81.24999999999999, + "79": -99.44999999999999, + "80": -14.549999999999985, + "81": -17.99999999999997, + "82": -10.299999999999999, + "83": -18.599999999999973, + "84": -19.399999999999974, + "85": -13.29999999999998, + "86": -17.449999999999964, + "87": -6.199999999999989, + "88": -13.64999999999999, + "89": -15.29999999999998, + "90": -21.299999999999958, + "91": -22.649999999999952, + "92": -37.04999999999996, + "93": -43.75, + "94": -18.949999999999967, + "95": 7.350000000000055, + "96": 0.45000000000000284, + "97": -15.599999999999978, + "98": -10.99999999999999, + "99": -23.39999999999995, + "100": 8.149999999999983, + "101": -21.499999999999957, + "102": -5.899999999999998, + "103": -60.800000000000004, + "104": -17.399999999999977, + "105": -11.449999999999996, + "106": -3.8499999999999934, + "107": -5.199999999999982, + "108": 6.199999999999969, + "109": -18.09999999999997, + "110": -7.749999999999988, + "111": -21.899999999999956, + "112": -4.249999999999994, + "113": -15.649999999999974, + "114": 13.999999999999961, + "115": -17.449999999999974, + "116": -76.54999999999998, + "117": -16.999999999999975, + "118": 0.5500000000000362, + "119": -96.30000000000001, + "120": -10.299999999999992, + "121": -9.849999999999998, + "122": 1.1000000000000212, + "123": -19.29999999999997, + "124": -51.999999999999986, + "125": -63.09999999999992, + "126": -6.800000000000003, + "127": 4.050000000000029, + "128": -26.9, + "129": -14.49999999999999, + "130": -5.649999999999986, + "131": -11.649999999999988, + "132": 16.399999999999977, + "133": -7.700000000000009, + "134": -20.84999999999996, + "135": -86.35, + "136": -1.7499999999999682, + "137": -10.099999999999994, + "138": -20.84999999999996, + "139": -11.149999999999988, + "140": -51.24999999999998, + "141": -57.450000000000074, + "142": -59.95, + "143": -61.0500000000001, + "144": -13.949999999999996, + "145": -44.30000000000004, + "146": -12.449999999999985, + "147": -13.099999999999984, + "148": -88.30000000000001, + "149": 29.049999999999894, + "150": -14.549999999999974, + "151": -17.399999999999952, + "152": -4.199999999999987, + "153": -8.450000000000014, + "154": -54.95000000000001, + "155": -10.699999999999996, + "156": -13.64999999999999, + "157": -83.3, + "158": -77.10000000000002, + "159": 19.20000000000006, + "160": -89.9, + "161": -21.899999999999956, + "162": 2.450000000000035, + "163": -0.9999999999999734, + "164": -82.25, + "165": -17.69999999999997, + "166": 24.500000000000004, + "167": -94.69999999999997, + "168": -35.55000000000001, + "169": 3.6499999999999897, + "170": -58.60000000000009, + "171": 9.400000000000055, + "172": 4.549999999999919, + "173": -36.60000000000006, + "174": -41.00000000000005, + "175": -20.550000000000004, + "176": 42.949999999999854, + "177": -2.3499999999999632, + "178": 25.49999999999991, + "179": -24.199999999999953, + "180": -82.60000000000001, + "181": -79.80000000000005, + "182": -80.19999999999999, + "183": -90.00000000000004, + "184": -55.65000000000001, + "185": 5.35000000000006, + "186": -10.599999999999994, + "187": -1.1999999999999567, + "188": -74.04999999999995, + "189": 3.849999999999965, + "190": 33.14999999999997, + "191": -12.94999999999999, + "192": -88.75000000000006, + "193": -39.90000000000005, + "194": -61.14999999999996, + "195": -93.74999999999997, + "196": -67.25000000000001, + "197": -17.799999999999976, + "198": -7.799999999999997, + "199": 11.099999999999955, + "200": 60.500000000000085, + "201": -24.500000000000046, + "202": -77.94999999999999, + "203": 8.100000000000044, + "204": -23.799999999999947, + "205": -9.949999999999998, + "206": -22.049999999999955, + "207": -7.25, + "208": -6.500000000000011, + "209": 14.650000000000045, + "210": -33.500000000000036, + "211": -34.94999999999998, + "212": -18.80000000000001, + "213": 16.199999999999925, + "214": -69.09999999999991, + "215": -26.499999999999993, + "216": -57.64999999999995, + "217": -78.80000000000001, + "218": -52.29999999999998, + "219": 2.2000000000000286, + "220": -75.5, + "221": -5.999999999999991, + "222": -60.20000000000003, + "223": 25.90000000000001, + "224": -6.9999999999999805, + "225": -89.2, + "226": -65.49999999999989, + "227": 62.649999999999885, + "228": -59.1, + "229": 5.9499999999999895, + "230": 5.449999999999991, + "231": -69.70000000000003, + "232": 16.650000000000027, + "233": -65.65, + "234": -50.750000000000014, + "235": -91.8, + "236": -63.10000000000002, + "237": 1.8500000000000345, + "238": -3.850000000000064, + "239": 22.999999999999805, + "240": -48.10000000000006, + "241": 21.850000000000033, + "242": -18.35000000000004, + "243": -72.15000000000002, + "244": -19.65000000000002, + "245": -81.54999999999998, + "246": -82.14999999999998, + "247": -63.40000000000003, + "248": -35.45000000000002, + "249": 18.00000000000001, + "250": -12.24999999999999, + "251": -15.899999999999975, + "252": 5.30000000000001, + "253": -16.29999999999998, + "254": -71.85000000000002, + "255": -64.99999999999996, + "256": 11.650000000000006, + "257": 1.6431300764452317e-14, + "258": 40.499999999999815, + "259": 21.899999999999974, + "260": -30.40000000000009, + "261": -57.69999999999998, + "262": 55.14999999999978, + "263": 31.349999999999795, + "264": 16.000000000000025, + "265": -14.250000000000025, + "266": -33.50000000000003, + "267": 11.750000000000016, + "268": -40.1, + "269": -72.89999999999999, + "270": -12.149999999999991, + "271": -74.6999999999999, + "272": 17.350000000000005, + "273": -11.649999999999961, + "274": -69.14999999999998, + "275": -62.8, + "276": -73.35000000000002, + "277": 18.50000000000003, + "278": 84.69999999999979, + "279": -78.19999999999999, + "280": -55.99999999999995, + "281": 22.24999999999989, + "282": 8.999999999999998, + "283": -34.75000000000002, + "284": 4.550000000000049, + "285": -10.39999999999997, + "286": -20.699999999999996, + "287": 2.400000000000027, + "288": 5.150000000000025, + "289": 1.950000000000022, + "290": -49.15, + "291": 19.70000000000004, + "292": 19.249999999999975, + "293": -30.650000000000023, + "294": 19.449999999999992, + "295": 71.89999999999985, + "296": 30.750000000000032, + "297": 6.350000000000021, + "298": -42.299999999999976, + "299": 46.899999999999835, + "300": -83.29999999999998, + "301": -51.74999999999998, + "302": -68.84999999999997, + "303": -34.95, + "304": 8.850000000000065, + "305": 66.49999999999997, + "306": 18.150000000000055, + "307": -38.549999999999955, + "308": -14.05000000000004, + "309": 15.250000000000071, + "310": -1.8999999999999382, + "311": -2.3499999999999543, + "312": -59.44999999999996, + "313": -7.699999999999989, + "314": 12.500000000000021, + "315": 59.79999999999999, + "316": 50.99999999999974, + "317": -49.24999999999995, + "318": -84.79999999999998, + "319": -82.55000000000001, + "320": 7.45000000000005, + "321": -63.84999999999997, + "322": -43.64999999999999, + "323": -92.05, + "324": 41.19999999999977, + "325": -75.6, + "326": -6.3499999999999845, + "327": 16.800000000000008, + "328": -10.900000000000002, + "329": -26.049999999999986, + "330": 6.650000000000029, + "331": -68.70000000000002, + "332": 7.45000000000005, + "333": -73.35000000000001, + "334": 22.799999999999915, + "335": -54.39999999999998, + "336": -66.99999999999991, + "337": -75.5, + "338": 67.44999999999995, + "339": -55.09999999999995, + "340": -42.15000000000001, + "341": -85.85000000000002, + "342": -47.39999999999994, + "343": 0.10000000000002318, + "344": 60.74999999999988, + "345": -37.14999999999996, + "346": 57.14999999999979, + "347": 100.45000000000013, + "348": -32.450000000000024, + "349": 61.499999999999815, + "350": 23.199999999999974, + "351": -30.900000000000002, + "352": 6.449999999999954, + "353": 13.850000000000115, + "354": 34.800000000000026, + "355": -10.750000000000037, + "356": 15.450000000000012, + "357": -20.99999999999998, + "358": 26.75, + "359": -52.849999999999966, + "360": -60.4, + "361": 60.04999999999992, + "362": 27.249999999999886, + "363": -62.199999999999896, + "364": 74.85, + "365": -21.550000000000022, + "366": 62.699999999999974, + "367": -44.59999999999998, + "368": -62.69999999999995, + "369": 58.54999999999974, + "370": -69.65, + "371": -20.899999999999928, + "372": -16.750000000000032, + "373": -2.9999999999999973, + "374": 35.84999999999978, + "375": 7.59999999999997, + "376": 56.09999999999981, + "377": -40.700000000000074, + "378": 58.19999999999996, + "379": 22.800000000000047, + "380": 85.55000000000005, + "381": 79.44999999999973, + "382": -25.95000000000004, + "383": 42.44999999999986, + "384": 32.199999999999754, + "385": 7.05000000000005, + "386": -65.84999999999991, + "387": 98.69999999999973, + "388": 2.8999999999999675, + "389": 59.199999999999775, + "390": 12.29999999999999, + "391": 73.34999999999981, + "392": 36.99999999999997, + "393": 96.69999999999973, + "394": 42.84999999999977, + "395": -23.49999999999994, + "396": 5.150000000000007, + "397": 73.8499999999998, + "398": -47.99999999999994, + "399": 81.15000000000003, + "400": -10.250000000000023, + "401": -55.30000000000001, + "402": 69.94999999999996, + "403": 16.04999999999995, + "404": 17.94999999999997, + "405": 58.1499999999998, + "406": 3.6500000000000163, + "407": -28.950000000000063, + "408": -45.950000000000095, + "409": 51.90000000000002, + "410": 58.849999999999866, + "411": 93.74999999999972, + "412": 1.7000000000000013, + "413": -11.400000000000016, + "414": 17.250000000000046, + "415": 8.399999999999967, + "416": -65.70000000000002, + "417": 97.54999999999977, + "418": 63.49999999999979, + "419": -41.25000000000003, + "420": 38.34999999999996, + "421": 25.50000000000001, + "422": 5.85000000000004, + "423": -10.34999999999994, + "424": 113.75000000000013, + "425": 91.14999999999978, + "426": 77.60000000000011, + "427": 93.74999999999974, + "428": 86.59999999999978, + "429": 68.34999999999972, + "430": 111.74999999999979, + "431": 110.94999999999986, + "432": 92.4000000000001, + "433": 95.25000000000013, + "434": 60.549999999999855, + "435": 59.84999999999999, + "436": -38.15000000000002, + "437": 91.24999999999974, + "438": -12.849999999999984, + "439": 80.79999999999986, + "440": 87.94999999999975, + "441": 103.79999999999976, + "442": 115.2, + "443": 14.149999999999999, + "444": 97.59999999999998, + "445": -8.300000000000017, + "446": 5.3000000000000345, + "447": 95.74999999999972, + "448": 46.69999999999977, + "449": 89.84999999999988, + "450": 59.14999999999998, + "451": 58.19999999999991, + "452": 81.89999999999978, + "453": 106.59999999999971, + "454": 48.99999999999993, + "455": 103.59999999999981, + "456": -40.000000000000014, + "457": 23.30000000000003, + "458": 29.900000000000063, + "459": 105.54999999999974, + "460": -11.549999999999962, + "461": 60.79999999999976, + "462": 86.69999999999978, + "463": 41.04999999999997, + "464": -27.25000000000002, + "465": 104.04999999999981, + "466": -27.650000000000016, + "467": -3.3500000000000316, + "468": 84.35000000000014, + "469": 77.80000000000004, + "470": 83.64999999999974, + "471": 66.09999999999975, + "472": -49.750000000000085, + "473": 75.44999999999985, + "474": 81.49999999999987, + "475": 99.64999999999978, + "476": -1.8499999999999952, + "477": 86.69999999999975, + "478": 75.34999999999982, + "479": 103.39999999999974, + "480": 90.59999999999975, + "481": 97.60000000000001, + "482": 88.44999999999979, + "483": 105.8499999999998, + "484": 75.69999999999975, + "485": 60.599999999999824, + "486": 105.09999999999974, + "487": 102.14999999999975, + "488": 106.64999999999972, + "489": 1.4499999999999973, + "490": 103.24999999999991, + "491": 80.89999999999979, + "492": 73.14999999999975, + "493": 88.54999999999977, + "494": 73.39999999999982, + "495": 59.099999999999724, + "496": 102.59999999999977, + "497": 96.49999999999976, + "498": 87.39999999999975, + "499": 105.84999999999981, + "500": 48.39999999999987, + "501": 101.14999999999976, + "502": 96.14999999999986, + "503": 105.09999999999974, + "504": 102.44999999999975, + "505": 70.54999999999993, + "506": 55.6999999999999, + "507": 92.24999999999984, + "508": 112.09999999999981, + "509": 96.54999999999976, + "510": 106.24999999999973, + "511": 83.54999999999973, + "512": 104.14999999999976, + "513": 103.54999999999977, + "514": 91.89999999999995, + "515": 99.64999999999976, + "516": 80.99999999999976, + "517": 105.09999999999982, + "518": 84.49999999999982, + "519": 99.64999999999976, + "520": 104.89999999999976, + "521": 103.54999999999977, + "522": 108.74999999999974, + "523": 85.44999999999973, + "524": 97.3999999999998, + "525": 102.79999999999977, + "526": 103.99999999999976, + "527": 80.1499999999998, + "528": 112.09999999999981, + "529": 99.59999999999977, + "530": 101.39999999999975, + "531": 97.39999999999972, + "532": 100.79999999999977, + "533": 106.39999999999972, + "534": 104.99999999999977, + "535": 62.59999999999974, + "536": 105.59999999999974, + "537": 84.59999999999991, + "538": 43.199999999999946, + "539": 79.74999999999993, + "540": 92.34999999999977, + "541": -40.00000000000001, + "542": 107.44999999999978, + "543": 93.84999999999995, + "544": 104.64999999999978, + "545": 105.89999999999975, + "546": 100.79999999999974, + "547": 65.9499999999998, + "548": 106.54999999999973, + "549": 100.04999999999977, + "550": 71.94999999999987, + "551": 97.94999999999992, + "552": 99.09999999999975, + "553": 106.94999999999975, + "554": 92.14999999999974, + "555": 109.50000000000009, + "556": 103.29999999999977, + "557": 103.49999999999977, + "558": 111.15000000000006, + "559": 88.29999999999978, + "560": 99.84999999999974, + "561": 89.04999999999981, + "562": 46.94999999999975, + "563": 99.0000000000001, + "564": 113.00000000000018, + "565": 107.59999999999972, + "566": 98.09999999999978, + "567": 106.10000000000007, + "568": 107.04999999999978, + "569": 106.49999999999973, + "570": 64.09999999999992, + "571": 104.94999999999976, + "572": 68.59999999999995, + "573": 49.799999999999805, + "574": 18.150000000000034, + "575": 99.19999999999976, + "576": 1.5499999999999903, + "577": 103.69999999999976, + "578": 1.5500000000000538, + "579": 111.64999999999978, + "580": 89.24999999999977, + "581": 100.39999999999976, + "582": 102.79999999999991, + "583": 112.25000000000021, + "584": 64.59999999999992, + "585": 108.79999999999986, + "586": 108.89999999999984, + "587": 117.20000000000027, + "588": 85.94999999999976, + "589": 98.65000000000008, + "590": 112.55000000000005, + "591": 108.29999999999973, + "592": 105.39999999999979, + "593": 101.04999999999976, + "594": 106.99999999999974, + "595": 107.14999999999978, + "596": 72.29999999999994, + "597": 89.94999999999986, + "598": 109.04999999999984, + "599": 105.19999999999975, + "600": 107.69999999999976, + "601": 63.09999999999971, + "602": 96.34999999999978, + "603": 103.89999999999975, + "604": 102.9500000000001, + "605": 105.79999999999974, + "606": 109.30000000000001, + "607": 105.39999999999975, + "608": 73.19999999999999, + "609": 106.7499999999998, + "610": 96.75000000000018, + "611": 105.8499999999999, + "612": 103.14999999999976, + "613": 102.84999999999975, + "614": 104.94999999999976, + "615": 105.39999999999999, + "616": 111.10000000000007, + "617": 107.89999999999995, + "618": 100.80000000000001, + "619": 62.34999999999977, + "620": 111.50000000000007, + "621": 104.64999999999972, + "622": 115.34999999999992, + "623": 112.69999999999997, + "624": 108.19999999999973, + "625": 108.19999999999979, + "626": 105.99999999999994, + "627": 109.59999999999998, + "628": 103.30000000000008, + "629": 109.34999999999998, + "630": 89.59999999999988, + "631": 107.59999999999975, + "632": 107.44999999999973, + "633": 104.94999999999975, + "634": 104.09999999999977, + "635": 108.14999999999975, + "636": 103.10000000000005, + "637": 102.35000000000005, + "638": 98.79999999999977, + "639": 106.69999999999973, + "640": 107.24999999999973, + "641": 107.4499999999998, + "642": 102.64999999999976, + "643": 108.84999999999978, + "644": 103.29999999999977, + "645": 91.54999999999983, + "646": 109.49999999999974, + "647": 107.69999999999987, + "648": 97.14999999999978, + "649": 107.10000000000022, + "650": 112.1500000000001, + "651": 105.59999999999974, + "652": 107.30000000000004, + "653": -72.25000000000003, + "654": 107.20000000000016, + "655": 109.49999999999991, + "656": 112.95000000000009, + "657": 109.80000000000001, + "658": 107.24999999999989, + "659": 111.50000000000009, + "660": 116.40000000000026, + "661": 116.3500000000001, + "662": 62.04999999999983, + "663": 104.7000000000002, + "664": 74.59999999999997, + "665": 90.09999999999974, + "666": 100.7499999999999, + "667": 60.29999999999991, + "668": 110.74999999999983, + "669": 106.59999999999975, + "670": 110.70000000000006, + "671": 97.94999999999976, + "672": 116.85000000000015, + "673": 110.35000000000001, + "674": 56.799999999999756, + "675": 109.64999999999986, + "676": 86.40000000000002, + "677": 108.45, + "678": 108.24999999999991, + "679": 46.59999999999973, + "680": 115.65000000000005, + "681": 112.10000000000002, + "682": 108.00000000000007, + "683": 111.0, + "684": 109.4999999999999, + "685": 111.10000000000008, + "686": 109.89999999999992, + "687": 111.54999999999986, + "688": 107.49999999999976, + "689": 105.40000000000002, + "690": 79.29999999999998, + "691": 111.15000000000022, + "692": 90.50000000000014, + "693": 85.20000000000009, + "694": -0.19999999999996576, + "695": 116.10000000000002, + "696": 108.0499999999998, + "697": 112.40000000000003, + "698": 109.14999999999999, + "699": 112.05000000000014, + "700": 99.54999999999998, + "701": 109.75000000000003, + "702": 114.19999999999993, + "703": 110.75000000000011, + "704": 122.45000000000006, + "705": 94.0499999999999, + "706": 107.29999999999977, + "707": 112.75000000000024, + "708": 110.55000000000004, + "709": 104.4999999999999, + "710": 104.05000000000018, + "711": 114.10000000000012, + "712": 112.55000000000003, + "713": 110.6000000000002, + "714": 104.59999999999982, + "715": 113.1000000000002, + "716": 109.8000000000002, + "717": 112.8000000000002, + "718": 91.75000000000006, + "719": 99.00000000000007, + "720": 98.2500000000001, + "721": 88.24999999999999, + "722": 98.45000000000007, + "723": 107.29999999999976, + "724": 109.55, + "725": 19.300000000000004, + "726": 95.39999999999988, + "727": 112.60000000000024, + "728": 113.60000000000018, + "729": 108.80000000000013, + "730": 108.85000000000002, + "731": 107.00000000000013, + "732": 111.39999999999996, + "733": 105.55000000000018, + "734": 95.75000000000009, + "735": 107.70000000000019, + "736": 97.75000000000001, + "737": 97.35000000000004, + "738": 111.05000000000007, + "739": 99.40000000000016, + "740": 102.39999999999998, + "741": 112.2000000000001, + "742": 85.64999999999993, + "743": 107.20000000000006, + "744": 107.90000000000016, + "745": 83.19999999999999, + "746": 100.15000000000018, + "747": 100.99999999999976, + "748": 94.60000000000002, + "749": 110.55000000000024, + "750": 100.65000000000023, + "751": 86.7, + "752": 86.10000000000004, + "753": 104.75000000000016, + "754": 98.20000000000003, + "755": 99.54999999999995, + "756": 113.40000000000013, + "757": 111.95000000000005, + "758": 106.85000000000007, + "759": 105.00000000000016, + "760": 112.85000000000015, + "761": 111.75000000000011, + "762": 105.54999999999973, + "763": 104.2000000000001, + "764": 114.30000000000027, + "765": 113.60000000000011, + "766": 97.99999999999993, + "767": 112.35000000000024, + "768": 95.6, + "769": 109.84999999999995, + "770": 113.05000000000011, + "771": 57.799999999999976, + "772": 97.75000000000009, + "773": 114.35000000000018, + "774": 112.55000000000011, + "775": 108.95000000000002, + "776": 94.55000000000014, + "777": 99.85000000000012, + "778": 113.3500000000002, + "779": 102.70000000000017, + "780": 109.20000000000013, + "781": 101.4500000000001, + "782": 114.10000000000002, + "783": 92.20000000000003, + "784": 106.64999999999998, + "785": 105.95000000000012, + "786": 113.70000000000007, + "787": 117.80000000000008, + "788": 121.95000000000019, + "789": 96.99999999999983, + "790": 111.90000000000005, + "791": -4.449999999999992, + "792": 77.60000000000005, + "793": -13.999999999999984, + "794": 79.89999999999989, + "795": 110.35000000000008, + "796": 100.30000000000007, + "797": 108.1, + "798": 115.70000000000006, + "799": 46.099999999999774, + "800": 91.54999999999978, + "801": 30.349999999999792, + "802": 54.19999999999978, + "803": 109.40000000000006, + "804": 69.19999999999999, + "805": 57.74999999999975, + "806": 99.95000000000003, + "807": 93.6999999999999, + "808": 82.65000000000002, + "809": 110.75000000000011, + "810": 102.60000000000016, + "811": 98.89999999999988, + "812": 50.1999999999998, + "813": 119.15000000000005, + "814": 101.45, + "815": 114.05000000000028, + "816": 106.44999999999986, + "817": 104.64999999999989, + "818": 91.6500000000001, + "819": -9.500000000000005, + "820": 118.60000000000002, + "821": 116.09999999999997, + "822": 113.94999999999996, + "823": 116.80000000000018, + "824": 110.5500000000001, + "825": 48.799999999999855, + "826": 72.84999999999991, + "827": 93.25000000000016, + "828": 106.90000000000008, + "829": 26.050000000000008, + "830": 107.10000000000014, + "831": 111.50000000000011, + "832": 107.39999999999993, + "833": 103.9500000000002, + "834": 103.80000000000015, + "835": 108.59999999999995, + "836": 108.2, + "837": 107.05000000000018, + "838": 109.40000000000009, + "839": 109.3500000000001, + "840": 108.55000000000004, + "841": 107.30000000000014, + "842": 107.59999999999997, + "843": 108.90000000000015, + "844": 101.15000000000016, + "845": 108.59999999999997, + "846": 104.0000000000002, + "847": 113.90000000000026, + "848": 92.89999999999999, + "849": 108.64999999999999, + "850": 96.40000000000015, + "851": 109.1000000000001, + "852": 91.90000000000018, + "853": 103.45000000000014, + "854": 102.50000000000011, + "855": 106.90000000000003, + "856": 112.90000000000006, + "857": 79.85000000000002, + "858": 106.50000000000003, + "859": 106.00000000000016, + "860": 102.80000000000018, + "861": 109.79999999999991, + "862": 112.55000000000011, + "863": 102.9500000000001, + "864": 111.00000000000017, + "865": 111.90000000000006, + "866": 103.40000000000002, + "867": 87.09999999999995, + "868": 106.69999999999983, + "869": 115.10000000000011, + "870": 110.1999999999999, + "871": 114.50000000000017, + "872": 96.70000000000007, + "873": 109.5000000000001, + "874": 108.20000000000003, + "875": 110.75000000000006, + "876": 109.35000000000011, + "877": 109.35000000000012, + "878": 112.80000000000004, + "879": 117.99999999999996, + "880": 45.04999999999988, + "881": 39.900000000000006, + "882": 115.1, + "883": 108.25000000000017, + "884": 111.95, + "885": 112.15000000000013, + "886": 122.84999999999997, + "887": 110.80000000000004, + "888": 105.1, + "889": 120.40000000000012, + "890": 113.40000000000006, + "891": 113.45000000000009, + "892": 109.59999999999998, + "893": 106.19999999999996, + "894": 107.35000000000001, + "895": 112.50000000000003, + "896": 114.75000000000018, + "897": 120.6000000000002, + "898": 107.75000000000013, + "899": 111.10000000000012, + "900": 112.9000000000001, + "901": 111.60000000000005, + "902": 114.85000000000004, + "903": 112.85000000000002, + "904": 119.55000000000013, + "905": 117.30000000000004, + "906": 108.60000000000011, + "907": 103.45000000000006, + "908": 116.95000000000009, + "909": 113.75000000000013, + "910": 98.75000000000004, + "911": 74.19999999999996, + "912": 91.95, + "913": 67.64999999999986, + "914": 114.20000000000009, + "915": 105.7, + "916": 111.15000000000002, + "917": 102.25000000000004, + "918": 106.80000000000001, + "919": 106.50000000000001, + "920": 108.55000000000005, + "921": 98.45000000000002, + "922": 109.84999999999997, + "923": 99.05000000000005, + "924": 122.60000000000001, + "925": 114.85000000000022, + "926": 108.44999999999993, + "927": 99.99999999999994, + "928": 110.05000000000025, + "929": 95.64999999999982, + "930": 111.55000000000004, + "931": 112.80000000000005, + "932": 117.2500000000002, + "933": 109.00000000000001, + "934": 103.60000000000001, + "935": 108.19999999999999, + "936": 113.1500000000001, + "937": 103.10000000000004, + "938": 106.90000000000009, + "939": 102.30000000000001, + "940": 86.45, + "941": 96.80000000000003, + "942": 115.00000000000007, + "943": 108.25000000000003, + "944": 106.54999999999998, + "945": 106.50000000000003, + "946": 117.50000000000017, + "947": 110.20000000000013, + "948": 113.50000000000006, + "949": 107.35000000000011, + "950": 114.90000000000013, + "951": 114.50000000000001, + "952": 116.50000000000007, + "953": 98.49999999999999, + "954": 113.45000000000013, + "955": 110.69999999999997, + "956": 117.35000000000008, + "957": 112.55000000000013, + "958": 114.2000000000001, + "959": 107.94999999999987, + "960": 107.50000000000011, + "961": 111.7500000000001, + "962": 98.25000000000016, + "963": 101.80000000000014, + "964": 112.00000000000006, + "965": 106.20000000000006, + "966": 99.4, + "967": 111.10000000000005, + "968": 111.55000000000007, + "969": 114.00000000000004, + "970": 113.85000000000012, + "971": 115.25000000000016, + "972": 104.60000000000002, + "973": 111.85000000000005, + "974": 109.54999999999993, + "975": 109.24999999999994, + "976": 104.84999999999998, + "977": 112.49999999999997, + "978": 108.60000000000022, + "979": 103.84999999999997, + "980": 109.85000000000015, + "981": 108.65000000000005, + "982": 109.5500000000002, + "983": 111.00000000000014, + "984": 108.75000000000014, + "985": 113.75000000000013, + "986": 105.85000000000004, + "987": 95.80000000000007, + "988": 116.80000000000005, + "989": 110.35000000000011, + "990": 109.20000000000014, + "991": 100.09999999999995, + "992": 102.65000000000013, + "993": 110.00000000000021, + "994": 108.15000000000019, + "995": 116.64999999999996, + "996": 113.40000000000012, + "997": 118.90000000000003, + "998": 110.64999999999996, + "999": 98.74999999999996, + "1000": 111.2000000000001 + }, + "5": { + "1": -91.15000000000013, + "2": -51.900000000000084, + "3": -62.6500000000001, + "4": -10.700000000000012, + "5": -33.2, + "6": -36.80000000000003, + "7": -38.95000000000003, + "8": -17.79999999999997, + "9": -68.50000000000006, + "10": -23.29999999999995, + "11": -20.49999999999996, + "12": -17.849999999999973, + "13": -49.700000000000074, + "14": -7.550000000000016, + "15": -21.649999999999956, + "16": -21.04999999999996, + "17": -15.299999999999972, + "18": -47.15000000000004, + "19": -32.25000000000002, + "20": -99.40000000000003, + "21": -36.70000000000004, + "22": -24.350000000000012, + "23": -18.44999999999996, + "24": -19.599999999999984, + "25": -22.199999999999953, + "26": -47.850000000000065, + "27": -11.299999999999995, + "28": -14.199999999999978, + "29": -55.75000000000013, + "30": -61.1000000000001, + "31": -100.15, + "32": -16.399999999999974, + "33": -11.399999999999986, + "34": -32.850000000000016, + "35": -12.199999999999985, + "36": -20.39999999999996, + "37": -30.299999999999976, + "38": -5.399999999999988, + "39": -14.649999999999988, + "40": -61.5000000000001, + "41": -81.95000000000002, + "42": -66.4, + "43": -14.949999999999982, + "44": -79.80000000000007, + "45": -16.349999999999977, + "46": -9.849999999999989, + "47": -18.14999999999997, + "48": -16.099999999999973, + "49": -5.450000000000002, + "50": -11.700000000000003, + "51": -10.099999999999987, + "52": -14.549999999999981, + "53": -21.64999999999995, + "54": -63.35000000000011, + "55": -14.399999999999988, + "56": -12.199999999999996, + "57": -12.499999999999968, + "58": -18.649999999999963, + "59": -15.499999999999977, + "60": -49.250000000000064, + "61": -15.54999999999998, + "62": -17.39999999999997, + "63": -17.94999999999997, + "64": -2.399999999999996, + "65": -29.950000000000006, + "66": -34.349999999999994, + "67": -16.049999999999976, + "68": -6.849999999999996, + "69": -11.449999999999994, + "70": -18.04999999999997, + "71": -67.4, + "72": -46.099999999999994, + "73": -65.1000000000001, + "74": -19.399999999999963, + "75": -34.250000000000014, + "76": -12.199999999999987, + "77": -19.09999999999997, + "78": -17.499999999999975, + "79": -3.149999999999984, + "80": -82.30000000000005, + "81": -18.399999999999967, + "82": -45.00000000000006, + "83": -17.599999999999973, + "84": -6.2999999999999945, + "85": -11.699999999999989, + "86": -72.3, + "87": 29.89999999999986, + "88": -17.39999999999997, + "89": -17.099999999999977, + "90": -15.049999999999974, + "91": -14.399999999999983, + "92": -64.35000000000011, + "93": -8.299999999999992, + "94": -5.400000000000002, + "95": 4.699999999999991, + "96": -39.84999999999997, + "97": -21.999999999999954, + "98": -0.9000000000000068, + "99": 4.200000000000021, + "100": -0.4999999999999927, + "101": -13.249999999999977, + "102": -42.09999999999998, + "103": -11.649999999999972, + "104": -31.550000000000004, + "105": -8.05, + "106": -18.399999999999963, + "107": -41.15000000000005, + "108": -29.550000000000022, + "109": 22.550000000000004, + "110": -62.49999999999995, + "111": -5.900000000000001, + "112": -17.149999999999984, + "113": -16.599999999999973, + "114": -79.15000000000008, + "115": 0.800000000000026, + "116": -87.55000000000001, + "117": -27.199999999999953, + "118": -92.80000000000001, + "119": -15.999999999999982, + "120": -9.999999999999995, + "121": -81.20000000000002, + "122": -20.149999999999967, + "123": -22.84999999999995, + "124": 8.300000000000042, + "125": -3.6499999999999826, + "126": -64.0, + "127": -9.699999999999989, + "128": -1.5499999999999772, + "129": -22.99999999999995, + "130": 2.4500000000000313, + "131": -23.69999999999995, + "132": 1.250000000000063, + "133": -77.99999999999997, + "134": -9.849999999999998, + "135": 6.800000000000063, + "136": -41.50000000000009, + "137": -18.19999999999997, + "138": -42.15000000000015, + "139": -39.04999999999997, + "140": -13.1, + "141": -70.95000000000002, + "142": -17.699999999999967, + "143": 9.450000000000006, + "144": -8.199999999999957, + "145": -6.749999999999992, + "146": -5.199999999999982, + "147": -9.249999999999993, + "148": -1.049999999999974, + "149": 2.4500000000000135, + "150": -8.999999999999996, + "151": -92.0, + "152": -6.999999999999993, + "153": -18.09999999999997, + "154": -15.149999999999979, + "155": -56.999999999999986, + "156": -1.7999999999999725, + "157": -95.25, + "158": 3.000000000000017, + "159": 28.299999999999866, + "160": -76.94999999999996, + "161": -73.75, + "162": -3.799999999999974, + "163": 15.850000000000026, + "164": -9.449999999999989, + "165": -76.4, + "166": -1.249999999999967, + "167": -14.549999999999981, + "168": -96.15, + "169": -24.14999999999995, + "170": -12.149999999999984, + "171": -16.899999999999974, + "172": -13.099999999999978, + "173": -73.5, + "174": -11.549999999999986, + "175": -20.44999999999996, + "176": -64.80000000000003, + "177": -11.85, + "178": -20.999999999999957, + "179": -18.54999999999997, + "180": -13.099999999999985, + "181": -14.499999999999984, + "182": 1.450000000000031, + "183": -15.799999999999972, + "184": 78.49999999999999, + "185": -17.049999999999972, + "186": -14.149999999999984, + "187": -4.45000000000001, + "188": -8.599999999999996, + "189": -4.349999999999988, + "190": -6.249999999999987, + "191": 33.04999999999976, + "192": -22.950000000000053, + "193": -13.099999999999987, + "194": -56.30000000000006, + "195": -8.600000000000003, + "196": -7.299999999999995, + "197": -74.55, + "198": 3.2000000000000277, + "199": -10.349999999999985, + "200": -7.349999999999974, + "201": -1.0999999999999703, + "202": 37.35000000000006, + "203": 35.499999999999794, + "204": -16.099999999999977, + "205": 2.400000000000027, + "206": -10.399999999999988, + "207": -65.20000000000002, + "208": 24.149999999999903, + "209": -83.04999999999994, + "210": 0.5000000000000036, + "211": 25.65000000000005, + "212": -14.449999999999985, + "213": -78.99999999999999, + "214": -73.7, + "215": -46.69999999999998, + "216": -18.69999999999997, + "217": -29.05000000000006, + "218": -24.849999999999987, + "219": 7.049999999999965, + "220": -74.75000000000001, + "221": 41.84999999999983, + "222": 16.04999999999997, + "223": 27.05000000000003, + "224": -68.60000000000002, + "225": -69.19999999999999, + "226": -59.94999999999998, + "227": -84.09999999999994, + "228": 31.349999999999802, + "229": -73.39999999999999, + "230": 18.099999999999962, + "231": -1.4000000000000472, + "232": -84.40000000000002, + "233": -65.29999999999995, + "234": -79.49999999999997, + "235": -56.6, + "236": -16.449999999999978, + "237": -12.39999999999999, + "238": -39.600000000000016, + "239": 0.7500000000000113, + "240": 2.049999999999933, + "241": -11.149999999999956, + "242": -64.05, + "243": 65.99999999999993, + "244": -12.099999999999982, + "245": 4.750000000000041, + "246": 27.600000000000055, + "247": -65.59999999999997, + "248": -25.85000000000006, + "249": -26.449999999999964, + "250": -7.700000000000044, + "251": -6.049999999999983, + "252": 18.450000000000017, + "253": 61.799999999999976, + "254": -54.24999999999999, + "255": -12.699999999999989, + "256": 0.05000000000002558, + "257": 27.049999999999866, + "258": -47.849999999999994, + "259": -1.7999999999999938, + "260": -41.45, + "261": 41.2499999999998, + "262": 17.900000000000063, + "263": 30.999999999999986, + "264": 33.649999999999956, + "265": 8.650000000000029, + "266": -11.800000000000031, + "267": 15.000000000000025, + "268": -3.100000000000004, + "269": -23.19999999999996, + "270": -38.35000000000007, + "271": 79.55000000000008, + "272": 35.34999999999975, + "273": -3.7499999999999645, + "274": -19.79999999999999, + "275": -13.549999999999983, + "276": 29.949999999999786, + "277": 8.60000000000001, + "278": 46.4499999999999, + "279": 79.50000000000001, + "280": 21.899999999999988, + "281": 16.750000000000018, + "282": 18.250000000000053, + "283": 55.69999999999982, + "284": -80.39999999999999, + "285": 36.59999999999987, + "286": 19.649999999999963, + "287": 24.900000000000013, + "288": -36.99999999999999, + "289": -40.349999999999994, + "290": 25.14999999999997, + "291": 19.850000000000023, + "292": 102.10000000000004, + "293": 5.449999999999989, + "294": 7.399999999999948, + "295": 74.25000000000024, + "296": 72.94999999999992, + "297": 46.74999999999995, + "298": 71.84999999999995, + "299": 84.64999999999985, + "300": 11.900000000000054, + "301": -40.25000000000002, + "302": -49.69999999999996, + "303": -8.099999999999989, + "304": -47.54999999999997, + "305": -38.9500000000001, + "306": 90.04999999999991, + "307": 62.799999999999784, + "308": -30.949999999999996, + "309": -33.4, + "310": -18.349999999999998, + "311": 100.50000000000013, + "312": 40.049999999999756, + "313": -10.050000000000004, + "314": 20.400000000000002, + "315": 6.900000000000025, + "316": 43.59999999999993, + "317": 111.95000000000012, + "318": -33.15000000000002, + "319": -89.35000000000011, + "320": 51.94999999999981, + "321": 65.74999999999987, + "322": -7.000000000000031, + "323": 66.5999999999998, + "324": 86.14999999999996, + "325": -23.79999999999999, + "326": 55.599999999999866, + "327": 32.049999999999955, + "328": 80.85000000000001, + "329": 13.750000000000057, + "330": 54.049999999999855, + "331": 111.9500000000003, + "332": -65.95000000000002, + "333": 118.90000000000023, + "334": 32.34999999999996, + "335": -24.05, + "336": 92.4500000000001, + "337": -5.849999999999974, + "338": 48.09999999999994, + "339": 22.3, + "340": 3.0499999999999527, + "341": 82.05000000000017, + "342": 66.09999999999991, + "343": 22.499999999999922, + "344": 76.49999999999994, + "345": 8.550000000000034, + "346": 96.9500000000001, + "347": 101.94999999999999, + "348": 74.69999999999989, + "349": 81.49999999999991, + "350": 37.24999999999996, + "351": 50.39999999999997, + "352": 36.600000000000044, + "353": 83.44999999999997, + "354": 27.549999999999955, + "355": 41.64999999999997, + "356": 51.84999999999993, + "357": -12.500000000000005, + "358": 25.950000000000088, + "359": -54.200000000000074, + "360": 28.59999999999988, + "361": 96.4000000000002, + "362": 56.449999999999996, + "363": 1.149999999999966, + "364": -28.799999999999976, + "365": 5.599999999999952, + "366": 57.849999999999895, + "367": -55.8499999999999, + "368": 58.95000000000009, + "369": 27.55000000000001, + "370": 65.14999999999985, + "371": 97.99999999999997, + "372": -25.74999999999995, + "373": -11.499999999999986, + "374": 39.749999999999964, + "375": 103.19999999999993, + "376": 90.75000000000006, + "377": 59.29999999999992, + "378": 39.19999999999992, + "379": 113.74999999999999, + "380": 73.04999999999995, + "381": 87.70000000000007, + "382": 45.05000000000005, + "383": 58.49999999999996, + "384": -64.64999999999988, + "385": 101.40000000000015, + "386": -73.69999999999985, + "387": 85.49999999999993, + "388": 53.599999999999774, + "389": 111.04999999999994, + "390": 81.44999999999993, + "391": 19.499999999999943, + "392": 106.20000000000017, + "393": 79.75000000000001, + "394": 110.00000000000009, + "395": 75.39999999999998, + "396": -13.350000000000001, + "397": 78.54999999999983, + "398": -1.7000000000000186, + "399": 81.30000000000003, + "400": 118.55000000000011, + "401": 99.05000000000005, + "402": 78.80000000000004, + "403": 46.599999999999824, + "404": -30.59999999999997, + "405": 27.04999999999996, + "406": -11.949999999999967, + "407": 117.15000000000012, + "408": 47.44999999999978, + "409": 88.74999999999989, + "410": 83.00000000000003, + "411": 55.39999999999994, + "412": 11.850000000000012, + "413": 101.45, + "414": 96.10000000000012, + "415": 44.24999999999995, + "416": 112.14999999999995, + "417": 71.5999999999999, + "418": 11.450000000000042, + "419": 29.199999999999996, + "420": 101.04999999999984, + "421": 75.70000000000002, + "422": 95.29999999999991, + "423": 81.19999999999985, + "424": 39.6999999999998, + "425": 35.89999999999996, + "426": 80.65, + "427": 79.35000000000002, + "428": 47.1999999999999, + "429": 80.59999999999977, + "430": 105.19999999999983, + "431": 98.64999999999999, + "432": 79.69999999999999, + "433": 73.25000000000003, + "434": 102.9000000000001, + "435": 103.04999999999994, + "436": 58.699999999999925, + "437": 78.24999999999994, + "438": 53.89999999999997, + "439": 91.95000000000009, + "440": 115.15000000000008, + "441": 102.15000000000013, + "442": 79.99999999999994, + "443": 66.94999999999995, + "444": 102.05000000000017, + "445": 86.6499999999999, + "446": 99.00000000000009, + "447": 47.59999999999991, + "448": 10.200000000000035, + "449": 83.54999999999984, + "450": 100.89999999999999, + "451": 110.15000000000026, + "452": 14.400000000000011, + "453": 79.75, + "454": 65.09999999999991, + "455": 108.25000000000007, + "456": 47.54999999999999, + "457": 117.35000000000007, + "458": 75.20000000000005, + "459": 99.89999999999998, + "460": 63.50000000000004, + "461": 106.09999999999991, + "462": 98.00000000000017, + "463": 111.80000000000018, + "464": 109.65000000000005, + "465": 93.25000000000004, + "466": 99.95000000000014, + "467": 115.15000000000032, + "468": 107.39999999999978, + "469": 55.34999999999979, + "470": 105.74999999999996, + "471": 74.09999999999995, + "472": 101.55, + "473": 111.75000000000007, + "474": 77.95000000000003, + "475": 113.3999999999998, + "476": 101.55000000000014, + "477": 113.25000000000001, + "478": 110.85000000000014, + "479": 113.40000000000012, + "480": 98.20000000000003, + "481": 106.69999999999992, + "482": 83.50000000000003, + "483": 49.49999999999982, + "484": 116.85000000000004, + "485": 72.69999999999982, + "486": 114.65000000000025, + "487": 99.50000000000003, + "488": 109.15000000000018, + "489": 111.3999999999999, + "490": 103.1500000000002, + "491": 112.75000000000013, + "492": 98.29999999999995, + "493": 103.69999999999993, + "494": 48.14999999999975, + "495": 98.05000000000001, + "496": 113.40000000000015, + "497": 94.79999999999991, + "498": 86.40000000000005, + "499": 110.50000000000023, + "500": 108.60000000000002, + "501": 106.65000000000022, + "502": 114.05000000000017, + "503": 92.55000000000004, + "504": 105.40000000000005, + "505": 112.7000000000001, + "506": 92.65000000000029, + "507": 114.00000000000014, + "508": 106.45000000000019, + "509": 112.85000000000015, + "510": 111.10000000000012, + "511": 87.5, + "512": 90.40000000000003, + "513": 75.6, + "514": 110.40000000000025, + "515": 113.85000000000016, + "516": 106.2500000000002, + "517": 108.1500000000002, + "518": 87.80000000000007, + "519": 101.80000000000008, + "520": 107.14999999999974, + "521": 101.74999999999973, + "522": 113.10000000000015, + "523": 111.0500000000001, + "524": 113.75000000000023, + "525": 87.50000000000009, + "526": 112.75000000000023, + "527": 32.65, + "528": 105.85000000000001, + "529": 89.04999999999986, + "530": 113.55000000000011, + "531": 102.15000000000005, + "532": 111.75000000000013, + "533": 101.64999999999992, + "534": 114.50000000000026, + "535": 101.55000000000007, + "536": 101.44999999999992, + "537": 109.45000000000014, + "538": 99.60000000000014, + "539": 107.60000000000021, + "540": 106.5, + "541": 90.50000000000001, + "542": 86.55000000000003, + "543": 105.05000000000005, + "544": 77.39999999999998, + "545": 80.04999999999977, + "546": 104.15000000000015, + "547": 114.95000000000022, + "548": 78.49999999999993, + "549": 109.79999999999987, + "550": 84.55000000000003, + "551": 107.50000000000003, + "552": 113.80000000000011, + "553": 112.09999999999998, + "554": 112.10000000000016, + "555": 107.69999999999996, + "556": 94.10000000000004, + "557": 110.25000000000004, + "558": 111.55000000000021, + "559": 109.70000000000003, + "560": 108.90000000000026, + "561": 83.9000000000001, + "562": 107.89999999999985, + "563": 111.85000000000018, + "564": 109.99999999999987, + "565": 103.85000000000015, + "566": 104.10000000000016, + "567": 112.00000000000026, + "568": 114.0500000000001, + "569": 103.45000000000006, + "570": 113.75000000000021, + "571": 109.35000000000018, + "572": 107.74999999999984, + "573": 115.85000000000002, + "574": 113.25000000000016, + "575": 113.10000000000025, + "576": 112.00000000000026, + "577": 113.05000000000013, + "578": 112.85000000000014, + "579": 74.75000000000001, + "580": 100.2, + "581": 105.40000000000009, + "582": 105.60000000000018, + "583": 111.30000000000022, + "584": 109.15000000000015, + "585": 113.80000000000024, + "586": 110.39999999999996, + "587": 100.85000000000015, + "588": 103.04999999999987, + "589": 109.85000000000021, + "590": 113.00000000000016, + "591": 100.54999999999994, + "592": 111.70000000000012, + "593": 110.10000000000018, + "594": 103.19999999999982, + "595": 109.15000000000016, + "596": 109.50000000000016, + "597": 108.09999999999988, + "598": 101.60000000000011, + "599": 112.25000000000007, + "600": 105.35000000000004, + "601": 103.45000000000009, + "602": 110.74999999999996, + "603": 109.80000000000013, + "604": 95.35000000000011, + "605": 107.75000000000023, + "606": 103.45000000000019, + "607": 7.800000000000029, + "608": 114.05000000000007, + "609": 101.24999999999996, + "610": 112.15000000000005, + "611": 56.99999999999985, + "612": -1.8999999999999908, + "613": 1.9000000000000141, + "614": 60.399999999999835, + "615": 112.75000000000016, + "616": 103.05000000000013, + "617": 60.249999999999844, + "618": 19.349999999999955, + "619": 105.45000000000019, + "620": 24.24999999999988, + "621": -8.549999999999995, + "622": -15.699999999999978, + "623": 1.0000000000000235, + "624": -4.400000000000001, + "625": 4.799999999999985, + "626": -1.7000000000000013, + "627": 13.749999999999996, + "628": -24.650000000000016, + "629": 34.04999999999989, + "630": -5.750000000000003, + "631": 4.800000000000043, + "632": -15.649999999999991, + "633": -3.449999999999973, + "634": 14.79999999999994, + "635": 0.5500000000000266, + "636": -7.099999999999992, + "637": 1.950000000000029, + "638": -9.999999999999986, + "639": -4.799999999999984, + "640": -7.399999999999976, + "641": -2.84999999999998, + "642": -21.54999999999996, + "643": -10.34999999999999, + "644": -8.99999999999999, + "645": -6.199999999999989, + "646": 46.09999999999994, + "647": -3.0499999999999865, + "648": -0.6499999999999873, + "649": -22.14999999999997, + "650": -12.049999999999986, + "651": -11.299999999999986, + "652": -18.800000000000043, + "653": 77.50000000000024, + "654": 40.64999999999985, + "655": 16.199999999999893, + "656": 5.450000000000059, + "657": 38.7, + "658": 10.549999999999946, + "659": -11.200000000000003, + "660": 2.1500000000000252, + "661": 60.09999999999999, + "662": 37.849999999999866, + "663": 40.49999999999983, + "664": 45.04999999999991, + "665": -2.849999999999974, + "666": 21.549999999999937, + "667": 3.20000000000004, + "668": 2.650000000000035, + "669": 12.149999999999991, + "670": 53.549999999999834, + "671": 53.09999999999984, + "672": 48.29999999999994, + "673": -24.400000000000006, + "674": 30.299999999999844, + "675": 99.19999999999999, + "676": 82.05000000000008, + "677": 14.149999999999933, + "678": -52.099999999999994, + "679": 21.400000000000055, + "680": 19.19999999999986, + "681": 1.7500000000000244, + "682": 95.95000000000013, + "683": 71.04999999999991, + "684": 32.899999999999835, + "685": 56.199999999999946, + "686": 9.999999999999956, + "687": 4.200000000000049, + "688": 98.44999999999992, + "689": 51.049999999999855, + "690": 59.24999999999994, + "691": 66.95000000000019, + "692": 76.60000000000004, + "693": 15.04999999999993, + "694": 55.54999999999983, + "695": 109.90000000000019, + "696": 100.95000000000009, + "697": 115.15000000000028, + "698": 44.89999999999987, + "699": 41.49999999999992, + "700": 41.449999999999875, + "701": 33.19999999999982, + "702": 22.49999999999996, + "703": -15.749999999999975, + "704": 87.34999999999997, + "705": 70.75000000000001, + "706": -15.199999999999982, + "707": 24.299999999999876, + "708": 53.09999999999979, + "709": 93.05000000000008, + "710": 10.74999999999999, + "711": 83.40000000000003, + "712": 57.24999999999984, + "713": 2.000000000000024, + "714": 111.70000000000014, + "715": -5.549999999999987, + "716": 88.05000000000008, + "717": 74.9500000000001, + "718": 109.25000000000021, + "719": 105.70000000000023, + "720": 104.75000000000007, + "721": 35.20000000000003, + "722": 104.15000000000019, + "723": 66.35000000000008, + "724": 113.35000000000001, + "725": 102.10000000000002, + "726": 50.94999999999982, + "727": 109.85, + "728": 1.7500000000000377, + "729": 108.45000000000014, + "730": 83.94999999999983, + "731": 108.80000000000015, + "732": 108.70000000000013, + "733": 43.09999999999986, + "734": 92.60000000000014, + "735": 0.7999999999999722, + "736": 81.80000000000001, + "737": 114.20000000000016, + "738": 87.60000000000001, + "739": 106.40000000000008, + "740": 96.40000000000012, + "741": 115.10000000000022, + "742": 98.40000000000008, + "743": 87.25000000000009, + "744": 21.599999999999905, + "745": 62.49999999999997, + "746": 104.70000000000012, + "747": 67.80000000000013, + "748": 97.35000000000022, + "749": 91.25000000000007, + "750": -76.0, + "751": 116.84999999999997, + "752": 89.15000000000026, + "753": 116.30000000000008, + "754": 108.60000000000011, + "755": 116.00000000000006, + "756": 115.25000000000013, + "757": 102.39999999999992, + "758": 115.25000000000026, + "759": 53.04999999999993, + "760": 107.09999999999997, + "761": 104.94999999999997, + "762": 104.45000000000017, + "763": 111.15000000000026, + "764": 100.25000000000003, + "765": 109.75000000000016, + "766": 111.35000000000011, + "767": 103.35000000000002, + "768": 111.69999999999997, + "769": 104.65, + "770": 11.049999999999994, + "771": 104.2, + "772": 111.65000000000002, + "773": 107.05000000000013, + "774": 107.05000000000013, + "775": 103.60000000000001, + "776": 99.4500000000002, + "777": 100.35000000000018, + "778": 101.55000000000007, + "779": 96.0500000000002, + "780": 98.24999999999999, + "781": 109.75000000000017, + "782": 117.10000000000007, + "783": 114.30000000000011, + "784": 105.5500000000001, + "785": 106.8500000000001, + "786": 115.5000000000001, + "787": 117.60000000000014, + "788": 112.9500000000001, + "789": 109.8000000000001, + "790": 111.15, + "791": 108.30000000000018, + "792": 101.55000000000004, + "793": 110.35000000000012, + "794": 81.20000000000003, + "795": 66.09999999999994, + "796": 105.40000000000009, + "797": 107.95000000000007, + "798": 97.75000000000004, + "799": 104.80000000000014, + "800": 110.0000000000001, + "801": 61.44999999999985, + "802": 116.25000000000026, + "803": 100.3, + "804": 104.15000000000005, + "805": 106.30000000000011, + "806": 114.35000000000008, + "807": 2.000000000000009, + "808": 91.30000000000004, + "809": 101.55000000000005, + "810": 106.75000000000017, + "811": 72.79999999999993, + "812": 111.40000000000009, + "813": 107.35000000000018, + "814": 65.05000000000018, + "815": 100.35, + "816": 101.00000000000009, + "817": 102.0500000000001, + "818": 102.50000000000006, + "819": 100.25, + "820": 107.95000000000009, + "821": 111.95000000000017, + "822": 104.2000000000001, + "823": 97.3500000000001, + "824": 103.50000000000003, + "825": 111.35000000000002, + "826": 114.09999999999998, + "827": 103.75000000000006, + "828": 81.94999999999995, + "829": 115.75000000000001, + "830": 60.59999999999999, + "831": 119.0500000000001, + "832": 90.90000000000012, + "833": 97.84999999999998, + "834": 93.9, + "835": 107.59999999999998, + "836": 98.30000000000003, + "837": 108.35000000000011, + "838": 112.85000000000012, + "839": 113.10000000000004, + "840": 109.75000000000009, + "841": 115.35000000000001, + "842": 104.3500000000001, + "843": 82.3, + "844": 110.35000000000005, + "845": 113.50000000000006, + "846": 111.3500000000001, + "847": 115.6500000000001, + "848": 114.40000000000002, + "849": 110.5, + "850": 110.74999999999997, + "851": 63.39999999999985, + "852": 61.750000000000014, + "853": 98.70000000000002, + "854": 104.09999999999992, + "855": 94.55000000000001, + "856": 103.25000000000003, + "857": 109.29999999999994, + "858": 119.35000000000002, + "859": 111.54999999999998, + "860": 101.35000000000014, + "861": 84.05000000000005, + "862": 95.35000000000004, + "863": 52.349999999999916, + "864": 114.14999999999995, + "865": 112.34999999999998, + "866": 115.95000000000016, + "867": 111.60000000000016, + "868": 115.20000000000005, + "869": 115.35, + "870": 110.40000000000012, + "871": 112.1000000000001, + "872": 34.349999999999945, + "873": 94.95000000000022, + "874": 94.04999999999984, + "875": 108.90000000000003, + "876": 101.09999999999992, + "877": 111.45000000000016, + "878": 109.80000000000008, + "879": 118.05000000000005, + "880": 111.2, + "881": 104.45000000000016, + "882": 101.85000000000002, + "883": 101.40000000000006, + "884": 109.6499999999999, + "885": 104.94999999999999, + "886": 116.85000000000005, + "887": 115.60000000000012, + "888": 113.55000000000005, + "889": 88.50000000000003, + "890": 77.25, + "891": 102.75000000000001, + "892": 122.10000000000005, + "893": 104.15000000000015, + "894": 111.80000000000008, + "895": 102.80000000000013, + "896": 103.40000000000002, + "897": 117.95000000000003, + "898": 113.00000000000011, + "899": 109.05000000000003, + "900": 114.30000000000011, + "901": 114.20000000000016, + "902": 109.50000000000003, + "903": 108.20000000000013, + "904": 112.40000000000005, + "905": 112.10000000000011, + "906": 107.75000000000016, + "907": 112.95000000000007, + "908": 120.25000000000009, + "909": 112.05000000000007, + "910": 65.89999999999988, + "911": 109.3500000000002, + "912": 93.05000000000008, + "913": 115.20000000000003, + "914": 110.60000000000007, + "915": 99.85, + "916": 8.90000000000009, + "917": 116.50000000000007, + "918": 103.3500000000001, + "919": 112.50000000000003, + "920": 101.0500000000001, + "921": 113.4, + "922": 107.85000000000007, + "923": 105.44999999999992, + "924": 106.79999999999995, + "925": 82.00000000000009, + "926": 119.50000000000014, + "927": 111.20000000000016, + "928": 115.75, + "929": 107.70000000000002, + "930": 112.80000000000017, + "931": 112.75000000000011, + "932": 110.20000000000019, + "933": 111.05000000000005, + "934": 106.80000000000017, + "935": 102.60000000000012, + "936": 113.90000000000002, + "937": 109.40000000000002, + "938": 104.00000000000018, + "939": 88.60000000000002, + "940": 110.69999999999992, + "941": 116.95000000000013, + "942": 40.09999999999982, + "943": 117.45000000000007, + "944": 116.05000000000011, + "945": 110.75000000000009, + "946": 108.60000000000015, + "947": 107.09999999999997, + "948": 106.40000000000016, + "949": 107.75000000000017, + "950": 116.65, + "951": 91.60000000000008, + "952": 92.65000000000003, + "953": 100.40000000000005, + "954": 112.09999999999994, + "955": 111.55000000000011, + "956": 96.14999999999999, + "957": 106.55000000000004, + "958": 115.50000000000007, + "959": 110.24999999999996, + "960": 112.40000000000008, + "961": 107.90000000000003, + "962": 48.24999999999995, + "963": 112.8500000000001, + "964": 114.70000000000007, + "965": 106.94999999999996, + "966": 118.7000000000001, + "967": 107.44999999999999, + "968": 104.59999999999994, + "969": 107.70000000000019, + "970": 121.3000000000001, + "971": 109.04999999999994, + "972": 115.45000000000012, + "973": 117.50000000000013, + "974": 120.14999999999998, + "975": 101.65000000000013, + "976": 114.35000000000015, + "977": 103.10000000000004, + "978": 109.80000000000008, + "979": 115.5500000000001, + "980": 91.84999999999997, + "981": 114.70000000000022, + "982": 111.20000000000009, + "983": 117.40000000000008, + "984": 110.6, + "985": 109.40000000000013, + "986": 117.45000000000009, + "987": 114.00000000000009, + "988": 105.80000000000011, + "989": 110.80000000000008, + "990": 105.65000000000005, + "991": 108.45000000000014, + "992": 109.35000000000004, + "993": 115.85000000000005, + "994": 114.05000000000014, + "995": 111.05000000000005, + "996": 111.49999999999997, + "997": 99.10000000000015, + "998": 114.95000000000014, + "999": 119.40000000000015, + "1000": 104.3 + } + }, + "config": { + "io_settings": { + "save_agent_actions": true, + "save_step_metadata": false, + "save_pcap_logs": false, + "save_sys_logs": false, + "sys_log_level": "WARNING" + }, + "game": { + "max_episode_length": 128, + "ports": [ + "HTTP", + "POSTGRES_SERVER" + ], + "protocols": [ + "ICMP", + "TCP", + "UDP" + ], + "thresholds": { + "nmne": { + "high": 10, + "medium": 5, + "low": 0 + } + } + }, + "agents": [ + { + "ref": "client_2_green_user", + "team": "GREEN", + "type": "ProbabilisticAgent", + "agent_settings": { + "action_probabilities": { + "0": 0.3, + "1": 0.6, + "2": 0.1 + } + }, + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_2", + "applications": [ + { + "application_name": "WebBrowser" + }, + { + "application_name": "DatabaseClient" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1, + "max_applications_per_node": 2 + }, + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 0 + } + }, + "2": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 1 + } + } + } + }, + "reward_function": { + "reward_components": [ + { + "type": "WEBPAGE_UNAVAILABLE_PENALTY", + "weight": 0.25, + "options": { + "node_hostname": "client_2" + } + }, + { + "type": "GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY", + "weight": 0.05, + "options": { + "node_hostname": "client_2" + } + } + ] + } + }, + { + "ref": "client_1_green_user", + "team": "GREEN", + "type": "ProbabilisticAgent", + "agent_settings": { + "action_probabilities": { + "0": 0.3, + "1": 0.6, + "2": 0.1 + } + }, + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_1", + "applications": [ + { + "application_name": "WebBrowser" + }, + { + "application_name": "DatabaseClient" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1, + "max_applications_per_node": 2 + }, + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 0 + } + }, + "2": { + "action": "NODE_APPLICATION_EXECUTE", + "options": { + "node_id": 0, + "application_id": 1 + } + } + } + }, + "reward_function": { + "reward_components": [ + { + "type": "WEBPAGE_UNAVAILABLE_PENALTY", + "weight": 0.25, + "options": { + "node_hostname": "client_1" + } + }, + { + "type": "GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY", + "weight": 0.05, + "options": { + "node_hostname": "client_1" + } + } + ] + } + }, + { + "ref": "data_manipulation_attacker", + "team": "RED", + "type": "RedDatabaseCorruptingAgent", + "observation_space": null, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_APPLICATION_EXECUTE" + } + ], + "options": { + "nodes": [ + { + "node_name": "client_1", + "applications": [ + { + "application_name": "DataManipulationBot" + } + ] + }, + { + "node_name": "client_2", + "applications": [ + { + "application_name": "DataManipulationBot" + } + ] + } + ], + "max_folders_per_node": 1, + "max_files_per_folder": 1, + "max_services_per_node": 1 + } + }, + "reward_function": { + "reward_components": [ + { + "type": "DUMMY" + } + ] + }, + "agent_settings": { + "start_settings": { + "start_step": 25, + "frequency": 20, + "variance": 5 + } + } + }, + { + "ref": "defender", + "team": "BLUE", + "type": "ProxyAgent", + "observation_space": { + "type": "CUSTOM", + "options": { + "components": [ + { + "type": "NODES", + "label": "NODES", + "options": { + "hosts": [ + { + "hostname": "domain_controller" + }, + { + "hostname": "web_server", + "services": [ + { + "service_name": "WebServer" + } + ] + }, + { + "hostname": "database_server", + "folders": [ + { + "folder_name": "database", + "files": [ + { + "file_name": "database.db" + } + ] + } + ] + }, + { + "hostname": "backup_server" + }, + { + "hostname": "security_suite" + }, + { + "hostname": "client_1" + }, + { + "hostname": "client_2" + } + ], + "num_services": 1, + "num_applications": 0, + "num_folders": 1, + "num_files": 1, + "num_nics": 2, + "include_num_access": false, + "include_nmne": true, + "monitored_traffic": { + "icmp": [ + "NONE" + ], + "tcp": [ + "DNS" + ] + }, + "routers": [ + { + "hostname": "router_1" + } + ], + "num_ports": 0, + "ip_list": [ + "192.168.1.10", + "192.168.1.12", + "192.168.1.14", + "192.168.1.16", + "192.168.1.110", + "192.168.10.21", + "192.168.10.22", + "192.168.10.110" + ], + "wildcard_list": [ + "0.0.0.1" + ], + "port_list": [ + 80, + 5432 + ], + "protocol_list": [ + "ICMP", + "TCP", + "UDP" + ], + "num_rules": 10 + } + }, + { + "type": "LINKS", + "label": "LINKS", + "options": { + "link_references": [ + "router_1:eth-1<->switch_1:eth-8", + "router_1:eth-2<->switch_2:eth-8", + "switch_1:eth-1<->domain_controller:eth-1", + "switch_1:eth-2<->web_server:eth-1", + "switch_1:eth-3<->database_server:eth-1", + "switch_1:eth-4<->backup_server:eth-1", + "switch_1:eth-7<->security_suite:eth-1", + "switch_2:eth-1<->client_1:eth-1", + "switch_2:eth-2<->client_2:eth-1", + "switch_2:eth-7<->security_suite:eth-2" + ] + } + }, + { + "type": "NONE", + "label": "ICS", + "options": {} + } + ] + } + }, + "action_space": { + "action_list": [ + { + "type": "DONOTHING" + }, + { + "type": "NODE_SERVICE_SCAN" + }, + { + "type": "NODE_SERVICE_STOP" + }, + { + "type": "NODE_SERVICE_START" + }, + { + "type": "NODE_SERVICE_PAUSE" + }, + { + "type": "NODE_SERVICE_RESUME" + }, + { + "type": "NODE_SERVICE_RESTART" + }, + { + "type": "NODE_SERVICE_DISABLE" + }, + { + "type": "NODE_SERVICE_ENABLE" + }, + { + "type": "NODE_SERVICE_FIX" + }, + { + "type": "NODE_FILE_SCAN" + }, + { + "type": "NODE_FILE_CHECKHASH" + }, + { + "type": "NODE_FILE_DELETE" + }, + { + "type": "NODE_FILE_REPAIR" + }, + { + "type": "NODE_FILE_RESTORE" + }, + { + "type": "NODE_FOLDER_SCAN" + }, + { + "type": "NODE_FOLDER_CHECKHASH" + }, + { + "type": "NODE_FOLDER_REPAIR" + }, + { + "type": "NODE_FOLDER_RESTORE" + }, + { + "type": "NODE_OS_SCAN" + }, + { + "type": "NODE_SHUTDOWN" + }, + { + "type": "NODE_STARTUP" + }, + { + "type": "NODE_RESET" + }, + { + "type": "ROUTER_ACL_ADDRULE" + }, + { + "type": "ROUTER_ACL_REMOVERULE" + }, + { + "type": "HOST_NIC_ENABLE" + }, + { + "type": "HOST_NIC_DISABLE" + } + ], + "action_map": { + "0": { + "action": "DONOTHING", + "options": {} + }, + "1": { + "action": "NODE_SERVICE_SCAN", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "2": { + "action": "NODE_SERVICE_STOP", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "3": { + "action": "NODE_SERVICE_START", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "4": { + "action": "NODE_SERVICE_PAUSE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "5": { + "action": "NODE_SERVICE_RESUME", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "6": { + "action": "NODE_SERVICE_RESTART", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "7": { + "action": "NODE_SERVICE_DISABLE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "8": { + "action": "NODE_SERVICE_ENABLE", + "options": { + "node_id": 1, + "service_id": 0 + } + }, + "9": { + "action": "NODE_FILE_SCAN", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "10": { + "action": "NODE_FILE_CHECKHASH", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "11": { + "action": "NODE_FILE_DELETE", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "12": { + "action": "NODE_FILE_REPAIR", + "options": { + "node_id": 2, + "folder_id": 0, + "file_id": 0 + } + }, + "13": { + "action": "NODE_SERVICE_FIX", + "options": { + "node_id": 2, + "service_id": 0 + } + }, + "14": { + "action": "NODE_FOLDER_SCAN", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "15": { + "action": "NODE_FOLDER_CHECKHASH", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "16": { + "action": "NODE_FOLDER_REPAIR", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "17": { + "action": "NODE_FOLDER_RESTORE", + "options": { + "node_id": 2, + "folder_id": 0 + } + }, + "18": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 0 + } + }, + "19": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 0 + } + }, + "20": { + "action": "NODE_STARTUP", + "options": { + "node_id": 0 + } + }, + "21": { + "action": "NODE_RESET", + "options": { + "node_id": 0 + } + }, + "22": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 1 + } + }, + "23": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 1 + } + }, + "24": { + "action": "NODE_STARTUP", + "options": { + "node_id": 1 + } + }, + "25": { + "action": "NODE_RESET", + "options": { + "node_id": 1 + } + }, + "26": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 2 + } + }, + "27": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 2 + } + }, + "28": { + "action": "NODE_STARTUP", + "options": { + "node_id": 2 + } + }, + "29": { + "action": "NODE_RESET", + "options": { + "node_id": 2 + } + }, + "30": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 3 + } + }, + "31": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 3 + } + }, + "32": { + "action": "NODE_STARTUP", + "options": { + "node_id": 3 + } + }, + "33": { + "action": "NODE_RESET", + "options": { + "node_id": 3 + } + }, + "34": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 4 + } + }, + "35": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 4 + } + }, + "36": { + "action": "NODE_STARTUP", + "options": { + "node_id": 4 + } + }, + "37": { + "action": "NODE_RESET", + "options": { + "node_id": 4 + } + }, + "38": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 5 + } + }, + "39": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 5 + } + }, + "40": { + "action": "NODE_STARTUP", + "options": { + "node_id": 5 + } + }, + "41": { + "action": "NODE_RESET", + "options": { + "node_id": 5 + } + }, + "42": { + "action": "NODE_OS_SCAN", + "options": { + "node_id": 6 + } + }, + "43": { + "action": "NODE_SHUTDOWN", + "options": { + "node_id": 6 + } + }, + "44": { + "action": "NODE_STARTUP", + "options": { + "node_id": 6 + } + }, + "45": { + "action": "NODE_RESET", + "options": { + "node_id": 6 + } + }, + "46": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 1, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 1, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 1, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "47": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 2, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 1, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 1, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "48": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 3, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 3, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "49": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 4, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 3, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "50": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 5, + "permission": 2, + "source_ip_id": 7, + "dest_ip_id": 4, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "51": { + "action": "ROUTER_ACL_ADDRULE", + "options": { + "target_router": "router_1", + "position": 6, + "permission": 2, + "source_ip_id": 8, + "dest_ip_id": 4, + "source_port_id": 1, + "dest_port_id": 1, + "protocol_id": 3, + "source_wildcard_id": 0, + "dest_wildcard_id": 0 + } + }, + "52": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 0 + } + }, + "53": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 1 + } + }, + "54": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 2 + } + }, + "55": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 3 + } + }, + "56": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 4 + } + }, + "57": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 5 + } + }, + "58": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 6 + } + }, + "59": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 7 + } + }, + "60": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 8 + } + }, + "61": { + "action": "ROUTER_ACL_REMOVERULE", + "options": { + "target_router": "router_1", + "position": 9 + } + }, + "62": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 0, + "nic_id": 0 + } + }, + "63": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 0, + "nic_id": 0 + } + }, + "64": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 1, + "nic_id": 0 + } + }, + "65": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 1, + "nic_id": 0 + } + }, + "66": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 2, + "nic_id": 0 + } + }, + "67": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 2, + "nic_id": 0 + } + }, + "68": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 3, + "nic_id": 0 + } + }, + "69": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 3, + "nic_id": 0 + } + }, + "70": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 4, + "nic_id": 0 + } + }, + "71": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 4, + "nic_id": 0 + } + }, + "72": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 4, + "nic_id": 1 + } + }, + "73": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 4, + "nic_id": 1 + } + }, + "74": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 5, + "nic_id": 0 + } + }, + "75": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 5, + "nic_id": 0 + } + }, + "76": { + "action": "HOST_NIC_DISABLE", + "options": { + "node_id": 6, + "nic_id": 0 + } + }, + "77": { + "action": "HOST_NIC_ENABLE", + "options": { + "node_id": 6, + "nic_id": 0 + } + } + }, + "options": { + "nodes": [ + { + "node_name": "domain_controller" + }, + { + "node_name": "web_server", + "applications": [ + { + "application_name": "DatabaseClient" + } + ], + "services": [ + { + "service_name": "WebServer" + } + ] + }, + { + "node_name": "database_server", + "folders": [ + { + "folder_name": "database", + "files": [ + { + "file_name": "database.db" + } + ] + } + ], + "services": [ + { + "service_name": "DatabaseService" + } + ] + }, + { + "node_name": "backup_server" + }, + { + "node_name": "security_suite" + }, + { + "node_name": "client_1" + }, + { + "node_name": "client_2" + } + ], + "max_folders_per_node": 2, + "max_files_per_folder": 2, + "max_services_per_node": 2, + "max_nics_per_node": 8, + "max_acl_rules": 10, + "ip_list": [ + "192.168.1.10", + "192.168.1.12", + "192.168.1.14", + "192.168.1.16", + "192.168.1.110", + "192.168.10.21", + "192.168.10.22", + "192.168.10.110" + ] + } + }, + "reward_function": { + "reward_components": [ + { + "type": "DATABASE_FILE_INTEGRITY", + "weight": 0.4, + "options": { + "node_hostname": "database_server", + "folder_name": "database", + "file_name": "database.db" + } + }, + { + "type": "SHARED_REWARD", + "weight": 1.0, + "options": { + "agent_name": "client_1_green_user" + } + }, + { + "type": "SHARED_REWARD", + "weight": 1.0, + "options": { + "agent_name": "client_2_green_user" + } + } + ] + }, + "agent_settings": { + "flatten_obs": true + } + } + ], + "simulation": { + "network": { + "nmne_config": { + "capture_nmne": true, + "nmne_capture_keywords": [ + "DELETE" + ] + }, + "nodes": [ + { + "hostname": "router_1", + "type": "router", + "num_ports": 5, + "ports": { + "1": { + "ip_address": "192.168.1.1", + "subnet_mask": "255.255.255.0" + }, + "2": { + "ip_address": "192.168.10.1", + "subnet_mask": "255.255.255.0" + } + }, + "acl": { + "18": { + "action": "PERMIT", + "src_port": "POSTGRES_SERVER", + "dst_port": "POSTGRES_SERVER" + }, + "19": { + "action": "PERMIT", + "src_port": "DNS", + "dst_port": "DNS" + }, + "20": { + "action": "PERMIT", + "src_port": "FTP", + "dst_port": "FTP" + }, + "21": { + "action": "PERMIT", + "src_port": "HTTP", + "dst_port": "HTTP" + }, + "22": { + "action": "PERMIT", + "src_port": "ARP", + "dst_port": "ARP" + }, + "23": { + "action": "PERMIT", + "protocol": "ICMP" + } + } + }, + { + "hostname": "switch_1", + "type": "switch", + "num_ports": 8 + }, + { + "hostname": "switch_2", + "type": "switch", + "num_ports": 8 + }, + { + "hostname": "domain_controller", + "type": "server", + "ip_address": "192.168.1.10", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "services": [ + { + "type": "DNSServer", + "options": { + "domain_mapping": { + "arcd.com": "192.168.1.12" + } + } + } + ] + }, + { + "hostname": "web_server", + "type": "server", + "ip_address": "192.168.1.12", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "WebServer" + } + ], + "applications": [ + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ] + }, + { + "hostname": "database_server", + "type": "server", + "ip_address": "192.168.1.14", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "DatabaseService", + "options": { + "backup_server_ip": "192.168.1.16" + } + }, + { + "type": "FTPClient" + } + ] + }, + { + "hostname": "backup_server", + "type": "server", + "ip_address": "192.168.1.16", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "services": [ + { + "type": "FTPServer" + } + ] + }, + { + "hostname": "security_suite", + "type": "server", + "ip_address": "192.168.1.110", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.1.1", + "dns_server": "192.168.1.10", + "network_interfaces": { + "2": { + "ip_address": "192.168.10.110", + "subnet_mask": "255.255.255.0" + } + } + }, + { + "hostname": "client_1", + "type": "computer", + "ip_address": "192.168.10.21", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.10.1", + "dns_server": "192.168.1.10", + "applications": [ + { + "type": "DataManipulationBot", + "options": { + "port_scan_p_of_success": 0.8, + "data_manipulation_p_of_success": 0.8, + "payload": "DELETE", + "server_ip": "192.168.1.14" + } + }, + { + "type": "WebBrowser", + "options": { + "target_url": "http://arcd.com/users/" + } + }, + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ], + "services": [ + { + "type": "DNSClient" + } + ] + }, + { + "hostname": "client_2", + "type": "computer", + "ip_address": "192.168.10.22", + "subnet_mask": "255.255.255.0", + "default_gateway": "192.168.10.1", + "dns_server": "192.168.1.10", + "applications": [ + { + "type": "WebBrowser", + "options": { + "target_url": "http://arcd.com/users/" + } + }, + { + "type": "DataManipulationBot", + "options": { + "port_scan_p_of_success": 0.8, + "data_manipulation_p_of_success": 0.8, + "payload": "DELETE", + "server_ip": "192.168.1.14" + } + }, + { + "type": "DatabaseClient", + "options": { + "db_server_ip": "192.168.1.14" + } + } + ], + "services": [ + { + "type": "DNSClient" + } + ] + } + ], + "links": [ + { + "endpoint_a_hostname": "router_1", + "endpoint_a_port": 1, + "endpoint_b_hostname": "switch_1", + "endpoint_b_port": 8 + }, + { + "endpoint_a_hostname": "router_1", + "endpoint_a_port": 2, + "endpoint_b_hostname": "switch_2", + "endpoint_b_port": 8 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 1, + "endpoint_b_hostname": "domain_controller", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 2, + "endpoint_b_hostname": "web_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 3, + "endpoint_b_hostname": "database_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 4, + "endpoint_b_hostname": "backup_server", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_1", + "endpoint_a_port": 7, + "endpoint_b_hostname": "security_suite", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 1, + "endpoint_b_hostname": "client_1", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 2, + "endpoint_b_hostname": "client_2", + "endpoint_b_port": 1 + }, + { + "endpoint_a_hostname": "switch_2", + "endpoint_a_port": 7, + "endpoint_b_hostname": "security_suite", + "endpoint_b_port": 2 + } + ] + } + } + } +} From f409d0c27c246c711d0dc372ffa36ffed2695692 Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 14:11:48 +0000 Subject: [PATCH 37/42] #2758 - Updated azure-benchmark-pipeline.yaml to use 'Imaginary Yak Pool' --- .azure/azure-benchmark-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 8bd7d08e..378187e4 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -19,7 +19,7 @@ jobs: - job: PrimAITE_Benchmark timeoutInMinutes: 360 # 6-hour maximum pool: - vmImage: ubuntu-latest + name: 'Imaginary Yak Pool' workspace: clean: all steps: From c7431fa0c81f69e269eae39a0a3519aa7045a45f Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 14:20:53 +0000 Subject: [PATCH 38/42] #2758 - Updated azure-benchmark-pipeline.yaml to use python3.10 on the yak pool vm --- .azure/azure-benchmark-pipeline.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 378187e4..f29a85ef 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -47,15 +47,15 @@ jobs: addToPath: true - script: | - python -m pip install --upgrade pip - pip install -e .[dev,rl] + python3.10 -m pip install --upgrade pip + python3.10 -m pip install -e .[dev,rl] primaite setup displayName: 'Install Dependencies' - script: | set -e cd benchmark - python3 primaite_benchmark.py + python3.10 -m pip primaite_benchmark.py cd .. displayName: 'Run Benchmarking Script' From 2900ca9b2af36cd4ef438ad0f531f5dda009f81c Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 14:33:44 +0000 Subject: [PATCH 39/42] #2758 - Updated azure-benchmark-pipeline.yaml so that is created a venv on the vm --- .azure/azure-benchmark-pipeline.yaml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index f29a85ef..0d0575b7 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -22,10 +22,15 @@ jobs: name: 'Imaginary Yak Pool' workspace: clean: all + steps: - checkout: self persistCredentials: true + - script: | + $(python.version)-m venv venv + displayName: 'Create venv' + - script: | VERSION=$(cat src/primaite/VERSION | tr -d '\n') if [[ "$(Build.SourceBranch)" == "refs/heads/dev" ]]; then @@ -41,21 +46,18 @@ jobs: echo "##vso[task.setvariable variable=MAJOR_VERSION]$MAJOR_VERSION" displayName: 'Set Version Variables' - - task: UsePythonVersion@0 - inputs: - versionSpec: '3.11' - addToPath: true - - script: | - python3.10 -m pip install --upgrade pip - python3.10 -m pip install -e .[dev,rl] + source venv/bin/activate + pip install --upgrade pip + pip install -e .[dev,rl] primaite setup displayName: 'Install Dependencies' - script: | set -e + source venv/bin/activate cd benchmark - python3.10 -m pip primaite_benchmark.py + python primaite_benchmark.py cd .. displayName: 'Run Benchmarking Script' From b83bab2e2e916b93862d621cecf0c0d43c8e71ba Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 14:34:51 +0000 Subject: [PATCH 40/42] #2758 - Updated azure-benchmark-pipeline.yaml --- .azure/azure-benchmark-pipeline.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/azure-benchmark-pipeline.yaml b/.azure/azure-benchmark-pipeline.yaml index 0d0575b7..78c40bfd 100644 --- a/.azure/azure-benchmark-pipeline.yaml +++ b/.azure/azure-benchmark-pipeline.yaml @@ -28,7 +28,7 @@ jobs: persistCredentials: true - script: | - $(python.version)-m venv venv + python3.10 -m venv venv displayName: 'Create venv' - script: | From 6b14d6de4444e3a01a956af858727298daf7a8bb Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 15:45:25 +0000 Subject: [PATCH 41/42] Bumped version number to 3.3.0-dev0 --- src/primaite/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/primaite/VERSION b/src/primaite/VERSION index fd2a0186..68d02a53 100644 --- a/src/primaite/VERSION +++ b/src/primaite/VERSION @@ -1 +1 @@ -3.1.0 +3.3.0-dev0 \ No newline at end of file From b651ee3837e3adcb1f16d44bc87743032159e6bc Mon Sep 17 00:00:00 2001 From: Christopher McCarthy Date: Wed, 17 Jul 2024 16:08:30 +0000 Subject: [PATCH 42/42] fixed line ending in VERSION --- src/primaite/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/primaite/VERSION b/src/primaite/VERSION index 68d02a53..6d0e8e51 100644 --- a/src/primaite/VERSION +++ b/src/primaite/VERSION @@ -1 +1 @@ -3.3.0-dev0 \ No newline at end of file +3.3.0-dev0

d}KbBpvCX2_8NHa5IY+0PH0$=O9FeF04W&Gb8 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�%hJlPQjK|v{N4tF`+cRp%* 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