2026年中青杯数学建模
A题 数学建模论文智能评估系统与多智能体优化方法
原题再现:
《新一代人工智能发展规划》明确提出推动智能教育创新发展,利用人工智能技术改进教育评价体系。在高等教育领域,数学建模竞赛作为培养学生创新能力和实践能力的重要载体,每年吸引数十万学生参与。随着大语言模型、智能写作工具等技术的快速发展,参赛者广泛借助AI辅助完成论文撰写,这对传统的人工评审模式提出了新的挑战。
数学建模论文具有结构标准化、逻辑严密性、符号规范性等特殊要求,其质量评估涉及多维度、多层次的复杂判断。如何利用自然语言处理、知识图谱、强化学习等技术,构建能够自动识别论文逻辑缺陷、评估建模质量、提供优化建议的智能系统,已成为教育评价领域的重要研究方向。请建立数学模型,解决以下问题:
问题1:附件1是2025年中青杯竞赛的30篇参赛论文,涵盖优化、预测、评价等多种建模类型。请分析这些论文的质量特征,建立数学建模论文质量的综合评价指标体系。将“逻辑严密性”“方法合理性”等核心维度拆解为可量化的二级指标(如逻辑连接词密度、模型假设与问题匹配度、公式推导完整性等),构建自动评分模型,并对附件1中的30篇论文进行质量分级(优秀、良好、中等、及格、不及格)。说明指标体系的规范依据及权重设定的合理性。
问题2:附件2是10篇基于同一赛题的论文,建立统计模型分析论文质量与可量化文本特征(如篇幅结构、公式密度、逻辑连接词使用、参考文献规范性等)之间的关联关系,识别影响论文质量的关键特征。引入论文质量调整因子,建立基于关键特征的质量预测模型,并分析小样本条件下模型的稳定性。
问题3:考虑到AI辅助撰写论文的鉴别需求与评审主观性差异,基于问题1的评分模型和问题2的关键特征识别结果,设计论文优化策略(含AI生成痕迹检测、逻辑断层识别与修正),建立数学模型,针对附件3中的3篇“中等”质量论文给出具体修改方案、AI辅助程度评估及优化后的质量得分预测。
整体求解过程概述(摘要)
针对问题一,为了把“逻辑严密性”“方法合理性”等抽象评审概念转化为可计算、可复核的量化指标,本文首先对附件1的30篇PDF论文实施语料级数据理解与探索。样本包含A题12篇、B题17篇、C题1篇,页数范围为11—84页,中位数为25页;其中25号论文为纯扫描件。鉴于论文题型、篇幅和PDF可抽取性存在显著异质性,本文构建“文本内容特征—版式结构特征—证据链特征”三源特征底座,并采用稳健缩尾、适度型指标变换、同题中位数插补及置信度惩罚完成预处理。在此基础上,将论文质量拆解为结构规范性、逻辑严密性、方法合理性、结果可信度、创新表达性5个一级指标及15个二级指标;一级权重由AHP确定,二级权重由CRITIC客观赋权,最终通过TOPSIS与加权总分融合得到综合评分。AHP一致性比率CR=0.0173<0.10,权重扰动实验的平均秩相关系数为0.9938。30篇论文被分为优秀1篇、良好10篇、中等12篇、及格6篇、不及格1篇。
针对问题二,考虑到附件2仅含10篇同题论文,直接使用高维黑箱模型会导致参数不可辨识和泛化误差膨胀,本文不重复问题一的PDF清洗,而是在共享特征底座上进一步构造结构完整、公式信息、逻辑衔接、文献规范、验证充分、方法丰富、图表证据、表达波动和文本可靠9个同题特征指数。为削弱扫描质量、证据充分性与题意一致性造成的系统偏差,引入论文质量调整因子,并比较Elastic Net、偏最小二乘回归和贝叶斯岭回归。嵌套留一交叉验证表明,Elastic Net取得MAE=4.37、RMSE=5.19、R²=0.830、Spearman=0.867,为综合误差最小的模型。置换检验与Bootstrap共同表明,验证充分指数、图表证据指数、结构完整指数和表达波动指数是较稳定的关键特征,其中验证充分指数与调整后质量的Spearman相关系数为0.815。
针对问题三,基于问题一的15项评分结果与问题二识别出的关键特征,本文构建“AI生成痕迹风险—逻辑断层风险—修改动作收益”三层优化框架。AI辅助程度不被视为事实标签,而被定义为由模板化短语密度、句长突发性、字符四元组重复率、词汇多样性与段落均匀度共同决定的风格风险指数;逻辑断层通过“问题—假设—数据—模型—求解—验证—结论”论证链闭合度识别。随后设置结构规范、逻辑审校、方法论、数据证据、验证评估、复现审计和AI痕迹审校等智能体,协调智能体在编辑成本约束下求解质量增益、AI风险和修改成本的Pareto方案。对附件3三篇已知“中等”论文进行等级锚定后,其基准得分分别为69.35、70.00和71.51,优化预测得分分别为73.77、74.86和76.04。
综上,本文形成了一套可解释、可复现、可推广的数学建模论文智能评估系统。该系统既保留专家判断对“逻辑与方法”的价值偏好,又利用样本差异度与指标冲突性修正主观权重;既可输出总分与等级,又能定位具体薄弱指标和修改动作。模型的主要优势是审计链完整、对小样本友好、可支持人机协同评审;主要局限是缺少正式专家金标准、扫描件语义抽取受限、AI痕迹只能给出风险而不能作为学术不端判据。
模型假设:
(1)假设1:PDF中能够抽取的正文文本、标题、图表题注和公式符号能够代表论文的主要结构与表达特征;对纯扫描件采用缺失机制处理,而不把不可抽取性直接解释为低质量。
(2)假设2:同一题型论文的核心问题词和常用方法词具有相对稳定的语义范围,题型词典能够用于估计模型假设与问题之间的匹配程度。
(3)假设3:逻辑连接词、公式密度和句长波动存在合理区间,偏离该区间的两个方向均可能降低学术表达质量。
(4)假设4:附件1虽然没有人工评分标签,但可通过规范标准、专家偏好矩阵和样本信息量建立相对可信的基准评分;该评分用于问题二的弱监督目标。
(5)假设5:附件2的10篇论文基于同一赛题,其题型差异可以忽略,质量变化主要由结构、证据、方法和表达特征造成。
(6)假设6:题面已说明附件3三篇论文为“中等”质量,该信息可作为等级先验对自动得分进行锚定校准,校准只压缩量纲漂移,不改变三篇论文的组内排序。
(7)假设7:AI文本检测只能输出概率性风险。除非存在写作过程证据,否则任何风格统计量均不能单独构成AI使用或学术不端的事实认定。
(8)假设8:修改动作对指标的增益具有边际递减特征,即指标越接近满分,同类修改带来的新增收益越小。
问题分析:
问题一分析
本题属于多准则组合赋权综合评价建模问题,核心实现数学建模论文全自动量化分级评审。核心难点:评审标准包含结构、逻辑、方法等多层抽象维度,单一主观赋权易存在评委偏好偏差;论文样本题型、篇幅、PDF 扫描可读性差异巨大,篇幅长短不能等价代表论文质量;指标存在适度型特征(逻辑词、公式密度过多 / 过少均减分),普通线性计分无法贴合评审规则;扫描件无文本抽取数据,直接扣分存在不公平性。建模思路:构建 “结构规范、逻辑严密、方法合理、结果可信、创新表达”5 大一级维度、15 项可量化二级指标体系;采用 AHP 法承载专家评审主观价值倾向,CRITIC 法依托样本数据客观修正指标权重,二者相乘得到组合权重消除单一赋权缺陷;对偏态指标做稳健缩尾,适度指标采用高斯函数映射,扫描件采用同题型中位数插补并附加置信惩罚;融合线性加权与 TOPSIS 理想解贴近度得到百分制得分,设置五级分级阈值,通过权重扰动实验验证评分稳定性,输出分项得分、综合总分与质量等级,为后序特征挖掘、优化模块提供统一量化标签底座。
问题二分析
本题属于极小样本监督回归建模问题,完全复用问题一 PDF 文本、版式特征提取流水线与评分结果作为预测标签。核心难点:仅 10 篇同题型论文,高维原始特征极易引发多重共线性与过拟合;论文扫描件文本缺失带来系统性评分偏移;单纯线性模型难以区分特征的真实贡献度,无法定位影响论文质量的核心要素。建模思路:将海量原始统计特征压缩为 9 个具备明确评审含义的综合指数,降低模型维度;设计题型、证据完备度、文本可读性三维质量调整因子修正跨题型评分量纲偏差;对比贝叶斯岭、PLS、Elastic Net 三类回归模型,采用嵌套留一交叉验证规避数据泄露,选用兼具 L1 稀疏选择与 L2 正则的 Elastic Net 作为最优模型;结合 Spearman 秩相关、置换检验、Bootstrap 系数抽样三重方法筛选稳定核心特征,量化验证、图表、篇章结构三类指标对论文质量的决定性作用,形成小样本下稳定的论文质量预测工具。
问题三分析
本题属于多智能体协同多目标优化 + AI 文本风险识别复合建模问题,依托前两问指标体系、预测特征结论构建论文智能修改闭环。核心难点:修改动作存在收益冲突(丰富方法易提升 AI 模板痕迹、删减模板会损失结构完整度);AI 文本检测仅能输出概率风险,无法作为学术不端判定依据;修改存在编辑成本约束,需平衡得分提升、AI 风险降低、人力消耗多重目标。建模思路:搭建七类专业优化智能体(结构 / 逻辑 / 方法 / 数据 / 验证 / 复现 / AI 审校)+ 协调决策智能体架构;基于句长、四元组重复、模板短语等多维度构建 AI 痕迹风险指数,仅作人工复核线索;构建 “问题 – 假设 – 数据 – 模型 – 求解 – 验证 – 结论” 链式闭合度指标识别逻辑断层;以单项指标边际递减增益建立 0-1 修改动作整数规划,在固定编辑成本预算下求解 Pareto 最优修改方案;对三篇中等基准论文完成分项短板诊断,输出优先级修改清单、优化后得分与 AI 风险降幅,形成可落地的论文人机协同优化方案。
模型的建立与求解整体论文缩略图

