-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
345 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# HSVI c++ | ||
|
||
This directory contains example scripts for solving OS-POSGs using [hsvi](https://www.sciencedirect.com/science/article/pii/S0004370222001783). | ||
|
||
Command for running hsvi with game file "apt_game.posg", 0.01 epsilon (target precision), | ||
4 pDelta (presolve delta which determined the lenght of the presolve phase), and 2000 pLimit (presolve time-limit) | ||
```bash | ||
./StochasticGamesCpp games/apt_game.posg 0.01 4 2000 | ||
``` | ||
|
||
## Author & Maintainer | ||
|
||
Kim Hammar <[email protected]> | ||
|
||
## Copyright and license | ||
|
||
[LICENSE](../../../LICENSE.md) | ||
|
||
Creative Commons | ||
|
||
(C) 2020-2024, Kim Hammar |
40 changes: 40 additions & 0 deletions
40
examples/training/posg_solve/intrusion_recovery_pomdp/run_vs_random_attacker_v_001.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import numpy as np | ||
from csle_tolerance.dao.intrusion_recovery_game_config import IntrusionRecoveryGameConfig | ||
from csle_tolerance.util.intrusion_recovery_pomdp_util import IntrusionRecoveryPomdpUtil | ||
|
||
if __name__ == '__main__': | ||
eta = 8 | ||
p_a = 1 | ||
p_c_1 = 0.01 | ||
BTR = np.inf | ||
negate_costs = False | ||
discount_factor = 0.999 | ||
num_observations = 10 | ||
simulation_name = "csle-tolerance-intrusion-recovery-pomdp-defender-001" | ||
cost_tensor = IntrusionRecoveryPomdpUtil.cost_tensor(eta=eta, states=IntrusionRecoveryPomdpUtil.state_space(), | ||
actions=IntrusionRecoveryPomdpUtil.action_space(), | ||
negate=negate_costs) | ||
observation_tensor = IntrusionRecoveryPomdpUtil.observation_tensor( | ||
states=IntrusionRecoveryPomdpUtil.state_space(), | ||
observations=IntrusionRecoveryPomdpUtil.observation_space(num_observations=num_observations)) | ||
transition_tensor = IntrusionRecoveryPomdpUtil.transition_tensor_game( | ||
states=IntrusionRecoveryPomdpUtil.state_space(), defender_actions=IntrusionRecoveryPomdpUtil.action_space(), | ||
attacker_actions=IntrusionRecoveryPomdpUtil.action_space(), p_a=p_a, p_c_1=p_c_1) | ||
config = IntrusionRecoveryGameConfig( | ||
eta=eta, p_a=p_a, p_c_1=p_c_1, BTR=BTR, negate_costs=negate_costs, seed=999, | ||
discount_factor=discount_factor, states=IntrusionRecoveryPomdpUtil.state_space(), | ||
actions=IntrusionRecoveryPomdpUtil.action_space(), | ||
observations=IntrusionRecoveryPomdpUtil.observation_space(num_observations=num_observations), | ||
cost_tensor=cost_tensor, observation_tensor=observation_tensor, transition_tensor=transition_tensor, | ||
b1=IntrusionRecoveryPomdpUtil.initial_belief(p_a=p_a), T=BTR, | ||
simulation_env_name=simulation_name, gym_env_name="csle-tolerance-intrusion-recovery-pomdp-v1" | ||
) | ||
|
||
# s = 0 | ||
# for i in range(100): | ||
# s = IntrusionRecoveryPomdpUtil.sample_next_state_game(transition_tensor=config.transition_tensor, s=s, | ||
# a1=0, a2=1) | ||
# c = config.cost_tensor[0][s] | ||
# print(f"cost: {c}, s: {s}") | ||
|
||
IntrusionRecoveryPomdpUtil.generate_os_posg_game_file(game_config=config) |
123 changes: 123 additions & 0 deletions
123
...ation-system/libs/csle-tolerance/src/csle_tolerance/dao/intrusion_recovery_game_config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
from typing import List, Dict, Any | ||
import numpy as np | ||
from csle_common.dao.simulation_config.simulation_env_input_config import SimulationEnvInputConfig | ||
|
||
|
||
class IntrusionRecoveryGameConfig(SimulationEnvInputConfig): | ||
""" | ||
DTO containing the configuration of an intrusion recovery POSG | ||
""" | ||
|
||
def __init__(self, eta: float, p_a: float, p_c_1: float, BTR: int, negate_costs: bool, | ||
seed: int, discount_factor: float, states: List[int], actions: List[int], observations: List[int], | ||
cost_tensor: List[List[float]], observation_tensor: List[List[float]], | ||
transition_tensor: List[List[List[List[float]]]], b1: List[float], T: int, simulation_env_name: str, | ||
gym_env_name: str, max_horizon: float = np.inf) -> None: | ||
""" | ||
Initializes the DTO | ||
:param eta: the scaling factor for the cost function | ||
:param p_a: the intrusion probability | ||
:param p_c_1: the crash probability in the healthy state | ||
:param BTR: the periodic recovery interval | ||
:param negate_costs: boolean flag indicating whether costs should be negated or not | ||
:param seed: the random seed | ||
:param discount_factor: the discount factor | ||
:param states: the list of states | ||
:param actions: the list of actions | ||
:param observations: the list of observations | ||
:param cost_tensor: the cost tensor | ||
:param observation_tensor: the observation tensor | ||
:param transition_tensor: the transition tensor | ||
:param b1: the initial belief | ||
:param T: the time horizon | ||
:param simulation_env_name: name of the simulation environment | ||
:param gym_env_name: name of the gym environment | ||
:param max_horizon: the maximum horizon to avoid infinie simulations | ||
""" | ||
self.eta = eta | ||
self.p_a = p_a | ||
self.p_c_1 = p_c_1 | ||
self.BTR = BTR | ||
self.negate_costs = negate_costs | ||
self.seed = seed | ||
self.discount_factor = discount_factor | ||
self.states = states | ||
self.actions = actions | ||
self.observations = observations | ||
self.cost_tensor = cost_tensor | ||
self.observation_tensor = observation_tensor | ||
self.transition_tensor = transition_tensor | ||
self.b1 = b1 | ||
self.T = T | ||
self.simulation_env_name = simulation_env_name | ||
self.gym_env_name = gym_env_name | ||
self.max_horizon = max_horizon | ||
|
||
def __str__(self) -> str: | ||
""" | ||
:return: a string representation of the DTO | ||
""" | ||
return (f"eta: {self.eta}, p_a: {self.p_a}, p_c_1: {self.p_c_1}," | ||
f"BTR: {self.BTR}, negate_costs: {self.negate_costs}, seed: {self.seed}, " | ||
f"discount_factor: {self.discount_factor}, states: {self.states}, actions: {self.actions}, " | ||
f"observations: {self.observation_tensor}, cost_tensor: {self.cost_tensor}, " | ||
f"observation_tensor: {self.observation_tensor}, transition_tensor: {self.transition_tensor}, " | ||
f"b1:{self.b1}, T: {self.T}, simulation_env_name: {self.simulation_env_name}, " | ||
f"gym_env_name: {self.gym_env_name}, max_horizon: {self.max_horizon}") | ||
|
||
@staticmethod | ||
def from_dict(d: Dict[str, Any]) -> "IntrusionRecoveryGameConfig": | ||
""" | ||
Converts a dict representation to an instance | ||
:param d: the dict to convert | ||
:return: the created instance | ||
""" | ||
dto = IntrusionRecoveryGameConfig( | ||
eta=d["eta"], p_a=d["p_a"], p_c_1=d["p_c_1"], BTR=d["BTR"], | ||
negate_costs=d["negate_costs"], seed=d["seed"], discount_factor=d["discount_factor"], states=d["states"], | ||
actions=d["actions"], observations=d["observations"], cost_tensor=d["cost_tensor"], | ||
observation_tensor=d["observation_tensor"], transition_tensor=d["transition_tensor"], b1=d["b1"], | ||
T=d["T"], simulation_env_name=d["simulation_env_name"], gym_env_name=d["gym_env_name"]) | ||
return dto | ||
|
||
def to_dict(self) -> Dict[str, Any]: | ||
""" | ||
Gets a dict representation of the object | ||
:return: A dict representation of the object | ||
""" | ||
d: Dict[str, Any] = {} | ||
d["eta"] = self.eta | ||
d["p_a"] = self.p_a | ||
d["p_c_1"] = self.p_c_1 | ||
d["BTR"] = self.BTR | ||
d["negate_costs"] = self.negate_costs | ||
d["seed"] = self.seed | ||
d["discount_factor"] = self.discount_factor | ||
d["states"] = self.states | ||
d["actions"] = self.actions | ||
d["observations"] = self.observations | ||
d["cost_tensor"] = self.cost_tensor | ||
d["observation_tensor"] = self.observation_tensor | ||
d["transition_tensor"] = self.transition_tensor | ||
d["b1"] = self.b1 | ||
d["T"] = self.T | ||
d["simulation_env_name"] = self.simulation_env_name | ||
d["gym_env_name"] = self.simulation_env_name | ||
return d | ||
|
||
@staticmethod | ||
def from_json_file(json_file_path: str) -> "IntrusionRecoveryGameConfig": | ||
""" | ||
Reads a json file and converts it to a DTO | ||
:param json_file_path: the json file path | ||
:return: the converted DTO | ||
""" | ||
import io | ||
import json | ||
with io.open(json_file_path, 'r') as f: | ||
json_str = f.read() | ||
return IntrusionRecoveryGameConfig.from_dict(json.loads(json_str)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters