.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/hybrid_choice_specs/plot_b01_model_specification.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_hybrid_choice_specs_plot_b01_model_specification.py: Generate files from latent-variable measurement specifications. This script illustrates the latent-variables specification API. It does not estimate any model and does not use data. Instead, it starts from pure specification objects, resolves them into semantic ``ResolvedModel`` objects, and uses the resolved specifications to generate files that can be inspected or used elsewhere. The script shows how to: - define pure latent-variable and measurement specifications, - define normalization plans in expert mode, using explicit parameter fixings, - resolve a specification into a semantic ``ResolvedModel``, - build live Biogeme expressions from the resolved specification, - generate files from the resolved specification: - pedagogical runnable Python code, - a LaTeX scientific report, - a static HTML report. The same specification is resolved under several build contexts: - maximum likelihood and Bayesian estimation modes, - log/exp and lower-bound parameterizations for positive parameters, - automatic normalization and an explicit normalization plan. Only specification files and reports are generated. No estimation algorithm is run in this example. Michel Bierlaire Sat Jun 06 2026, 15:20:15 .. GENERATED FROM PYTHON SOURCE LINES 33-364 .. rst-class:: sphx-glr-script-out .. code-block:: none ==================== SPEC loaded ==================== - #latent_variables: 2 - #likert_indicators: 14 - #likert_types: 1 ==================== Normalization plans ready ==================== - plan_empty: (no fixings) - plan_example: (some intercept/loadings/sigma fixed) ============================================================ CASE 1: ML + log/exp positivity + EMPTY plan ============================================================ - estimation mode: maximum_likelihood - positivity mode: log_exp - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * )))) + ( * ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * )))) / exp()), [(UnaryMinus((exp() + exp())) / exp()), (UnaryMinus(exp()) / exp()), (exp() / exp()), ((exp() + exp()) / exp())]) - generated Python file: b01_generated_files/case_1_ml_plus_log_exp_positivity_plus_empty_plan.py - generated LaTeX file: b01_generated_files/case_1_ml_plus_log_exp_positivity_plus_empty_plan.tex - generated HTML file: b01_generated_files/case_1_ml_plus_log_exp_positivity_plus_empty_plan.html - normalization rules: none - warnings: * No obvious reference indicator could be inferred for latent variable 'car_centric_attitude'. * No obvious reference indicator could be inferred for latent variable 'environmental_attitude'. ============================================================ CASE 2: ML + log/exp positivity + EXAMPLE plan ============================================================ - estimation mode: maximum_likelihood - positivity mode: log_exp - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * )))) + ( * ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * )))) / ), [(UnaryMinus((exp() + exp())) / ), (UnaryMinus(exp()) / ), (exp() / ), ((exp() + exp()) / )]) - generated Python file: b01_generated_files/case_2_ml_plus_log_exp_positivity_plus_example_plan.py - generated LaTeX file: b01_generated_files/case_2_ml_plus_log_exp_positivity_plus_example_plan.tex - generated HTML file: b01_generated_files/case_2_ml_plus_log_exp_positivity_plus_example_plan.html - normalization rules: * MeasurementIntercept(indicator_name='Envir01') = 0.0 (reference indicator (location)) * MeasurementIntercept(indicator_name='Envir02') = 0.0 (reference indicator (location)) * MeasurementLoading(latent_name='car_centric_attitude', indicator_name='Envir01') = -1.0 (reference indicator (scale)) * MeasurementLoading(latent_name='environmental_attitude', indicator_name='Envir02') = 1.0 (reference indicator (scale)) * MeasurementSigma(indicator_name='Envir01') = 1.0 (ordinal threshold scale) - warnings: none ============================================================ CASE 3: ML + BOUNDED positivity + EMPTY plan (non-standard but illustrative) ============================================================ - estimation mode: maximum_likelihood - positivity mode: lower_bound - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )))) + ( * ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )))) / ), [(UnaryMinus(( + )) / ), (UnaryMinus() / ), ( / ), (( + ) / )]) - generated Python file: b01_generated_files/case_3_ml_plus_bounded_positivity_plus_empty_plan_non_standard_but_illustrative.py - generated LaTeX file: b01_generated_files/case_3_ml_plus_bounded_positivity_plus_empty_plan_non_standard_but_illustrative.tex - generated HTML file: b01_generated_files/case_3_ml_plus_bounded_positivity_plus_empty_plan_non_standard_but_illustrative.html - normalization rules: none - warnings: * No obvious reference indicator could be inferred for latent variable 'car_centric_attitude'. * No obvious reference indicator could be inferred for latent variable 'environmental_attitude'. ============================================================ CASE 4: ML + BOUNDED positivity + EXAMPLE plan (non-standard but illustrative) ============================================================ - estimation mode: maximum_likelihood - positivity mode: lower_bound - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )))) + ( * ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )))) / ), [(UnaryMinus(( + )) / ), (UnaryMinus() / ), ( / ), (( + ) / )]) - generated Python file: b01_generated_files/case_4_ml_plus_bounded_positivity_plus_example_plan_non_standard_but_illustrative.py - generated LaTeX file: b01_generated_files/case_4_ml_plus_bounded_positivity_plus_example_plan_non_standard_but_illustrative.tex - generated HTML file: b01_generated_files/case_4_ml_plus_bounded_positivity_plus_example_plan_non_standard_but_illustrative.html - normalization rules: * MeasurementIntercept(indicator_name='Envir01') = 0.0 (reference indicator (location)) * MeasurementIntercept(indicator_name='Envir02') = 0.0 (reference indicator (location)) * MeasurementLoading(latent_name='car_centric_attitude', indicator_name='Envir01') = -1.0 (reference indicator (scale)) * MeasurementLoading(latent_name='environmental_attitude', indicator_name='Envir02') = 1.0 (reference indicator (scale)) * MeasurementSigma(indicator_name='Envir01') = 1.0 (ordinal threshold scale) - warnings: none ============================================================ CASE 5: BAYESIAN + BOUNDED positivity + EMPTY plan ============================================================ - estimation mode: bayesian - positivity mode: lower_bound - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * DistributedParameter(car_centric_attitude, (((((((((((`0.0` + Beta('struct_car_centric_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_top_manager', 0.0, None, None, 0) * top_manager)) + (Beta('struct_car_centric_attitude_age_30_less', 0.0, None, None, 0) * age_30_less)) + (Beta('struct_car_centric_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_car_centric_attitude_car_oriented_parents', 0.0, None, None, 0) * car_oriented_parents)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_car_centric_attitude_male', 0.0, None, None, 0) * male)) + (Beta('struct_car_centric_attitude_used_to_go_to_school_by_car', 0.0, None, None, 0) * used_to_go_to_school_by_car)) + (Beta('struct_car_centric_attitude_sigma', 10.0, 1e-15, None, 0) * Draws("struct_car_centric_attitude_draws", "Normal"))), ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * ))))) + ( * DistributedParameter(environmental_attitude, (((((((((`0.0` + Beta('struct_environmental_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_environmental_attitude_childSuburb', 0.0, None, None, 0) * childSuburb)) + (Beta('struct_environmental_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_environmental_attitude_city_center_as_kid', 0.0, None, None, 0) * city_center_as_kid)) + (Beta('struct_environmental_attitude_artisans', 0.0, None, None, 0) * artisans)) + (Beta('struct_environmental_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_environmental_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_environmental_attitude_single', 0.0, None, None, 0) * single)) + (Beta('struct_environmental_attitude_sigma', 10.0, 1e-15, None, 0) * Draws("struct_environmental_attitude_draws", "Normal"))), ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * ))))) / ), [(UnaryMinus(( + )) / ), (UnaryMinus() / ), ( / ), (( + ) / )]) - generated Python file: b01_generated_files/case_5_bayesian_plus_bounded_positivity_plus_empty_plan.py - generated LaTeX file: b01_generated_files/case_5_bayesian_plus_bounded_positivity_plus_empty_plan.tex - generated HTML file: b01_generated_files/case_5_bayesian_plus_bounded_positivity_plus_empty_plan.html - normalization rules: none - warnings: * No obvious reference indicator could be inferred for latent variable 'car_centric_attitude'. * No obvious reference indicator could be inferred for latent variable 'environmental_attitude'. ============================================================ CASE 6: BAYESIAN + BOUNDED positivity + EXAMPLE plan ============================================================ - estimation mode: bayesian - positivity mode: lower_bound - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * DistributedParameter(car_centric_attitude, (((((((((((`0.0` + Beta('struct_car_centric_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_top_manager', 0.0, None, None, 0) * top_manager)) + (Beta('struct_car_centric_attitude_age_30_less', 0.0, None, None, 0) * age_30_less)) + (Beta('struct_car_centric_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_car_centric_attitude_car_oriented_parents', 0.0, None, None, 0) * car_oriented_parents)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_car_centric_attitude_male', 0.0, None, None, 0) * male)) + (Beta('struct_car_centric_attitude_used_to_go_to_school_by_car', 0.0, None, None, 0) * used_to_go_to_school_by_car)) + (Beta('struct_car_centric_attitude_sigma', 10.0, 1e-15, None, 0) * Draws("struct_car_centric_attitude_draws", "Normal"))), ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * ))))) + ( * DistributedParameter(environmental_attitude, (((((((((`0.0` + Beta('struct_environmental_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_environmental_attitude_childSuburb', 0.0, None, None, 0) * childSuburb)) + (Beta('struct_environmental_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_environmental_attitude_city_center_as_kid', 0.0, None, None, 0) * city_center_as_kid)) + (Beta('struct_environmental_attitude_artisans', 0.0, None, None, 0) * artisans)) + (Beta('struct_environmental_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_environmental_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_environmental_attitude_single', 0.0, None, None, 0) * single)) + (Beta('struct_environmental_attitude_sigma', 10.0, 1e-15, None, 0) * Draws("struct_environmental_attitude_draws", "Normal"))), ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * ))))) / ), [(UnaryMinus(( + )) / ), (UnaryMinus() / ), ( / ), (( + ) / )]) - generated Python file: b01_generated_files/case_6_bayesian_plus_bounded_positivity_plus_example_plan.py - generated LaTeX file: b01_generated_files/case_6_bayesian_plus_bounded_positivity_plus_example_plan.tex - generated HTML file: b01_generated_files/case_6_bayesian_plus_bounded_positivity_plus_example_plan.html - normalization rules: * MeasurementIntercept(indicator_name='Envir01') = 0.0 (reference indicator (location)) * MeasurementIntercept(indicator_name='Envir02') = 0.0 (reference indicator (location)) * MeasurementLoading(latent_name='car_centric_attitude', indicator_name='Envir01') = -1.0 (reference indicator (scale)) * MeasurementLoading(latent_name='environmental_attitude', indicator_name='Envir02') = 1.0 (reference indicator (scale)) * MeasurementSigma(indicator_name='Envir01') = 1.0 (ordinal threshold scale) - warnings: none ============================================================ CASE 7: BAYESIAN + log/exp positivity + EMPTY plan (non-standard but illustrative) ============================================================ - estimation mode: bayesian - positivity mode: log_exp - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * DistributedParameter(car_centric_attitude, (((((((((((`0.0` + Beta('struct_car_centric_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_top_manager', 0.0, None, None, 0) * top_manager)) + (Beta('struct_car_centric_attitude_age_30_less', 0.0, None, None, 0) * age_30_less)) + (Beta('struct_car_centric_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_car_centric_attitude_car_oriented_parents', 0.0, None, None, 0) * car_oriented_parents)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_car_centric_attitude_male', 0.0, None, None, 0) * male)) + (Beta('struct_car_centric_attitude_used_to_go_to_school_by_car', 0.0, None, None, 0) * used_to_go_to_school_by_car)) + (exp(Beta('struct_car_centric_attitude_sigma_log', 2.302585092994046, None, None, 0)) * Draws("struct_car_centric_attitude_draws", "Normal"))), ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * ))))) + ( * DistributedParameter(environmental_attitude, (((((((((`0.0` + Beta('struct_environmental_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_environmental_attitude_childSuburb', 0.0, None, None, 0) * childSuburb)) + (Beta('struct_environmental_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_environmental_attitude_city_center_as_kid', 0.0, None, None, 0) * city_center_as_kid)) + (Beta('struct_environmental_attitude_artisans', 0.0, None, None, 0) * artisans)) + (Beta('struct_environmental_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_environmental_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_environmental_attitude_single', 0.0, None, None, 0) * single)) + (exp(Beta('struct_environmental_attitude_sigma_log', 2.302585092994046, None, None, 0)) * Draws("struct_environmental_attitude_draws", "Normal"))), ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * ))))) / exp()), [(UnaryMinus((exp() + exp())) / exp()), (UnaryMinus(exp()) / exp()), (exp() / exp()), ((exp() + exp()) / exp())]) - generated Python file: b01_generated_files/case_7_bayesian_plus_log_exp_positivity_plus_empty_plan_non_standard_but_illustrative.py - generated LaTeX file: b01_generated_files/case_7_bayesian_plus_log_exp_positivity_plus_empty_plan_non_standard_but_illustrative.tex - generated HTML file: b01_generated_files/case_7_bayesian_plus_log_exp_positivity_plus_empty_plan_non_standard_but_illustrative.html - normalization rules: none - warnings: * No obvious reference indicator could be inferred for latent variable 'car_centric_attitude'. * No obvious reference indicator could be inferred for latent variable 'environmental_attitude'. ============================================================ CASE 8: BAYESIAN + log/exp positivity + EXAMPLE plan (non-standard but illustrative) ============================================================ - estimation mode: bayesian - positivity mode: log_exp - latent variables: 2 - indicators: 14 - ordinal threshold systems: 1 - measurement models present: ['ordered_probit'] - resolved parameters: 66 - structural expressions: ['car_centric_attitude', 'environmental_attitude'] - threshold systems: ['likert'] - measurement terms: 14 indicators example term (Envir01): OrderedProbit((((( + ) + ( * DistributedParameter(car_centric_attitude, (((((((((((`0.0` + Beta('struct_car_centric_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_top_manager', 0.0, None, None, 0) * top_manager)) + (Beta('struct_car_centric_attitude_age_30_less', 0.0, None, None, 0) * age_30_less)) + (Beta('struct_car_centric_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_car_centric_attitude_car_oriented_parents', 0.0, None, None, 0) * car_oriented_parents)) + (Beta('struct_car_centric_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_car_centric_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_car_centric_attitude_male', 0.0, None, None, 0) * male)) + (Beta('struct_car_centric_attitude_used_to_go_to_school_by_car', 0.0, None, None, 0) * used_to_go_to_school_by_car)) + (exp(Beta('struct_car_centric_attitude_sigma_log', 2.302585092994046, None, None, 0)) * Draws("struct_car_centric_attitude_draws", "Normal"))), ((((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * ))))) + ( * DistributedParameter(environmental_attitude, (((((((((`0.0` + Beta('struct_environmental_attitude_intercept', 0.0, None, None, 0)) + (Beta('struct_environmental_attitude_childSuburb', 0.0, None, None, 0) * childSuburb)) + (Beta('struct_environmental_attitude_ScaledIncome', 0.0, None, None, 0) * ScaledIncome)) + (Beta('struct_environmental_attitude_city_center_as_kid', 0.0, None, None, 0) * city_center_as_kid)) + (Beta('struct_environmental_attitude_artisans', 0.0, None, None, 0) * artisans)) + (Beta('struct_environmental_attitude_high_education', 0.0, None, None, 0) * high_education)) + (Beta('struct_environmental_attitude_low_education', 0.0, None, None, 0) * low_education)) + (Beta('struct_environmental_attitude_single', 0.0, None, None, 0) * single)) + (exp(Beta('struct_environmental_attitude_sigma_log', 2.302585092994046, None, None, 0)) * Draws("struct_environmental_attitude_draws", "Normal"))), ((((((((( + ) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + ( * )) + (exp() * ))))) / ), [(UnaryMinus((exp() + exp())) / ), (UnaryMinus(exp()) / ), (exp() / ), ((exp() + exp()) / )]) - generated Python file: b01_generated_files/case_8_bayesian_plus_log_exp_positivity_plus_example_plan_non_standard_but_illustrative.py - generated LaTeX file: b01_generated_files/case_8_bayesian_plus_log_exp_positivity_plus_example_plan_non_standard_but_illustrative.tex - generated HTML file: b01_generated_files/case_8_bayesian_plus_log_exp_positivity_plus_example_plan_non_standard_but_illustrative.html - normalization rules: * MeasurementIntercept(indicator_name='Envir01') = 0.0 (reference indicator (location)) * MeasurementIntercept(indicator_name='Envir02') = 0.0 (reference indicator (location)) * MeasurementLoading(latent_name='car_centric_attitude', indicator_name='Envir01') = -1.0 (reference indicator (scale)) * MeasurementLoading(latent_name='environmental_attitude', indicator_name='Envir02') = 1.0 (reference indicator (scale)) * MeasurementSigma(indicator_name='Envir01') = 1.0 (ordinal threshold scale) - warnings: none ==================== END OF SCRIPT ==================== | .. code-block:: Python from __future__ import annotations from pathlib import Path from likert_spec import likert_indicators, likert_types from two_latent_variables_spec import latent_variables from biogeme.latent_variables import ( BuildContext, EstimationMode, Fixing, IndicatorMeasurementSpec, MeasurementConfiguration, MeasurementIntercept, MeasurementLoading, MeasurementModel, MeasurementSigma, NormalizationPlan, PositiveParameterSpec, PositivityMode, build_biogeme_model, generate_html_report, generate_latex_report, generate_python_code, resolve_model, save_html_report, save_latex_report, save_python_code, ) OUTPUT_DIR = Path('b01_generated_files') OUTPUT_DIR.mkdir(parents=True, exist_ok=True) print('\n====================') print('SPEC loaded') print('====================') print(f'- #latent_variables: {len(latent_variables)}') print(f'- #likert_indicators: {len(likert_indicators)}') print(f'- #likert_types: {len(likert_types)}') # ============================================================================= # Homogeneous ordinal measurement configuration used by the resolver # ============================================================================= DEFAULT_SIGMA_START = 10.0 measurement_configuration = MeasurementConfiguration( specifications=[ IndicatorMeasurementSpec( indicator_name=indicator.name, measurement_model=MeasurementModel.ORDERED_PROBIT, measurement_sigma=PositiveParameterSpec(start=DEFAULT_SIGMA_START), ) for indicator in likert_indicators ] ) # ============================================================================= # Normalization plans used when resolving the specifications # ============================================================================= # Plan A: empty plan. The resolver determines the required normalizations. plan_empty = NormalizationPlan() # Plan B: explicit plan. These fixings illustrate how expert-specified # normalizations are passed to the resolver. plan_example = NormalizationPlan() # --- LV normalizations by reference-indicator strategy (examples) # car_centric_attitude anchored on Envir01 plan_example.add( Fixing(MeasurementIntercept('Envir01'), 0.0, note='reference indicator (location)') ) plan_example.add( Fixing( MeasurementLoading('car_centric_attitude', 'Envir01'), -1.0, note='reference indicator (scale)', ) ) # environmental_attitude anchored on Envir02 plan_example.add( Fixing(MeasurementIntercept('Envir02'), 0.0, note='reference indicator (location)') ) plan_example.add( Fixing( MeasurementLoading('environmental_attitude', 'Envir02'), 1.0, note='reference indicator (scale)', ) ) # --- Ordinal scale normalization (one per ordinal threshold system) # With a single ordinal threshold system ("likert"), fix one measurement sigma. plan_example.add( Fixing(MeasurementSigma('Envir01'), 1.0, note='ordinal threshold scale') ) print('\n====================') print('Normalization plans ready') print('====================') print('- plan_empty: (no fixings)') print('- plan_example: (some intercept/loadings/sigma fixed)') # ============================================================================= # Helpers # ============================================================================= def make_context( estimation_mode: EstimationMode, positivity_mode: PositivityMode, ) -> BuildContext: """Create a build context used to resolve and generate a specification.""" base = BuildContext.default(estimation_mode) return BuildContext( estimation_mode=base.estimation_mode, draw_type=base.draw_type, positivity_mode=positivity_mode, naming=base.naming, ordinal_eps=base.ordinal_eps, ordinal_enforce_order=base.ordinal_enforce_order, ) def title_to_file_stem(title: str) -> str: """Convert a case title into a filesystem-friendly stem.""" stem = title.lower() replacements = { ' ': '_', '/': '_', '+': 'plus', ':': '', ',': '', '(': '', ')': '', '-': '_', } for source, target in replacements.items(): stem = stem.replace(source, target) while '__' in stem: stem = stem.replace('__', '_') return stem.strip('_') def summarize_case( *, title: str, context: BuildContext, plan: NormalizationPlan ) -> None: """Resolve one specification, generate files, and print a compact summary. No estimation is performed. The generated Python, LaTeX, and HTML files are derived from the resolved specification. """ print('\n' + '=' * 60) print(title) print('=' * 60) resolved = resolve_model( latent_variables=latent_variables, likert_indicators=likert_indicators, likert_types=likert_types, measurement_configuration=measurement_configuration, context=context, normalization_plan=plan, ) built = build_biogeme_model(resolved) python_code = generate_python_code(resolved) latex_report = generate_latex_report(resolved) html_report = generate_html_report(resolved) stem = title_to_file_stem(title) python_path = OUTPUT_DIR / f'{stem}.py' latex_path = OUTPUT_DIR / f'{stem}.tex' html_path = OUTPUT_DIR / f'{stem}.html' save_python_code(python_code, python_path) save_latex_report(latex_report, latex_path) save_html_report(html_report, html_path) measurement_models = [ model.value for model in resolved.metadata.measurement_models_present ] print(f'- estimation mode: {context.estimation_mode.value}') print(f'- positivity mode: {context.positivity_mode.value}') print(f'- latent variables: {resolved.metadata.n_latent_variables}') print(f'- indicators: {resolved.metadata.n_indicators}') print(f'- ordinal threshold systems: {resolved.metadata.n_threshold_systems}') print(f'- measurement models present: {measurement_models}') print(f'- resolved parameters: {len(resolved.parameters)}') print(f'- structural expressions: {list(built.latent_expressions.keys())}') print(f'- threshold systems: {list(built.threshold_expressions.keys())}') print(f'- measurement terms: {len(built.measurement_terms)} indicators') print(f' example term (Envir01): {built.measurement_terms.get("Envir01")}') print(f'- generated Python file: {python_path.as_posix()}') print(f'- generated LaTeX file: {latex_path.as_posix()}') print(f'- generated HTML file: {html_path.as_posix()}') if resolved.normalization.rules: print('- normalization rules:') for rule in resolved.normalization.rules: print(f' * {rule.target_name} = {rule.value} ({rule.reason})') else: print('- normalization rules: none') if resolved.normalization.warnings: print('- warnings:') for warning in resolved.normalization.warnings: print(f' * {warning}') else: print('- warnings: none') # ============================================================================= # Enumerate build contexts and normalization plans explicitly # ============================================================================= # We generate files for 8 cases: # modes: maximum likelihood vs Bayesian, # positivity: log/exp vs lower-bound parameterization, # normalization plan: automatic vs explicit. # # Some combinations are not intended as recommended estimation settings. They # are included to exercise the specification resolver and code generators. # ------------------------------------------------------------------------- # CASE 1: ML + log/exp positivity + empty plan # ------------------------------------------------------------------------- context_1 = make_context( EstimationMode.MAXIMUM_LIKELIHOOD, PositivityMode.LOG_EXP, ) summarize_case( title='CASE 1: ML + log/exp positivity + EMPTY plan', context=context_1, plan=plan_empty, ) # ------------------------------------------------------------------------- # CASE 2: ML + log/exp positivity + example plan # ------------------------------------------------------------------------- context_2 = make_context( EstimationMode.MAXIMUM_LIKELIHOOD, PositivityMode.LOG_EXP, ) summarize_case( title='CASE 2: ML + log/exp positivity + EXAMPLE plan', context=context_2, plan=plan_example, ) # ------------------------------------------------------------------------- # CASE 3: ML + bounded positivity + empty plan # ------------------------------------------------------------------------- context_3 = make_context( EstimationMode.MAXIMUM_LIKELIHOOD, PositivityMode.LOWER_BOUND, ) summarize_case( title='CASE 3: ML + BOUNDED positivity + EMPTY plan (non-standard but illustrative)', context=context_3, plan=plan_empty, ) # ------------------------------------------------------------------------- # CASE 4: ML + bounded positivity + example plan # ------------------------------------------------------------------------- context_4 = make_context( EstimationMode.MAXIMUM_LIKELIHOOD, PositivityMode.LOWER_BOUND, ) summarize_case( title='CASE 4: ML + BOUNDED positivity + EXAMPLE plan (non-standard but illustrative)', context=context_4, plan=plan_example, ) # ------------------------------------------------------------------------- # CASE 5: Bayesian + bounded positivity + empty plan # ------------------------------------------------------------------------- context_5 = make_context( EstimationMode.BAYESIAN, PositivityMode.LOWER_BOUND, ) summarize_case( title='CASE 5: BAYESIAN + BOUNDED positivity + EMPTY plan', context=context_5, plan=plan_empty, ) # ------------------------------------------------------------------------- # CASE 6: Bayesian + bounded positivity + example plan # ------------------------------------------------------------------------- context_6 = make_context( EstimationMode.BAYESIAN, PositivityMode.LOWER_BOUND, ) summarize_case( title='CASE 6: BAYESIAN + BOUNDED positivity + EXAMPLE plan', context=context_6, plan=plan_example, ) # ------------------------------------------------------------------------- # CASE 7: Bayesian + log/exp positivity + empty plan # ------------------------------------------------------------------------- context_7 = make_context( EstimationMode.BAYESIAN, PositivityMode.LOG_EXP, ) summarize_case( title='CASE 7: BAYESIAN + log/exp positivity + EMPTY plan (non-standard but illustrative)', context=context_7, plan=plan_empty, ) # ------------------------------------------------------------------------- # CASE 8: Bayesian + log/exp positivity + example plan # ------------------------------------------------------------------------- context_8 = make_context( EstimationMode.BAYESIAN, PositivityMode.LOG_EXP, ) summarize_case( title='CASE 8: BAYESIAN + log/exp positivity + EXAMPLE plan (non-standard but illustrative)', context=context_8, plan=plan_example, ) print('\n====================') print('END OF SCRIPT') print('====================') .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.058 seconds) .. _sphx_glr_download_auto_examples_hybrid_choice_specs_plot_b01_model_specification.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_b01_model_specification.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_b01_model_specification.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_b01_model_specification.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_