JuMP 做优化、Makie 做交互图、Graphs 做图论、Symbolics 做符号计算——这些领域库不如前两节的常青,但一旦撞上对应问题,它们就是唯一答案。本节每个库给一个能跑的最小例子,建索引备查。
线性规划示例:工厂决定两种产品产量,最大化利润:
] add JuMP HiGHS using JuMP, HiGHS model = Model(HiGHS.Optimizer) @variable(model, x1 >= 0) # 产品1 产量 @variable(model, x2 >= 0) # 产品2 产量 @constraint(model, 2x1 + x2 <= 100) # 工时限制 @constraint(model, x1 + 3x2 <= 90) # 材料限制 @objective(model, Max, 3x1 + 5x2) # 利润最大化 optimize!(model) value(x1), value(x2), objective_value(model) # 最优解
@variable / @constraint / @objective 三个宏让代码几乎与数学式一一对应——第 3 章的宏知识在这里兑现成生产力。换个求解器(Gurobi、Ipopt)只改一个构造参数。
Plots 够用但交互弱,Makie 面向可缩放、可动画的图:
] add GLMakie using GLMakie fig = Figure() ax = Axis(fig[1, 1], title = "等高线", xlabel = "x", ylabel = "y") xs = range(-2, 2, length = 100) contour!(ax, xs, xs, (x, y) -> exp(-(x^2 + y^2))) display(fig)
滚动缩放、拖动平移是默认行为;做参数扫描动画时它的 Observable 机制一行刷新图形。
] add Graphs Symbolics using Graphs g = SimpleGraph(5) add_edge!(g, 1, 2); add_edge!(g, 2, 3); add_edge!(g, 3, 1) dijkstra_shortest_paths(g, 1) # 最短路径
Symbolics 正确用法:
@variables x y expand((x + y)^3) Dx = Differential(x) Dx(x^2 + y^2) |> simplify # 2x,符号求导
| 领域 | 库 | 一句话定位 |
|---|---|---|
| 优化建模 | JuMP | 数学规划的事实标准,求解器可插拔 |
| 微分方程 | DifferentialEquations | 见 6.1,业界最快之一 |
| 可视化 | Makie / Plots | 前者交互与出版质量,后者简单够用 |
| 图论 | Graphs | 顶点边与经典算法全家桶 |
| 符号计算 | Symbolics | 符号求导、化简、代码生成 |
| 天文/生物/化学 | 众多领域包 | 生态特色:领域科学家自己写的原生库 |
💡 关键直觉:Julia 生态的核心卖点不是"库多",而是"库底层都是 Julia 写的"。出问题时可以一路
@descend进库源码调试,这在调用 C 扩展的生态里不可想象。
⚠️ 常见坑:不同 Makie 后端(GLMakie/CairoMakie/WGLMakie)不能混装在同一环境同时显示,脚本出图用 Cairo,交互探索用 GL,按项目切换。
背景:6.3 开头的工厂利润问题解出最优解只是第一步,管理层真正的问题是"工时再买 10 小时值不值"。这要用对偶价格——约束每放宽一单位,目标改善多少。操作:
using JuMP, HiGHS model = Model(HiGHS.Optimizer) @variable(model, x1 >= 0) @variable(model, x2 >= 0) @constraint(model, labor, 2x1 + x2 <= 100) # 给约束起名 @constraint(model, mat, x1 + 3x2 <= 90) @objective(model, Max, 3x1 + 5x2) optimize!(model) println("最优产量: ", round.(value.([x1, x2]); digits=2)) println("工时影子价格: ", round(shadow_price(labor); digits=3)) # 影子价格为正 → 每增 1 工时利润上升该数值;为 0 → 该约束不紧
解读:影子价格把"约束松紧"翻译成钱。工时约束若影子价格为 2,意味着外购工时单价低于 2 就值得买——决策信息直接从模型里长出来。变式:把目标系数微调 5% 重解一遍看解是否跳到另一个顶点,这就是最粗糙但最实用的灵敏度分析;再进一步,对参数区间批量求解并画利润曲线,JuMP 宏建模的简洁性让这种"批量重解"几乎零额外成本。
Symbolics 最值钱的用法不是手推代数,而是"推导→生成代码→高速执行"三连。例如对方程右端做符号微分再转成 Julia 函数:
using Symbolics @variables t k c @variables u(t) # 把 6.1 的振子右端符号化后求雅可比,自动线性化 rhs = -k * u D = Differential(t) expand_derivatives(D(rhs)) # -k*u,链式法则自动执行
工程意义:非线性系统的稳定性分析、自动微分训练网络、生成 C/Fortran 代码嵌进旧框架,底座都是这套符号操作。它与 3.3 元编程的关系值得点一句——Symbolics 生成代码用的正是表达式与宏那一套,学到此处,前六章的知识线全部接上了。