Source code for prodigy.analysis.instructionhandler.queryblock_handler

from __future__ import annotations

import logging
from typing import Union, Sequence, Callable

from prodigy.pgcl import Instr, QueryInstr, AsgnInstr, ObserveInstr

from prodigy.analysis.config import ForwardAnalysisConfig
from prodigy.analysis.instructionhandler import _assume
from prodigy.analysis.instructionhandler.assignment_handler import AssignmentHandler
from prodigy.analysis.instructionhandler.instruction_handler import InstructionHandler
from prodigy.analysis.instructionhandler.program_info import ProgramInfo
from prodigy.distribution import Distribution, MarginalType
from prodigy.util.logger import log_setup

logger = log_setup(str(__name__).rsplit(".", maxsplit=1)[-1], logging.DEBUG)


[docs] class QueryBlockHandler(InstructionHandler):
[docs] @staticmethod def compute( instruction: Union[Instr, Sequence[Instr]], prog_info: ProgramInfo, distribution: Distribution, error_prob: Distribution, config: ForwardAnalysisConfig, analyzer: Callable[ [Union[Instr, Sequence[Instr]], ProgramInfo, Distribution, Distribution, ForwardAnalysisConfig], tuple[Distribution, Distribution] ] ) -> tuple[Distribution, Distribution]: _assume(instruction, QueryInstr, "QueryBlockHandler") instrs = instruction.instrs # type: ignore assert len(instrs) == 2 assert isinstance(instrs[0], AsgnInstr) assert isinstance(instrs[1], ObserveInstr) assert distribution.is_finite() assert error_prob.is_zero_dist( ) # this means the sum of all probabilities used below is 1 respectively dist, _ = AssignmentHandler.compute(instrs[0], prog_info, distribution, error_prob, config, analyzer) marginal = dist.marginal(instrs[0].lhs) assert marginal.is_finite() # this assumes that the updated variable is independent from the rest of the distribution zero: Distribution = config.factory.one(*dist.get_variables()) * '0' for rest_prob, rest_state in dist.marginal( instrs[0].lhs, method=MarginalType.EXCLUDE): if rest_prob == "0": continue new = zero for me_prob, me_state in marginal: if me_prob == "0": continue state = rest_state.extend(me_state) if dist.evaluate_condition(instrs[1].cond, state): new += dist.filter_state(state) new /= str(new.get_probability_mass()) new *= rest_prob dist -= dist.filter_state(rest_state) dist += new return dist, error_prob