Chronaxis用户手册English
本页目录

chronaxis.core.conditional_time_reduction_reference

源码基线:8904c2f744951857659abd40aaa3535d57faf53c

1"""独立标量归约有限条件极值、规范化时间均值和主BOOL持续时间。23push保留值与外条件各自的覆盖、真实更新、未知及完整来源;跨块仅保存候选与时长。4min/max保留原整数,duration累计外TRUE主TRUE的精确ns并保留主FALSE零证据。5mean首遍只查有效/选择事实,次遍以全窗TRUE有效时长D计算x*(dt/D),不先算面积。6权重及原序求和故障与输入覆盖分开;单位仅finish转换一次。纯核不读来源、不预约7预算或保存全轴,有限临时列及误差项须由外层owner计费,推进异常后须放弃状态。8"""910# 仅使用标量及同后端原序误差核,不调用数组面积、对齐或归约。11from math import isfinite12from .calculation_output_reference import convert_result_reference13from .conditional_time_reduction import ConditionalTimeCalculationFacts, require_conditional_time_series14from .integral_sum_reference import ReferenceIntegralSum15from .moments import TIME_MOMENTS16from .moments_reference import ReferenceMoments17from .calculations import merge_ranges18from .models import Interval19from .numeric import ScalarValue, to_float_reference20from .time_reduction import TimeReductionResult, require_time_config, require_time_options21from .integral_terms import require_valid_until22from .record_intervals import clipped_record_seconds23from .types import QualityFlag as Q2425from .time_reduction import MeanTimeBlock26from .mean_weights_reference import normalized_mean_terms272829class ReferenceConditionalTimeReduction:30    """保存一个原dtype候选、精确时长与有界误差项,mean两遍实例不能混用。"""3132    def __init__(self, spec, input_unit, dtype, *, selected_duration_ns=None, partial_limit=4096,33                 step_ns=None, selected_weight_seconds=None):34        """验证原配置并建立本后端有限状态。3536        参数: spec/input_unit/dtype为原配置;selected_duration_ns为mean次遍全TRUE有效分母;37            partial_limit为误差项容量;step_ns选周期,周期均值次遍传selected_weight_seconds。返回: None。异常: 配置或分配错误传播。38        """39        # 共享的静态门槛先核对算子、类型、单位及mean分母,不执行数值计算。40        self._conversion = require_time_config(spec, input_unit, dtype, selected_duration_ns, partial_limit,41            step_ns=step_ns, selected_weight_seconds=selected_weight_seconds)42        self._unit, self._factor = self._conversion.unit, self._conversion.factor43        self._moments = ReferenceMoments(spec.operation) if spec.operation in TIME_MOMENTS else None44        self._spec, self._input_unit, self._dtype = spec, input_unit, dtype45        self._step_ns = step_ns46        self._denominator = selected_duration_ns if step_ns is None else selected_weight_seconds47        # 固定状态不随块数增加;mean首遍不建立数值误差状态。48        self._identity = self._candidate = None49        self._value_duration = self._selected_duration = self._terms = 050        self._numeric_quality = Q.NONE51        self._sum = ReferenceIntegralSum(partial_limit) if spec.operation == 'time_weighted_mean' and self._denominator is not None else None52        self._weight_sum = ReferenceIntegralSum(partial_limit) if step_ns is not None and spec.operation in ('duration', 'time_weighted_mean') else None5354    @property55    def selected_weight_seconds(self):56        """读取必要周期权重。参数: 无。返回: float或不适用None。异常: 权重求和故障。"""57        if self._weight_sum is None:58            return None59        result = self._weight_sum.finish('s')60        if result.calculation_failed:61            raise OverflowError('条件周期权重累计失败')62        return 0.0 if result.value is None else result.value6364    @property65    def selected_duration_ns(self):66        """读取累计选择时长。参数: 无。返回: 原生int纳秒。异常: 无。"""67        return self._selected_duration  # duration仅主TRUE;mean为全TRUE有效分母事实。6869    @property70    def value_valid_duration_ns(self):71        """读取累计值有效时长。参数: 无。返回: 原生int纳秒。异常: 无。"""72        return self._value_duration  # 外FALSE/UNKNOWN不改变原值可用性。7374    def push(self, series, *, valid_until_ns=None, condition_valid_until_ns=None, retain_unknown_ranges=True, retain_mean_terms=False):75        """独立消费有限联合块,返回完整双覆盖并推进原单位候选。7677        参数: series为同单位/dtype且有显式BOOL条件的有限CalculationSeries。78        valid_until_ns/condition_valid_until_ns分别截断实际有效期;79            retain_unknown_ranges=False省去两类未知范围。80        retain_mean_terms仅均值首遍返回MeanTimeBlock,其他调用返回事实。81        返回: ConditionalTimeCalculationFacts;mean权重故障只记数值质量,不改覆盖。82        异常: 结构、身份、容量或分配错误传播;外层不得继续使用异常前缀状态。83        """84        # 输入先过明确条件/单位/dtype与交集门槛,跨块不能更换原值绑定身份。85        actual = require_conditional_time_series(series, self._spec, self._input_unit, self._dtype)86        require_time_options(series, self._step_ns, valid_until_ns, retain_unknown_ranges)87        require_valid_until(series.times_ns, condition_valid_until_ns)88        if type(retain_mean_terms) is not bool or retain_mean_terms and (self._spec.operation != 'time_weighted_mean' or self._denominator is not None):89            raise ValueError('仅均值首遍可请求必要回读项')90        if self._identity is not None and self._identity != series.binding_identity:91            raise ValueError('条件时间归约不能跨绑定身份累计')92        self._identity = series.binding_identity93        # 只有mean检查to_float精度;极值和主BOOL不被提升成浮点类型。94        values = tuple(to_float_reference(value) for value in series.values) if self._spec.operation == 'time_weighted_mean' or self._moments is not None else series.values95        start, end = (actual.start_ns, actual.end_ns) if actual is not None else (0, 0)96        value_duration = known_duration = selected_duration = selected_unknown = false_duration = selected_false = samples = terms = 097        value_unknown, condition_unknown, weighted = [], [], []98        period_weights = [] if self._weight_sum is not None else None99        mean_values = [] if self._moments is not None or (self._spec.operation == 'time_weighted_mean' and100                            (self._denominator is not None or retain_mean_terms)) else None101        mean_weights = [] if mean_values is not None else None102        quality, weight_quality = Q.NONE, Q.NONE103        # 每个正区间先核对双覆盖,再决定TRUE有效数值是否推进,末点没有区间。104        for index in range(len(series.times_ns) - 1):105            left, right = max(series.times_ns[index], start), min(series.times_ns[index+1], end)106            if left >= right:107                continue108            value, condition = values[index], series.conditions[index]109            quality |= series.diagnostics[index] | value.quality | condition.quality110            deadline = None if valid_until_ns is None else valid_until_ns[index]111            condition_deadline = None if condition_valid_until_ns is None else condition_valid_until_ns[index]112            value_end = max(left, min(right, deadline)) if deadline is not None else right113            condition_end = max(left, min(right, condition_deadline)) if condition_deadline is not None else right114            value_end = value_end if value.valid else left115            condition_end = condition_end if condition.valid else left116            value_duration += value_end - left117            known_duration += condition_end - left118            if value_end < right:119                if retain_unknown_ranges:120                    value_unknown.append(Interval(value_end, right))121                if value.valid:122                    quality |= Q.STALE123            if condition_end < right:124                if retain_unknown_ranges:125                    condition_unknown.append(Interval(condition_end, right))126                if condition.valid:127                    quality |= Q.STALE128            if condition_end <= left:129                continue130            if not condition.value:131                false_duration += condition_end - left132                continue133            chosen_end = min(value_end, condition_end)134            selected_unknown += condition_end - chosen_end135            if chosen_end <= left:136                continue137            dt = chosen_end - left138            # 外TRUE主FALSE仍是duration正常0证据,但不增加已选时长与真实样本。139            terms += 1140            if self._spec.operation == 'duration' and not value.value:141                selected_false += dt142            else:143                selected_duration += dt144            measure = dt145            if (period_weights is not None or (self._step_ns is not None and self._moments is not None)) and (self._spec.operation != 'duration' or value.value):146                measure = clipped_record_seconds(series.times_ns[index], series.times_ns[index+1],147                    Interval(left, chosen_end), step_ns=self._step_ns)148                if period_weights is not None:149                    period_weights.append(measure)150            if self._spec.operation in ('min_time', 'max_time'):151                # 每次只比较一个原dtype候选,跨块不转float,保留大整数的精确极值。152                self._candidate = value.value if self._candidate is None else (min if self._spec.operation == 'min_time' else max)(self._candidate, value.value)153            elif mean_values is not None:154                mean_values.append(value.value)155                mean_weights.append(measure)156        # 原值真实更新才计样本,外条件TRUE且duration另须主TRUE;右端与条件更新不计。157        for index, time in enumerate(series.times_ns):158            if not start <= time < end or not series.actual_value_updates[index]:159                continue160            value, condition = values[index], series.conditions[index]161            quality |= series.diagnostics[index] | value.quality | condition.quality162            deadline = None if valid_until_ns is None else valid_until_ns[index]163            condition_deadline = None if condition_valid_until_ns is None else condition_valid_until_ns[index]164            if (value.valid and condition.valid and condition.value165                    and (deadline is None or time < deadline) and (condition_deadline is None or time < condition_deadline)166                    and (self._spec.operation != 'duration' or value.value)):167                samples += 1168        # 任意权重故障使整次数值失败,不清除前述可核实覆盖;正常权重按原序推进。169        if self._denominator is not None:170            weighted, weight_quality = normalized_mean_terms(mean_values, mean_weights, self._denominator)171        if self._moments is not None:172            self._moments.push(mean_values, mean_weights)173        self._numeric_quality |= weight_quality174        if period_weights is not None:175            self._weight_sum.push_values(tuple(period_weights), (True,)*len(period_weights))176        if self._sum is not None and self._numeric_quality == Q.NONE:177            self._sum.push_values(tuple(weighted), (True,)*len(weighted))178        self._value_duration += value_duration179        self._selected_duration += selected_duration180        self._terms += terms181        facts = ConditionalTimeCalculationFacts(self._spec, actual, value_duration, known_duration, selected_duration,182            selected_unknown, false_duration, selected_false, samples, merge_ranges(value_unknown),183            merge_ranges(condition_unknown), quality, self._input_unit, self._dtype, series.binding_identity, series.source_refs, retain_unknown_ranges)184        return MeanTimeBlock(facts, tuple(mean_values), tuple(mean_weights)) if retain_mean_terms else facts185186    def finish(self):187        """生成数值快照并只转换一次,覆盖与全外FALSE分类由外层处理。188189        参数: 无。返回: 既有TimeReductionResult。异常: mean首遍RuntimeError、次遍分母不符ValueError;190            配置/分配错误传播,数值故障保留None和质量。191        """192        # mean首遍没有候选;次遍只有累计选择时长与原确认分母一致才能交付。193        if self._moments is not None:194            value, quality = self._moments.finish(self._spec.ddof, self._conversion.factor)195            return TimeReductionResult(value, self._unit, quality != Q.NONE, quality, self._terms)196        if self._spec.operation == 'time_weighted_mean':197            if self._denominator is None:198                raise RuntimeError('条件时间均值首遍只收事实,不能生成数值')199            measured = self._selected_duration if self._step_ns is None else self.selected_weight_seconds200            if measured != self._denominator:201                raise ValueError('条件均值次遍选择时长与全窗分母不同')202            if self._numeric_quality != Q.NONE:203                return TimeReductionResult(None, self._unit, True, self._numeric_quality, self._terms)204            # 同后端原序核负责一次最终单位转换,不在映射结果时再次乘因子。205            number = self._sum.finish(self._input_unit,206                                      1.0)207            if not number.calculation_failed:208                value, quality = convert_result_reference(number.value, self._dtype, self._conversion)209                return TimeReductionResult(value, self._unit, quality != Q.NONE, quality, self._terms)210            return TimeReductionResult(number.value, self._unit, number.calculation_failed, number.quality, self._terms)211        # 外FALSE/UNKNOWN或值全未知没有有效项,空证据分类由外层负责。212        if self._terms == 0:213            return TimeReductionResult(None, self._unit, False, Q.NONE, 0)214        value = ((self._selected_duration / 1_000_000_000 if self._step_ns is None else self.selected_weight_seconds)215                 if self._spec.operation == 'duration' else self._candidate)216        quality = Q.NONE217        # 极值factor=1保留精确整数;显式换单位先检查整数浮点可表示性。218        # v4换算包含偏移;输入/归约故障不能被正常单位结果覆盖。219        if quality == Q.NONE:220            value, quality = convert_result_reference(value, self._dtype, self._conversion)221        return TimeReductionResult(None if quality != Q.NONE else value, self._unit, quality != Q.NONE, quality, self._terms)222
Chronaxis 用户手册 · 离线阅读