Skip to main content
Glama
sets.py6.9 kB
from typing import Union, Literal, get_args, Dict, Any from sympy import ( Interval as _Interval, FiniteSet as _FiniteSet, Union as _Union, Intersection as _Intersection, sympify, S, Basic, ) from sympy.sets import Set # Define operation types for type hints SetOperation = Literal[ "finiteset", "interval", "union", "intersection", "issubset", "issuperset", "contains", "cardinality", ] def _parse_set_elements(elements): """Parse elements for finite sets.""" if isinstance(elements, (list, tuple)): return [sympify(x) for x in elements] elif isinstance(elements, str): if elements.startswith("{") and elements.endswith("}"): elements = elements[1:-1] return [sympify(x.strip()) for x in elements.split(",") if x.strip()] return [sympify(elements)] def _parse_interval_args(args: Dict[str, Any]) -> Dict[str, Any]: """Parse arguments for interval creation.""" parsed = {} for key in ["start", "end", "left_open", "right_open"]: if key in args: parsed[key] = sympify(args[key]) if key in ["start", "end"] else args[key] return parsed def set_operation(operation: SetOperation, *args, **kwargs) -> Union[Set, bool, int]: """ Unified interface for set operations. Args: operation: The set operation to perform. One of: - 'finiteset': Create a finite set - 'interval': Create an interval - 'union': Compute union of sets - 'intersection': Compute intersection of sets - 'issubset': Check if set is a subset - 'issuperset': Check if set is a superset - 'contains': Check if element is in set - 'cardinality': Get the cardinality of a set *args: Positional arguments for the operation **kwargs: Keyword arguments for the operation Returns: The result of the set operation, which could be a Set, bool, or int depending on the operation. Examples: >>> set_operation('finiteset', [1, 2, 3, 4]) {1, 2, 3, 4} >>> set_operation('interval', start=0, end=1, left_open=True) Interval.open(0, 1) >>> A = set_operation('finiteset', [1, 2, 3]) >>> B = set_operation('finiteset', [3, 4, 5]) >>> set_operation('union', A, B) {1, 2, 3, 4, 5} >>> set_operation('contains', A, 2) True >>> set_operation('cardinality', A) 3 """ # Handle finite set creation if operation == "finiteset": if not args and "elements" in kwargs: elements = kwargs["elements"] elif len(args) == 1 and not kwargs: elements = args[0] else: elements = list(args) + list(kwargs.values()) return _FiniteSet(*_parse_set_elements(elements)) # Handle interval creation elif operation == "interval": if args and len(args) == 2 and not kwargs: # Handle interval(0, 1) syntax start, end = map(sympify, args) left_open = kwargs.get("left_open", False) right_open = kwargs.get("right_open", False) else: # Handle keyword arguments params = _parse_interval_args(kwargs) start = params.get("start", S.NegativeInfinity) end = params.get("end", S.Infinity) left_open = params.get("left_open", False) right_open = params.get("right_open", False) if left_open and right_open: return _Interval.open(start, end) elif left_open: return _Interval.Lopen(start, end) elif right_open: return _Interval.Ropen(start, end) else: return _Interval(start, end) # Handle set operations elif operation in ("union", "intersection", "issubset", "issuperset"): if len(args) < 2: raise ValueError(f"At least two sets required for {operation}") # Convert args to SymPy sets if they aren't already sets = [] for arg in args: if isinstance(arg, (list, tuple, str)): sets.append(set_operation("finiteset", arg)) elif isinstance(arg, dict) and "start" in arg and "end" in arg: sets.append(set_operation("interval", **arg)) elif isinstance(arg, (Set, Basic)): sets.append(arg) else: raise ValueError(f"Cannot convert {arg} to a set") if operation == "union": return _Union(*sets) elif operation == "intersection": return _Intersection(*sets) elif operation == "issubset": return sets[0].is_subset(*sets[1:]) elif operation == "issuperset": return sets[0].is_superset(*sets[1:]) # Handle element operations elif operation == "contains": if len(args) != 2: raise ValueError( "'contains' operation requires exactly 2 arguments (set, element)" ) # First argument is the set, second is the element set_arg, element = args # Convert set_arg to a SymPy set if it isn't already if not isinstance(set_arg, (Set, Basic)): if isinstance(set_arg, (list, tuple, str)): set_obj = set_operation("finiteset", set_arg) elif isinstance(set_arg, dict) and "start" in set_arg and "end" in set_arg: set_obj = set_operation("interval", **set_arg) else: raise ValueError("First argument must be a set or convertible to a set") else: set_obj = set_arg # Convert element to a SymPy object if it isn't already if not isinstance(element, Basic): element = sympify(element) return element in set_obj # Handle cardinality elif operation == "cardinality": if not args: raise ValueError("No set provided for cardinality operation") set_arg = args[0] # Convert set_arg to a SymPy set if it isn't already if not isinstance(set_arg, (Set, Basic)): if isinstance(set_arg, (list, tuple, str)): set_obj = set_operation("finiteset", set_arg) elif isinstance(set_arg, dict) and "start" in set_arg and "end" in set_arg: set_obj = set_operation("interval", **set_arg) else: raise ValueError("Argument must be a set or convertible to a set") else: set_obj = set_arg return len(set_obj) if hasattr(set_obj, "__len__") else float("inf") else: valid_ops = get_args(SetOperation) raise ValueError(f"Invalid operation. Must be one of: {valid_ops}") # Add type hints for better IDE support set_operation.__annotations__["return"] = Union[Set, bool, int]

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/abhiphile/fermat-mcp'

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