全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:
部分程序如下:
from __future__ import annotations
import json
import math
import os
import re
import warnings
import zipfile
from collections import Counter
from dataclasses import dataclass
from itertools import combinations
from pathlib import Path
from typing import Dict, Iterable, List, Sequence, Tuple
import fitz
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
from scipy.stats import spearmanr
from sklearn.base import clone
from sklearn.cross_decomposition import PLSRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import BayesianRidge, ElasticNet
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.model_selection import LeaveOneOut
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
warnings.filterwarnings("ignore")
ROOT = Path(__file__).resolve().parent
WORK = ROOT / "建模运行结果"
ATT1 = WORK / "att1"
ATT2 = WORK / "att2"
ATT3 = WORK / "att3"
OUT = WORK / "results"
FIG = OUT / "figures"
OUT.mkdir(parents=True, exist_ok=True)
FIG.mkdir(parents=True, exist_ok=True)
def _safe_extract_zip(zip_path: Path, target: Path) –> None:
"""安全解压附件,防止路径穿越;压缩包内可包含任意层级目录。"""
target.mkdir(parents=True, exist_ok=True)
root = target.resolve()
with zipfile.ZipFile(zip_path, "r") as zf:
for member in zf.infolist():
destination = (target / member.filename).resolve()
if root not in destination.parents and destination != root:
raise ValueError(f"压缩包包含不安全路径:{member.filename}")
zf.extractall(target)
def prepare_inputs() –> None:
"""
自动准备输入数据。
将本脚本与“附件1.zip、附件2.zip、附件3.zip”放在同一目录后运行;
程序会解压到“建模运行结果/att1~att3”,并递归检索 PDF。
若用户已经手工放置 PDF,则不会重复解压。
"""
mapping = [(ROOT / "附件1.zip", ATT1), (ROOT / "附件2.zip", ATT2), (ROOT / "附件3.zip", ATT3)]
missing = []
for zip_path, target in mapping:
target.mkdir(parents=True, exist_ok=True)
if not any(target.rglob("*.pdf")):
if zip_path.exists():
print(f"正在解压:{zip_path.name} -> {target}")
_safe_extract_zip(zip_path, target)
else:
missing.append(zip_path.name)
if not any(target.rglob("*.pdf")):
missing.append(f"{target}(未发现PDF)")
if missing:
raise FileNotFoundError(
"缺少输入数据:" + ";".join(dict.fromkeys(missing)) +
"。请将本脚本与附件1.zip、附件2.zip、附件3.zip置于同一目录。"
)
# —————————- 字体与绘图参数 —————————-
def setup_chinese_font() –> None:
preferred = [
"Noto Sans CJK SC", "Noto Serif CJK SC", "Microsoft YaHei", "SimHei",
"WenQuanYi Micro Hei", "AR PL UMing CN"
]
available = {f.name for f in font_manager.fontManager.ttflist}
for name in preferred:
if name in available:
plt.rcParams["font.sans-serif"] = [name]
break
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["figure.dpi"] = 150
plt.rcParams["savefig.dpi"] = 220
plt.rcParams["axes.titleweight"] = "bold"
plt.rcParams["axes.grid"] = True
plt.rcParams["grid.alpha"] = 0.18
setup_chinese_font()
# —————————- 词典 —————————-
STRUCTURE_KEYS = {
"摘要": ["摘要"],
"关键词": ["关键词", "关键字"],
"问题重述": ["问题重述", "问题背景", "问题提出"],
"问题分析": ["问题分析", "问题剖析"],
"模型假设": ["模型假设", "基本假设", "问题假设"],
"符号说明": ["符号说明", "符号约定", "符号定义"],
"模型建立": ["模型建立", "模型的建立", "模型构建"],
"模型求解": ["模型求解", "模型的求解", "求解过程"],
"检验评价": ["模型检验", "灵敏度分析", "敏感性分析", "误差分析", "模型评价", "模型优缺点"],
"参考文献": ["参考文献"],
"附录": ["附录", "程序代码", "代码"],
}
LOGIC_WORDS = [
"因此", "因而", "从而", "所以", "由此", "可得", "这表明", "说明", "鉴于", "考虑到",
"首先", "其次", "然后", "最后", "进一步", "在此基础上", "基于上述", "综上", "反之",
"然而", "但是", "与此同时", "为了", "其中", "若", "则", "故", "由于"
]
DERIVATION_WORDS = ["代入", "化简", "整理得", "推导", "求导", "拉格朗日", "约束", "目标函数", "最优解", "由式", "联立", "迭代"]
VALIDATION_WORDS = [
"验证", "检验", "拟合优度", "决定系数", "R2", "R²", "均方误差", "MSE", "RMSE", "MAE", "MAPE",
"交叉验证", "留一法", "鲁棒", "敏感性", "灵敏度", "误差", "残差", "置信区间", "稳定性", "对比实验"
]
DATA_WORDS = [
"缺失值", "异常值", "数据清洗", "数据预处理", "标准化", "归一化", "插值", "去重", "平滑",
"箱线图", "主成分", "特征工程", "编码", "数据来源", "爬虫", "采集", "样本", "训练集", "测试集"
]
REPRO_WORDS = ["参数设置", "算法流程", "伪代码", "Python", "MATLAB", "代码", "随机种子", "迭代次数", "收敛阈值", "数据来源"]
INNOVATION_WORDS = ["创新", "改进", "融合", "耦合", "集成", "多模型", "动态", "自适应", "多目标", "强化学习", "知识图谱", "智能体"]
TEMPLATE_PHRASES = [
"针对问题一", "针对问题二", "针对问题三", "针对问题四", "本文首先", "本文通过", "本文构建",
"基于上述结果进一步", "在此基础上进一步考虑", "由此可得", "这表明", "综上所述"
]
METHODS = [
"层次分析法", "AHP", "熵权法", "CRITIC", "TOPSIS", "主成分分析", "PCA", "因子分析",
"线性回归", "多元回归", "逻辑回归", "岭回归", "LASSO", "弹性网络", "支持向量机", "SVM",
"随机森林", "XGBoost", "神经网络", "LSTM", "ARIMA", "灰色预测", "GM(1,1)", "聚类",
"K-means", "遗传算法", "粒子群", "模拟退火", "蚁群算法", "NSGA", "整数规划", "线性规划",
"非线性规划", "多目标规划", "系统动力学", "结构方程", "SEM", "德尔菲法", "博弈论",
"强化学习", "深度强化学习", "马尔可夫", "蒙特卡洛", "Bootstrap", "贝叶斯", "模糊综合评价",
"灰色关联", "熵值法", "神经网络", "时间序列", "空间分析", "核密度", "GIS"
]
TOPIC_LEXICON = {
"A": ["康养", "养老", "医疗", "资源", "城市", "公平", "覆盖", "设施", "空间", "配置", "老龄化"],
"B": ["教师", "数字胜任力", "数字素养", "高校", "教育数字化", "增值", "教学", "培训", "职称"],
"C": ["忧郁", "抑郁", "情绪", "心理", "治疗", "预测", "生理", "语音", "表情"]
}
TOPIC_METHODS = {
"A": ["空间分析", "核密度", "GIS", "多目标规划", "整数规划", "遗传算法", "粒子群", "强化学习", "覆盖", "公平"],
"B": ["层次分析法", "AHP", "德尔菲法", "结构方程", "SEM", "多元回归", "系统动力学", "增值评价", "XGBoost"],
"C": ["逻辑回归", "支持向量机", "随机森林", "XGBoost", "神经网络", "LSTM", "时间序列", "分类"]
}
INDICATOR_GROUPS = {
"结构规范性": ["S1结构完整度", "S2层级规范度", "S3参考文献规范度"],
"逻辑严密性": ["L1逻辑衔接适度", "L2假设问题匹配度", "L3公式推导完整性", "L4论证链闭合度"],
"方法合理性": ["M1方法问题适配度", "M2方法多样与互证", "M3数据预处理充分度"],
"结果可信度": ["R1检验验证充分度", "R2图表证据充分度", "R3可复现性"],
"创新表达性": ["I1模型创新度", "I2学术表达质量"],
}
INDICATORS = [x for v in INDICATOR_GROUPS.values() for x in v]
# —————————- 通用函数 —————————-
def count_terms(text: str, terms: Sequence[str]) –> int:
return int(sum(text.count(t) for t in terms))
def clip01(x: float) –> float:
return float(max(0.0, min(1.0, x)))
def sat(x: float, scale: float) –> float:
"""单调饱和函数。"""
return clip01(1.0 – math.exp(–max(0.0, x) / max(scale, 1e-9)))
def optimal_score(x: float, center: float, width: float) –> float:
"""适度型指标,越接近 center 越好。"""
return float(math.exp(–((x – center) / max(width, 1e-9)) ** 2))
def infer_topic(text: str) –> str:
# 优先读取封面“选题”
m = re.search(r"选题\\s*([ABC])\\s*题", text[:2000], flags=re.I)
if m:
return m.group(1).upper()
scores = {k: count_terms(text[:10000], v) for k, v in TOPIC_LEXICON.items()}
return max(scores, key=scores.get)
def split_sentences(text: str) –> List[str]:
items = re.split(r"[。!?!?;;\\n]+", text)
return [x.strip() for x in items if len(x.strip()) >= 6]
def char_ngrams(text: str, n: int = 4) –> List[str]:
t = re.sub(r"\\s+", "", text)
t = re.sub(r"[^\\u4e00-\\u9fffA-Za-z0-9]", "", t)
return [t[i:i+n] for i in range(max(0, len(t)–n+1))]
def ratio_reference_norm(ref_text: str) –> float:
lines = [x.strip() for x in ref_text.splitlines() if len(x.strip()) > 5]
lines = [x for x in lines if not re.fullmatch(r"\\d+", x)]
if not lines:
return 0.0
valid = 0
for line in lines:
has_index = bool(re.search(r"^\\s*[\\[【]?\\d+[\\]】\\.、]", line))
has_year = bool(re.search(r"(19|20)\\d{2}", line))
has_type = bool(re.search(r"\\[[JMCDRNEB]\\]", line, re.I))
has_punc = sum(line.count(p) for p in [".", ",", ",", ":", ":"]) >= 2
if (has_index and has_year) or (has_year and has_type) or (has_index and has_punc):
valid += 1
return valid / max(1, len(lines))
def extract_reference_section(text: str) –> str:
pos = text.rfind("参考文献")
if pos < 0:
return ""
section = text[pos:]
# 附录之后不再计入
ap = section.find("附录")
if ap > 0:
section = section[:ap]
return section[:12000]
def estimate_formula_count(lines: Sequence[str], drawings: int) –> int:
formula_lines = 0
math_pat = re.compile(r"[=∑Σ∏√∫≤≥≈±×÷]|\\b(?:arg|min|max|sin|cos|exp|ln|log)\\b", re.I)
for line in lines:
s = line.strip()
if 3 <= len(s) <= 180 and math_pat.search(s):
# 排除普通目录中的等号噪声
if sum(ch.isdigit() for ch in s) + count_terms(s, ["=", "∑", "√", "≤", "≥"]) >= 2:
formula_lines += 1
# PDF矢量绘图中常包含公式组件,折算后作为补充
return int(formula_lines + min(drawings / 25.0, 80))
def detect_heading_positions(text: str) –> Dict[str, int]:
pos = {}
for key, variants in STRUCTURE_KEYS.items():
p = min([text.find(v) for v in variants if text.find(v) >= 0] or [–1])
pos[key] = p
return pos
def heading_order_score(pos: Dict[str, int]) –> float:
expected = ["摘要", "关键词", "问题重述", "问题分析", "模型假设", "符号说明", "模型建立", "模型求解", "检验评价", "参考文献", "附录"]
observed = [(k, pos[k]) for k in expected if pos.get(k, –1) >= 0]
if len(observed) <= 2:
return 0.25 * len(observed) / 2
seq = [expected.index(k) for k, _ in sorted(observed, key=lambda z: z[1])]
concordant = 0
total = 0
for i in range(len(seq)):
for j in range(i+1, len(seq)):
total += 1
concordant += int(seq[i] < seq[j])
return concordant / max(1, total)
def extract_pdf_features(path: Path, group: str) –> Dict[str, float | str | bool]:
doc = fitz.open(path)
page_texts = []
image_count = 0
drawings = 0
text_blocks = 0
page_areas = []
for page in doc:
t = page.get_text("text") or ""
page_texts.append(t)
image_count += len(page.get_images(full=True))
try:
drawings += len(page.get_drawings())
except Exception:
pass
try:
text_blocks += len(page.get_text("blocks"))
except Exception:
pass
page_areas.append(float(page.rect.width * page.rect.height))
text = "\\n".join(page_texts)
text_clean = re.sub(r"[ \\t]+", "", text)
chars = len(re.sub(r"\\s+", "", text))
pages = len(doc)
lines = [x.strip() for x in text.splitlines() if x.strip()]
sentences = split_sentences(text)
para_lengths = np.array([len(re.sub(r"\\s+", "", x)) for x in lines if len(x) >= 8], dtype=float)
sent_lengths = np.array([len(re.sub(r"\\s+", "", x)) for x in sentences], dtype=float)
topic = infer_topic(text)
scan_flag = chars < max(1000, pages * 120)
extraction_reliability = clip01(chars / max(1.0, pages * 550.0))
positions = detect_heading_positions(text)
struct_present = {k: int(v >= 0) for k, v in positions.items()}
struct_count = sum(struct_present.values())
order_score = heading_order_score(positions)
ref_section = extract_reference_section(text)
ref_lines = [x for x in ref_section.splitlines()[1:] if len(x.strip()) > 8]
refs_count = sum(bool(re.search(r"^\\s*[\\[【]?\\d+[\\]】\\.、]", x)) for x in ref_lines)
if refs_count == 0 and ref_section:
refs_count = max(0, len(ref_lines) // 2)
ref_norm = ratio_reference_norm(ref_section)
intext_citations = len(re.findall(r"[\\[【]\\d{1,3}[\\]】]", text))
formula_count = estimate_formula_count(lines, drawings)
fig_count = len(re.findall(r"(?:图|Figure|Fig\\.)\\s*\\d+", text, flags=re.I))
table_count = len(re.findall(r"(?:表|Table)\\s*\\d+", text, flags=re.I))
equation_refs = len(re.findall(r"(?:式|公式)\\s*[((]?\\d+[))]?", text))
numbered_headings = len(re.findall(r"(?:^|\\n)\\s*(?:第?[一二三四五六七八九十]+[章节]|\\d+(?:\\.\\d+){0,3})\\s*[^\\n]{2,30}", text))
logic_count = count_terms(text, LOGIC_WORDS)
derivation_count = count_terms(text, DERIVATION_WORDS)
validation_count = count_terms(text, VALIDATION_WORDS)
data_count = count_terms(text, DATA_WORDS)
repro_count = count_terms(text, REPRO_WORDS)
innovation_count = count_terms(text, INNOVATION_WORDS)
template_count = count_terms(text, TEMPLATE_PHRASES)
methods_found = sorted({m for m in METHODS if m.lower() in text.lower()})
topic_methods_found = sorted({m for m in TOPIC_METHODS[topic] if m.lower() in text.lower()})
topic_count = count_terms(text[:15000], TOPIC_LEXICON[topic])
other_topic_count = sum(count_terms(text[:15000], v) for k, v in TOPIC_LEXICON.items() if k != topic)
topic_purity = topic_count / max(1, topic_count + other_topic_count)
assumptions_pos = positions.get("模型假设", –1)
assumption_text = text[assumptions_pos:assumptions_pos+5000] if assumptions_pos >= 0 else ""
assumption_topic_overlap = count_terms(assumption_text, TOPIC_LEXICON[topic]) / max(1, len(TOPIC_LEXICON[topic]))
# 问题覆盖:摘要/正文中问题一至问题四的覆盖情况
problem_mentions = 0
for p in ["一", "二", "三", "四", "1", "2", "3", "4"]:
if re.search(rf"(?:问题|针对问题)\\s*{p}", text[:12000]):
problem_mentions += 1
problem_mentions = min(problem_mentions, 4)
# 语言风格特征
ngrams = char_ngrams(text[:60000], 4)
if ngrams:
c = Counter(ngrams)
repeated = sum(v–1 for v in c.values() if v > 1)
repeat_ngram_rate = repeated / len(ngrams)
lexical_diversity = len(c) / len(ngrams)
top_ngram_share = sum(v for _, v in c.most_common(20)) / len(ngrams)
else:
repeat_ngram_rate = 1.0
lexical_diversity = 0.0
top_ngram_share = 1.0
sentence_len_cv = float(np.std(sent_lengths) / max(np.mean(sent_lengths), 1)) if len(sent_lengths) > 2 else 0.0
paragraph_len_cv = float(np.std(para_lengths) / max(np.mean(para_lengths), 1)) if len(para_lengths) > 2 else 0.0
digit_density = sum(ch.isdigit() for ch in text) / max(1, chars)
网硕互联帮助中心

评论前必须登录!
注册