Skip to main content
Glama
categorical_helpers.py6.21 kB
""" Categorical reasoning helpers for translating categorical properties to FOL. Provides utilities for working with category theory concepts in first-order logic. """ from typing import List, Dict, Tuple class CategoricalHelpers: """Helper functions for categorical reasoning in first-order logic""" @staticmethod def category_axioms() -> List[str]: """Generate basic category theory axioms Returns: List of FOL axioms defining a category """ return [ # Identity morphisms exist "all x (object(x) -> exists i (morphism(i) & source(i,x) & target(i,x) & identity(i,x)))", # Identity is unique "all x all i1 all i2 ((identity(i1,x) & identity(i2,x)) -> i1 = i2)", # Composition exists when source/target match "all f all g ((morphism(f) & morphism(g) & target(f) = source(g)) -> exists h (morphism(h) & compose(g,f,h)))", # Composition is associative "all f all g all h all fg all gh all fgh all gfh ((compose(g,f,fg) & compose(h,g,gh) & compose(h,fg,fgh) & compose(gh,f,gfh)) -> fgh = gfh)", # Left identity law "all f all a all id ((morphism(f) & source(f,a) & identity(id,a) & compose(f,id,comp)) -> comp = f)", # Right identity law "all f all b all id ((morphism(f) & target(f,b) & identity(id,b) & compose(id,f,comp)) -> comp = f)", ] @staticmethod def functor_axioms(functor_name: str = "F") -> List[str]: """Generate functor axioms Args: functor_name: Name of the functor (default: F) Returns: List of FOL axioms defining a functor """ f = functor_name.lower() return [ # Functor preserves identity f"all x all id (identity(id,x) -> identity({f}(id), {f}(x)))", # Functor preserves composition f"all g all h all gh ((compose(g,h,gh)) -> compose({f}(g), {f}(h), {f}(gh)))", ] @staticmethod def verify_commutativity(path_a: List[str], path_b: List[str], object_start: str, object_end: str) -> Tuple[List[str], str]: """Generate FOL to verify diagram commutativity Two paths in a diagram commute if composing morphisms along each path yields the same result. Args: path_a: List of morphism names in first path path_b: List of morphism names in second path object_start: Starting object object_end: Ending object Returns: Tuple of (premises, conclusion) for proving commutativity """ premises = [] # Define morphisms in path A for i, morph in enumerate(path_a): if i == 0: premises.append(f"morphism({morph})") premises.append(f"source({morph}, {object_start})") else: premises.append(f"morphism({morph})") if i == len(path_a) - 1: premises.append(f"target({morph}, {object_end})") # Define morphisms in path B for i, morph in enumerate(path_b): if i == 0: premises.append(f"morphism({morph})") premises.append(f"source({morph}, {object_start})") else: premises.append(f"morphism({morph})") if i == len(path_b) - 1: premises.append(f"target({morph}, {object_end})") # Compose paths comp_a = _compose_path_helper(path_a, "comp_a") comp_b = _compose_path_helper(path_b, "comp_b") premises.extend(comp_a["premises"]) premises.extend(comp_b["premises"]) # Conclusion: composed paths are equal conclusion = f"{comp_a['result']} = {comp_b['result']}" return (premises, conclusion) @staticmethod def natural_transformation_condition(functor_f: str = "F", functor_g: str = "G", component: str = "alpha") -> List[str]: """Generate naturality condition for a natural transformation For natural transformation α: F ⇒ G, the naturality square must commute: For any morphism f: A → B, G(f) ∘ α_A = α_B ∘ F(f) Args: functor_f: First functor name functor_g: Second functor name component: Natural transformation component name Returns: List of FOL statements for naturality """ f_lower = functor_f.lower() g_lower = functor_g.lower() return [ # Naturality condition f"all morph all a all b ((morphism(morph) & source(morph,a) & target(morph,b)) -> exists comp1 exists comp2 (compose({g_lower}(morph), {component}(a), comp1) & compose({component}(b), {f_lower}(morph), comp2) & comp1 = comp2))" ] def _compose_path_helper(path: List[str], result_name: str) -> Dict: """Helper to generate composition premises for a path Args: path: List of morphism names result_name: Name for the final composed morphism Returns: Dict with premises and result name """ if len(path) == 1: return {"premises": [], "result": path[0]} premises = [] current = path[0] for i in range(1, len(path)): temp_name = f"{result_name}_temp_{i}" if i < len(path) - 1 else result_name premises.append(f"compose({path[i]}, {current}, {temp_name})") current = temp_name return {"premises": premises, "result": current} # Convenience functions for common categorical concepts def monoid_axioms() -> List[str]: """Axioms for a monoid (category with one object)""" return [ # Binary operation "all x all y exists z (mult(x,y,z))", # Associativity "all x all y all z all xy all yz all xyz all ybc ((mult(x,y,xy) & mult(y,z,yz) & mult(xy,z,xyz) & mult(x,yz,xyz2)) -> xyz = xyz2)", # Identity exists "exists e (all x (mult(e,x,x) & mult(x,e,x)))", ] def group_axioms() -> List[str]: """Axioms for a group""" return monoid_axioms() + [ # Inverses exist "all x exists y (mult(x,y,e) & mult(y,x,e))" ]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/angrysky56/mcp-logic'

If you have feedback or need assistance with the MCP directory API, please join our Discord server