Skip to content

Instantly share code, notes, and snippets.

@yuya-maemichi-synspective
Created March 13, 2025 02:33
Show Gist options
  • Save yuya-maemichi-synspective/7a6adb0c701dbfc4342dcf5750c8b87f to your computer and use it in GitHub Desktop.
Save yuya-maemichi-synspective/7a6adb0c701dbfc4342dcf5750c8b87f to your computer and use it in GitHub Desktop.
math complementable interval in Python
from __future__ import annotations
from dataclasses import dataclass, replace
import math
from numbers import Number
from typing import Tuple
NEG_INF = -math.inf
POS_INF = math.inf
@dataclass(frozen=True)
class IntervalEnd:
value: Number
closed: bool
@property
def is_open(self) -> bool:
return not self.closed
def invert(self) -> IntervalEnd:
return replace(self, closed=not self.closed)
def __lt__(self, other: IntervalEnd) -> bool:
# Handle infinite bounds first
if self.value == NEG_INF:
return other.value != NEG_INF
if other.value == POS_INF:
return self.value != POS_INF
# Compare values, then openness (open ends sort before closed at same value)
return (self.value, self.is_open) < (other.value, other.is_open)
@dataclass(frozen=True)
class Interval:
left: IntervalEnd
right: IntervalEnd
def __post_init__(self):
if self.left > self.right:
raise ValueError(f"Malformed interval: {self.left} > {self.right}")
@property
def is_empty(self) -> bool:
return (
self.left.value > self.right.value or
(self.left.value == self.right.value and
(self.left.is_open or self.right.is_open))
)
def __invert__(self) -> IntervalUnion:
if self.is_empty:
return IntervalUnion(Interval(NEG_INF_END, POS_INF_END))
return IntervalUnion(
Interval(NEG_INF_END, self.left.invert()),
Interval(self.right.invert(), POS_INF_END)
)
def __contains__(self, x: Number) -> bool:
left_cond = (x > self.left.value) or (x == self.left.value and self.left.closed)
right_cond = (x < self.right.value) or (x == self.right.value and self.right.closed)
return left_cond and right_cond
@dataclass(frozen=True)
class IntervalUnion:
intervals: Tuple[Interval, ...]
def __invert__(self) -> Interval:
# Implement using De Morgan's laws through interval intersections
raise NotImplementedError("Requires full interval algebra implementation")
# Predefined infinite ends
NEG_INF_END = IntervalEnd(NEG_INF, False)
POS_INF_END = IntervalEnd(POS_INF, False)
@yuya-maemichi-synspective
Copy link
Author

Maybe just give up IntervalEnd?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment