diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..0f1d5fd2 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include src/primaite/config/*.yaml \ No newline at end of file diff --git a/PRIMAITE/docs/Makefile b/docs/Makefile similarity index 100% rename from PRIMAITE/docs/Makefile rename to docs/Makefile diff --git a/PRIMAITE/docs/make.bat b/docs/make.bat similarity index 100% rename from PRIMAITE/docs/make.bat rename to docs/make.bat diff --git a/PRIMAITE/docs/source/about.rst b/docs/source/about.rst similarity index 100% rename from PRIMAITE/docs/source/about.rst rename to docs/source/about.rst diff --git a/PRIMAITE/docs/source/conf.py b/docs/source/conf.py similarity index 100% rename from PRIMAITE/docs/source/conf.py rename to docs/source/conf.py diff --git a/PRIMAITE/docs/source/config.rst b/docs/source/config.rst similarity index 100% rename from PRIMAITE/docs/source/config.rst rename to docs/source/config.rst diff --git a/PRIMAITE/docs/source/dependencies.rst b/docs/source/dependencies.rst similarity index 100% rename from PRIMAITE/docs/source/dependencies.rst rename to docs/source/dependencies.rst diff --git a/PRIMAITE/docs/source/index.rst b/docs/source/index.rst similarity index 100% rename from PRIMAITE/docs/source/index.rst rename to docs/source/index.rst diff --git a/PRIMAITE/docs/source/results.rst b/docs/source/results.rst similarity index 89% rename from PRIMAITE/docs/source/results.rst rename to docs/source/results.rst index 46296a82..cbf27d88 100644 --- a/PRIMAITE/docs/source/results.rst +++ b/docs/source/results.rst @@ -10,9 +10,9 @@ PrimAITE produces four types of data: * Outputs - Saved agents * Logging -Outputs can be found in the *[Install Directory]\\PRIMAITE\\PRIMAITE\\outputs* directory +Outputs can be found in the *[Install Directory]\\Primaite\\Primaite\\outputs* directory -Logging can be found in the *[Install Directory]\\PRIMAITE\\PRIMAITE\\logs* directory +Logging can be found in the *[Install Directory]\\Primaite\\Primaite\\logs* directory **Outputs - Results** @@ -39,4 +39,4 @@ For each training session, assuming the agent being trained implements the *save **Logging** -PrimAITE also provides output logs (for diagnosis) using the Python Logging package. These can be found in the *[Install Directory]\\PRIMAITE\\PRIMAITE\\logs* directory \ No newline at end of file +PrimAITE also provides output logs (for diagnosis) using the Python Logging package. These can be found in the *[Install Directory]\\Primaite\\Primaite\\logs* directory \ No newline at end of file diff --git a/PRIMAITE/docs/source/session.rst b/docs/source/session.rst similarity index 97% rename from PRIMAITE/docs/source/session.rst rename to docs/source/session.rst index 81deb826..6a4a458c 100644 --- a/PRIMAITE/docs/source/session.rst +++ b/docs/source/session.rst @@ -80,8 +80,8 @@ environment is reset between episodes. Note that the example below should not be In order to execute a session, carry out the following steps: -1. Navigate to "[Install directory]\\PRIMAITE\\PRIMAITE\\” -2. Start a console window (type “CMD” in path window, or start a console window first and navigate to “[Install Directory]\\PRIMAITE\\PRIMAITE\\”) +1. Navigate to "[Install directory]\\Primaite\\Primaite\\” +2. Start a console window (type “CMD” in path window, or start a console window first and navigate to “[Install Directory]\\Primaite\\Primaite\\”) 3. Type “python main.py” 4. The session will start with an output indicating the current episode, and average reward value for the episode diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..9524c74e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,60 @@ +[build-system] +requires = ["setuptools", "setuptools-scm", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "primaite" +description = "PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme." +authors = [{name="QinetiQ Training and Simulation Ltd"}] +license = {text = "GFX"} +requires-python = ">=3.8" +dynamic = ["version", "readme"] +classifiers = [ + "License :: GFX", + "Development Status :: 4 - Beta", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Unix", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3 :: Only", +] + +dependencies = [ + "gym==0.21.0", + "matplotlib==3.7.1", + "networkx==3.1", + "numpy==1.23.5", + "PyYAML==6.0", + "stable-baselines3==1.6.2" +] + +[tool.setuptools.dynamic] +version = {file = ["src/primaite/VERSION"]} +readme = {file = ["README.md"]} + +[tool.setuptools] +package-dir = {"" = "src"} +include-package-data = true +license-files = ["LICENSE"] + + +[project.optional-dependencies] +dev = [ + "setuptools==66", + "pytest==7.2.0", + "flake8==6.0.0", + "Sphinx==6.1.3", + "furo==2023.3.27", + "sphinx-code-tabs==0.5.3", + "sphinx-copybutton==0.5.2", + "pytest-cov==4.0.0", + "pytest-flake8==1.1.1", + "pip-licenses==4.3.0", + "wheel==0.38.4", + "build==0.10.0" +] diff --git a/setup.py b/setup.py index 8d0b7e8b..a700336a 100644 --- a/setup.py +++ b/setup.py @@ -1,26 +1,17 @@ # Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence. -""" -Setup -""" +from setuptools import setup +from wheel.bdist_wheel import bdist_wheel as _bdist_wheel -from setuptools import find_packages, setup + +class bdist_wheel(_bdist_wheel): # noqa + def finalize_options(self): # noqa + super().finalize_options() + # forces whee to be platform and Python version specific + # Source: https://stackoverflow.com/a/45150383 + self.root_is_pure = False setup( - name="primaite", - maintainer="QinetiQ Training and Simulation Ltd", - url="https://github.com/qtsl/PrimAITE", - description="A primary-level simulation tool", - python_requires=">=3.7", - version="1.1.0", - install_requires=[ - "gym==0.21.0", - "matplotlib==3.6.2", - "networkx==2.8.8", - "numpy==1.23.5", - "stable_baselines3==1.6.2", - # Required for older versions of Gym that aren't compliant with - # Setuptools>=67. - "setuptools==66" - ], - packages=find_packages() -) + cmdclass={ + "bdist_wheel": bdist_wheel, + } +) \ No newline at end of file diff --git a/src/VERSION b/src/VERSION new file mode 100644 index 00000000..867e5243 --- /dev/null +++ b/src/VERSION @@ -0,0 +1 @@ +1.2.0 \ No newline at end of file diff --git a/PRIMAITE/Main.py b/src/primaite/Main.py similarity index 97% rename from PRIMAITE/Main.py rename to src/primaite/Main.py index d5aa0e5a..de5b6e10 100644 --- a/PRIMAITE/Main.py +++ b/src/primaite/Main.py @@ -1,6 +1,6 @@ # Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence. """ -PRIMAITE - main (harness) module +Primaite - main (harness) module Coding Standards: PEP 8 """ @@ -12,9 +12,9 @@ import os.path import logging from datetime import datetime -from environment.primaite import PRIMAITE -from transactions.transactions_to_file import write_transaction_to_file -from common.config_values_main import config_values_main +from primaite.environment.primaite_env import Primaite +from primaite.transactions.transactions_to_file import write_transaction_to_file +from primaite.common.config_values_main import config_values_main from stable_baselines3 import PPO from stable_baselines3.ppo import MlpPolicy as PPOMlp @@ -271,9 +271,9 @@ except Exception as e: # - new observation space transaction_list = [] -# Create the PRIMAITE environment +# Create the Primaite environment try: - env = PRIMAITE(config_values, transaction_list) + env = Primaite(config_values, transaction_list) logging.info("PrimAITE environment created") except Exception as e: logging.error("Could not create PrimAITE environment") diff --git a/PRIMAITE/acl/__init__.py b/src/primaite/acl/__init__.py similarity index 100% rename from PRIMAITE/acl/__init__.py rename to src/primaite/acl/__init__.py diff --git a/PRIMAITE/acl/access_control_list.py b/src/primaite/acl/access_control_list.py similarity index 99% rename from PRIMAITE/acl/access_control_list.py rename to src/primaite/acl/access_control_list.py index eb5b7ab1..7aa22f5d 100644 --- a/PRIMAITE/acl/access_control_list.py +++ b/src/primaite/acl/access_control_list.py @@ -3,7 +3,7 @@ A class that implements the access control list implementation for the network """ -from acl.acl_rule import ACLRule +from primaite.acl.acl_rule import ACLRule class AccessControlList(): """ diff --git a/PRIMAITE/acl/acl_rule.py b/src/primaite/acl/acl_rule.py similarity index 100% rename from PRIMAITE/acl/acl_rule.py rename to src/primaite/acl/acl_rule.py diff --git a/PRIMAITE/common/__init__.py b/src/primaite/common/__init__.py similarity index 100% rename from PRIMAITE/common/__init__.py rename to src/primaite/common/__init__.py diff --git a/PRIMAITE/common/config_values_main.py b/src/primaite/common/config_values_main.py similarity index 100% rename from PRIMAITE/common/config_values_main.py rename to src/primaite/common/config_values_main.py diff --git a/PRIMAITE/common/enums.py b/src/primaite/common/enums.py similarity index 100% rename from PRIMAITE/common/enums.py rename to src/primaite/common/enums.py diff --git a/PRIMAITE/common/protocol.py b/src/primaite/common/protocol.py similarity index 100% rename from PRIMAITE/common/protocol.py rename to src/primaite/common/protocol.py diff --git a/PRIMAITE/common/service.py b/src/primaite/common/service.py similarity index 97% rename from PRIMAITE/common/service.py rename to src/primaite/common/service.py index 6b3d6b61..35032440 100644 --- a/PRIMAITE/common/service.py +++ b/src/primaite/common/service.py @@ -3,7 +3,7 @@ The Service class """ -from common.enums import SOFTWARE_STATE +from primaite.common.enums import SOFTWARE_STATE class Service(object): """ diff --git a/PRIMAITE/tests/test_reward.py b/src/primaite/config/__init__.py similarity index 100% rename from PRIMAITE/tests/test_reward.py rename to src/primaite/config/__init__.py diff --git a/PRIMAITE/config/config_1_DDOS_BASIC.yaml b/src/primaite/config/config_1_DDOS_BASIC.yaml similarity index 100% rename from PRIMAITE/config/config_1_DDOS_BASIC.yaml rename to src/primaite/config/config_1_DDOS_BASIC.yaml diff --git a/PRIMAITE/config/config_2_DDOS_BASIC.yaml b/src/primaite/config/config_2_DDOS_BASIC.yaml similarity index 100% rename from PRIMAITE/config/config_2_DDOS_BASIC.yaml rename to src/primaite/config/config_2_DDOS_BASIC.yaml diff --git a/PRIMAITE/config/config_3_DOS_VERY_BASIC.yaml b/src/primaite/config/config_3_DOS_VERY_BASIC.yaml similarity index 100% rename from PRIMAITE/config/config_3_DOS_VERY_BASIC.yaml rename to src/primaite/config/config_3_DOS_VERY_BASIC.yaml diff --git a/PRIMAITE/config/config_5_DATA_MANIPULATION.yaml b/src/primaite/config/config_5_DATA_MANIPULATION.yaml similarity index 100% rename from PRIMAITE/config/config_5_DATA_MANIPULATION.yaml rename to src/primaite/config/config_5_DATA_MANIPULATION.yaml diff --git a/PRIMAITE/config/config_UNIT_TEST.yaml b/src/primaite/config/config_UNIT_TEST.yaml similarity index 100% rename from PRIMAITE/config/config_UNIT_TEST.yaml rename to src/primaite/config/config_UNIT_TEST.yaml diff --git a/PRIMAITE/config/config_main.yaml b/src/primaite/config/config_main.yaml similarity index 99% rename from PRIMAITE/config/config_main.yaml rename to src/primaite/config/config_main.yaml index f0940c0d..4c16750f 100644 --- a/PRIMAITE/config/config_main.yaml +++ b/src/primaite/config/config_main.yaml @@ -7,7 +7,7 @@ # "GENERIC" agentIdentifier: STABLE_BASELINES3_A2C # Number of episodes to run per session -numEpisodes: 10 +numEpisodes: 10000 # Time delay between steps (for generic agents) timeDelay: 10 # Filename of the scenario / laydown diff --git a/PRIMAITE/environment/__init__.py b/src/primaite/environment/__init__.py similarity index 100% rename from PRIMAITE/environment/__init__.py rename to src/primaite/environment/__init__.py diff --git a/PRIMAITE/environment/primaite.py b/src/primaite/environment/primaite_env.py similarity index 97% rename from PRIMAITE/environment/primaite.py rename to src/primaite/environment/primaite_env.py index 754deeb0..dc37c93e 100644 --- a/PRIMAITE/environment/primaite.py +++ b/src/primaite/environment/primaite_env.py @@ -1,6 +1,6 @@ # Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence. """ -Main environment module containing the PRIMmary AI Training Evironment (PRIMAITE) class +Main environment module containing the PRIMmary AI Training Evironment (Primaite) class """ import numpy as np @@ -15,24 +15,24 @@ from gym import Env, spaces from matplotlib import pyplot as plt from datetime import datetime -from common.enums import * -from links.link import Link -from pol.ier import IER -from nodes.node_state_instruction_green import NodeStateInstructionGreen -from nodes.node_state_instruction_red import NodeStateInstructionRed -from pol.green_pol import apply_iers, apply_node_pol -from pol.red_agent_pol import apply_red_agent_iers, apply_red_agent_node_pol -from nodes.active_node import ActiveNode -from nodes.passive_node import PassiveNode -from nodes.service_node import ServiceNode -from common.service import Service -from acl.access_control_list import AccessControlList -from environment.reward import calculate_reward_function -from transactions.transaction import Transaction +from primaite.common.enums import * +from primaite.links.link import Link +from primaite.pol.ier import IER +from primaite.nodes.node_state_instruction_green import NodeStateInstructionGreen +from primaite.nodes.node_state_instruction_red import NodeStateInstructionRed +from primaite.pol.green_pol import apply_iers, apply_node_pol +from primaite.pol.red_agent_pol import apply_red_agent_iers, apply_red_agent_node_pol +from primaite.nodes.active_node import ActiveNode +from primaite.nodes.passive_node import PassiveNode +from primaite.nodes.service_node import ServiceNode +from primaite.common.service import Service +from primaite.acl.access_control_list import AccessControlList +from primaite.environment.reward import calculate_reward_function +from primaite.transactions.transaction import Transaction -class PRIMAITE(Env): +class Primaite(Env): """ - PRIMmary AI Training Evironment (PRIMAITE) class + PRIMmary AI Training Evironment (Primaite) class """ # Observation / Action Space contants @@ -55,7 +55,7 @@ class PRIMAITE(Env): _agent_identifier: Identifier for the agent """ - super(PRIMAITE, self).__init__() + super(Primaite, self).__init__() # Take a copy of the config values self.config_values = _config_values diff --git a/PRIMAITE/environment/reward.py b/src/primaite/environment/reward.py similarity index 99% rename from PRIMAITE/environment/reward.py rename to src/primaite/environment/reward.py index 8685aacd..0140849c 100644 --- a/PRIMAITE/environment/reward.py +++ b/src/primaite/environment/reward.py @@ -3,9 +3,9 @@ Implements reward function """ -from common.enums import * -from nodes.active_node import ActiveNode -from nodes.service_node import ServiceNode +from primaite.common.enums import * +from primaite.nodes.active_node import ActiveNode +from primaite.nodes.service_node import ServiceNode def calculate_reward_function(initial_nodes, final_nodes, reference_nodes, green_iers, red_iers, step_count, config_values): """ diff --git a/PRIMAITE/links/__init__.py b/src/primaite/links/__init__.py similarity index 100% rename from PRIMAITE/links/__init__.py rename to src/primaite/links/__init__.py diff --git a/PRIMAITE/links/link.py b/src/primaite/links/link.py similarity index 97% rename from PRIMAITE/links/link.py rename to src/primaite/links/link.py index 5155e541..0de5e4d2 100644 --- a/PRIMAITE/links/link.py +++ b/src/primaite/links/link.py @@ -3,8 +3,8 @@ The link class """ -from common.protocol import Protocol -from common.enums import * +from primaite.common.protocol import Protocol +from primaite.common.enums import * class Link(object): """ diff --git a/PRIMAITE/nodes/__init__.py b/src/primaite/nodes/__init__.py similarity index 100% rename from PRIMAITE/nodes/__init__.py rename to src/primaite/nodes/__init__.py diff --git a/PRIMAITE/nodes/active_node.py b/src/primaite/nodes/active_node.py similarity index 98% rename from PRIMAITE/nodes/active_node.py rename to src/primaite/nodes/active_node.py index 3cd1c01f..0ae564aa 100644 --- a/PRIMAITE/nodes/active_node.py +++ b/src/primaite/nodes/active_node.py @@ -3,8 +3,8 @@ An Active Node (i.e. not an actuator) """ -from nodes.node import Node -from common.enums import * +from primaite.nodes.node import Node +from primaite.common.enums import * class ActiveNode(Node): """ diff --git a/PRIMAITE/nodes/node.py b/src/primaite/nodes/node.py similarity index 98% rename from PRIMAITE/nodes/node.py rename to src/primaite/nodes/node.py index a6964666..f2746e3d 100644 --- a/PRIMAITE/nodes/node.py +++ b/src/primaite/nodes/node.py @@ -3,7 +3,7 @@ The base Node class """ -from common.enums import * +from primaite.common.enums import * class Node: """ diff --git a/PRIMAITE/nodes/node_state_instruction_green.py b/src/primaite/nodes/node_state_instruction_green.py similarity index 100% rename from PRIMAITE/nodes/node_state_instruction_green.py rename to src/primaite/nodes/node_state_instruction_green.py diff --git a/PRIMAITE/nodes/node_state_instruction_red.py b/src/primaite/nodes/node_state_instruction_red.py similarity index 100% rename from PRIMAITE/nodes/node_state_instruction_red.py rename to src/primaite/nodes/node_state_instruction_red.py diff --git a/PRIMAITE/nodes/passive_node.py b/src/primaite/nodes/passive_node.py similarity index 93% rename from PRIMAITE/nodes/passive_node.py rename to src/primaite/nodes/passive_node.py index dfce4713..7ad6362b 100644 --- a/PRIMAITE/nodes/passive_node.py +++ b/src/primaite/nodes/passive_node.py @@ -3,7 +3,7 @@ The Passive Node class (i.e. an actuator) """ -from nodes.node import Node +from primaite.nodes.node import Node class PassiveNode(Node): """ diff --git a/PRIMAITE/nodes/service_node.py b/src/primaite/nodes/service_node.py similarity index 98% rename from PRIMAITE/nodes/service_node.py rename to src/primaite/nodes/service_node.py index 7c908dec..2408723f 100644 --- a/PRIMAITE/nodes/service_node.py +++ b/src/primaite/nodes/service_node.py @@ -3,8 +3,8 @@ A Service Node (i.e. not an actuator) """ -from nodes.active_node import ActiveNode -from common.enums import * +from primaite.nodes.active_node import ActiveNode +from primaite.common.enums import * class ServiceNode(ActiveNode): """ diff --git a/PRIMAITE/pol/__init__.py b/src/primaite/pol/__init__.py similarity index 100% rename from PRIMAITE/pol/__init__.py rename to src/primaite/pol/__init__.py diff --git a/PRIMAITE/pol/green_pol.py b/src/primaite/pol/green_pol.py similarity index 98% rename from PRIMAITE/pol/green_pol.py rename to src/primaite/pol/green_pol.py index 27afbb4d..6d0ab70c 100644 --- a/PRIMAITE/pol/green_pol.py +++ b/src/primaite/pol/green_pol.py @@ -5,9 +5,9 @@ Implements Pattern of Life on the network (nodes and links) from networkx import shortest_path -from common.enums import * -from nodes.active_node import ActiveNode -from nodes.service_node import ServiceNode +from primaite.common.enums import * +from primaite.nodes.active_node import ActiveNode +from primaite.nodes.service_node import ServiceNode _VERBOSE = False diff --git a/PRIMAITE/pol/ier.py b/src/primaite/pol/ier.py similarity index 100% rename from PRIMAITE/pol/ier.py rename to src/primaite/pol/ier.py diff --git a/PRIMAITE/pol/red_agent_pol.py b/src/primaite/pol/red_agent_pol.py similarity index 98% rename from PRIMAITE/pol/red_agent_pol.py rename to src/primaite/pol/red_agent_pol.py index 7d13e565..ff99af74 100644 --- a/PRIMAITE/pol/red_agent_pol.py +++ b/src/primaite/pol/red_agent_pol.py @@ -5,9 +5,9 @@ Implements Pattern of Life on the network (nodes and links) resulting from the r from networkx import shortest_path -from common.enums import * -from nodes.active_node import ActiveNode -from nodes.service_node import ServiceNode +from primaite.common.enums import * +from primaite.nodes.active_node import ActiveNode +from primaite.nodes.service_node import ServiceNode _VERBOSE = False diff --git a/PRIMAITE/transactions/__init__.py b/src/primaite/transactions/__init__.py similarity index 100% rename from PRIMAITE/transactions/__init__.py rename to src/primaite/transactions/__init__.py diff --git a/PRIMAITE/transactions/transaction.py b/src/primaite/transactions/transaction.py similarity index 100% rename from PRIMAITE/transactions/transaction.py rename to src/primaite/transactions/transaction.py diff --git a/PRIMAITE/transactions/transactions_to_file.py b/src/primaite/transactions/transactions_to_file.py similarity index 98% rename from PRIMAITE/transactions/transactions_to_file.py rename to src/primaite/transactions/transactions_to_file.py index 139fd22d..0e892791 100644 --- a/PRIMAITE/transactions/transactions_to_file.py +++ b/src/primaite/transactions/transactions_to_file.py @@ -9,7 +9,7 @@ import os.path from datetime import datetime -from transactions.transaction import Transaction +from primaite.transactions.transaction import Transaction def turn_action_space_to_array(_action_space): """ diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/PRIMAITE/tests/test_acl.py b/tests/test_acl.py similarity index 96% rename from PRIMAITE/tests/test_acl.py rename to tests/test_acl.py index f38c5432..643f01e3 100644 --- a/PRIMAITE/tests/test_acl.py +++ b/tests/test_acl.py @@ -4,8 +4,8 @@ Used to tes the ACL functions """ -from acl.acl_rule import ACLRule -from acl.access_control_list import AccessControlList +from primaite.acl.acl_rule import ACLRule +from primaite.acl.access_control_list import AccessControlList def test_acl_address_match_1(): """ diff --git a/tests/test_reward.py b/tests/test_reward.py new file mode 100644 index 00000000..e69de29b