Source code for biogeme.catalog.generic_alt_specific_catalog
"""Defines a catalog containing generic and alternative specific specificationsMichel BierlaireSun Apr 27 2025, 15:49:25"""frombiogeme.exceptionsimportBiogemeErrorfrombiogeme.expressionsimportBetafrombiogeme.segmentationimportDiscreteSegmentationTuplefrom.catalogimportCatalogfrom.controllerimportControllerfrom.segmentation_catalogimportSegmentedParameters,segmentation_catalogs
[docs]defgeneric_alt_specific_catalogs(generic_name:str,beta_parameters:list[Beta],alternatives:tuple[str,...],potential_segmentations:tuple[DiscreteSegmentationTuple,...]|None=None,maximum_number=5,):"""Generate catalogs selecting generic or alternative specific coefficients :param generic_name: name associated with all the parameters in the catalog :type generic_name: str :param beta_parameters: coefficients of interest :type beta_parameters: list(biogeme.expressions.Beta) :param alternatives: names of the alternatives :type alternatives: tuple(str) :param potential_segmentations: tuple of potential segmentations, or None :type potential_segmentations: tuple(biogeme.segmentation.DiscreteSegmentationTuple) :param maximum_number: maximum number of segmentations to consider :type maximum_number: int :return: a list of catalogs for each alternative :rtype: list(dict(str: biogeme.catalog.Catalog)) """iflen(alternatives)<2:error_msg=(f'An alternative specific specification requires at least 2 'f'alternatives, and not {len(alternatives)}')raiseBiogemeError(error_msg)ifnotisinstance(beta_parameters,list):error_msg=(f'Argument "beta_parameters" of function 'f'"{generic_alt_specific_catalogs.__name__}" must be a list.')raiseBiogemeError(error_msg)wrong_indices=[]forindex,betainenumerate(beta_parameters):ifnotisinstance(beta,Beta):wrong_indices.append(index)ifwrong_indices:error_msg=(f'The entries at the following indices are not Beta expressions: 'f'{wrong_indices}')raiseBiogemeError(error_msg)# We first generate the alternative specific versions of the parametersgeneric_parameters=beta_parametersthe_segmented_parameters=SegmentedParameters(beta_parameters=generic_parameters,alternatives=alternatives,)# If applicable, we apply the potential segmentationsifpotential_segmentations:segmented_catalogs=segmentation_catalogs(generic_name=generic_name,beta_parameters=the_segmented_parameters.all_parameters,potential_segmentations=potential_segmentations,maximum_number=maximum_number,)defget_expression(param_index:int,alternative:str|None):"""Returns either the parameter, or the segmented version if applicable"""ifpotential_segmentations:the_index=the_segmented_parameters.get_index(param_index,alternative)returnsegmented_catalogs[the_index]returnthe_segmented_parameters.get_beta(param_index,alternative)# We now control for generic or alternative specific with a single# controller for all catalogsthe_controller=Controller(controller_name=f'{generic_name}_gen_altspec',specification_names=('generic','altspec'),)# We organize the catalogs as a list of dictresults=[]forindex,betainenumerate(beta_parameters):the_dict={alternative:Catalog.from_dict(catalog_name=f'{beta.name}_{alternative}_gen_altspec',dict_of_expressions={'generic':get_expression(index,None),'altspec':get_expression(index,alternative),},controlled_by=the_controller,)foralternativeinalternatives}results.append(the_dict)returnresults