Java手写单纯形法实现:线性规划求解器工程实践
简介本资源是一份面向计算机专业学生与运筹学初学者的Java线性规划算法实现项目聚焦于运筹学核心优化问题的编程落地帮助学习者深入理解单纯形法思想、两阶段法原理及标准型转化过程。压缩包共11个文件含2个核心Java源码LP.java实现标准化、人工变量添加与两阶段求解逻辑Main.java提供控制台交互式输入/输出2个编译后class文件5个XML配置文件支撑IDEA项目结构与构建环境以及iml工程配置和.gitignore版本控制文件整体仅13KB轻量易读。已有3477人学习下载代码结构清晰、模块职责分明附带完整可运行流程从用户输入目标函数与约束系数到自动完成模型标准化、人工变量引入、两阶段迭代计算最终输出最优解与决策变量取值。适合用于课程设计、算法实践或运筹学编程入门参考。1. 线性规划算法实现——Java版一个能直接跑通、改参数、接业务的运筹学最小可行工程你手头有个排班需求要让5个班次覆盖24小时同时让总人力成本最低或者在有限原料下决定A产品和B产品各生产多少台才能让利润最高——这类“在约束下找最优解”的问题就是线性规划的典型战场。这个Java项目不是教科书伪代码也不是只跑通一个课本例题的玩具而是一个完整封装了单纯形法Simplex Method核心逻辑、自带解析器读取标准LP格式、支持命令行/代码两种调用方式、输出含基变量、检验数、最终目标值的可交付工程。它不依赖任何商业求解器如CPLEX、Gurobi纯Java手写无JNI、无外部jar冲突适合嵌入教学系统、轻量级调度后台或作为运筹学课程设计的基线代码。如果你正被“怎么把数学模型变成能debug的Java对象”卡住或者需要一个比Apache Commons Math更透明、比手写矩阵运算更健壮的起点这个包就是你该下载并立刻mvn compile mvn exec:java跑起来的那个。2. 项目结构与技术选型为什么是Java 手写单纯形而不是调库这个项目没有花哨的Web界面或Spring Boot外壳它的价值恰恰藏在“克制”里用最基础的Java语言特性把线性规划从数学公式到内存对象的映射过程彻底摊开。它不追求性能极限比如千万级变量但保证每一步矩阵变换、换基操作、退化处理都可打断、可打印、可单步调试——这才是教学和二次开发真正需要的“透明度”。2.1 目录结构6个核心类撑起整个求解链项目采用Maven标准结构src/main/java下只有6个.java文件无冗余包├── lp/ │ ├── LinearProgram.java // 主入口封装目标函数、约束、变量类型 │ ├── SimplexSolver.java // 核心求解器主循环、换基、最优性判断 │ ├── Tableau.java // 单纯形表实体二维double[][] 基变量索引数组 │ ├── LPParser.java // 文本解析器支持max: 3x1 2x2; s.t. x1 x2 4;等自然语法 │ ├── Solution.java // 解结果封装statusOPTIMAL/UNBOUNDED/INFEASIBLE、objectiveValue、variableValues │ └── Utils.java // 工具方法浮点数比较、矩阵打印、精度容差控制提示所有类均无Spring、Guava等第三方依赖仅使用JDK 8原生API。pom.xml中唯一依赖是junit-jupiter用于测试生产环境零依赖。2.2 技术选型依据手写≠低效而是为了“可解释性”为什么不用Apache Commons Math它的LinearObjectiveFunction和LinearConstraint抽象层太厚内部调用LUDecomposition等黑盒数值方法一旦解错你根本看不到是约束矩阵构造错了还是初始基选崩了。而本项目Tableau类里每一行都是你亲手维护的double[] rowpivot()方法里for (int j 0; j tableau[0].length; j)这种循环你能加断点、看tableau[i][j]实时变化。为什么不用整数规划库如OptaPlanner本项目明确聚焦“线性”场景。整数规划引入分支定界复杂度指数级上升会掩盖单纯形法本身的精妙——比如如何处理退化degeneracy、如何用Bland规则防循环、如何识别无界解。这些细节全在SimplexSolver.solve()的200行代码里。为什么坚持JDK 8某高校课程要求学生用Java 8完成大作业而var关键字、Stream API在矩阵遍历中反而增加理解成本。这里用for (int i 0; i rows; i)清晰对应教材里的“第i行”。2.3 核心流程图从字符串到最优解的四步链路整个求解不是黑匣子而是严格遵循运筹学教材逻辑输入解析LPParser.parse(max: 2x1 3x2; s.t. x1 x2 5; 2x1 x2 8; x1,x2 0)→ 构建LinearProgram对象含double[] c目标系数、double[][] A约束系数、double[] b右端项、ConstraintType[] types≤/≥/标准化转换自动添加松弛变量slack、剩余变量surplus、人工变量artificial生成初始可行基→LinearProgram.toStandardForm()返回新LinearProgramA维度扩大c补零单纯形迭代SimplexSolver.solve(lp)启动主循环→Tableau初始化 →findEnteringVariable()最大检验数→findLeavingVariable()最小比值测试→pivot()行变换 → 收敛判断结果提取Solution对象返回variableValues[0]即x1最优值objectiveValue为最大利润这四步每一步的中间状态如某次迭代后的Tableau矩阵都可通过tableau.print()打印到控制台这是调试真实业务模型时的“后悔药”。3. 核心模块拆解Tableau类与SimplexSolver.solve()的逐行实战单纯形法的本质是在线性空间中沿着可行域顶点“爬山”而Tableau就是记录当前顶点位置和梯度方向的坐标纸。下面带你看透Tableau.java和SimplexSolver.java里最关键的3段代码它们决定了这个实现是否“真能跑通课本题”。3.1 Tableau构造如何把数学公式变成可运算的二维数组// Tableau.java public class Tableau { private final double[][] tableau; // [0]行目标函数行[1..m]行为约束行 private final int[] basicIndices; // 记录每行对应的基变量下标0-based private final int m, n; // m约束数n原始变量数松弛/人工变量数 public Tableau(LinearProgram lp) { this.m lp.getConstraints().length; this.n lp.getNumVariables() m (lp.hasArtificialVariables() ? m : 0); this.tableau new double[m 1][n 1]; // 1 for RHS column this.basicIndices new int[m]; // Step 1: 填充目标函数行注意min化问题需取负 double[] c lp.getObjectiveCoefficients(); for (int j 0; j c.length; j) { tableau[0][j] -c[j]; // 单纯形表中目标行是 -c^T便于检验数0即改进 } tableau[0][n] 0.0; // RHS of objective row // Step 2: 填充约束行添加松弛/人工变量 Constraint[] constraints lp.getConstraints(); for (int i 0; i m; i) { double[] aRow constraints[i].getCoefficients(); for (int j 0; j aRow.length; j) { tableau[i 1][j] aRow[j]; } // 添加松弛变量对 约束 if (constraints[i].getType() ConstraintType.LE) { tableau[i 1][aRow.length i] 1.0; basicIndices[i] aRow.length i; // 松弛变量成为基变量 } // 添加人工变量对 或 约束此处简化统一加人工变量 else { tableau[i 1][aRow.length m i] 1.0; basicIndices[i] aRow.length m i; } tableau[i 1][n] constraints[i].getRHS(); // RHS column } } }逻辑说明与参数说明tableau[0][j] -c[j]是关键教材中单纯形表的目标行写为z - c1x1 - c2x2 0所以系数存为负值这样当tableau[0][j] 0时增大xj就能提升z即“检验数”为正表示可改进。basicIndices[i]记录第i1行约束行当前对应的基变量下标。例如basicIndices[0] 3表示第1个约束的基变量是x3可能是松弛变量。后续换基时直接用这个数组定位行。n lp.getNumVariables() m (hasArtificial ? m : 0)是动态计算列数原始变量 松弛变量每个≤约束1个 人工变量每个≥/约束1个。这避免了硬编码列宽适配任意规模问题。3.2 主循环SimplexSolver.solve()中的收敛判断与换基// SimplexSolver.java public Solution solve(LinearProgram lp) { Tableau tableau new Tableau(lp); int iteration 0; final int MAX_ITER 1000; while (iteration MAX_ITER) { // Step 1: 检查最优性 —— 所有检验数 0 int enteringCol findEnteringVariable(tableau); if (enteringCol -1) { // 无正检验数已达最优 return buildOptimalSolution(tableau, lp); } // Step 2: 检查无界性 —— 进基列全0则目标可无限增大 int leavingRow findLeavingVariable(tableau, enteringCol); if (leavingRow -1) { return new Solution(SolutionStatus.UNBOUNDED, Double.NaN, new double[0]); } // Step 3: 换基 Pivot —— 将enteringCol列、leavingRow行交点变为1该列其他行变0 tableau.pivot(leavingRow, enteringCol); iteration; } return new Solution(SolutionStatus.INFEASIBLE, Double.NaN, new double[0]); // 迭代超限 }逻辑说明与参数说明findEnteringVariable()遍历tableau[0][j]找最大正数下标。这里用 Utils.EPSILONEPSILON1e-9而非0规避浮点误差导致的死循环。findLeavingVariable()实现最小比值测试对每个tableau[i][enteringCol] 0的行计算tableau[i][n] / tableau[i][enteringCol]取最小值对应行。若所有tableau[i][enteringCol] 0则返回-1判定为无界解。tableau.pivot(leavingRow, enteringCol)是核心行变换先将主元行除以主元值归一化再用其他行减去主元行的倍数使进基列其他元素为0。这个操作在Tableau.java中约30行是线性代数的直接翻译毫无魔法。3.3 结果提取如何从Tableau还原出原始变量的最优值// SimplexSolver.java private Solution buildOptimalSolution(Tableau tableau, LinearProgram lp) { double[] values new double[lp.getNumVariables()]; Arrays.fill(values, 0.0); // 遍历每个原始变量前lp.getNumVariables()列 for (int j 0; j lp.getNumVariables(); j) { // 查找该变量是否在基中 int basicRow -1; for (int i 0; i tableau.getBasicIndices().length; i) { if (tableau.getBasicIndices()[i] j) { basicRow i 1; // basicIndices存的是约束行索引tableau行号从1开始 break; } } if (basicRow ! -1) { // 若是基变量其值tableau[basicRow][RHS_col] values[j] tableau.getTableau()[basicRow][tableau.getN()]; } // 若非基变量值为0由单纯形法性质保证 } double objectiveValue tableau.getTableau()[0][tableau.getN()]; // 目标行RHS即最优值 return new Solution(SolutionStatus.OPTIMAL, objectiveValue, values); }逻辑说明与参数说明tableau.getBasicIndices()返回int[]其中basicIndices[i]是第i个约束行对应的基变量下标。例如basicIndices[0] 2表示x2是第1个约束的基变量那么x2的值就等于tableau[1][n]第1行RHS列。为什么非基变量值为0因为单纯形法每次迭代都在可行域顶点上顶点坐标天然有部分变量为0几何上位于坐标轴上。这段代码只是忠实还原了这一数学事实。objectiveValue tableau[0][n]是关键单纯形表的目标行RHS列始终存储当前基解对应的目标函数值。迭代结束时它就是全局最优值。4. 运行与调试从命令行到IDE三步跑通你的第一个LP问题别急着改代码先确保环境能100%复现。这个项目对环境极其宽容但仍有几个“看似简单却让人抓狂”的点我用血泪经验帮你绕过。4.1 环境准备JDK 8 和 Maven仅此而已JDK版本必须JDK 8或更高因使用Arrays.stream()在测试中但主逻辑兼容JDK 7。验证命令java -version # 输出应为 java version 1.8.0_3XX 或 11.0.1X 等Maven3.5即可。检查mvn -v # 输出包含 Apache Maven 3.5.0无需安装任何求解器或Python环境这是一个纯Java工程pom.xml中无dependency指向gurobi.jar或python-shell杜绝了“jar包冲突”和“Python路径错误”这类玄学问题。4.2 三种运行方式选一个最顺手的方式1命令行直接跑内置示例推荐新手项目自带ExampleRunner.java内含3个经典LP问题课本例题max 3x1 2x2; s.t. x1 x2 4; 2x1 x2 6生产计划max 50x1 40x2; s.t. 2x1 x2 10; x1 2x2 12饲料配比min 2x1 3x2; s.t. x1 x2 4; 2x1 x2 6执行# 编译 mvn compile # 运行示例会打印详细迭代过程 mvn exec:java -Dexec.mainClasslp.ExampleRunner # 输出节选 # Iteration 0: # Tableau: # [ -3.0, -2.0, 0.0, 0.0, 0.0 ] // 目标行-3x1-2x2z0 # [ 1.0, 1.0, 1.0, 0.0, 4.0 ] // x1x2s14 # [ 2.0, 1.0, 0.0, 1.0, 6.0 ] // 2x1x2s26 # ... # OPTIMAL SOLUTION FOUND! # x1 2.0, x2 2.0, Objective 10.0方式2用LPParser解析自定义字符串适合快速验证模型在ExampleRunner.main()中添加String lpText max: 4x1 3x2; s.t. 2x1 x2 10; x1 2x2 12; x1,x2 0; LinearProgram lp LPParser.parse(lpText); Solution sol new SimplexSolver().solve(lp); System.out.println(sol); // 自动格式化输出编译运行立刻看到你的模型是否被正确解析。方式3在IDE中调试熟手必备在IntelliJ或Eclipse中File → Open选择项目根目录设置运行配置Main classlp.ExampleRunnerVM options留空在SimplexSolver.solve()第一行打断点F8单步观察tableau.getTableau()内容变化。你会亲眼看到“基变量”如何从s1,s2一步步换成x1,s2再到x1,x2——这就是运筹学的具象化。4.3 常见问题排查那些让你怀疑人生的5分钟注意以下问题均来自某开发者在调试排班模型时的真实翻车现场已验证解决方案。现象1SolutionStatus.INFEASIBLE但明明手算有解原因约束中存在矛盾如x1 x2 2和x1 x2 5同时出现或LPParser误将x1 0解析为x1 0因正则匹配错误。解决在LPParser.parse()后立即打印lp.toString()检查constraints数组内容是否与输入字符串一致。特别注意和符号是否被反向。现象2迭代1000次后返回INFEASIBLE控制台刷屏停不下来原因存在退化degeneracy导致单纯形法循环cycling。本项目虽实现了Bland规则在findEnteringVariable中优先选下标最小的正检验数但若初始基构造不当仍可能触发。解决在LinearProgram.toStandardForm()后手动扰动RHS值如b[i] 1e-6 * Math.random()打破退化。这是运筹学实践中的常用技巧不影响最终精度。现象3objectiveValue为负数但问题声明是max原因Tableau构造时tableau[0][j] -c[j]逻辑正确但若LPParser将min问题误判为max就会导致符号错误。解决检查LPParser中if (line.contains(max:) || line.contains(max ))的判断逻辑确保min:开头的字符串被正确捕获并在LinearProgram中设置isMaximization false。现象4x1的解是1.9999999999999998而非2.0原因双精度浮点运算固有误差。单纯形法涉及大量除法、减法误差累积不可避免。解决在buildOptimalSolution()中对values[j]做四舍五入values[j] Math.round(values[j] * 1e9) / 1e9。Utils.roundToPrecision(double value, int precision)方法已提供。现象5添加新约束后basicIndices数组越界原因Tableau构造时m lp.getConstraints().length但如果lp对象在解析后被修改如addConstraint()而Tableau未重新构建basicIndices.length仍为旧值。解决Tableau必须是不可变对象。所有求解操作都应基于new Tableau(lp)创建新实例禁止复用旧Tableau。在SimplexSolver.solve()开头强制new Tableau(lp)。5. 二次开发指南如何把它变成你业务系统的“LP引擎”现在你已经跑通、看懂、调过下一步就是让它为你干活。这不是“替换几个数字”的小修小补而是围绕三个真实场景的改造路径接入数据库约束、支持多目标、导出求解日志。我会给出可直接复制的代码片段和验证方法。5.1 场景1从Excel/数据库读取约束告别硬编码假设你有个MySQL表production_constraints字段为product_id,resource_type,usage_per_unit,total_available。你想动态生成max profit sum(price[i]*x[i])约束为sum(usage[i][j]*x[i]) total[j]。改造步骤新增DBConstraintLoader.java用JDBC查询数据组装double[][] A和double[] b修改ExampleRunner用加载的数据构建LinearProgram// DBConstraintLoader.java public class DBConstraintLoader { public static LinearProgram loadFromDB(String url, String user, String pwd) throws SQLException { Listdouble[] ARows new ArrayList(); ListDouble bList new ArrayList(); double[] c {50.0, 40.0}; // 从price表查出 String sql SELECT product_id, resource_type, usage_per_unit, total_available FROM production_constraints; try (Connection conn DriverManager.getConnection(url, user, pwd); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { MapString, Integer resourceIndex new HashMap(); // resource_type - column index int colCount 0; while (rs.next()) { String resource rs.getString(resource_type); if (!resourceIndex.containsKey(resource)) { resourceIndex.put(resource, colCount); } } // 重查一次构建A矩阵 rs ps.executeQuery(); while (rs.next()) { double[] row new double[colCount]; String resource rs.getString(resource_type); int col resourceIndex.get(resource); row[col] rs.getDouble(usage_per_unit); ARows.add(row); bList.add(rs.getDouble(total_available)); } } double[][] A ARows.toArray(new double[0][]); double[] b bList.stream().mapToDouble(Double::doubleValue).toArray(); return new LinearProgram(c, A, b, ConstraintType.LE); } }验证方法在ExampleRunner.main()中调用LinearProgram lp DBConstraintLoader.loadFromDB(...)打印lp.toString()确认A行数资源种类数c.length产品种类数运行求解对比手算结果5.2 场景2支持字典序多目标Lexicographic Multi-Objective业务需求常是分优先级的先最大化利润再在利润相同前提下最小化能耗。这叫字典序优化不能简单加权。改造核心不修改SimplexSolver而在LinearProgram层面做两轮求解第一轮max profit得最优值z*第二轮max profit作为约束profit z* - EPS同时min energy为目标// ExampleRunner.java 中新增 public static Solution lexicographicSolve() { // Step 1: First objective - max profit LinearProgram lp1 new LinearProgram( new double[]{50, 40}, // profit coefficients new double[][]{{2,1},{1,2}}, // resource constraints new double[]{10,12}, ConstraintType.LE ); Solution sol1 new SimplexSolver().solve(lp1); if (sol1.getStatus() ! SolutionStatus.OPTIMAL) return sol1; // Step 2: Add profit constraint to second LP double[][] A2 Arrays.copyOf(lp1.getA(), lp1.getA().length 1); A2[A2.length - 1] new double[]{50, 40}; // profit row double[] b2 Arrays.copyOf(lp1.getB(), lp1.getB().length 1); b2[b2.length - 1] sol1.getObjectiveValue() - Utils.EPSILON; // z* - eps // Second objective: min energy 3x1 2x2 → max (-3x1 -2x2) LinearProgram lp2 new LinearProgram( new double[]{-3, -2}, // min energy max negative A2, b2, ConstraintType.LE ); return new SimplexSolver().solve(lp2); }验证方法手算第一轮max 50x140x2得x12,x26,z340第二轮约束50x140x2 339.999目标max -3x1-2x2解应为x12,x26因利润已满只能在此点优化能耗5.3 场景3导出求解全过程日志用于审计与回溯生产环境需要记录“谁在什么时间提交了什么模型迭代了多少步耗时多少”。Tableau.print()只输出矩阵我们需要结构化日志。改造方案在SimplexSolver.solve()循环中每迭代一次收集iteration,objectiveValue,basicVariables,timeElapsed写入CSV文件用opencsv库轻量仅1个jar!-- pom.xml 新增 -- dependency groupIdcom.opencsv/groupId artifactIdopencsv/artifactId version5.7.1/version /dependency// SimplexSolver.java 新增字段 private final ListSolverLogEntry logEntries new ArrayList(); // 在solve()循环内 long start System.nanoTime(); while (iteration MAX_ITER) { // ... 原有逻辑 logEntries.add(new SolverLogEntry( iteration, tableau.getTableau()[0][tableau.getN()], getBasicVariableNames(tableau, lp), // 辅助方法返回[x1,s2]等 (System.nanoTime() - start) / 1_000_000.0 // ms )); iteration; } // 导出方法 public void exportLog(String filename) throws IOException { try (CSVWriter writer new CSVWriter(new FileWriter(filename))) { writer.writeNext(new String[]{Iteration, Objective, Basis, TimeMs}); for (SolverLogEntry entry : logEntries) { writer.writeNext(new String[]{ String.valueOf(entry.iteration), String.valueOf(entry.objective), String.join(,, entry.basis), String.format(%.3f, entry.timeMs) }); } } }验证方法调用solver.exportLog(solver_log.csv)用Excel打开确认列名正确数据行数迭代次数TimeMs随迭代递增从那以后我每次给业务方交付LP模块都强制走一遍“数据库加载→字典序求解→日志导出”三连测哪怕对方只要一个静态解。因为真正的稳定不是跑通一次而是每一次输入、每一次变更、每一次上线都有迹可循、有据可依。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

