diff --git a/README.rst b/README.rst index 3d05d9a..38a7c57 100755 --- a/README.rst +++ b/README.rst @@ -79,6 +79,12 @@ License What's new ---------- + +- 2023-05-14 (v 0.12.0) (MINOR release) + + + Renamed `NASimEnv.get_minimum_actions -> NASimEnv.get_minumum_hops` to better reflect what it does (thanks @rzvnbr for the suggestion). + + - 2023-03-13 (v 0.11.0) (MINOR release) + Migrated to `gymnasium (formerly Open AI gym) `_ fromOpen AI gym (thanks @rzvnbr for the suggestion). diff --git a/docs/source/index.rst b/docs/source/index.rst index 78a9b87..4c44be2 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -9,6 +9,12 @@ The environment is modelled after the `gymnasium (formerly Open AI gym) NASimEnv.get_minumum_hops` to better reflect what it does (thanks @rzvnbr for the suggestion). + + Version 0.11.0 ************** diff --git a/nasim/__init__.py b/nasim/__init__.py index 2e6a575..40e593b 100755 --- a/nasim/__init__.py +++ b/nasim/__init__.py @@ -211,4 +211,4 @@ def _register(id, entry_point, kwargs, nondeterministic, force=True): nondeterministic=True ) -__version__ = "0.11.0" +__version__ = "0.12.0" diff --git a/nasim/envs/environment.py b/nasim/envs/environment.py index 6a87f7f..dcd74be 100755 --- a/nasim/envs/environment.py +++ b/nasim/envs/environment.py @@ -395,18 +395,19 @@ def render_network_graph(self, ax=None, show=False): state = self.current_state self._renderer.render_graph(state, ax, show) - def get_minimum_actions(self): - """Get the minimum number of actions required to reach the goal. + def get_minimum_hops(self): + """Get the minimum number of network hops required to reach targets. - That is minimum number of actions to exploit all sensitive hosts on - the network starting from the initial state + That is minimum number of hosts that must be traversed in the network + in order to reach all sensitive hosts on the network starting from the + initial state Returns ------- int - minumum possible actions to reach goal + minumum possible number of network hops to reach target hosts """ - return self.network.get_minimal_steps() + return self.network.get_minimal_hops() def get_action_mask(self): """Get a vector mask for valid actions. @@ -432,10 +433,10 @@ def get_score_upper_bound(self): The theoretical upper bound score is where the agent exploits only a single host in each subnet that is required to reach sensitive hosts - along the shortest bath in network graph, and exploits the two - sensitive hosts (i.e. the minial steps). Assuming action cost of 1 and - each sensitive host is exploitable from any other connected subnet - (which may not be true, hence being an upper bound). + along the shortest bath in network graph, and exploits the all + sensitive hosts (i.e. the minimum network hops). Assuming action cost + of 1 and each sensitive host is exploitable from any other connected + subnet (which may not be true, hence being an upper bound). Returns ------- @@ -444,7 +445,7 @@ def get_score_upper_bound(self): """ max_reward = self.network.get_total_sensitive_host_value() max_reward += self.network.get_total_discovery_value() - max_reward -= self.network.get_minimal_steps() + max_reward -= self.network.get_minimal_hops() return max_reward def goal_reached(self, state=None): diff --git a/nasim/envs/network.py b/nasim/envs/network.py index 359b188..5284d1f 100755 --- a/nasim/envs/network.py +++ b/nasim/envs/network.py @@ -1,7 +1,7 @@ import numpy as np from nasim.envs.action import ActionResult -from nasim.envs.utils import get_minimal_steps_to_goal, min_subnet_depth, AccessLevel +from nasim.envs.utils import get_minimal_hops_to_goal, min_subnet_depth, AccessLevel # column in topology adjacency matrix that represents connection between # subnet and public @@ -225,8 +225,8 @@ def get_total_discovery_value(self): total += host.discovery_value return total - def get_minimal_steps(self): - return get_minimal_steps_to_goal( + def get_minimal_hops(self): + return get_minimal_hops_to_goal( self.topology, self.sensitive_addresses ) diff --git a/nasim/envs/utils.py b/nasim/envs/utils.py index d348789..7b4fca8 100644 --- a/nasim/envs/utils.py +++ b/nasim/envs/utils.py @@ -49,15 +49,15 @@ def __repr__(self): return self.name -def get_minimal_steps_to_goal(topology, sensitive_addresses): - """Get the minimum total number of steps required to reach all sensitive - hosts in the network starting from outside the network (i.e. can only - reach exposed subnets). +def get_minimal_hops_to_goal(topology, sensitive_addresses): + """Get minimum network hops required to reach all sensitive hosts. + + Starting from outside the network (i.e. can only reach exposed subnets). Returns ------- int - minimum number of steps to reach all sensitive hosts + minimum number of network hops to reach all sensitive hosts """ num_subnets = len(topology) max_value = np.iinfo(np.int16).max diff --git a/test/test_env.py b/test/test_env.py index 149f476..2f3943e 100644 --- a/test/test_env.py +++ b/test/test_env.py @@ -60,3 +60,14 @@ def test_get_total_sensitive_host_value(scenario, expected_value): env.reset() actual_value = env.network.get_total_sensitive_host_value() assert actual_value == expected_value + + +@pytest.mark.parametrize( + ("scenario", "expected_value"), + [("tiny", 3), ("small", 4)] +) +def test_get_minumum_hops(scenario, expected_value): + env = nasim.make_benchmark(scenario) + env.reset() + actual_value = env.get_minimum_hops() + assert actual_value == expected_value