From eaf79ae871653e649382736f6b0906ee84451f7f Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Fri, 3 Nov 2023 13:11:26 +0100 Subject: [PATCH 1/2] Added implementation for parsing and evaluation of FSCs for POMDPs --- models/fsc-examples/4x3-95.fsc | 227 +++++++++++++++++++++++++++++++ paynt/cli.py | 18 ++- paynt/parser/fsc_parser.py | 90 ++++++++++++ paynt/quotient/quotient_pomdp.py | 31 +++++ 4 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 models/fsc-examples/4x3-95.fsc create mode 100644 paynt/parser/fsc_parser.py diff --git a/models/fsc-examples/4x3-95.fsc b/models/fsc-examples/4x3-95.fsc new file mode 100644 index 000000000..f74f6c12a --- /dev/null +++ b/models/fsc-examples/4x3-95.fsc @@ -0,0 +1,227 @@ +# Transitions are tuples (current node, observation, next node, probability) + +action labels: n s e w +observation labels: left right neither both good bad +nodes: 0 0 3 2 0 2 2 0 0 0 0 2 2 2 2 2 0 2 2 0 2 0 0 2 0 2 2 0 2 0 2 0 0 2 0 0 +0 0 1 1 +0 1 1 1 +0 2 1 1 +0 3 1 1 +0 4 1 1 +0 5 1 1 +1 0 2 1 +1 1 3 1 +1 2 4 1 +1 3 2 1 +1 4 5 1 +1 5 5 1 +2 0 6 1 +2 1 2 1 +2 2 7 1 +2 3 2 1 +2 4 2 1 +2 5 5 1 +3 0 3 1 +3 1 3 1 +3 2 8 1 +3 3 3 1 +3 4 3 1 +3 5 5 1 +4 0 9 1 +4 1 3 1 +4 2 10 1 +4 3 4 1 +4 4 5 1 +4 5 4 1 +5 0 11 1 +5 1 3 1 +5 2 12 1 +5 3 2 1 +5 4 5 1 +5 5 5 1 +6 0 6 1 +6 1 6 1 +6 2 13 1 +6 3 2 1 +6 4 6 1 +6 5 5 1 +7 0 9 1 +7 1 7 1 +7 2 14 1 +7 3 7 1 +7 4 5 1 +7 5 7 1 +8 0 9 1 +8 1 3 1 +8 2 15 1 +8 3 8 1 +8 4 8 1 +8 5 8 1 +9 0 9 1 +9 1 9 1 +9 2 16 1 +9 3 9 1 +9 4 9 1 +9 5 5 1 +10 0 17 1 +10 1 3 1 +10 2 18 1 +10 3 10 1 +10 4 5 1 +10 5 10 1 +11 0 2 1 +11 1 11 1 +11 2 19 1 +11 3 2 1 +11 4 11 1 +11 5 5 1 +12 0 9 1 +12 1 3 1 +12 2 20 1 +12 3 12 1 +12 4 5 1 +12 5 12 1 +13 0 9 1 +13 1 3 1 +13 2 13 1 +13 3 13 1 +13 4 5 1 +13 5 13 1 +14 0 9 1 +14 1 3 1 +14 2 21 1 +14 3 14 1 +14 4 5 1 +14 5 14 1 +15 0 15 1 +15 1 15 1 +15 2 22 1 +15 3 15 1 +15 4 15 1 +15 5 15 1 +16 0 9 1 +16 1 16 1 +16 2 16 1 +16 3 16 1 +16 4 5 1 +16 5 16 1 +17 0 23 1 +17 1 17 1 +17 2 24 1 +17 3 2 1 +17 4 17 1 +17 5 5 1 +18 0 9 1 +18 1 3 1 +18 2 25 1 +18 3 18 1 +18 4 5 1 +18 5 18 1 +19 0 9 1 +19 1 19 1 +19 2 26 1 +19 3 19 1 +19 4 5 1 +19 5 19 1 +20 0 17 1 +20 1 3 1 +20 2 27 1 +20 3 20 1 +20 4 5 1 +20 5 20 1 +21 0 9 1 +21 1 3 1 +21 2 19 1 +21 3 21 1 +21 4 5 1 +21 5 21 1 +22 0 28 1 +22 1 3 1 +22 2 29 1 +22 3 22 1 +22 4 22 1 +22 5 22 1 +23 0 30 1 +23 1 23 1 +23 2 14 1 +23 3 2 1 +23 4 23 1 +23 5 5 1 +24 0 9 1 +24 1 24 1 +24 2 19 1 +24 3 24 1 +24 4 5 1 +24 5 24 1 +25 0 17 1 +25 1 3 1 +25 2 19 1 +25 3 25 1 +25 4 5 1 +25 5 25 1 +26 0 9 1 +26 1 3 1 +26 2 31 1 +26 3 26 1 +26 4 5 1 +26 5 26 1 +27 0 9 1 +27 1 3 1 +27 2 32 1 +27 3 27 1 +27 4 5 1 +27 5 27 1 +28 0 28 1 +28 1 28 1 +28 2 24 1 +28 3 2 1 +28 4 28 1 +28 5 5 1 +29 0 9 1 +29 1 3 1 +29 2 22 1 +29 3 29 1 +29 4 29 1 +29 5 29 1 +30 0 6 1 +30 1 30 1 +30 2 13 1 +30 3 2 1 +30 4 30 1 +30 5 5 1 +31 0 9 1 +31 1 3 1 +31 2 33 1 +31 3 31 1 +31 4 5 1 +31 5 31 1 +32 0 17 1 +32 1 3 1 +32 2 34 1 +32 3 32 1 +32 4 5 1 +32 5 32 1 +33 0 35 1 +33 1 3 1 +33 2 31 1 +33 3 33 1 +33 4 5 1 +33 5 33 1 +34 0 9 1 +34 1 3 1 +34 2 36 1 +34 3 34 1 +34 4 5 1 +34 5 34 1 +35 0 17 1 +35 1 35 1 +35 2 24 1 +35 3 2 1 +35 4 35 1 +35 5 5 1 +36 0 17 1 +36 1 3 1 +36 2 4 1 +36 3 36 1 +36 4 5 1 +36 5 36 1 diff --git a/paynt/cli.py b/paynt/cli.py index f5a96a337..bce11b632 100644 --- a/paynt/cli.py +++ b/paynt/cli.py @@ -1,6 +1,7 @@ from . import version import paynt.parser.sketch +import paynt.parser.fsc_parser import paynt.quotient import paynt.quotient.quotient_pomdp @@ -113,6 +114,9 @@ def setup_logger(log_path = None): @click.option("--export-fsc-paynt", type=click.Path(), default=None, help="path to output file for SAYNT inductive FSC") +@click.option("--evaluate-fsc", type=click.Path(), default=None, + help="path to FSC file") + @click.option( "--ce-generator", default="storm", @@ -137,7 +141,8 @@ def paynt_run( ce_generator, pomcp, profiling, - export_fsc_storm, export_fsc_paynt + export_fsc_storm, export_fsc_paynt, + evaluate_fsc ): logger.info("This is Paynt version {}.".format(version())) @@ -154,6 +159,17 @@ def paynt_run( quotient = paynt.parser.sketch.Sketch.load_sketch(sketch_path, properties_path, export, relative_error, discount_factor) + if evaluate_fsc: + if not isinstance(quotient, paynt.quotient.quotient_pomdp.POMDPQuotientContainer): + logger.error("FSC evaluation expects POMDP input!") + exit(1) + + fsc = paynt.parser.fsc_parser.FSCParser.read_fsc_my_format(evaluate_fsc, quotient.observation_labels, quotient.action_labels_at_observation) + fsc_value = quotient.evaluate_given_fsc(fsc) + print(f"FSC value: {fsc_value}") + + exit() + if pomcp: from paynt.simulation.pomcp import POMCP if not profiling: diff --git a/paynt/parser/fsc_parser.py b/paynt/parser/fsc_parser.py new file mode 100644 index 000000000..daed4501e --- /dev/null +++ b/paynt/parser/fsc_parser.py @@ -0,0 +1,90 @@ +from paynt.quotient.pomdp_family import FSC + +import logging +logger = logging.getLogger(__name__) + +# Parser for FSCs extracted from SARSOP alpha-vectors +# Might support other FSC input formats in the future +class FSCParser: + + @classmethod + def read_fsc_my_format(self, fsc_path, pomdp_obs_labels, pomdp_act_labels): + with open(fsc_path) as f: + fsc_lines = f.readlines() + + logger.info(f"parsing FSC from {fsc_path}") + + p_act_labels = self.transform_act_labels(pomdp_act_labels) + p_obs_labels = list(pomdp_obs_labels) + + action_labels = [] + observation_labels = [] + node_actions = [] + + fsc_transitions = {} + + try: + for line in fsc_lines: + if line.startswith("#"): + continue + if line.isspace(): + continue + if line.startswith("action labels:"): + line = line.split(":") + action_labels = line[1].strip().split(' ') + continue + if line.startswith("observation labels:"): + line = line.split(":") + observation_labels = line[1].strip().split(' ') + continue + if line.startswith("nodes:"): + line = line.split(":") + node_actions = line[1].strip().split(' ') + continue + + s_init, obs, s_end, probability = line.split() + + if probability != "1": + logger.error("Randomized FSCs are not supprted currently!") + raise ValueError + + if s_init not in fsc_transitions.keys(): + fsc_transitions[s_init] = {} + fsc_transitions[s_init][obs] = s_end + + parsed_fsc = FSC(len(node_actions)+1, len(pomdp_obs_labels)) + + # 'init state', no_obs state and sink state initialization + # TODO not sure about the action and the memory update here for no_obs + parsed_fsc.action_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.action_function[0][p_obs_labels.index('__no_obs__')] = p_act_labels[0].index(action_labels[int(node_actions[0])]) + parsed_fsc.update_function[0][p_obs_labels.index('__no_obs__')] = 1 + parsed_fsc.action_function[0][p_obs_labels.index('discount_sink')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('discount_sink')] = 0 + + for node_s, node_s_dict in fsc_transitions.items(): + for obs, node_e in node_s_dict.items(): + obs_index = p_obs_labels.index(observation_labels[int(obs)]) + act_index = p_act_labels[obs_index].index(action_labels[int(node_actions[int(node_e)-1])]) + parsed_fsc.action_function[int(node_s)][obs_index] = act_index + parsed_fsc.update_function[int(node_s)][obs_index] = int(node_e) + + except: + logger.error("Could not parse the given FSC format!") + raise SyntaxError + + return parsed_fsc + + @classmethod + def transform_act_labels(self, pomdp_act_labels): + result_act_labels = [] + for obs_act_labels in pomdp_act_labels: + res = [] + for label in obs_act_labels: + r = str(label.pop()) + r = r.strip("()") + res.append(r) + result_act_labels.append(res) + + return result_act_labels \ No newline at end of file diff --git a/paynt/quotient/quotient_pomdp.py b/paynt/quotient/quotient_pomdp.py index 49304fced..7d7d01443 100644 --- a/paynt/quotient/quotient_pomdp.py +++ b/paynt/quotient/quotient_pomdp.py @@ -6,6 +6,7 @@ from .holes import Hole,Holes,DesignSpace from .quotient import QuotientContainer from .coloring import Coloring +from .pomdp_family import FSC import math import re @@ -750,3 +751,33 @@ def get_family_pomdp(self, mdp): pomdp = stormpy.pomdp.make_canonic(pomdp) return pomdp + + + # TODO there should be a more efficient way to implement this + def evaluate_given_fsc(self, fsc): + memory_list = [] + for ind in range(len(self.observation_labels)): + count = 0 + for x in fsc.action_function: + if x[ind] is not None: + count += 1 + memory_list.append(count) + + self.observation_memory_size = memory_list + self.set_manager_memory_vector() + + self.unfold_memory() + logger.info("memory unfolded") + + fsc_fam = self.design_space.copy() + for obs in range(self.observations): + for act_hole, index in zip(self.observation_action_holes[obs], range(len(self.observation_action_holes[obs]))): + fsc_fam[act_hole].assume_options([fsc.action_function[index][obs]]) + for mem_holes, index in zip(self.observation_memory_holes[obs], range(len(self.observation_memory_holes[obs]))): + fsc_fam[mem_holes].assume_options([fsc.update_function[index][obs]]) + + self.build(fsc_fam) + res = fsc_fam.mdp.check_specification(self.specification, short_evaluation=True) + fsc_fam.analysis_result = res + + return fsc_fam.analysis_result.improving_value From 3c8abac2799d103288bd4713a6a56ec8f4cebafe Mon Sep 17 00:00:00 2001 From: Filip Macak Date: Wed, 15 Nov 2023 15:24:28 +0100 Subject: [PATCH 2/2] Added support for FSC with no labels --- .../{4x3-95.fsc => 4x3-95-labels.fsc} | 0 models/fsc-examples/4x3.fsc | 293 ++++++++++++++++++ paynt/parser/fsc_parser.py | 85 +++-- 3 files changed, 353 insertions(+), 25 deletions(-) rename models/fsc-examples/{4x3-95.fsc => 4x3-95-labels.fsc} (100%) create mode 100644 models/fsc-examples/4x3.fsc diff --git a/models/fsc-examples/4x3-95.fsc b/models/fsc-examples/4x3-95-labels.fsc similarity index 100% rename from models/fsc-examples/4x3-95.fsc rename to models/fsc-examples/4x3-95-labels.fsc diff --git a/models/fsc-examples/4x3.fsc b/models/fsc-examples/4x3.fsc new file mode 100644 index 000000000..23736e286 --- /dev/null +++ b/models/fsc-examples/4x3.fsc @@ -0,0 +1,293 @@ +# Transitions are tuples (current node, observation, next node, probability) + +action labels: 0 1 2 3 +observation labels: 0 1 2 3 4 5 +nodes: 0 0 3 2 0 2 2 0 0 0 0 2 2 2 2 0 2 2 0 2 0 0 2 0 2 2 2 0 2 0 2 0 2 0 2 2 0 0 0 2 0 0 2 0 0 0 2 +0 0 1 1 +0 1 1 1 +0 2 1 1 +0 3 1 1 +0 4 1 1 +0 5 1 1 +1 0 2 1 +1 1 3 1 +1 2 4 1 +1 3 2 1 +1 4 5 1 +1 5 5 1 +2 0 6 1 +2 1 2 1 +2 2 7 1 +2 3 2 1 +2 4 2 1 +2 5 5 1 +3 0 3 1 +3 1 3 1 +3 2 8 1 +3 3 3 1 +3 4 3 1 +3 5 5 1 +4 0 9 1 +4 1 3 1 +4 2 10 1 +4 3 4 1 +4 4 5 1 +4 5 4 1 +5 0 11 1 +5 1 3 1 +5 2 12 1 +5 3 2 1 +5 4 5 1 +5 5 5 1 +6 0 6 1 +6 1 6 1 +6 2 13 1 +6 3 2 1 +6 4 6 1 +6 5 5 1 +7 0 9 1 +7 1 7 1 +7 2 14 1 +7 3 7 1 +7 4 7 1 +7 5 7 1 +8 0 9 1 +8 1 3 1 +8 2 15 1 +8 3 8 1 +8 4 8 1 +8 5 8 1 +9 0 9 1 +9 1 9 1 +9 2 13 1 +9 3 9 1 +9 4 9 1 +9 5 5 1 +10 0 16 1 +10 1 3 1 +10 2 17 1 +10 3 10 1 +10 4 5 1 +10 5 10 1 +11 0 2 1 +11 1 11 1 +11 2 18 1 +11 3 2 1 +11 4 11 1 +11 5 5 1 +12 0 9 1 +12 1 3 1 +12 2 19 1 +12 3 12 1 +12 4 5 1 +12 5 12 1 +13 0 9 1 +13 1 3 1 +13 2 13 1 +13 3 13 1 +13 4 5 1 +13 5 13 1 +14 0 9 1 +14 1 3 1 +14 2 20 1 +14 3 14 1 +14 4 5 1 +14 5 14 1 +15 0 15 1 +15 1 15 1 +15 2 21 1 +15 3 15 1 +15 4 15 1 +15 5 15 1 +16 0 22 1 +16 1 16 1 +16 2 23 1 +16 3 2 1 +16 4 16 1 +16 5 5 1 +17 0 9 1 +17 1 3 1 +17 2 24 1 +17 3 17 1 +17 4 5 1 +17 5 17 1 +18 0 9 1 +18 1 18 1 +18 2 25 1 +18 3 18 1 +18 4 18 1 +18 5 18 1 +19 0 16 1 +19 1 3 1 +19 2 26 1 +19 3 19 1 +19 4 5 1 +19 5 19 1 +20 0 9 1 +20 1 3 1 +20 2 27 1 +20 3 20 1 +20 4 5 1 +20 5 20 1 +21 0 28 1 +21 1 3 1 +21 2 29 1 +21 3 21 1 +21 4 21 1 +21 5 21 1 +22 0 30 1 +22 1 22 1 +22 2 7 1 +22 3 2 1 +22 4 22 1 +22 5 5 1 +23 0 9 1 +23 1 23 1 +23 2 18 1 +23 3 23 1 +23 4 23 1 +23 5 23 1 +24 0 16 1 +24 1 3 1 +24 2 18 1 +24 3 24 1 +24 4 5 1 +24 5 24 1 +25 0 9 1 +25 1 3 1 +25 2 31 1 +25 3 25 1 +25 4 5 1 +25 5 25 1 +26 0 9 1 +26 1 3 1 +26 2 32 1 +26 3 26 1 +26 4 5 1 +26 5 26 1 +27 0 9 1 +27 1 3 1 +27 2 33 1 +27 3 27 1 +27 4 5 1 +27 5 27 1 +28 0 28 1 +28 1 28 1 +28 2 23 1 +28 3 2 1 +28 4 28 1 +28 5 5 1 +29 0 9 1 +29 1 3 1 +29 2 21 1 +29 3 29 1 +29 4 29 1 +29 5 29 1 +30 0 6 1 +30 1 30 1 +30 2 13 1 +30 3 2 1 +30 4 30 1 +30 5 5 1 +31 0 9 1 +31 1 3 1 +31 2 34 1 +31 3 31 1 +31 4 5 1 +31 5 31 1 +32 0 16 1 +32 1 3 1 +32 2 35 1 +32 3 32 1 +32 4 5 1 +32 5 32 1 +33 0 9 1 +33 1 3 1 +33 2 36 1 +33 3 33 1 +33 4 5 1 +33 5 33 1 +34 0 37 1 +34 1 3 1 +34 2 31 1 +34 3 34 1 +34 4 5 1 +34 5 34 1 +35 0 9 1 +35 1 3 1 +35 2 38 1 +35 3 35 1 +35 4 5 1 +35 5 35 1 +36 0 9 1 +36 1 3 1 +36 2 39 1 +36 3 36 1 +36 4 5 1 +36 5 36 1 +37 0 16 1 +37 1 37 1 +37 2 23 1 +37 3 2 1 +37 4 37 1 +37 5 5 1 +38 0 16 1 +38 1 3 1 +38 2 4 1 +38 3 38 1 +38 4 5 1 +38 5 38 1 +39 0 16 1 +39 1 3 1 +39 2 40 1 +39 3 39 1 +39 4 5 1 +39 5 39 1 +40 0 9 1 +40 1 3 1 +40 2 41 1 +40 3 40 1 +40 4 5 1 +40 5 40 1 +41 0 42 1 +41 1 3 1 +41 2 43 1 +41 3 41 1 +41 4 5 1 +41 5 41 1 +42 0 44 1 +42 1 42 1 +42 2 23 1 +42 3 2 1 +42 4 42 1 +42 5 5 1 +43 0 9 1 +43 1 3 1 +43 2 45 1 +43 3 43 1 +43 4 5 1 +43 5 43 1 +44 0 46 1 +44 1 44 1 +44 2 14 1 +44 3 2 1 +44 4 44 1 +44 5 5 1 +45 0 16 1 +45 1 3 1 +45 2 43 1 +45 3 45 1 +45 4 5 1 +45 5 45 1 +46 0 30 1 +46 1 46 1 +46 2 47 1 +46 3 2 1 +46 4 46 1 +46 5 5 1 +47 0 9 1 +47 1 47 1 +47 2 7 1 +47 3 47 1 +47 4 47 1 +47 5 47 1 diff --git a/paynt/parser/fsc_parser.py b/paynt/parser/fsc_parser.py index daed4501e..093610cba 100644 --- a/paynt/parser/fsc_parser.py +++ b/paynt/parser/fsc_parser.py @@ -1,10 +1,11 @@ +# Parser for FSCs extracted from SARSOP alpha-vectors +# Might support other FSC input formats in the future + from paynt.quotient.pomdp_family import FSC import logging logger = logging.getLogger(__name__) -# Parser for FSCs extracted from SARSOP alpha-vectors -# Might support other FSC input formats in the future class FSCParser: @classmethod @@ -12,11 +13,11 @@ def read_fsc_my_format(self, fsc_path, pomdp_obs_labels, pomdp_act_labels): with open(fsc_path) as f: fsc_lines = f.readlines() - logger.info(f"parsing FSC from {fsc_path}") - p_act_labels = self.transform_act_labels(pomdp_act_labels) p_obs_labels = list(pomdp_obs_labels) + labels_not_available = True + action_labels = [] observation_labels = [] node_actions = [] @@ -42,36 +43,70 @@ def read_fsc_my_format(self, fsc_path, pomdp_obs_labels, pomdp_act_labels): node_actions = line[1].strip().split(' ') continue - s_init, obs, s_end, probability = line.split() + for label in action_labels: + if not label.isdigit(): + labels_not_available = False + break + + for label in observation_labels: + if not label.isdigit(): + labels_not_available = False + break - if probability != "1": - logger.error("Randomized FSCs are not supprted currently!") - raise ValueError + s_init, obs, s_end, _ = line.split() if s_init not in fsc_transitions.keys(): fsc_transitions[s_init] = {} fsc_transitions[s_init][obs] = s_end + # print(action_labels) + # print(observation_labels) + # print(node_actions) + # print(len(node_actions)) + # print(p_obs_labels) + # print(p_act_labels) + # print(fsc_transitions) + parsed_fsc = FSC(len(node_actions)+1, len(pomdp_obs_labels)) - # 'init state', no_obs state and sink state initialization - # TODO not sure about the action and the memory update here for no_obs - parsed_fsc.action_function[0][p_obs_labels.index('init')] = 0 - parsed_fsc.update_function[0][p_obs_labels.index('init')] = 0 - parsed_fsc.action_function[0][p_obs_labels.index('__no_obs__')] = p_act_labels[0].index(action_labels[int(node_actions[0])]) - parsed_fsc.update_function[0][p_obs_labels.index('__no_obs__')] = 1 - parsed_fsc.action_function[0][p_obs_labels.index('discount_sink')] = 0 - parsed_fsc.update_function[0][p_obs_labels.index('discount_sink')] = 0 - - for node_s, node_s_dict in fsc_transitions.items(): - for obs, node_e in node_s_dict.items(): - obs_index = p_obs_labels.index(observation_labels[int(obs)]) - act_index = p_act_labels[obs_index].index(action_labels[int(node_actions[int(node_e)-1])]) - parsed_fsc.action_function[int(node_s)][obs_index] = act_index - parsed_fsc.update_function[int(node_s)][obs_index] = int(node_e) + # TODO I'm not sure that the indeces of the actions/observations in sarsop and here are the same! (SARSOP doesn't support labels in POMDPs right now) + if labels_not_available: + + # init state, no_obs state, sink state + # TODO not sure about the action and the memory update here for no_obs + parsed_fsc.action_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.action_function[0][p_obs_labels.index('__no_obs__')] = int(action_labels[int(node_actions[0])]) + parsed_fsc.update_function[0][p_obs_labels.index('__no_obs__')] = 1 + parsed_fsc.action_function[0][p_obs_labels.index('discount_sink')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('discount_sink')] = 0 + + for node_s, node_s_dict in fsc_transitions.items(): + for obs, node_e in node_s_dict.items(): + obs_index = int(observation_labels[int(obs)]) + act_index = int(action_labels[int(node_actions[int(node_e)-1])]) + parsed_fsc.action_function[int(node_s)][obs_index] = act_index + parsed_fsc.update_function[int(node_s)][obs_index] = int(node_e) + + else: + + # init state, no_obs state, sink state + # TODO not sure about the action and the memory update here for no_obs + parsed_fsc.action_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('init')] = 0 + parsed_fsc.action_function[0][p_obs_labels.index('__no_obs__')] = p_act_labels[0].index(action_labels[int(node_actions[0])]) + parsed_fsc.update_function[0][p_obs_labels.index('__no_obs__')] = 1 + parsed_fsc.action_function[0][p_obs_labels.index('discount_sink')] = 0 + parsed_fsc.update_function[0][p_obs_labels.index('discount_sink')] = 0 + + for node_s, node_s_dict in fsc_transitions.items(): + for obs, node_e in node_s_dict.items(): + obs_index = p_obs_labels.index(observation_labels[int(obs)]) + act_index = p_act_labels[obs_index].index(action_labels[int(node_actions[int(node_e)-1])]) + parsed_fsc.action_function[int(node_s)][obs_index] = act_index + parsed_fsc.update_function[int(node_s)][obs_index] = int(node_e) except: - logger.error("Could not parse the given FSC format!") raise SyntaxError return parsed_fsc @@ -87,4 +122,4 @@ def transform_act_labels(self, pomdp_act_labels): res.append(r) result_act_labels.append(res) - return result_act_labels \ No newline at end of file + return result_act_labels