
Julia 像C 一样快,像MATLAB 一样方便,并且像Python 一样通用。在Julia 开发者,特别是JuMP 包开发者的大力支持下,Julia 为运筹学及相关领域的高性能科学计算提供了一个强大的工具——JuMP。本书对Julia 语法基础及其标准库、编程技巧、数值优化、优化求解、计算机科学计算都有所涉及,它可以作为计算机科学计算的入门图书使用;本书作者是美国南佛罗里达大学副教授Changhyun Kwon,他为了方便学生的研究、学习写下本书,所以本书也可以作为高校研究生和教师的有用的参考书。
推荐序1 Julia 语言(以下简称Julia)作为一门在MIT(Massachusetts Institute of Technology,麻省理工学院)开源框架协议下开发的高性能计算语言,至今也不过十年左右的历史。Julia 在开发之初就有相当大的野心:它要像C 语言(以下简称C)一样快速,同时要有如同Ruby 的动态性;要具有Lisp 般的元编程能力而又有MATLAB 那样的数学符号输入;要像Python 般通用、像R 般在统计分析上得心应手、像Perl 般自然地处理字符串、像MATLAB 般强大的线性代数运算能力、像Shell 般具有“胶水语言”的进程管理能力,它要易于学习而又不让真正的黑客感到无聊;还有,它应该是交互式的,同时又是编译型的…… 最终,Julia 选择了更适合科学工作者思维和编程习惯的多重派发作为其面向对象的核心特性。随着2018 年8 月Julia 1.0 版本的发布,这门编程语言也进入了一个崭新的阶段。虽然上一段的“野心”里提到的很多目标还没有完美地实现, Julia语言目前也没有完全成熟,并且还有很长的路要走(类似Python 的2.0 版本阶段),但是它已经在科学计算、数学规划、数值优化、机器学习、交互性编程设计等多个方面有了很多成熟的应用。当然,这并不是说你随便写一段Julia 代码就真的能达到和C++相当的速度。Julia 这门语言的特色是,它给你提供了充分优化的空间 和(达到高性能代码的)相对容易的编程体验。 这也正是这本中译版的《Julia 高性能科学计算》能给你带来帮助的地方。如果你是一位对Julia 编程感兴趣的编程初学者,可能对Python 或MATLAB 有一点经验但经验并不丰富,那么希望你对Julia 在1.0 版本之后对科学计算、运筹优化的具体实现感兴趣。这本书里丰富的实例和Kwon 教授的代码及讲解将能循序渐进地带你入门。尤其是Julia 是一门开源语言,目前还没有像MATLAB 社区这样系统和规范的官方文件,这就显得Kwon 教授在自己学习和使用Julia 后分享的这个教程更加地难能可贵了。 最后谈一点我自己使用Julia 的心得。我是从2015 年开始使用这门语言的,当时还是0.3 版本,处在非常初期的阶段。虽然有各种各样的问题,但是在琢磨package相应的.jl 源码,包括在Julia 英文和中文社区与诸多Julia 语言的先行者切磋交流之后,我便无法自拔地爱上了这门语言。我曾经是一位MATLAB 重度用户,Python/C++开发者,但现在已经很少使用这些语言了在我的日常研究中,倒是天天在用Julia。 欢迎尝试、学习、使用Julia 这门潜力无限的编程语言。 覃含章 2020 年1 月于美国剑桥 推荐序2 Julia 是我最喜欢的语言:它是一门以科学计算为主要服务目标的语言,同时兼顾了易用性和高性能。2018 年,在Julia 1.0 发布之后,其就因为宏大的目标而颇受关注。作为一名科研工作者,我和我身边的老师在长期的实践中使用Julia 解决了很多实际的数值问题,它无疑在一定程度上解决了科学计算中的两语言问题。 与此同时,Julia 社区也是目前为止我所知道的对科学计算最友好的社区,在这个社区里聚集着多个科学研究领域的专家,其中很大的一个分支就是以JuMP 为代表的数学优化社区。JuMP 作为一个优秀的开源项目也已经在数学优化领域里颇具规模,它的作者在2016 年获得了INFORMS Computing Society(这是一个研究计算机、人工智能,以及与之相关的运筹学和管理学的社团。它的目的是帮助运筹学和管理学研究协会的成员提高计算机技术和人工智能技术)奖。JuMP 也已经成为NumFOCUS 官方支持的项目,同时围绕着这样一个开源项目,社区里也聚集了一批数学优化专家。 Julia 中文社区一直缺乏优秀的书籍和资料将Julia 社区的优势引入中国,我很高兴能够看到这样一本专业书籍被翻译成中文。在阅读本书的过程中,作为一个运筹学的门外汉,我也学到了一些运筹学的知识。更重要的是本书将会在传授运筹学知识的同时讲解如何具体地通过使用JuMP 来应用相关的算法。它很适合对Julia 还不太熟悉且对运筹学感兴趣的朋友。希望这样一本中译本图书能够帮到中文世界里对运筹学和Julia 感兴趣的朋友。 罗秀哲 2020 年2 月于滑铁卢 前 言 写作本书的主要目的是“帮助我自己”。我是一位运筹学教授,每天都做着构建数学优化模型、开发解决问题的算法、用计算机编程语言执行这些算法、用数据做实验等工作。这期间会用到人类语言、数学语言和计算机语言这3 种语言。我的学生和我需要在这3 种语言之间进行跳转,我们需要在这3 种语言之间进行“翻译”。 当有学生因这类“翻译”任务向我求助时,我通常把自己之前的“翻译”作为例子,或者查找网上可能有帮助的资源给他。如果学生的数学基础不错,有足够的计算机编程经验,对数学计算的工作原理理解得很好,那么他学起来就会比 较容易,我每天的研究和教学任务也会进行得比较顺利。 但不尽如人意的是,很多搞运筹学的研究生需要花很长时间去学习如何“翻译”。写作本书就是为了让我能够更好地帮助他们。 我既不是计算机科学家,也不是软件工程师。所以,本书并没有教授最好的“翻译”方法,而是讲解在运筹学和管理学的研究和开发工作中,如何完成一些常见的任务。这只是“一种翻译”,并且很可能不是最好的“翻译”。但阅读本书后,读者应该能够学会用这样或那样的方式去搞定任务。 本书教些什么 本书不只是关于数值计算方法的教科书、Julia 编程综合介绍书、数值优化的教科书、优化求解完全手册,也不只是计算机科学和工程的入门书——本书对这些内容都有所涉及。 本书首先会讲解如何安装Julia 语言。然后讲一些语法、Julia 的标准库、Julia编程技巧、一些数值方法、优化模型、蒙特卡洛方法、算法和一些优化解决方案。 本书绝不是以上提到的各个领域的完整的教科书,也不该被单独当作教科书来使用。在我看来,最好把本书与其他运筹学和管理学的主要教科书和参考书一起使用。本书的读者需要熟悉或愿意从其他参考文献中自学优化理论和算法。当然,我在书中提供了相关领域的我所知的最好的参考资料。 阅读本书后,读者就有了一些写代码的经验,就应该能够检索和阅读更多网上的技术文档了。本书将帮助你迈出学习运筹学和管理学计算的第一步——这事实上是一本计算机入门图书。 本书怎么用 本书无疑对研究生及他们的导师完成研究任务会有很大的帮助。低年级研究生可以把本书当作可选优化求解器和算法的辅导书,也可以当作学习指南。当研究生在学习各种课程时,本书将会是学习如何解决特定优化问题和实现算法的好起点。最后,本书也将会是他们做论文研究的有用参考书之一。 高年级研究生可以把本书作为参考文献。例如,当需要为他们的问题执行拉格朗日松弛法时,他们可以参考本书的对应章节学习如何执行。 我同时还希望,本书可以作为运筹学、分析学、线性规划、非线性规划、数值优化、网络优化、管理学及运输工程的补充教科书。对运筹学专业和管理学专业来说,数值方法和计算机计算工具是必修的课程,老师可以根据自己的主要关注点,将本书作为初级或中级教科书。 高级程序员需注意 如果你已经熟悉计算机计算和至少一种计算机编程语言,我认为本书可能对你意义不大。网上有很多资源可以让你学习Julia 语言并很容易地跟进最新进展。但如果你希望学得更快,遇到的问题更少,本书将对你有所帮助。 我在学Julia 之前有MATLAB 和Java 的编程经验。学习Julia 并不难,相反它令人激动又很有趣。我们只需要一些好的“借口”去学习和使用Julia。阅读第1章可以了解这些“借口”。 参考资料说明 本书提供了大量的参考资料以方便读者更好地了解书中提到的相关技术及工具。为了保证参考资料相关链接能够实时更新,特将“参考资料”文档放于博文视点官方网站,读者可在http://www.broadview.com.cn/38177 页面进行下载。 致谢 我诚挚地感谢Julia 开发者的辛勤努力。Julia 是一门美丽的语言,我非常喜欢。它完全改变了我每天的计算生活。我也很感激JuMP 和其他相关软件包的开发者。自从有了JuMP,我不再需要去寻找更好的模型语言了。 Changhyun Kwon 于美国弗罗里达州 坦帕
第1 章 介绍和安装 ·················································································································.1 1.1 什么是Julia 及为什么要使用Julia ·····································································.2 1.2 安装Julia ····················································································································.4 1.2.1 在Windows 系统上安装Julia ··································································.4 1.2.2 在macOS 系统上安装Julia ·····································································.9 1.2.3 运行Julia 脚本 ···························································································.13 1.2.4 安装Gurobi·································································································.13 1.2.5 安装CPLEX ·······························································································.15 1.3 安装IJulia·················································································································.17 1.4 包管理 ·······················································································································.20 1.5 帮助 ····························································································································.22 第2 章 简单线性规划···········································································································.24 2.1 线性规划问题 ··········································································································.25 2.2 写线性规划问题的其他方式 ···············································································.29 2.3 写线性规划问题的另一种方式 ··········································································.31 2.4 混合整数线性规划问题 ························································································.32 第3 章 Julia 语言基础 ·········································································································.35 3.1 向量、矩阵和数组 ·································································································.35 3.2 元组 ····························································································································.40 3.3 索引和范围 ··············································································································.42 3.4 打印信息 ···················································································································.45 3.5 集合、字典和循环 ·································································································.47 3.6 函数 ····························································································································.50 3.7 变量的作用域 ··········································································································.52 3.8 随机数生成 ··············································································································.55 3.9 文件读/写 ·················································································································.59 3.10 绘图 ·························································································································.63 3.10.1 PyPlot 包····································································································.64 3.10.2 在PyPlot 中避免使用第三方字体······················································.68 第4 章 数值方法选题···········································································································.70 4.1 曲线拟合 ···················································································································.70 4.2 数值微分 ···················································································································.75 4.3 数值积分 ···················································································································.78 4.4 自动微分 ···················································································································.80 第5 章 单纯形法 ···················································································································.84 5.1 单纯形法简介 ··········································································································.84 5.2 查询所有基本可行解 ····························································································.87 5.3 使用JuMP 包 ··········································································································.93 5.4 表格式的枢轴旋转 ·································································································.93 5.5 单纯形法的实现 ·····································································································.95 5.5.1 initialize(c,A,b) ···························································································.97 5.5.2 is_optimal(tableau) ····················································································.99 5.5.3 pivoting!(tableau) ·····················································································.100 5.5.4 创建模型 ···································································································.104 5.6 后面的步骤 ············································································································.110 第6 章 网络优化问题·········································································································.111 6.1 最小费用网络流问题 ··························································································.111 6.2 运输问题 ·················································································································.121 6.3 最短路径问题 ········································································································.127 6.4 实现Dijkstra 算法 ································································································.132 第7 章 内点法 ······················································································································.138 7.1 仿射尺度算法 ········································································································.138 7.2 原路径跟踪算法 ···································································································.144 7.3 评述 ··························································································································.149 第8 章 非线性优化问题 ····································································································.151 8.1 无约束优化 ············································································································.151 8.1.1 线性搜索 ···································································································.151 8.1.2 无约束优化 ·······························································································.153 8.1.3 盒约束优化 ·······························································································.154 8.2 非线性优化 ············································································································.155 8.3 其他求解器 ············································································································.156 8.4 混合整数非线性规划 ··························································································.161 第9 章 蒙特卡洛方法·········································································································.163 9.1 概率分布 ·················································································································.163 9.2 随机线性规划 ········································································································.165 9.3 估算简单路径的数目 ··························································································.172 第10 章 拉格朗日松弛 ······································································································.181 10.1 拉格朗日松弛介绍 ····························································································.181 10.1.1 下界与上界 ·····························································································.182 10.1.2 次梯度优化 ·····························································································.183 10.1.3 总结 ··········································································································.184 10.2 p-中位问题 ···········································································································.184 10.2.1 读取数据文件 ························································································.186 10.2.2 最优化求解p-中位问题 ······································································.188 10.2.3 拉格朗日松弛应用 ···············································································.189 10.2.4 求解下界 ·································································································.189 10.2.5 求解上界 ·································································································.193 10.2.6 更新拉格朗日乘子 ···············································································.195 第11 章 互补问题 ···············································································································.208 11.1 线性互补问题(LCP) ····················································································.208 11.2 非线性互补问题(NCP) ···············································································.216 11.3 混合互补问题(MCP) ···················································································.220 第12 章 最优化求解器中的参数 ····················································································.221 12.1 设置CPU 时间限制 ··························································································.221 12.2 设置最优化间隙公差 ························································································.222 12.3 热启动 ···················································································································.223 12.4 Big-M 与积分容差率 ·························································································.224 12.5 关掉求解器的输出 ····························································································.225 12.6 其他求解器参数 ·································································································.226