Chronaxis用户手册English
本页目录

chronaxis.core.conditional_integral_terms

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""声明有限条件积分项及值、条件各自的覆盖事实,不执行数值计算。23条件为BOOL三值:TRUE且值可核实才产生面积,FALSE属于已知未选择,UNKNOWN4不是FALSE。两种未知区间分别划分实际窗口,真实样本只计有效值更新且条件TRUE。5ReferenceConditionalIntegralTerms保留原序面积与显式有效掩码,面积单位仍为6原输入单位乘秒;不在块内归约或转换最终单位,空归约不代表正常零。7本模块只校验冻结模型和公共输入门槛,不读文件、不改输入,也不申请预算;8有限临时列和事实须由调用方owner事先预约,独立留存须另行计费。9"""1011# 冻结协议与范围检查只依赖标准库;两面积核仅共享非数值输入门槛。12from dataclasses import dataclass13from math import isfinite14from .calculations import CalculationDefinition, CalculationSeries, calculation_unit15from .models import Interval, SourceRef16from .types import QualityFlag as Q, SignalDType as D17from .validation import require_text181920def _unknown_duration(ranges, actual):21    """校验一种未知范围完整有序、不重叠且不越过实际窗口。2223    参数: ranges为冻结Interval tuple,actual为实际交集或None。24    返回: 原生int纳秒未知总时长。异常: TypeError/ValueError为结构或不可能范围。25    """26    if type(ranges) is not tuple:27        raise TypeError('条件积分未知范围需要tuple')28    cursor, total = (actual.start_ns if actual is not None else 0), 029    # 只验证诊断几何,不能按总长度掩盖重复区间或已知缺口。30    for item in ranges:31        if (not isinstance(item, Interval) or actual is None or item.start_ns < cursor32                or item.start_ns >= item.end_ns or item.end_ns > actual.end_ns):33            raise ValueError('条件积分未知范围必须有序、不重叠且在实际窗口内')34        cursor, total = item.end_ns, total + item.end_ns - item.start_ns35    return total363738@dataclass(frozen=True)39class ConditionalIntegralFacts:40    """保存当前块原请求与完整覆盖,值缺失和条件未知分别说明。4142    known包含TRUE和FALSE;selected只计TRUE且面积可核实的时长。43    selected_value_unknown只计TRUE而值/面积不可核实的时长,不混入条件UNKNOWN。44    FALSE不乘面积,原值的类型和精度检查仍保留在值覆盖及质量中。45    """4647    spec: CalculationDefinition  # 原integral请求、scope和部分结果政策。48    actual_window: Interval | None  # 当前实际交集,不外推EOF。49    value_valid_duration_ns: int  # 原值经积分可用性检查后的有效时长。50    condition_known_duration_ns: int  # 可判断TRUE或FALSE的时长。51    selected_duration_ns: int  # TRUE且值/面积可核实的时长。52    selected_value_unknown_duration_ns: int  # TRUE但值/面积不可核实的时长。53    false_duration_ns: int  # 已知FALSE时长,只有完整窗才证明空选择零。54    valid_sample_count: int  # 半开当前块内原值真实更新且有效/TRUE的数量。55    value_unknown_ranges: tuple[Interval, ...]  # 值及面积计算不可核实的正区间。56    condition_unknown_ranges: tuple[Interval, ...]  # BOOL UNKNOWN正区间,与值未知独立。57    quality: Q  # 输入、依赖和精度/面积故障原因完整OR。58    input_unit: str  # 原输入工程单位,面积尚未转换输出单位。59    binding_identity: str  # 实际联合输入中原值表达式身份。60    source_refs: tuple[SourceRef, ...]  # 完整来源子类与原定位,不只保存字段名。61    ranges_retained: bool = True  # 仅明确请求时保留未知范围;False不能用于完整明细归约。6263    def __post_init__(self):64        """验证两完整分区、选中与FALSE恒等式,不修复矛盾事实。6566        参数: 无。返回: None。异常: TypeError/ValueError为类型、覆盖或未知几何错误。67        """68        if not isinstance(self.spec, CalculationDefinition) or self.spec.operation != 'integral':69            raise TypeError('条件积分事实需要integral CalculationDefinition')70        if self.actual_window is not None and not isinstance(self.actual_window, Interval):71            raise TypeError('条件积分实际范围需要Interval或None')72        actual, request = self.actual_window, self.spec.window73        span = 0 if actual is None else actual.end_ns - actual.start_ns74        if actual is not None and not request.start_ns <= actual.start_ns <= actual.end_ns <= request.end_ns:75            raise ValueError('条件积分实际范围越过原请求')76        durations = (self.value_valid_duration_ns, self.condition_known_duration_ns, self.selected_duration_ns,77                     self.selected_value_unknown_duration_ns, self.false_duration_ns)78        # 所有时长与样本计数为原生整数,不能把bool或浮点秒作纳秒。79        if any(type(value) is not int or not 0 <= value <= span for value in durations):80            raise ValueError('条件积分覆盖时长需要实际跨度内的非负原生int')81        if (type(self.valid_sample_count) is not int or not 0 <= self.valid_sample_count <= self.selected_duration_ns82                or self.selected_duration_ns > self.value_valid_duration_ns83                or self.selected_value_unknown_duration_ns > span - self.value_valid_duration_ns84                or self.false_duration_ns > self.condition_known_duration_ns85                or self.selected_duration_ns + self.selected_value_unknown_duration_ns !=86                   self.condition_known_duration_ns - self.false_duration_ns):87            raise ValueError('条件积分样本、选择、FALSE与已知时长矛盾')88        # 分别核对值与条件的完整实际域,不将UNKNOWN当FALSE合并。89        if type(self.ranges_retained) is not bool:90            raise TypeError('范围保留标志需要bool')91        if not self.ranges_retained and (self.value_unknown_ranges != () or self.condition_unknown_ranges != ()):92            raise ValueError('未请求范围时不能附带范围明细')93        if self.ranges_retained and _unknown_duration(self.value_unknown_ranges, actual) + self.value_valid_duration_ns != span:94            raise ValueError('条件积分值有效与未知未完整划分实际窗口')95        if self.ranges_retained and _unknown_duration(self.condition_unknown_ranges, actual) + self.condition_known_duration_ns != span:96            raise ValueError('条件积分已知与条件未知未完整划分实际窗口')97        if not isinstance(self.quality, Q) or type(self.source_refs) is not tuple or any(not isinstance(ref, SourceRef) for ref in self.source_refs):98            raise TypeError('条件积分事实需要typed质量和完整来源tuple')99        require_text(self.input_unit, 'conditional_integral.input_unit')100        require_text(self.binding_identity, 'conditional_integral.binding_identity')101102103@dataclass(frozen=True)104class ReferenceConditionalIntegralTerms:105    """保存有限原序面积,未知占位0只能与False掩码一起解释。"""106107    areas: tuple[float, ...]  # 形状N-1的原序有限float面积,未换最终单位。108    valid: tuple[bool, ...]  # 只有TRUE选择且正常面积为True。109    facts: ConditionalIntegralFacts  # 当前块覆盖与完整定位,不是整窗最终状态。110111    def __post_init__(self):112        """核对冻结同长面积与真实事实,不允许非有限或无效非零占位。113114        参数: 无。返回: None。异常: TypeError/ValueError为列结构、面积或事实类型。115        """116        if (type(self.areas) is not tuple or type(self.valid) is not tuple or len(self.areas) != len(self.valid)117                or not isinstance(self.facts, ConditionalIntegralFacts)):118            raise TypeError('参考条件积分项需要同长tuple及ConditionalIntegralFacts')119        if any(type(area) is not float or not isfinite(area) or type(keep) is not bool120               or not keep and area != 0 for area, keep in zip(self.areas, self.valid)):121            raise ValueError('条件积分面积需有限float/bool,无效位置只能存0')122123124def require_conditional_integral_terms(series, spec, *, step_ns=None, valid_until_ns=None, condition_valid_until_ns=None):125    """校验typed数值、BOOL条件、明确积分单位及可表示正跨度。126127    参数: series为有限CalculationSeries,spec为原integral请求。128        step_ns为所选周期,两个until列为值/条件的实际有效截止,均可省略保原行为。129    返回: None。异常: TypeError/ValueError/OverflowError为模型、能力、单位或时间错误。130    """131    # 仅共享结构门槛;两后端独立计算转换、面积、掩码、时长与样本。132    if not isinstance(series, CalculationSeries) or not isinstance(spec, CalculationDefinition):133        raise TypeError('条件积分需要CalculationSeries和CalculationDefinition')134    from .record_intervals import require_record_step135    from .integral_terms import require_valid_until136    require_record_step(step_ns, series.actual_value_updates)137    require_valid_until(series.times_ns, valid_until_ns)138    require_valid_until(series.times_ns, condition_valid_until_ns)139    if (spec.operation != 'integral' or series.conditions is None140            or series.values[0].dtype not in (D.INT64, D.UINT64, D.FLOAT64)141            or any(value.dtype is not D.BOOL for value in series.conditions)):142        raise ValueError('条件积分只支持数值integral及显式BOOL选择条件')143    calculation_unit(spec, series.unit)144    left, right = max(spec.window.start_ns, series.observation.start_ns), min(spec.window.end_ns, series.observation.end_ns)145    if right - left > 2 ** 63 - 1:146        raise OverflowError('条件积分正交集跨度超过int64')147
Chronaxis 用户手册 · 离线阅读