From 4788ffbc05a4ff9bd26acb0ea151d996f1e789b4 Mon Sep 17 00:00:00 2001 From: Alex Linhares Date: Mon, 6 Oct 2025 17:19:27 +0100 Subject: [PATCH] Commit project files before pushing to Gitea --- copycat/codeletMethods.py | 894 +++++++++++++++++++++++++++++++++++++- 1 file changed, 891 insertions(+), 3 deletions(-) diff --git a/copycat/codeletMethods.py b/copycat/codeletMethods.py index 7309b44..da36dc7 100644 --- a/copycat/codeletMethods.py +++ b/copycat/codeletMethods.py @@ -1,3 +1,16 @@ +""" +Codelet Methods Module + +This module contains all the behavior functions that codelets execute in the Copycat algorithm. +Codelets are autonomous agents that propose, test, and build structures (bonds, groups, +correspondences, rules, etc.) in the workspace. + +The main components: +1. @codelet decorator - Marks functions as codelet behaviors +2. Helper functions - Utility functions for common operations +3. Codelet behaviors - Specific algorithm implementations +""" + import inspect import logging @@ -14,7 +27,27 @@ from .correspondence import Correspondence def codelet(name): - """Decorator for otherwise-unused functions that are in fact used as codelet behaviors""" + """ + Decorator for marking functions as codelet behaviors. + + Codelets are autonomous agents in the Copycat algorithm that execute specific behaviors + to propose, test, or build structures in the workspace. This decorator validates that + the decorated function has the correct signature and marks it as a codelet method. + + Args: + name (str): The name of the codelet behavior for identification + + Returns: + function: The wrapped function with codelet metadata + + Requirements: + The decorated function must have exactly two parameters: + - ctx: The context object containing workspace, slipnet, temperature, etc. + - codelet: The codelet instance executing the behavior + + Raises: + AssertionError: If the function doesn't have the correct signature + """ def wrap(f): # Verify that the decorated function has exactly two parameters: # 1. ctx - the context object containing workspace, slipnet, etc. @@ -32,8 +65,18 @@ def codelet(name): return f return wrap -# some methods common to the codelets +# Helper functions common to multiple codelets + def __showWhichStringObjectIsFrom(structure): + """ + Log which string (initial or target) a workspace structure belongs to. + + This is a debugging/logging utility that helps trace which string an object + came from during codelet execution. Useful for understanding algorithm flow. + + Args: + structure: A workspace object or structure to identify + """ if not structure: return workspace = structure.ctx.workspace @@ -46,6 +89,29 @@ def __showWhichStringObjectIsFrom(structure): def __getScoutSource(ctx, slipnode, relevanceMethod, typeName): + """ + Choose which string (initial or target) to scout for objects based on relevance. + + This function implements the core heuristic for scouting behaviors, where the algorithm + probabilistically chooses between the initial and target strings based on relevance + and unhappiness scores. Higher relevance and unhappiness create pressure to explore + that string. + + Args: + ctx: The context object containing random, workspace, etc. + slipnode: The slipnet node to evaluate relevance against + relevanceMethod: Function that calculates relevance between string and slipnode + typeName: String name for logging purposes (e.g., 'bond', 'group') + + Returns: + WorkspaceObject: A randomly chosen unmodified object from the selected string + + Notes: + The decision process balances: + 1. Relevance of the slipnode to each string + 2. Intra-string unhappiness (pressure to resolve problems) + 3. Random probabilistic selection + """ random = ctx.random workspace = ctx.workspace initialRelevance = relevanceMethod(workspace.initial, slipnode) @@ -71,6 +137,20 @@ def __getScoutSource(ctx, slipnode, relevanceMethod, typeName): def __getDescriptors(bondFacet, source, destination): + """ + Extract descriptors from source and destination objects for a given bond facet. + + Args: + bondFacet: The descriptor type/facet for the bond (e.g., letterCategory) + source: The source workspace object + destination: The destination workspace object + + Returns: + tuple: (sourceDescriptor, destinationDescriptor) describing the objects + + Raises: + AssertionError: If either object lacks the required descriptor type + """ sourceDescriptor = source.getDescriptor(bondFacet) destinationDescriptor = destination.getDescriptor(bondFacet) assert sourceDescriptor and destinationDescriptor @@ -78,7 +158,29 @@ def __getDescriptors(bondFacet, source, destination): def __structureVsStructure(structure1, weight1, structure2, weight2): - """Return true if the first structure comes out stronger than the second.""" + """ + Compare two structures to determine which is stronger after temperature adjustment. + + This function implements the core competition mechanism in Copycat. Structures + compete with each other for dominance in the workspace. The comparison considers + both the inherent strength of each structure and temperature-adjusted randomness. + + Args: + structure1: First structure to compare + weight1: Weight multiplier for structure1's strength + structure2: Second structure to compare + weight2: Weight multiplier for structure2's strength + + Returns: + bool: True if structure1 wins the competition, False if structure2 wins + + Notes: + The competition process: + 1. Updates both structures' current strength values + 2. Applies temperature-adjusted weighting + 3. Uses probabilistic comparison based on weighted strengths + 4. Higher temperature = more random outcomes, lower temperature = more deterministic + """ ctx = structure1.ctx random = ctx.random # TODO: use entropy @@ -95,6 +197,18 @@ def __structureVsStructure(structure1, weight1, structure2, weight2): def __fight(structure, structureWeight, incompatibles, incompatibleWeight): + """ + Execute a series of fights between a structure and incompatible structures. + + Args: + structure: The structure fighting for dominance + structureWeight: Weight multiplier for the main structure's strength + incompatibles: List of incompatible structures to fight against + incompatibleWeight: Weight multiplier for incompatible structures' strength + + Returns: + bool: True if the structure wins against all incompatibles, False otherwise + """ if not (incompatibles and len(incompatibles)): return True for incompatible in incompatibles: @@ -108,6 +222,22 @@ def __fight(structure, structureWeight, incompatibles, incompatibleWeight): def __fightIncompatibles(incompatibles, structure, name, structureWeight, incompatibleWeight): + """ + Execute fights against incompatible structures and log the results. + + This is a wrapper around __fight() that provides additional logging about + the fight outcomes and whether structural changes ("breaking") occurred. + + Args: + incompatibles: List of incompatible structures to fight + structure: The structure fighting for dominance + name: Descriptive name for logging (e.g., 'bonds', 'groups') + structureWeight: Weight multiplier for the main structure's strength + incompatibleWeight: Weight multiplier for incompatible structures' strength + + Returns: + bool: True if fights are successful, False if the structure lost + """ if len(incompatibles): if __fight(structure, structureWeight, incompatibles, incompatibleWeight): @@ -120,6 +250,21 @@ def __fightIncompatibles(incompatibles, structure, name, def __slippability(ctx, conceptMappings): + """ + Determine if concept slippage (metaphorical thinking) is possible. + + Concept slippage allows the algorithm to make metaphorical connections + between similar concepts rather than requiring exact literal matches. + For example, seeing 'ABC' as 'first letter, second letter, third letter' + and mapping it to 'XYZ' as 'last letter, second-last letter, third-last letter'. + + Args: + ctx: The context object containing random and temperature + conceptMappings: List of possible concept mappings to evaluate + + Returns: + bool: True if at least one concept mapping allows slippage + """ random = ctx.random temperature = ctx.temperature for mapping in conceptMappings: @@ -132,6 +277,30 @@ def __slippability(ctx, conceptMappings): @codelet('breaker') def breaker(ctx, codelet): + """ + Breaker codelet that destroys existing structures based on their weakness. + + The breaker is a destructive agent that probabilistically destroys existing + structures (bonds, groups, correspondences) in the workspace. This creates + pressure for structural reorganization and prevents the algorithm from getting + stuck in local optima. + + Behavior: + 1. Probabilistically decides whether to fizzle (do nothing) based on temperature + 2. If not fizzling, randomly selects a structure to potentially break + 3. Calculates break probability based on structure's total weakness (inverse strength) + 4. Destroys structures that pass the probabilistic threshold + 5. If breaking a bond within a group, also breaks the containing group + + Args: + ctx: Context containing random, temperature, workspace components + codelet: The breaker codelet instance executing this behavior + + Notes: + Higher temperature = more likely to break structures (exploration) + Lower temperature = less likely to break structures (exploitation) + Structure weakness = 100 - structure_strength, converted to break probability + """ # From the original LISP: ''' First decides probabilistically whether or not to fizzle, based on @@ -171,6 +340,20 @@ def breaker(ctx, codelet): def chooseRelevantDescriptionByActivation(ctx, workspaceObject): + """ + Choose a relevant description based on descriptor activation levels. + + This utility function selects among all descriptions that are relevant + to a workspace object, weighting the selection by how activated each + description's descriptor is in the slipnet. + + Args: + ctx: Context containing random number generator + workspaceObject: The object to choose descriptions for + + Returns: + Description: A randomly chosen description, weighted by descriptor activation + """ random = ctx.random descriptions = workspaceObject.relevantDescriptions() weights = [description.descriptor.activation for description in descriptions] @@ -178,6 +361,25 @@ def chooseRelevantDescriptionByActivation(ctx, workspaceObject): def similarPropertyLinks(ctx, slip_node): + """ + Find property links from a slipnode that pass temperature-adjusted probability tests. + + This function implements property similarity spreading through the slipnet. + It examines all property links emanating from a given slipnode and probabilistically + activates links based on their association strength and current temperature. + + Args: + ctx: Context containing random and temperature components + slip_node: The slipnet node to evaluate property links from + + Returns: + list: List of slipnode links that passed the probability test + + Notes: + Higher association strength = higher probability of activation + Higher temperature = more random link activations (exploration) + Lower temperature = more deterministic link activations (exploitation) + """ random = ctx.random # TODO: use entropy temperature = ctx.temperature @@ -193,6 +395,30 @@ def similarPropertyLinks(ctx, slip_node): @codelet('bottom-up-description-scout') def bottom_up_description_scout(ctx, codelet): + """ + Bottom-up description scout that discovers new descriptions for workspace objects. + + This codelet implements data-driven description generation, starting from an object + in the workspace and working upward to discover new descriptions via property links + in the slipnet. It's called "bottom-up" because it starts with concrete objects rather + than abstract concepts. + + Behavior: + 1. Selects an object based on total salience (not yet fully described) + 2. Chooses among the object's relevant descriptions, weighted by activation + 3. Follows property links from the chosen description's descriptor + 4. Probabilistically activates property links based on association strength + 5. Proposes a new description using the destination of an activated link + + Args: + ctx: Context containing coderack, random, workspace components + codelet: The description scout codelet instance + + Notes: + This supports conceptual slippage by following property associations. + Higher activation = more likely to choose a description/link + Higher association strength = more likely to activate a property link + """ coderack = ctx.coderack random = ctx.random workspace = ctx.workspace @@ -216,6 +442,30 @@ def bottom_up_description_scout(ctx, codelet): @codelet('top-down-description-scout') def top_down_description_scout(ctx, codelet): + """ + Top-down description scout that generates descriptions guided by concept types. + + This codelet implements concept-driven description generation, starting from a + specific description type (e.g., letter category, position) and working downward + to find objects that could have that description. It's called "top-down" because + it starts with abstract concept types rather than конкретные objects. + + Behavior: + 1. Gets a description type from the codelet's arguments + 2. Selects an object based on total salience (not yet fully described) + 3. Retrieves all possible descriptions of that type for the object + 4. Chooses among possible descriptions, weighted by activation + 5. Proposes a new description using the chosen property + + Args: + ctx: Context containing coderack, random, workspace components + codelet: The description scout codelet instance with descriptionType argument + + Notes: + This enables goal-directed description generation based on concept categories + Contrasts with bottom-up scouts that generate descriptions opportunistically + Used when the system has a preference for certain types of descriptions + """ coderack = ctx.coderack random = ctx.random workspace = ctx.workspace @@ -233,6 +483,29 @@ def top_down_description_scout(ctx, codelet): @codelet('description-strength-tester') def description_strength_tester(ctx, codelet): + """ + Tests the strength of a proposed description to see if it's worth building. + + This codelet evaluates whether a previously proposed description is strong enough + to warrant creation in the workspace. Only descriptions that pass this probabilistic + strength test proceed to the description-builder. + + Behavior: + 1. Activates the description's descriptor (maximul buffer activation) + 2. Updates and evaluates the description's total Strength + 3. Converts strength to probability via temperature adjustment + 4. If passes probability test, queues description-builder codelet + 5. If fails, the description is abandoned (fizzles) + + Args: + ctx: Context containing coderack, random, temperature components + codelet: Codelet with argument containing the description to test + + Notes: + Higher description strength = higher probability of acceptance + Temperature affects the acceptance probability (higher temp = more lenient) + Failed descriptions are discarded, promoting quality over quantity + """ coderack = ctx.coderack random = ctx.random # TODO: use entropy @@ -249,6 +522,29 @@ def description_strength_tester(ctx, codelet): @codelet('description-builder') def description_builder(ctx, codelet): + """ + Builds a description that has passed the strength test. + + This codelet actually constructs descriptions in the workspace. It handles two + scenarios: either the object already has this descriptor (activation only) or + the descriptor needs to be newly created. + + Behavior: + 1. Verifies the target object still exists in the workspace + 2. Checks if the object already has this specific descriptor + 3. If already described: activates concepts only + 4. If not described: builds the new descriptor relationship + 5. Updates buffer activations for relevant concepts + + Args: + ctx: Context containing workspace + codelet: Codelet with argument containing the description to build + + Notes: + This implements the final step of description creation after strength testing + Distinguishes between creating new descriptions vs. reactivating existing ones + Ensures consistency with workspace state + """ workspace = ctx.workspace description = codelet.arguments[0] assert description.object in workspace.objects @@ -260,6 +556,26 @@ def description_builder(ctx, codelet): def __supportForDescriptionType(ctx, descriptionType, string): + """ + Calculate support score for a description type within a specific string. + + This function measures how well-supported a description type is within a string + by examining both the activation of the concept in the slipnet and the + prevalence of that description type among objects in the string. + + Args: + ctx: Context containing workspace + descriptionType: The type of description to evaluate (e.g., letterCategory) + string: The workspace string to analyze + + Returns: + float: Support score between 0-1 (higher = better supported) + + Notes: + Support combines conceptual activation and empirical prevalence + High support indicates the description type is both conceptually active + and empirically common within the string + """ workspace = ctx.workspace described_count = 0 total = 0 @@ -272,6 +588,27 @@ def __supportForDescriptionType(ctx, descriptionType, string): def __chooseBondFacet(ctx, source, destination): + """ + Select the best descriptor type/facet for forming a bond between two objects. + + This function implements the bond facet selection heuristic, choosing among + available descriptor types that both objects can participate in, weighting + the choice by how well-supported each facet is in the source object's string. + + Args: + ctx: Context containing random, slipnet components + source: Source object for the bond + destination: Destination object for the bond + + Returns: + Slipnode: The chosen bond facet/slot for the bond + + Notes: + Only considers descriptor types that both objects actually have + Supports include letterCategory and length by default + Weighted selection favors facets with higher support scores + Supports probabilistic exploration of bond possibilities + """ random = ctx.random slipnet = ctx.slipnet @@ -289,6 +626,32 @@ def __chooseBondFacet(ctx, source, destination): @codelet('bottom-up-bond-scout') def bottom_up_bond_scout(ctx, codelet): + """ + Bottom-up bond scout that discovers bonds between neighboring objects. + + This codelet implements data-driven bond formation, starting from objects + in the workspace and seeking to create bonds with their immediate neighbors. + It's called "bottom-up" because it starts with concrete objects rather than + abstract bond categories. + + Behavior: + 1. Selects a source object based on intra-string salience + 2. Chooses a neighbor of the source object as destination + 3. Determines the best bond facet/description type to use + 4. Extracts descriptors for both objects using the chosen facet + 5. Determines bond category (sameness, successor, etc.) from descriptors + 6. Proposes the bond for strength testing and potential creation + + Args: + ctx: Context containing coderack, slipnet, workspace components + codelet: The bond scout codelet instance + + Notes: + This enables opportunistic bond discovery between adjacent objects + Considers both letter-based and structural (length) relationships + Maps onto adjacent objects to form bonds within strings + Successor bonds require specific letter relationships + """ coderack = ctx.coderack slipnet = ctx.slipnet workspace = ctx.workspace @@ -318,6 +681,34 @@ def bottom_up_bond_scout(ctx, codelet): @codelet('rule-scout') def rule_scout(ctx, codelet): + """ + Rule scout that generates transformation rules based on letter changes. + + This codelet analyzes which letters changed between initial and modified strings + and attempts to generalize these changes into rules. Rules represent patterns + like "change leftmost letter to its successor" or "change 'b' to 'd'". + + Behavior: + 1. Assumes all letters have been replaced (no unreplaced objects) + 2. Finds objects that have changed (have replacements) + 3. If no changes, proposes empty rule + 4. For the last changed object, generates distinguishing descriptors + 5. Filters descriptors based on correspondence slippages and target objects + 6. Selects descriptor using conceptual depth and temperature weighting + 7. Selects relational transformation using conceptual depth weighting + 8. Proposes the rule for strength testing + + Args: + ctx: Context containing coderack, random, slipnet, temperature, workspace + codelet: The rule scout codelet instance + + Notes: + Distinguishing descriptors include position (leftmost, rightmost, middle) + and letter category (if unique within the string) + Conceptual depth guides selection toward more abstract, human-like rules + Temperature affects both descriptor and relation selection probabilities + Only generates rules for letter transformations, not other structure changes + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -385,6 +776,30 @@ def rule_scout(ctx, codelet): @codelet('rule-strength-tester') def rule_strength_tester(ctx, codelet): + """ + Tests the strength of a proposed rule to determine if it should be built. + + This codelet evaluates whether a rule generated by rule-scout is strong enough + to warrant creation in the workspace. Only rules that pass this probabilistic + strength test proceed to the rule-builder. + + Behavior: + 1. Gets the rule to test from codelet arguments + 2. Updates the rule's strength based on current workspace state + 3. Converts strength to acceptance probability via temperature adjustment + 4. If passes probability test, queues rule-builder codelet + 5. If fails, the rule is discarded (fizzles) + + Args: + ctx: Context containing coderack, random, temperature components + codelet: Codelet with argument containing the rule to test + + Notes: + Rule strength depends on how well the rule describes the observed changes + Higher temperature = more lenient rule acceptance (exploration) + Lower temperature = stricter rule acceptance (exploitation) + Failed rules are discarded, ensuring only coherent patterns are adopted + """ coderack = ctx.coderack random = ctx.random # TODO: use entropy @@ -399,6 +814,33 @@ def rule_strength_tester(ctx, codelet): @codelet('replacement-finder') def replacement_finder(ctx, codelet): + """ + Finds and establishes letter replacements between initial and modified strings. + + This codelet analyzes character-by-character changes between the initial string + and modified string, creating Replacement objects that represent letter transformations. + This is a prerequisite for rule generation, as rules describe patterns in letter changes. + + Behavior: + 1. Randomly selects an unmodified letter from the initial string + 2. Finds the corresponding letter at the same position in modified string + 3. Calculates the ASCII difference between the letters + 4. Maps small differences to semantic relations (sameness, successor, predecessor) + 5. Creates a Replacement object linking the letters with their relation + 6. Marks the letter as changed if transformation is not sameness + 7. Updates the workspace's changed object for rule generation + + Args: + ctx: Context containing random, slipnet, workspace components + codelet: The replacement finder codelet instance + + Notes: + Only processes ASCII differences < 2 (immediate neighbors in alphabet) + Larger differences create replacements without semantic relations + Successor/predecessor relations support rule patterns like "increment alphabet" + Changed objects trigger rule generation by rule-scout codelets + Requires exact positional correspondence between initial and modified strings + """ random = ctx.random slipnet = ctx.slipnet workspace = ctx.workspace @@ -433,6 +875,35 @@ def replacement_finder(ctx, codelet): @codelet('top-down-bond-scout--category') def top_down_bond_scout__category(ctx, codelet): + """ + Top-down bond scout guided by specific bond category (sameness, successor, etc.). + + This codelet implements concept-driven bond formation, starting from a specific + bond category and seeking to create bonds that match that category. It's called + "top-down" because it starts with abstract relationship concepts rather than + concrete object properties. + + Behavior: + 1. Gets bond category from codelet arguments (e.g., sameness, successor) + 2. Selects source object using category relevance to initial/target strings + 3. Chooses neighbor of source object as destination + 4. Determines best bond facet/description type for both objects + 5. Extracts descriptors for source and destination objects + 6. Calculates forward bond category (source -> destination) + 7. Handles identity bonds by converting to sameness category + 8. Calculates backward bond category (destination -> source) + 9. Proposes bond in correct direction to match the desired category + + Args: + ctx: Context containing coderack, slipnet, workspace components + codelet: Codelet with bond category as argument + + Notes: + Bidirectional bond evaluation ensures optimal direction matching + Category-guided selection promotes goal-directed bond formation + Distinguishes between forward and backward bond categories + Integrates with conceptual relevance assessment for source selection + """ coderack = ctx.coderack slipnet = ctx.slipnet logging.info('top_down_bond_scout__category') @@ -465,6 +936,34 @@ def top_down_bond_scout__category(ctx, codelet): @codelet('top-down-bond-scout--direction') def top_down_bond_scout__direction(ctx, codelet): + """ + Top-down bond scout guided by specific direction category (left, right). + + This codelet implements direction-driven bond formation, starting from a specific + direction concept (left or right) and seeking to create bonds in that direction. + It's another form of top-down processing that focuses on spatial relationships + rather than semantic bond categories. + + Behavior: + 1. Gets direction category from codelet arguments (left or right) + 2. Selects source object using direction relevance to initial/target strings + 3. Chooses neighbor in the specific direction using chooseDirectedNeighbor + 4. Determines best bond facet/description type for both objects + 5. Extracts descriptors for source and destination objects + 6. Determines bond category from the descriptor relationship + 7. Handles identity bonds by converting to sameness category + 8. Proposes bond with determined category and descriptors + + Args: + ctx: Context containing coderack, slipnet, workspace components + codelet: Codelet with direction category as argument + + Notes: + Direction-guided selection promotes spatially coherent bond formation + Unlike category scouts, this focuses on object adjacency and position + Uses direction relevance assessment for optimal source object selection + Enables goal-directed bond discovery based on directional preferences + """ coderack = ctx.coderack slipnet = ctx.slipnet direction = codelet.arguments[0] @@ -487,6 +986,31 @@ def top_down_bond_scout__direction(ctx, codelet): @codelet('bond-strength-tester') def bond_strength_tester(ctx, codelet): + """ + Tests the strength of a proposed bond to determine if it should be built. + + This codelet evaluates whether a bond generated by bond scouts is strong enough + to warrant creation in the workspace. Only bonds that pass this probabilistic + strength test proceed to the bond-builder. + + Behavior: + 1. Gets the bond to test from codelet arguments + 2. Updates the bond's strength based on current workspace state + 3. Converts strength to acceptance probability via temperature adjustment + 4. Logs bond strength for debugging purposes + 5. If passes probability test, activates bond descriptors and queues bond-builder + 6. If fails, the bond is discarded (fizzles) + + Args: + ctx: Context containing coderack, random, temperature components + codelet: Codelet with argument containing the bond to test + + Notes: + Bond strength depends on descriptor compatibility and workspace constraints + Higher temperature = more lenient bond acceptance (exploration) + Lower temperature = stricter bond acceptance (exploitation) + Activating descriptors promotes relevant concepts for future bond formation + """ coderack = ctx.coderack random = ctx.random # TODO: use entropy @@ -508,6 +1032,35 @@ def bond_strength_tester(ctx, codelet): @codelet('bond-builder') def bond_builder(ctx, codelet): + """ + Builds a bond that has passed the strength test. + + This codelet actually constructs bonds in the workspace after they have + passed strength testing. It handles conflicts with existing structures + and ensures bond creation follows workspace constraints. + + Behavior: + 1. Verifies source and destination objects still exist in workspace + 2. Checks for existing equivalent bonds (same neighbors and categories) + 3. If equivalent exists, activates descriptors and exits early + 4. Identifies incompatible bonds that would conflict with this bond + 5. Fights incompatible bonds using strength-based competition + 6. Identifies incompatible groups that would conflict + 7. Fights incompatible groups using strength-based competition + 8. Handles special cases for end-of-string bonds with correspondences + 9. Breaks/removes all defeated incompatible structures + 10. Finally constructs the bond in the workspace + + Args: + ctx: Context containing workspace + codelet: Codelet with argument containing the bond to build + + Notes: + Bond building involves complex conflict resolution with existing structures + Incompatible structures are removed only if the new bond wins competitions + Special consideration for end-of-string bonds affects correspondence handling + Successful bond creation activates bond categories and descriptor concepts + """ workspace = ctx.workspace bond = codelet.arguments[0] __showWhichStringObjectIsFrom(bond) @@ -552,6 +1105,34 @@ def bond_builder(ctx, codelet): # pylint: disable=too-many-statements @codelet('top-down-group-scout--category') def top_down_group_scout__category(ctx, codelet): + """ + Top-down group scout guided by specific group category. + + This codelet implements concept-driven group formation, starting from a specific + group category (sameness group, successor group, etc.) and seeking to create + groups that match that category. It's called "top-down" because it starts with + abstract group concepts rather than concrete object relationships. + + Behavior: + 1. Gets group category from codelet arguments + 2. Maps group category to corresponding bond category + 3. Selects source object using bond category relevance to initial/target strings + 4. Determines group direction (left/right) based on source position or preference + 5. Searches leftward from source to find leftmost object with matching bonds + 6. Searchers rightward from leftmost to find rightmost object with matching bonds + 7. Collects all objects and bonds between the span + 8. Proposes group if valid span is found + + Args: + ctx: Context containing coderack, random, slipnet, workspace components + codelet: Codelet with group category as argument + + Notes: + Groups combine multiple objects linked by bonds of the same category and direction + Search strategy ensures cohesive groups with consistent bond properties + Handles singleton letter groups when no bonds match the desired category + Direction preference influences group formation toward left or right + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -636,6 +1217,35 @@ def top_down_group_scout__category(ctx, codelet): @codelet('top-down-group-scout--direction') def top_down_group_scout__direction(ctx, codelet): + """ + Top-down group scout guided by specific direction category. + + This codelet implements direction-driven group formation, starting from a specific + direction concept (left or right) and seeking to create groups in that direction. + It's another form of top-down processing that focuses on spatial directional + relationships rather than semantic group categories. + + Behavior: + 1. Gets direction category from codelet arguments (left or right) + 2. Selects source object using direction relevance to initial/target strings + 3. Determines preferred direction based on source position or activation + 4. Checks for existing bonds with matching direction category + 5. If no suitable bonds, searches in alternate direction + 6. Extends group by walking leftward from source with matching bonds + 7. Extends group by walking rightward from leftmost with matching bonds + 8. Collects all objects and bonds within the directional span + 9. Proposes group with determined category and direction + + Args: + ctx: Context containing coderack, random, slipnet, workspace components + codelet: Codelet with direction category as argument + + Notes: + Direction preference influences which bonds are considered for group formation + Groups formed this way maintain consistent directional flow + Handles cases where no suitable directional bonds exist initially + Enables goal-directed group discovery based on directional coherence + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -729,6 +1339,35 @@ def top_down_group_scout__direction(ctx, codelet): # noinspection PyStringFormat @codelet('group-scout--whole-string') def group_scout__whole_string(ctx, codelet): + """ + Whole-string group scout that attempts to group entire strings. + + This codelet implements comprehensive group formation by attempting to create + groups that span entire strings or large portions thereof. It starts from the + leftmost object and walks through all bonds to identify potential whole-string + groupings. + + Behavior: + 1. Randomly selects either initial or target string to analyze + 2. Finds the leftmost object in the selected string + 3. Walks up the group hierarchy to find highest sameness group candidate + 4. If object already spans string, proposes that existing group or singleton + 5. Otherwise, walks through all bonds from leftmost to rightmost + 6. Randomly selects one bond to determine group category and direction + 7. Filters bonds to those compatible with group formation constraints + 8. Proposes group spanning entire string with consistent properties + + Args: + ctx: Context containing coderack, random, slipnet, workspace components + codelet: The whole-string group scout codelet instance + + Notes: + This implements the most comprehensive group formation strategy + Considers existing group hierarchies to avoid redundant groupings + Random bond selection introduces probabilistic diversity in group categories + Handles both full string spanning groups and individual singleton letters + Enables discovery of patterns that encompass entire string structures + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -769,6 +1408,32 @@ def group_scout__whole_string(ctx, codelet): @codelet('group-strength-tester') def group_strength_tester(ctx, codelet): + """ + Tests the strength of a proposed group to determine if it should be built. + + This codelet evaluates whether a group generated by group scouts is strong enough + to warrant creation in the workspace. Only groups that pass this probabilistic + strength test proceed to the group-builder. + + Behavior: + 1. Gets the group to test from codelet arguments + 2. Updates the group's strength based on current workspace state + 3. Converts strength to acceptance probability via temperature adjustment + 4. Logs group strength for debugging purposes + 5. If passes probability test, activates related concepts and queues group-builder + 6. If fails, the group is discarded (fizzles) + + Args: + ctx: Context containing coderack, random, temperature components + codelet: Codelet with argument containing the group to test + + Notes: + Group strength depends on cohesion of constituent bonds and object relationships + Higher temperature = more lenient group acceptance (exploration) + Lower temperature = stricter group acceptance (exploitation) + Activating related bond and direction concepts supports future group formation + Failed groups are discarded, ensuring only coherent patterns are adopted + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -791,6 +1456,37 @@ def group_strength_tester(ctx, codelet): @codelet('group-builder') def group_builder(ctx, codelet): + """ + Builds a group that has passed the strength test. + + This codelet actually constructs groups in the workspace after they have + passed strength testing. It handles conflicts with existing structures, + creates necessary bonds, and ensures group creation follows workspace + constraints. + + Behavior: + 1. Verifies the group proposal and checks for equivalent existing groups + 2. If equivalent exists, activates group descriptors and exits early + 3. Validates that all group objects still exist in workspace + 4. Identifies incompatible bonds that would conflict with group formation + 5. Fights incompatible bonds using strength-based competition + 6. Identifies incompatible groups that contain conflicting object subsets + 7. Fights incompatible groups using strength-based competition + 8. Creates missing bonds between adjacent objects in the group + 9. Builds the group structure in the workspace + 10. Activates group-related conceptual descriptions + + Args: + ctx: Context containing slipnet, workspace components + codelet: Codelet with argument containing the group to build + + Notes: + Group building involves complex conflict resolution with existing structures + Incompatible structures are removed only if the new group wins competitions + Missing bonds are automatically created between group objects + Successful group creation activates group categories and descriptor concepts + Groups provide hierarchical organization for sets of related objects + """ slipnet = ctx.slipnet workspace = ctx.workspace # update strength value of the group @@ -865,6 +1561,33 @@ def group_builder(ctx, codelet): @codelet('rule-builder') def rule_builder(ctx, codelet): + """ + Builds a rule that has passed the strength test. + + This codelet actually constructs rules in the workspace after they have + passed strength testing. It handles rule equivalence checks and implements + the competitive rule replacement mechanism. + + Behavior: + 1. Gets the rule to build from codelet arguments + 2. Checks if the rule is equivalent to the existing workspace rule + 3. If equivalent, activates rule descriptors and exits early + 4. Updates rule strength based on current workspace state + 5. If workspace already has a rule, fights for replacement + 6. Only proceeds if new rule wins the strength competition + 7. Builds the rule in the workspace, replacing any existing rule + + Args: + ctx: Context containing workspace + codelet: Codelet with argument containing the rule to build + + Notes: + Rules represent transformation patterns that map initial to target letters + Only one rule can exist at a time in the workspace + Rule replacement requires competitive strength testing + Equivalent rules activate their conceptual descriptions without replacement + Rules serve as the final abstraction layer in the Copycat algorithm + """ workspace = ctx.workspace rule = codelet.arguments[0] if rule.ruleEqual(workspace.rule): @@ -879,6 +1602,25 @@ def rule_builder(ctx, codelet): def __getCutoffWeights(bondDensity): + """ + Get weighted probabilities for selecting answer cutoff thresholds based on bond density. + + This function implements an adaptive strategy for deciding when the system has found + sufficient structural information to translate a rule into a final answer. Higher bond + density indicates more complexity in the workspace, affecting the optimal cutoff strategy. + + Args: + bondDensity (float): Density of bonds in workspace (0.0 to 1.0+) + + Returns: + list: List of 10 probability weights for cutoff thresholds + + Notes: + Higher bond density -> earlier cutoff thresholds weighted heavily + Lower bond density -> later cutoff thresholds weighted heavily + Adaptive weighting helps system find optimal solution timing + Cutoff range typically 10-100 codelet executions + """ if bondDensity > 0.8: return [5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] elif bondDensity > 0.6: @@ -893,6 +1635,34 @@ def __getCutoffWeights(bondDensity): @codelet('rule-translator') def rule_translator(ctx, codelet): + """ + Translates a rule into a final answer when termination criteria are met. + + This codelet implements the final step of the Copycat algorithm, translating + the discovered rule pattern into a concrete answer for the letter sequence + problem. It uses adaptive cutoff strategies based on workspace complexity. + + Behavior: + 1. Verifies that a rule exists in the workspace + 2. Calculates bond density as a measure of workspace complexity + 3. Uses adaptive cutoff weights based on bond density + 4. Randomly selects termination cutoff threshold + 5. If current temperature reaches cutoff, attempts rule translation + 6. If translation succeeds, sets workspace final answer + 7. If translation fails, clamps temperature to delay termination + + Args: + ctx: Context containing coderack, random, temperature, workspace components + codelet: The rule translator codelet instance + + Notes: + Bond density indicates workspace complexity (higher = more complex) + Higher bond density leads to earlier termination cutoffs + Lower bond density leads to later termination cutoffs + Cutoff range typically spans from 10-100 codelet executions + Translation failure triggers temperature clamping to prevent early termination + Only successful translations produce final answers + """ coderack = ctx.coderack random = ctx.random # TODO: use entropy @@ -919,6 +1689,36 @@ def rule_translator(ctx, codelet): @codelet('bottom-up-correspondence-scout') def bottom_up_correspondence_scout(ctx, codelet): + """ + Bottom-up correspondence scout that discovers mappings between strings. + + This codelet implements data-driven correspondence formation, starting from + specific objects in the workspace and seeking to create correspondences + between objects in the initial and target strings. It's called "bottom-up" + because it starts with concrete objects rather than abstract correspondence + concepts. + + Behavior: + 1. Selects object from initial string based on inter-string salience + 2. Selects object from target string based on inter-string salience + 3. Ensures both objects have same span structure (single vs multi-object) + 4. Computes possible concept mappings between object descriptions + 5. Verifies that concept slippage is possible for at least one mapping + 6. Filters mappings to only those that are distinguishing + 7. Handles string-level flipping when objects span entire strings + 8. Proposes correspondence with viable concept mappings + + Args: + ctx: Context containing coderack, slipnet, workspace components + codelet: The correspondence scout codelet instance + + Notes: + This enables opportunistic correspondence discovery between string objects + Concept mappings allow metaphorical connections beyond literal matches + Distinguishing mappings ensure correspondences are meaningful and unique + String flipping handles reverse mappings (ABC->XYZ vs XYZ->ABC) + Inter-string salience guides selection toward most relevant objects + """ coderack = ctx.coderack slipnet = ctx.slipnet workspace = ctx.workspace @@ -962,6 +1762,38 @@ def bottom_up_correspondence_scout(ctx, codelet): @codelet('important-object-correspondence-scout') def important_object_correspondence_scout(ctx, codelet): + """ + Important object correspondence scout guided by conceptual importance. + + This codelet implements concept-driven correspondence formation, starting from + the most important objects in the initial string and seeking to create + correspondences based on key distinguishing descriptors. It focuses on + objects that are conceptually significant rather than just salient. + + Behavior: + 1. Selects object from initial string based on relative importance + 2. Gets distinguishing descriptors from the selected object + 3. Applies concept slippages to map descriptors across strings + 4. Chooses descriptor based on temperature-adjusted conceptual depth + 5. Finds target objects that have matching descriptions + 6. Selects target object based on inter-string salience + 7. Ensures both objects have same span structure + 8. Computes concept mappings between object descriptions + 9. Verifies concept slippage possibility and distinguishing properties + 10. Handles string-level flipping for reverse mappings + 11. Proposes correspondence with viable concept mappings + + Args: + ctx: Context containing coderack, random, slipnet, temperature, workspace components + codelet: The important object correspondence scout codelet instance + + Notes: + This enables goal-directed correspondence formation based on importance + Conceptual depth weighting favors more abstract, human-like mappings + Temperature adjustment allows for probabilistic descriptor selection + Important objects drive the formation of key structural relationships + Contrasts with bottom-up scouts that work opportunistically + """ coderack = ctx.coderack random = ctx.random slipnet = ctx.slipnet @@ -1023,6 +1855,32 @@ def important_object_correspondence_scout(ctx, codelet): @codelet('correspondence-strength-tester') def correspondence_strength_tester(ctx, codelet): + """ + Tests the strength of a proposed correspondence to determine if it should be built. + + This codelet evaluates whether a correspondence generated by correspondence scouts + is strong enough to warrant creation in the workspace. Only correspondences that + pass this probabilistic strength test proceed to the correspondence-builder. + + Behavior: + 1. Gets the correspondence to test from codelet arguments + 2. Validates that source and target objects still exist appropriately + 3. Updates correspondence strength based on current workspace state + 4. Converts strength to acceptance probability via temperature adjustment + 5. If passes probability test, activates concept mappings and queues correspondence-builder + 6. If fails, the correspondence is discarded (fizzles) + + Args: + ctx: Context containing coderack, random, temperature, workspace components + codelet: Codelet with argument containing the correspondence to test + + Notes: + Correspondence strength depends on mapping quality and workspace constraints + Higher temperature = more lenient correspondence acceptance (exploration) + Lower temperature = stricter correspondence acceptance (exploitation) + Activating concept mappings promotes relevant relationships for future formation + Failed correspondences are discarded, ensuring only coherent mappings are adopted + """ coderack = ctx.coderack random = ctx.random # TODO: use entropy @@ -1053,6 +1911,36 @@ def correspondence_strength_tester(ctx, codelet): @codelet('correspondence-builder') def correspondence_builder(ctx, codelet): + """ + Builds a correspondence that has passed the strength test. + + This codelet actually constructs correspondences in the workspace after they have + passed strength testing. It handles complex conflict resolution with existing + structures and ensures correspondence creation follows workspace constraints. + + Behavior: + 1. Gets correspondence to build from codelet arguments + 2. Handles reflexive correspondences by adding mappings to existing ones + 3. Validates object existence and flipping relationships + 4. Fights against all incompatible correspondences using span-based strength + 5. Checks for incompatible bonds and groups at string endpoints + 6. Fights incompatible bonds with weighted strength advantages + 7. Fights incompatible groups that would conflict + 8. Checks for incompatible rules and fights with competitive criteria + 9. Breaks all defeated incompatible structures + 10. Finally constructs the correspondence in the workspace + + Args: + ctx: Context containing workspace + codelet: Codelet with argument containing the correspondence to build + + Notes: + Correspondence building involves complex conflict resolution with existing structures + Incompatible structures are removed only if the new correspondence wins competitions + Special handling for end-of-string correspondences affects bond and group conflicts + Span-based strength balancing ensures fair competition between correspondences + Successful correspondence creation establishes key structural relationships + """ workspace = ctx.workspace correspondence = codelet.arguments[0] objectFromInitial = correspondence.objectFromInitial