Source code for autowisp.fit_expression.process_terms_visitor

"""Implement base visitor class for processing individual terms in expression"""

from abc import ABC, abstractmethod

from scipy.special import binom

from autowisp.fit_expression.FitTermsParser import FitTermsParser
from autowisp.fit_expression.FitTermsParserVisitor import FitTermsParserVisitor


[docs] class ProcessTermsVisitor(FitTermsParserVisitor, ABC): """ Base visitor class for processing individual terms in fit terms expressions. Children should overwrite visitFit_term() to process individual terms, as well as implement the abstract methods. """
[docs] @abstractmethod def _start_polynomial_expansion(self, num_output_terms, input_terms_list): """ Called at the beginning of processing of a new polynomial expansion. Args: number_terms(int): The number of terms the polynomial expansion will produce. Returns: None """
[docs] @abstractmethod def _process_polynomial_term(self, input_terms, term_powers): """ Called for each term in a polynomial expansion. Args: input_terms([str]): The list of terms the polynomial expansion is being performed on. term_Powers([int]): The powerlaw indices for each term in ``input_terms``. Returns: None """
[docs] @abstractmethod def _end_polynomial_expansion(self): """ Called at the end of processing of a new polynomial expansion. Args: None Returns: The terms produced by the polynomial expansion, as generated by the repeated calls to process_polynomial_term(). """
[docs] @abstractmethod def _start_cross_product_expansion(self, input_term_sets): """ Called at the beginning of processing of a new cross product expansion. Args: input_term_sets([]): A list of the sets of terms taking part in the cross product. Returns: None """
[docs] @abstractmethod def _process_cross_product_term(self, sub_terms): """ Called for each term in a cross product expansion. Args: sub_terms([]): A list of the individual terms which must be multiplied together to form a single term in the resulting cross product expansion. Returns: None """
[docs] @abstractmethod def _end_cross_product_expansion(self): """ Called at the end of processing of a new cross product expansion. Args: None Returns: The terms produced by the cross producc expansion, as generated by the repeated calls to process_cross_product_term(). """
# Visit a parse tree produced by FitTermsParser#fit_terms_list.
[docs] def visitFit_terms_list(self, ctx: FitTermsParser.Fit_terms_listContext): """Return a list of the terms in the list.""" return [self.visit(term) for term in ctx.fit_term()]
# Visit a parse tree produced by FitTermsParser#fit_terms_set.
[docs] def visitFit_terms_set(self, ctx: FitTermsParser.Fit_terms_setContext): """Return a list of the terms in the set.""" return self.visit(ctx.getChild(0))
# Visit a parse tree produced by FitTermsParser#fit_polynomial.
[docs] def visitFit_polynomial(self, ctx: FitTermsParser.Fit_polynomialContext): """Process the list of terms the polynomial expression expands to.""" def next_power_set(powerlaw_indices): """ Advance to the next term powerlaw indices preserting total order. Args: powerlaw_indices: The powerlaw indices of the current term. One for each term in the list from which the polynomial is buing built. Returns: bool: False iff the input powerlaw indices correspond to the last term of the current maximum order. """ for i in range(len(powerlaw_indices) - 1): if powerlaw_indices[i]: powerlaw_indices[i + 1] += 1 powerlaw_indices[0] = powerlaw_indices[i] - 1 if i: powerlaw_indices[i] = 0 return True return False max_order = int(ctx.order.text) terms_list = self.visit(ctx.fit_terms_list()) self._start_polynomial_expansion( int(binom(len(terms_list) + max_order, max_order)), terms_list ) term_powers = [0 for term in terms_list] for total_order in range(max_order): term_powers[-1] = 0 term_powers[0] = total_order + 1 self._process_polynomial_term(terms_list, term_powers) while next_power_set(term_powers): self._process_polynomial_term(terms_list, term_powers) return self._end_polynomial_expansion()
# Visit a parse tree produced by FitTermsParser#fit_terms_set_cross_product.
[docs] def visitFit_terms_set_cross_product( self, ctx: FitTermsParser.Fit_terms_set_cross_productContext ): """Return all possible terms combining one term from each input set.""" term_sets = [self.visit(tset) for tset in ctx.fit_terms_set()] self._start_cross_product_expansion(term_sets) term_indices = [0 for s in term_sets] more_terms = True while more_terms: self._process_cross_product_term( [ term_sets[set_ind][term_indices[set_ind]] for set_ind in range(len(term_sets)) ] ) more_terms = False for set_ind, term_ind in enumerate(term_indices): if term_ind < len(term_sets[set_ind]) - 1: term_indices[set_ind] += 1 for i in range(0, set_ind): term_indices[i] = 0 more_terms = True break return self._end_cross_product_expansion()