:py:mod:`pyab_experiment.data_structures.syntax_tree`
=====================================================

.. py:module:: pyab_experiment.data_structures.syntax_tree

.. autoapi-nested-parse::

   Module that houses the abstract syntax tree (AST) representation of an experiment
   It's a collection of pydantic classes that represent a tree with several
   specialized nodes each representing a specific data structure of the experiment



Module Contents
---------------

Classes
~~~~~~~

.. autoapisummary::

   pyab_experiment.data_structures.syntax_tree.BooleanOperatorEnum
   pyab_experiment.data_structures.syntax_tree.ConditionalType
   pyab_experiment.data_structures.syntax_tree.ExperimentAST
   pyab_experiment.data_structures.syntax_tree.ExperimentConditional
   pyab_experiment.data_structures.syntax_tree.ExperimentGroup
   pyab_experiment.data_structures.syntax_tree.Identifier
   pyab_experiment.data_structures.syntax_tree.LogicalOperatorEnum
   pyab_experiment.data_structures.syntax_tree.RecursivePredicate
   pyab_experiment.data_structures.syntax_tree.TerminalPredicate




.. py:class:: BooleanOperatorEnum


   Bases: :py:obj:`enum.Enum`

   Enum representing the boolean operators that can be used in a
   recursive predicate, effectively chaining complex predicates.
   e.g. (predicate1 OR predicate2) AND NOT predicate3

   .. py:attribute:: AND

      

   .. py:attribute:: NOT

      

   .. py:attribute:: OR

      


.. py:class:: ConditionalType


   Bases: :py:obj:`enum.Enum`

   Enum representing the types of conditionals that can be used in an experiment.
   These are the classical if then else keywoods found in
   traditional programming languages

   .. py:attribute:: ELIF

      

   .. py:attribute:: ELSE

      

   .. py:attribute:: IF

      


.. py:class:: ExperimentAST


   Bases: :py:obj:`pydantic.BaseModel`

   A model representing the abstract syntax tree (AST) of an experiment.

   .. attribute:: id

      The ID of the experiment.

      :type: str

   .. attribute:: splitting_fields

      The fields used for splitting groups.

      :type: List[str] | None

   .. attribute:: salt

      The salt used change hashing. Useful in case multiple experiments with the
      same splitting fields are used.

      :type: str | None

   .. attribute:: conditions

      The conditions used in the experiment.

      :type: Union[ExperimentConditional, List[ExperimentGroup]]

   .. py:attribute:: conditions
      :type: Union[ExperimentConditional, list[ExperimentGroup]]

      

   .. py:attribute:: id
      :type: str

      

   .. py:attribute:: salt
      :type: str | None

      

   .. py:attribute:: splitting_fields
      :type: list[str] | None

      


.. py:class:: ExperimentConditional


   Bases: :py:obj:`pydantic.BaseModel`

   A model representing a conditional  (if then else) in an experiment.

   .. attribute:: conditional_type

      The type of conditional - either IF, ELSE IF, or ELSE)

      :type: ConditionalType

   .. attribute:: predicate

      The (possibly recursive) predicate used in the conditional.

      :type: Union[TerminalPredicate, RecursivePredicate, None]

   .. attribute:: true_branch

      The true branch of the conditional. could be a group (terminal) or
      nested conditional. For example IF p1{ IF (p2){...}}. Semantically
      represents the branch to explore if the predicate evaluates to TRUE

      :type: Union[list[ExperimentGroup], "ExperimentConditional"]

   .. attribute:: false_branch

      The false branch of the conditional (if any) same as above, but
      semantically representing the branch to explore if the predicate is FALSE.
      Note that it may be None, for ex on a clause "IF p1{ branch1 }" if
      the predicate p1 is false there is no branch to explore

      :type: Union[list[ExperimentGroup], "ExperimentConditional", None]

   .. py:attribute:: conditional_type
      :type: ConditionalType

      

   .. py:attribute:: false_branch
      :type: Union[list[ExperimentGroup], ExperimentConditional, None]

      

   .. py:attribute:: predicate
      :type: Union[TerminalPredicate, RecursivePredicate, None]

      

   .. py:attribute:: true_branch
      :type: Union[list[ExperimentGroup], ExperimentConditional]

      


.. py:class:: ExperimentGroup


   Bases: :py:obj:`pydantic.BaseModel`

   A group definition for an experiment. A group in an experiment
   (or element of a group) is a string associated with a weight
   The weight represents the likelyhood of choosing the element.

   For example with 2 groups A,B with weights 1,2 respectively.
   B is twice as likely to be chosen compared to A. Effectively
   the probability of choosing A becomes 1/3, while P(choosing B)
   becomes 2/3

   .. attribute:: group_definition

      The definition of the group.

      :type: str

   .. attribute:: group_weight

      The weight of the group.

      :type: Union[NonNegativeFloat, NonNegativeInt]

   .. py:class:: Config


      .. py:attribute:: smart_union
         :value: True

         


   .. py:attribute:: group_definition
      :type: Union[int, float, str]

      

   .. py:attribute:: group_weight
      :type: Union[pydantic.NonNegativeFloat, pydantic.NonNegativeInt]

      


.. py:class:: Identifier


   Bases: :py:obj:`pydantic.BaseModel`

   A model representing an identifier. (i.e a variable or function name)

   .. attribute:: name

      The name of the identifier.

      :type: str

   .. py:attribute:: name
      :type: str

      


.. py:class:: LogicalOperatorEnum


   Bases: :py:obj:`enum.Enum`

   Enum representing the logical operators that can be used in a terminal predicate.

   .. py:attribute:: EQ

      

   .. py:attribute:: GE

      

   .. py:attribute:: GT

      

   .. py:attribute:: IN

      

   .. py:attribute:: LE

      

   .. py:attribute:: LT

      

   .. py:attribute:: NE

      

   .. py:attribute:: NOT_IN

      


.. py:class:: RecursivePredicate


   Bases: :py:obj:`pydantic.BaseModel`

   A model representing a recursive predicate.
   Similar to terminal predicates, but chains recursive definitions with logical
   operators.

   e.g. in predicate1 AND predicate2
   predicate1 is the left term
   AND is the logical operator
   predicate2 is the right term

   .. attribute:: left_predicate

      The left predicate of the recursive predicate.

      :type: Union[TerminalPredicate, "RecursivePredicate"]

   .. attribute:: boolean_operator

      The boolean operator used in the recursive predicate.

      :type: BooleanOperatorEnum

   .. attribute:: right_predicate

      The right predicate of the recursive predicate.

      :type: Union[TerminalPredicate, "RecursivePredicate", None]

   .. py:attribute:: boolean_operator
      :type: BooleanOperatorEnum

      

   .. py:attribute:: left_predicate
      :type: Union[TerminalPredicate, RecursivePredicate]

      

   .. py:attribute:: right_predicate
      :type: Union[TerminalPredicate, RecursivePredicate, None]

      


.. py:class:: TerminalPredicate


   Bases: :py:obj:`pydantic.BaseModel`

   A model representing a terminal predicate. A terminal predicate
   typically consists of 2 terms (either literals, or identifiers)
   and a boolean operand between them.

   for example in the predicate my_int_variable >= 2, we have
   my_variable: - the left term
   ">=" the operand
   "2" - the right term (int literal with value 2)

   .. attribute:: left_term

      The left term of the predicate.

      :type: Union[float, int, str, tuple, Identifier]

   .. attribute:: logical_operator

      The logical operator used in the predicate.

      :type: LogicalOperatorEnum

   .. attribute:: right_term

      The right term of the predicate.

      :type: Union[float, int, str, tuple, Identifier]

   .. py:attribute:: left_term
      :type: Union[float, int, str, tuple, Identifier]

      

   .. py:attribute:: logical_operator
      :type: LogicalOperatorEnum

      

   .. py:attribute:: right_term
      :type: Union[float, int, str, tuple, Identifier]

      