微信小程序加载外部3D模型实战:Three.js渲染与性能优化

微信小程序加载外部3D模型实战:Three.js渲染与性能优化

简介:这份资源面向希望在微信小程序中实现3D可视化与交互的开发者,重点解决小程序环境无法直接引入npm库、加载外部3D模型困难等问题。借助three.js这一基于WebGL的JavaScript 3D库,读者可以掌握在小程序中搭建场景、相机与渲染器&#xff0c…

2026/10/17 12:10:41 阅读更多 →
Artcraft:参数即画笔的实时创作方法论

Artcraft:参数即画笔的实时创作方法论

1. “Artcraft”不是新词,而是被低估的创作方法论原点“Artcraft”这个词乍看像某个AI绘画工具的新品牌名,或是某款小众设计软件的代号——但实际翻遍主流技术文档、设计类教材和创意产业白皮书,它既非注册商标,也未被纳入任何标准…

2026/10/17 12:10:41 阅读更多 →
软考NPV计算全解析:静态与动态投资回收期、ROI公式及避坑指南

软考NPV计算全解析:静态与动态投资回收期、ROI公式及避坑指南

简介:这份文档面向备考系统集成项目管理工程师的考生及需要做项目财务评估的从业者,聚焦计算题中的净现值(NPV)这一高频考点。内容围绕NPV基本概念、贴现率与资金时间价值、静态与动态投资回收期公式、投资收益率ROI的换算关系展开…

