-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a5c2c4f
commit 2043ceb
Showing
5 changed files
with
255 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
"proportion", | ||
"nullproportion", | ||
"ospp", | ||
"unpooled" | ||
"unpooled", | ||
"ndigits" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,21 @@ | ||
from pystatpower.basic import * | ||
from pystatpower.procedures.two_proportion import * | ||
from numbers import Real | ||
|
||
a = fun_power(0.05, 64, 64, 0.60, 0.85, Alternative.AlternativeEnum.TWO_SIDED, TestType.EnumTestType.Z_TEST_POOLED) | ||
|
||
print(a) | ||
class Parent: | ||
_domain = [1, 2, 3] | ||
|
||
|
||
class Child(Parent): | ||
_domain = [4, 5, 6] | ||
|
||
def __init__(self, value: Real): | ||
if not isinstance(value, Real): | ||
raise TypeError(f"{value} is not a real number") | ||
if value not in type(self)._domain: | ||
raise ValueError(f"{value} is not in {type(self)._domain}") | ||
self._value = value | ||
|
||
|
||
# 测试 | ||
child_instance = Child(5) # 正常 | ||
child_instance_invalid = Child(3) # 抛出 ValueError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,273 @@ | ||
from abc import ABC, abstractmethod | ||
from enum import Enum | ||
from math import inf | ||
from math import ceil, floor, inf, trunc | ||
from numbers import Real | ||
|
||
from pystatpower.interval import Interval | ||
|
||
from dataclasses import dataclass | ||
|
||
class Param(ABC): | ||
"""抽象参数基类""" | ||
|
||
domain = None | ||
@dataclass(frozen=True) | ||
class Interval: | ||
"""定义一个区间,可指定是否包含上下限,不支持单点区间(例如:[1, 1])。 | ||
@abstractmethod | ||
def __init__(self, value): | ||
pass | ||
Parameters | ||
---------- | ||
lower (Real): 区间下限 | ||
upper (Real): 区间上限 | ||
lower_inclusive (bool): 是否包含区间下限 | ||
upper_inclusive (bool): 是否包含区间上限 | ||
@classmethod | ||
@abstractmethod | ||
def _check(cls, domain, value): | ||
pass | ||
Examples | ||
-------- | ||
>>> interval = Interval(0, 1, lower_inclusive=True, upper_inclusive=False) | ||
>>> 0.5 in interval | ||
True | ||
>>> 1 in interval | ||
False | ||
>>> 0 in interval | ||
False | ||
>>> interval.pseudo_bound() | ||
(0, 0.9999999999) | ||
""" | ||
|
||
lower: Real | ||
upper: Real | ||
lower_inclusive: bool = False | ||
upper_inclusive: bool = False | ||
|
||
class NumericParam(Param): | ||
"""数值参数基类""" | ||
|
||
domain = Interval(-inf, inf) | ||
def __contains__(self, value: Real) -> bool: | ||
if not isinstance(value, Real): | ||
return NotImplemented | ||
|
||
if self.lower_inclusive: | ||
if self.upper_inclusive: | ||
return self.lower <= value <= self.upper | ||
else: | ||
return self.lower <= value < self.upper | ||
else: | ||
if self.upper_inclusive: | ||
return self.lower < value <= self.upper | ||
else: | ||
return self.lower < value < self.upper | ||
|
||
def __eq__(self, other: object) -> bool: | ||
if not isinstance(other, Interval): | ||
return NotImplemented | ||
|
||
return (self.lower, self.upper, self.lower_inclusive, self.upper_inclusive) == ( | ||
other.lower, | ||
other.upper, | ||
other.lower_inclusive, | ||
other.upper_inclusive, | ||
) | ||
|
||
def __repr__(self) -> str: | ||
if self.lower_inclusive: | ||
if self.upper_inclusive: | ||
return f"[{self.lower}, {self.upper}]" | ||
else: | ||
return f"[{self.lower}, {self.upper})" | ||
else: | ||
if self.upper_inclusive: | ||
return f"({self.lower}, {self.upper}]" | ||
else: | ||
return f"({self.lower}, {self.upper})" | ||
|
||
def pseudo_lbound(self, eps: Real = 1e-10) -> Real: | ||
"""区间的伪下界,用于数值计算。""" | ||
if self.lower_inclusive: | ||
return self.lower | ||
else: | ||
return self.lower + eps | ||
|
||
def pseudo_ubound(self, eps: Real = 1e-10) -> Real: | ||
"""区间的伪上界,用于数值计算。""" | ||
if self.upper_inclusive: | ||
return self.upper | ||
else: | ||
return self.upper - eps | ||
|
||
def pseudo_bound(self, eps: Real) -> tuple[Real, Real]: | ||
"""区间的伪上下界,用于数值计算。""" | ||
return (self.pseudo_lbound(eps), self.pseudo_ubound(eps)) | ||
|
||
|
||
class NumericParam(Real): | ||
|
||
_domain = Interval(-inf, inf) | ||
|
||
def __init__(self, value: Real): | ||
cls = type(self) | ||
cls._check(value) | ||
if not isinstance(value, Real): | ||
raise TypeError(f"{value} is not a real number") | ||
if value not in self._domain: | ||
raise ValueError(f"{value} is not in {self._domain}") | ||
self._value = value | ||
|
||
@property | ||
def value(self): | ||
return self._value | ||
def __repr__(self): | ||
return f"{type(self).__name__}({self._value})" | ||
|
||
def __add__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value + other) | ||
return NotImplemented | ||
|
||
def __sub__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value - other) | ||
return NotImplemented | ||
|
||
@classmethod | ||
def _check(cls, value: Real): | ||
domain = cls.domain | ||
if not isinstance(value, Real): | ||
raise TypeError(f"{value} is not a real number") | ||
if value not in domain: | ||
raise ValueError(f"{value} is not in {domain}") | ||
def __mul__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value * other) | ||
return NotImplemented | ||
|
||
def __truediv__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value / other) | ||
return NotImplemented | ||
|
||
def __floordiv__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value // other) | ||
return NotImplemented | ||
|
||
def __mod__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value % other) | ||
return NotImplemented | ||
|
||
def __pow__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(self._value**other) | ||
return NotImplemented | ||
|
||
def __radd__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(other + self._value) | ||
return NotImplemented | ||
|
||
def __rfloordiv__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(other // self._value) | ||
return NotImplemented | ||
|
||
def __rmul__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(other * self._value) | ||
return NotImplemented | ||
|
||
def __rmod__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(other % self._value) | ||
return NotImplemented | ||
|
||
def __rpow__(self, base): | ||
if isinstance(base, Real): | ||
return type(self)(base**self._value) | ||
return NotImplemented | ||
|
||
def __rtruediv__(self, other): | ||
if isinstance(other, Real): | ||
return type(self)(other / self._value) | ||
return NotImplemented | ||
|
||
def __trunc__(self): | ||
return type(self)(trunc(self._value)) | ||
|
||
def __neg__(self): | ||
return type(self)(-self._value) | ||
|
||
def __pos__(self): | ||
return type(self)(+self._value) | ||
|
||
def __abs__(self): | ||
return type(self)(abs(self._value)) | ||
|
||
def __ceil__(self): | ||
return type(self)(ceil(self._value)) | ||
|
||
def __floor__(self): | ||
return type(self)(floor(self._value)) | ||
|
||
class OptionalParam(Param): | ||
"""选项参数基类""" | ||
def __round__(self, ndigits=None): | ||
return type(self)(round(self._value, ndigits)) | ||
|
||
class EmptyEnum(Enum): | ||
pass | ||
def __eq__(self, other): | ||
if isinstance(other, Real): | ||
return self._value == other | ||
return NotImplemented | ||
|
||
domain = EmptyEnum | ||
def __lt__(self, other): | ||
if isinstance(other, Real): | ||
return self._value < other | ||
return NotImplemented | ||
|
||
def __init__(self, value: Enum | str): | ||
cls = type(self) | ||
self._value = cls._check(value) | ||
def __le__(self, other): | ||
if isinstance(other, Real): | ||
return self._value <= other | ||
return NotImplemented | ||
|
||
@property | ||
def value(self): | ||
return self._value | ||
def __float__(self): | ||
return float(self._value) | ||
|
||
@classmethod | ||
def _check(cls, value: Enum | str) -> Enum: | ||
domain = cls.domain | ||
def __complex__(self): | ||
return complex(self._value) | ||
|
||
if isinstance(value, str): | ||
try: | ||
value = domain[value.upper()] | ||
except KeyError: | ||
raise ValueError(f"No such option '{value}' in {domain.__name__}") | ||
elif not isinstance(value, domain): | ||
raise TypeError(f"{value} is not a {domain.__name__}") | ||
def __hash__(self): | ||
return hash(self._value) | ||
|
||
return value | ||
def __bool__(self): | ||
return bool(self._value) | ||
|
||
|
||
class Alpha(NumericParam): | ||
"""显著性水平""" | ||
|
||
domain = Interval(0, 1) | ||
_domain = Interval(0, 1) | ||
|
||
|
||
class Power(NumericParam): | ||
"""检验效能""" | ||
|
||
domain = Interval(0, 1) | ||
_domain = Interval(0, 1) | ||
|
||
|
||
class Mean(NumericParam): | ||
"""均值""" | ||
|
||
domain = Interval(-inf, inf) | ||
_domain = Interval(-inf, inf) | ||
|
||
|
||
class STD(NumericParam): | ||
"""标准差""" | ||
|
||
domain = Interval(0, inf) | ||
_domain = Interval(0, inf) | ||
|
||
|
||
class Proportion(NumericParam): | ||
"""率""" | ||
|
||
domain = Interval(0, 1) | ||
_domain = Interval(0, 1) | ||
|
||
|
||
class Percent(NumericParam): | ||
"""百分比""" | ||
|
||
domain = Interval(0, 1) | ||
_domain = Interval(0, 1) | ||
|
||
|
||
class Ratio(NumericParam): | ||
"""比例""" | ||
|
||
domain = Interval(0, inf) | ||
_domain = Interval(0, inf) | ||
|
||
|
||
class Size(NumericParam): | ||
"""样本量""" | ||
|
||
domain = Interval(0, inf) | ||
_domain = Interval(0, inf) | ||
|
||
|
||
class DropOutRate(NumericParam): | ||
"""脱落率""" | ||
|
||
domain = Interval(0, 1, lower_inclusive=True) | ||
_domain = Interval(0, 1, lower_inclusive=True) |
Oops, something went wrong.