pik-copan / pycopancore

reference implementation of the copan:CORE World-Earth modelling framework
http://www.pik-potsdam.de/copan
Other
44 stars 10 forks source link

override default values, specify constant values, provide additional specification attributes at model composition #141

Open mensch72 opened 2 years ago

mensch72 commented 2 years ago

When composing a model, the model composer can...

  1. override a variable's default value:
    class Cell(A.Cell, B.Cell):
       A.Cell.terrestrial_carbon.default = 10 * D.GtC
  2. fix a variable to a constant value (e.g., to zero in order to turn off certain interactions):
    class Environment(carbon_cycle.Environment, ...):
       carbon_cycle.Environment.ocean_atmosphere_diffusion_rate.fixed = 0
  3. specify additional specification attributes (e.g., to specify which variables a generic component should act on):
    class Culture(B.Culture, imitation.Culture):
       imitation_variables = [awareness.Individual.is_environmentally_friendly, saving.Individual.savings_rate]

    A fixed variable cannot be changed by the model user or by any component. This is verified at runtime.

Example use case: Specify that environmental friendliness and savings rate will be imitated, one with simple contagion, the other with complex contagion, with some default imitation rates:

class Culture(B.Culture, imitation.Culture, optimal_saving.Culture):
    # specify which variables to imitate and how (cannot be changed by model user):
    imitation_variables = [awareness.Individual.is_environmentally_friendly, saving.Individual.savings_rate]
    imitation_types = { awareness.Individual.is_environmentally_friendly: 'simple', saving.Individual.savings_rate: 'complex' }
    # set default parameters (can be changed by model user):
    imitation.Culture.imitation_n_others.default = { saving.Individual.savings_rate: 2 }
    imitation.Culture.imitation_rates.default = { awareness.Individual.is_environmentally_friendly: 0.1 / D.years, saving.Individual.savings_rate: 0.2  / D.years }
    # turn off conflicting process from other component:
    optimal_saving.update_rate.fixed = 0
mensch72 commented 2 years ago
  1. and 3. may already work and thus not require any new coding.
  2. requires adding the fixed attribute to Variable and verifying that no change is attempted or has happened in set_value(s) and Runner.
mensch72 commented 2 years ago

@leander-j : please review this user story to see whether it would work for you in the granovetter model! I imagine we could then together code a generic component imitation that can do all sorts of imitation, either simple, or complex, or Granovetter-style with thresholds. It could use the following specification attributes and parameter variables:

Example:

# things the user cannot change:
imitation_variables = [A.Individual.is_active, A.Individual.savings_rate]
imitation_types = { A.Individual.is_active: 'threshold', A.Individual.savings_rate: 'simple' }
# things the user can change:
imitation.imitation_rates.default = { A.Individual.is_active: 1.0 / D.weeks, A.Individual.savings_rate: 3.0 / D.years }
imitation.imitation_neighbor_fractions.default = { A.Individual.is_active: 1.0 }  # -> always look at all nighbors
imitation.imitation_thresholds.default = { A.Individual.is_active: { True: 0.4, False: 0.6 } }  # -> it is easier to get active than to get inactive
leander-j commented 2 years ago

I think it makes a lot of sense that way. Assigning some nodes an unchangable state (maybe via thresholds) as well as probabilities for imitation are some additional features needed. The chosen network object should not be reassignable but it might evolve in time as well