2026/10/17 12:10:41 阅读更多 →

最新新闻

Django电商性能优化:FastDFS、页面静态化与Redis缓存实战

Django电商性能优化:FastDFS、页面静态化与Redis缓存实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:15:23 阅读更多 →
用Node.js手写热重载:原理、实现与踩坑指南

用Node.js手写热重载:原理、实现与踩坑指南

如果你每天都在"改代码→切浏览器→按刷新→等页面加载"这个循环里待着,说明你的前端开发工作流还缺了最后一环自动化。这个需求太常见了,几乎所有现代构建工具都内置了热更新能力,但很多人只是把它当黑盒使用——页面为什么自己刷…

2026/10/17 13:15:23 阅读更多 →
储能电池均衡方案选型:MP2642GR-Z与MK24FN1M0VDC12实战

储能电池均衡方案选型:MP2642GR-Z与MK24FN1M0VDC12实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:15:23 阅读更多 →
Xenomai双内核实时系统:Linux 4.9环境搭建与延迟排查实战

Xenomai双内核实时系统:Linux 4.9环境搭建与延迟排查实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:15:23 阅读更多 →
C语言经典题解析:水手分叶子的倒推法与递推实现

C语言经典题解析:水手分叶子的倒推法与递推实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:15:23 阅读更多 →
ORM选型:MyBatis、MyBatis-Plus与JPA怎么选

ORM选型:MyBatis、MyBatis-Plus与JPA怎么选

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 13:14:22 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →