Homeostasis leads to cognition and consciousness
The evolutionary development of animal nervous systems can be conceptualized as a progression of increasing complexity in response to the fundamental need for homeostasis. Homeostasis, the process by which biological systems maintain internal stability, serves as the driving force behind the evolution of the nervous system.
Our hypothesis is that the nervous system emerged with the sole purpose of homeostasis and that homeostasis continues to be the “outer loop” in everything that brains do. Roughly speaking, here are the steps we propose animal nervous systems went through during evolution.
Each step is illustrated with pseudocode to show how the concept of homeostasis is implemented in each stage. Note that the pseudocode is highly simplified and does not represent any specific biological system. So, consider the pseudocode as a rough guide only.
Step 1: Direct and Reactive
In the simplest form, single-cell organisms react directly to environmental stimuli. These organisms possess receptors that trigger biochemical processes resulting in immediate motor responses.
We can imply the presence of corresponding homeostatic variables (hvars), but these hvars are not explicitly implemented, nor managed.
Example: Bacteria sensing noxious chemical gradients and adjusting flagellar movement accordingly.
# Represents single-cell organisms with direct reactive behavior def reactive_organism_main_loop(): # Only implied hvars here, managed through biochemical processes hvars = initialize_implied_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get direct sensory input input = get_input() # Maintain homeostasis by generating actions to trigger actions = homeostasis(input, system_state) execute_actions(actions) # Execute the actions # system state gets updated due to the actions def homeostasis(input, system_state): # Simple reaction to sensory input # For example, noxious stimulus triggers a biochemical cascade resulting in # motor response that moves the organism away from the stimulus # Thus, the implied hvar "noxious_stimulus" is managed without ever being # explicitly represented actions = biochemical_cascade(input, system_state) # Note: hvars are not used here return actions # Simplified function to initialize implied hvars def initialize_implied_hvars(): return {"noxious_stimulus": 0} # Example of implied hvar whose target value is 0 # Simplified function to initialize the system state def initialize_system_state(): return {}
Step 2: Multi-source and Single Sink
Early multicellular organisms develop specialized sensory cells distributed across their bodies. These sensory inputs are transmitted to motor cells via primitive neuron-like cells, allowing for more coordinated responses across the entire body of the organism.
Example: Sea anemones exhibiting basic neural circuits where sensory inputs lead to direct motor outputs.
# Represents multicellular organisms with specialized sensory cells and simple # neural communication def multicellular_organism_main_loop(): # Only implied hvars here, managed through biochemical processes hvars = initialize_implied_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get multisensory inputs from various sensory cells inputs = get_multisensory_inputs() # Maintain homeostasis by generating actions to trigger actions = homeostasis(inputs, system_state) execute_actions(actions) # Execute the actions # system state gets updated due to the actions def homeostasis(inputs, system_state): actions = [] # Process each sensory input to generate corresponding actions for input in inputs: action = process_sensory_input(input, system_state) actions.append(action) # Note: hvars are not used here return actions # Simplified function to initialize the system state def initialize_system_state(): return {} # Simplified function to simulate getting multisensory inputs def get_multisensory_inputs(): return ["input1", "input2", "input3"] # Simplified function to process each sensory input def process_sensory_input(input, system_state): # Example of processing input (details would depend on specific organism) return f"action_for_{input}" # Simplified function to execute actions def execute_actions(actions): for action in actions: print(f"Executing: {action}")
Step 3: Centralized Processing and Non-linear Functions
The migration of neurons into centralized, protected structures (proto-brains) allows for more complex processing and integration of sensory inputs. Lateral connections among neurons enable non-linear transformations of sensory data. This is where dynamics such as LIF (Leaky Integrate-and-Fire) come into play, allowing for the accumulation of evidence over time, thus extending the time horizon of actions and enabling cooperation and competition among neurons. This is a precursor to planning. Note that these nonlinear computing units themselves start coding for certain homeostatic variables.
Example: Early vertebrates with centralized nervous systems capable of integrating and processing sensory information.
# Represents organisms with centralized nervous systems allowing complex # processing def centralized_nervous_system_main_loop(): # Only implied hvars here, managed through biochemical processes hvars = initialize_implied_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get multisensory inputs from various sensory cells inputs = get_multisensory_inputs() # Maintain homeostasis by generating actions to trigger actions = homeostasis(inputs, system_state) execute_actions(actions) # Execute the actions # system state gets updated due to the actions def homeostasis(inputs, system_state): # Apply non-linear processing to input actions = non_linear_processing(input, system_state) return actions # Non-linear processing of integrated inputs def non_linear_processing(input, system_state): # Non-linear transformation # For example, Leaky Integrate-and-Fire (LIF) model can accumulate # evidence for a particular input over time, and trigger an action # when enough evidence is accumulated in a short period of time actions = LeakyIntegrateFire(input, THRESHOLD) return actions # Simplified function to initialize the system state def initialize_system_state(): return {} # Simplified function to simulate getting multisensory inputs def get_multisensory_inputs(): return [1, 2, 3] # Example inputs # Simplified function to execute actions def execute_actions(actions): for action in actions: print(f"Executing: {action}")
Step 4: Predictive Mechanisms and Homeostatic Variables (Hvars)
As we saw in step 3, neurons start accumulating evidence for certain conditions and firing when sufficient evidence is available. Now, if another layer of neurons are added that get intput from the above neurons, they start representing complex spatiotemporal sequences, some of which may predict a future event.
Thus, a certain group of neurons started predicting future sensory (extero, intero, proprioceptive) inputs based on current sensory inputs. Now actions could be fired to prevent the system getting into undesirable future states. This is where homeostatic variables (“hvar"s) come into picture. They represent computed quantities that, when kept within certain ranges, results in meeting certain physical objectives of the organism. e.g. ion concentrations, CO2 levels, core body temperature, etc. Deviations in these hvars trigger hardcoded and learned mitigation action cascades. All relevant quantities to be regulated become encoded as hvars.
Predictions now enable anticipatory actions that maintain homeostasis proactively. Now homeostatic variables become more concrete in the form of the predictions. For instance, if a neuron fires when it predicts that the temperature will rise, it is now coding for the homeostatic variable "temperature” moving away from its steady state. Actions can now be triggered to prevent the temperature from rising.
Note that actions are generated only using hvars that are away from steady state. This implies that there is no agency other than maintaining homeostasis. No “free will” yet.
Example: The hypothalamus in mammals regulating variables like hunger, thirst, and temperature.
# Represents organisms that predict future states to maintain homeostasis def predictive_nervous_system_main_loop(): # Initialize physiological homeostatic variables that are represented # by certain neurons hvars = initialize_physiological_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get multisensory inputs from various sensory cells inputs = get_multisensory_inputs() # Maintain homeostasis by generating actions to trigger actions = homeostasis(inputs, system_state, hvars) execute_actions(actions) # Execute the actions # System state gets updated due to the actions def homeostasis(inputs, system_state, hvars): # Predict the homeostatic state of the system predicted_homeostatic_state = predict_future_homeostatic_state(system_state, hvars, previous_actions) # Compute which hvars are at steady state or away from steady state, # resulting in current valence current_valence = compute_valence(hvars, predicted_homeostatic_state) actions = [] # current_valence is a dictionary with hvars as keys and their # valence as values if !current_valence.all_neutral: # Generate actions to move hvars to steady state # Note that actions are generated only using hvars that are # away from steady state # There is no agency other than maintaining homeostasis! actions = generate_actions(hvars, current_valence) return actions # Predict future sensory input based on current inputs (simplified) def predict_future_homeostatic_state(system_state, hvars, previous_actions): # Example predicted future state future_state = {"temperature": 39, "oxygen_level": 90} return future_state # Compute the state of the homeostatic variables def get_homeostatic_state(predicted_state, hvars): homeostatic_state = {} for i, hvar in enumerate(hvars): homeostatic_state[hvar] = predicted_state[i] return homeostatic_state # Compute current valence based on deviation from steady state def compute_valence(hvars, predicted_homeostatic_state): valence = {} for hvar in hvars: valence[hvar] = hvars[hvar]['steady_state'] - predicted_homeostatic_state[hvar] return valence # Generate actions to maintain homeostatic balance def generate_actions(hvars, current_valence): actions = [] for hvar in hvars: if current_valence[hvar] != 0: if current_valence[hvar] > 0: actions.append(increase_activity(hvar)) else: actions.append(decrease_activity(hvar)) return actions # Increase activity (simplified action) def increase_activity(hvar): return f"increase_activity_for_{hvar}" # Decrease activity (simplified action) def decrease_activity(hvar): return f"decrease_activity_for_{hvar}" # Simplified function to initialize physiological homeostatic variables def initialize_physiological_hvars(): return { 'temperature': {'threshold': 37, 'steady_state': 37}, 'oxygen_level': {'threshold': 95, 'steady_state': 95} } # Simplified function to initialize the system state def initialize_system_state(): return {} # Simplified function to simulate getting multisensory inputs def get_multisensory_inputs(): return [36, 94] # Example inputs for temperature and oxygen level # Simplified function to execute actions def execute_actions(actions): for action in actions: print(f"Executing: {action}")
Step 5: Attention Mechanisms
Given current state of the set of hvars that the brain needs to manage (the homeostatic state, a lower dimensional subspace of the whole system state, mapped onto a homeostatic energy landscape), cascades of activities to manage all deviations get fired. This may result in conflicts, e.g. being hungry in the presence of a predator - explore find food or hide to stay safe. Considering the relative importance and deviation of each variable, brains developed mechanisms to attend to the most important (as of that moment) subset of hvars. This attention mechanism reused the same neural machinery available, i.e. higher level homeostatic variables were set up, e.g. being comfortable (satiated and safe). The predicted deviations in the higher level hvars selectively attend to (or otherwise suppress) lower level hvars.
There must be a cost to suppressing lower level hvars because otherwise certain hvars may be starved of attention and result in harm in the long run. This is probably driven again by higher level hvars that sounds alarm on extreme neglect of the lower level hvar.
The mechanism of building out this hierarchy (more appropriately, heterarchy) must be such that higher level hvars must get wired up to ensure management of all lower level hvars eventually.
Evolving attention mechanisms allow organisms to prioritize among multiple homeostatic deviations, enabling more complex behaviors. The importance of each hvar and the magnitude of its deviation from steady state determine the priority of each input. The hvars that are based in physiological needs have importance derived from their relevance to homeostasis, likely coded genetically.
Note that the importance of hvars can be updated based on the current state of the organism. For example, if an organism is in a state of starvation, the importance of the hvar “hunger” may increase, leading to a higher priority for actions that address this hvar.
This prioritization over multiple hvars is itself driven by a higher order homeostatic variable that represents the whole organism. This higher order hvar is coded by the brain and is the precursor to the concept of self.
Example: The hypothalamus in mammals prioritizing hvar deviations.
# Represents organisms with the ability to prioritize among # multiple homeostatic deviations def attention_mechanism_main_loop(): # Initialize physiological homeostatic variables hvars = initialize_physiological_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get multisensory inputs from various sensory cells inputs = get_multisensory_inputs() # Maintain homeostasis by generating actions to trigger actions = homeostasis(inputs, system_state, hvars) execute_actions(actions) # Execute the actions # System state gets updated due to the actions # Update attention mechanisms update_attention_mechanisms(hvars) def homeostasis(inputs, system_state, hvars): # Predict the homeostatic state of the system predicted_homeostatic_state = predict_future_homeostatic_state(system_state, hvars) # Compute which hvars are at steady state or away from steady # state, resulting in current valence current_valence = compute_valence(hvars, predicted_homeostatic_state) # Generate actions for the top priority hvars that are away # from steady state # Note that prioritization of hvars would happen during the # homeostasis of the "self" hvar. actions = generate_actions(prioritized_hvars, current_valence) return actions # Predict future homeostatic state based on current inputs and previous actions def predict_future_homeostatic_state(system_state, hvars): # Example predicted future state (simplified) future_state = {"temperature": 39, "oxygen_level": 90, "self_health": 45} return future_state # Compute current valence based on deviation from steady state def compute_valence(hvars, predicted_homeostatic_state): valence = {} for hvar in hvars: valence[hvar] = hvars[hvar]['steady_state'] - predicted_homeostatic_state[hvar] return valence # Prioritize hvars based on their importance and current valence def self_health_action(hvars, current_valence): prioritized_hvars = sorted(hvars, key=lambda hvar: abs(current_valence[hvar]) * hvars[hvar]['importance'], reverse=True) return prioritized_hvars # Generate actions to maintain homeostatic balance def generate_actions(prioritized_hvars, current_valence): actions = [] for hvar in prioritized_hvars: if hvar == "self_health": actions.append(self_health_action) if current_valence[hvar] != 0: if current_valence[hvar] > 0: actions.append(increase_activity(hvar)) else: actions.append(decrease_activity(hvar)) return actions # Increase activity (simplified action) def increase_activity(hvar): return f"increase_activity_for_{hvar}" # Decrease activity (simplified action) def decrease_activity(hvar): return f"decrease_activity_for_{hvar}" # Update attention mechanisms (simplified example) def update_attention_mechanisms(hvars): # Example of updating the importance of a cognitive goal if 'temperature' in hvars: hvars['temperature']['importance'] *= 1.1 # Simplified function to initialize physiological homeostatic variables def initialize_physiological_hvars(): return { 'temperature': {'steady_state': 37, 'importance': 0.5}, 'oxygen_level': {'steady_state': 95, 'importance': 0.8}, 'self_health': {'steady_state': 100, 'importance': 1.0} } # Simplified function to initialize the system state def initialize_system_state(): return {} # Simplified function to simulate getting multisensory inputs def get_multisensory_inputs(): return [36, 94] # Example inputs for temperature and oxygen level # Simplified function to execute actions def execute_actions(actions): for action in actions: print(f"Executing: {action}")
Step 6: Cognitive Homeostatic Variables
Once the brain had the ability to establish homeostatic variables, a mechanism to dynamically set up arbitrary hvars came about. This was to facilitate longer term goals. For instance, going back to food source by revisiting known waypoints, while avoiding predators and other distractions. Once established, these “cognitive hvars” would become part of all the hvars the system needs to manage, and get managed alongside physiological hvars.
Now, given that the cognitive hvars are “made up”, they can be abused. For instance, someone may set a goal for an unachievably low body weight as a goal, i.e. a cognitive hvar, and configure it to have an unusually high “value”. Then the homeostatic control system would be forced to keep this hvar in attention, the person would starve and become anorexic, leading to severe health issues.
Somewhere during this evolutionary phase, we probably developed a model of the self-preservation as the highest level cognitive hvar, which resulted in the “self” model and qualia that the self cannot escape (not just spikes coming from somewhere, but “felt experience” that is binding).
The brain develops the capability to set and manage cognitive goals (cognitive hvars) alongside physiological needs. This ability supports complex behaviors like planning and long-term goal pursuit.
Example: Human cognitive processes involving goal-setting and planning in the dorsolateral prefrontal cortex.
# Represents organisms with the ability to set and manage cognitive # homeostatic variables (hvars) def cognitive_hvars_main_loop(): # Initialize physiological homeostatic variables hvars = initialize_physiological_hvars() # Initialize system state system_state = initialize_system_state() # Main loop while True: # Get multisensory inputs from various sensory cells inputs = get_multisensory_inputs() # Maintain homeostasis by generating actions to trigger actions = homeostasis(inputs, system_state, hvars) execute_actions(actions) # Execute the actions # System state gets updated due to the actions # Update cognitive homeostatic variables update_cognitive_hvars(hvars) def homeostasis(inputs, system_state, hvars): # Predict the homeostatic state of the system predicted_homeostatic_state = predict_future_homeostatic_state(system_state, hvars) # Compute which hvars are at steady state or away from steady # state, resulting in current valence current_valence = compute_valence(hvars, predicted_homeostatic_state) # Generate actions for the top priority hvars that are away # from steady state prioritized_hvars = prioritize_hvars(hvars, current_valence) actions = generate_actions(prioritized_hvars, current_valence) return actions # Predict future homeostatic state based on current inputs and # previous actions def predict_future_homeostatic_state(system_state, hvars): # Example predicted future state (simplified) future_state = { "temperature": 39, "oxygen_level": 90, "self_health": 45, "cognitive_goal": 70 } return future_state # Compute current valence based on deviation from steady state def compute_valence(hvars, predicted_homeostatic_state): valence = {} for hvar in hvars: valence[hvar] = hvars[hvar]['steady_state'] - predicted_homeostatic_state[hvar] return valence # Prioritize hvars based on their importance and current valence def prioritize_hvars(hvars, current_valence): prioritized_hvars = sorted( hvars, key=lambda hvar: abs(current_valence[hvar]) * hvars[hvar]['importance'], reverse=True) return prioritized_hvars # Generate actions to maintain homeostatic balance def generate_actions(prioritized_hvars, current_valence): actions = [] for hvar in prioritized_hvars: if current_valence[hvar] != 0: if current_valence[hvar] > 0: actions.append(increase_activity(hvar)) else: actions.append(decrease_activity(hvar)) return actions # Increase activity (simplified action) def increase_activity(hvar): return f"increase_activity_for_{hvar}" # Decrease activity (simplified action) def decrease_activity(hvar): return f"decrease_activity_for_{hvar}" # Update cognitive homeostatic variables (add, reconfigure, or discard) def update_cognitive_hvars(hvars): # Example of adding a new cognitive goal hvars['cognitive_goal'] = {'steady_state': 80, 'importance': 1.2} # Example of reconfiguring an existing cognitive goal if 'cognitive_goal' in hvars: hvars['cognitive_goal']['steady_state'] = 75 # Example of discarding a cognitive goal if 'discard_goal' in hvars: del hvars['discard_goal'] # Simplified function to initialize physiological homeostatic variables def initialize_physiological_hvars(): return { 'temperature': {'steady_state': 37, 'importance': 0.5}, 'oxygen_level': {'steady_state': 95, 'importance': 0.8}, 'self_health': {'steady_state': 100, 'importance': 1.0}, 'cognitive_goal': {'steady_state': 80, 'importance': 1.0} } # Simplified function to initialize the system state def initialize_system_state(): return {} # Simplified function to simulate getting multisensory inputs def get_multisensory_inputs(): return [36, 94] # Example inputs for temperature and oxygen level # Simplified function to execute actions def execute_actions(actions): for action in actions: print(f"Executing: {action}")