Skip to content

城市动态权重矩阵

按实际城市子样本、经纬度、邻接关系和样本期人均 GDP 生成 W01–W08。

核心代码

py
def build_city_weight_matrices(
    *,
    adjacency: np.ndarray,
    coordinates: np.ndarray,
    per_capita_gdp_yuan: np.ndarray,
) -> tuple[dict[str, np.ndarray], dict[str, Any]]:
    """按平台 W01–W08 固定公式一次性构造城市矩阵。"""
    adjacency = np.asarray(adjacency, dtype=np.float64)
    coordinates = np.asarray(coordinates, dtype=np.float64)
    values = np.asarray(per_capita_gdp_yuan, dtype=np.float64).reshape(-1)
    size = len(values)
    if adjacency.shape != (size, size) or coordinates.shape != (size, 2):
        raise ValueError(_('城市邻接、经纬度和GDP数组维度不一致'))
    if not np.isfinite(adjacency).all() or not np.allclose(np.diag(adjacency), 0.0):
        raise ValueError(_('城市邻接矩阵无效'))

    adjacency_binary = (adjacency != 0).astype(np.float64)
    distance_km = pairwise_haversine_km(coordinates)
    geographic_inverse = 1.0 / distance_km
    np.fill_diagonal(geographic_inverse, 0.0)
    economic_inverse, economic_metadata = economic_distance_inverse(values)

    destination_economic = np.tile(values, (size, 1))
    np.fill_diagonal(destination_economic, 0.0)
    asymmetric_economic = row_standardize(destination_economic)

    matrices = {
        'W01': adjacency_binary,
        'W02': row_standardize(economic_inverse),
        'W03': row_standardize(geographic_inverse),
        'W04': row_standardize(geographic_inverse ** 2),
        'W05': economic_inverse * geographic_inverse,
        'W06': 0.5 * economic_inverse + 0.5 * geographic_inverse,
        'W07': asymmetric_economic,
        'W08': asymmetric_economic * geographic_inverse,
    }
    for key, matrix in matrices.items():
        if matrix.shape != (size, size) or not np.isfinite(matrix).all():
            raise ValueError(
                _('%(key)s 生成结果包含无效数值') % {'key': key}
            )
        np.fill_diagonal(matrix, 0.0)

    metadata = {
        **economic_metadata,
        'distance_method': 'haversine',
        'earth_radius_km': EARTH_RADIUS_KM,
        'distance_min_km': float(np.min(distance_km[np.isfinite(distance_km)])),
        'distance_max_km': float(np.max(distance_km[np.isfinite(distance_km)])),
        'formulas': dict(CITY_MATRIX_FORMULAS),
    }
    return matrices, metadata

Released under the AGPL-3.0 License.