-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.json
1 lines (1 loc) · 102 KB
/
content.json
1
{"meta":{"title":"技术杂货铺","subtitle":"","description":"","author":"技术杂货铺","url":"https://ben-xj.github.io","root":"/"},"pages":[{"title":"about","date":"2022-04-16T01:13:47.000Z","updated":"2023-08-25T11:31:48.000Z","comments":true,"path":"about/index.html","permalink":"https://ben-xj.github.io/about/index.html","excerpt":"","text":"足迹 本科(2015-2019) —— 上海交通大学 硕士(2019-2022) —— 上海交通大学 算法工程师(2022- ) —— hidden content 个人频道 B站:技术杂货铺_ YouTube:技术杂货铺 TG群组:https://t.me/+v4GY6wMx_ctiM2M1 TG频道:https://t.me/is_ten_days_enough Github: https://github.com/ben-xj 知乎: 闭上眼仔细看"},{"title":"categories","date":"2022-04-15T18:16:09.000Z","updated":"2022-04-16T01:01:24.000Z","comments":true,"path":"categories/index.html","permalink":"https://ben-xj.github.io/categories/index.html","excerpt":"","text":""},{"title":"friends","date":"2022-04-15T18:16:34.000Z","updated":"2022-04-15T18:19:34.000Z","comments":true,"path":"friends/index.html","permalink":"https://ben-xj.github.io/friends/index.html","excerpt":"","text":""},{"title":"tags","date":"2022-04-15T18:16:20.000Z","updated":"2022-04-16T01:01:36.000Z","comments":true,"path":"tags/index.html","permalink":"https://ben-xj.github.io/tags/index.html","excerpt":"","text":""}],"posts":[{"title":"Cython浅出:最常用知识点都在这儿了","slug":"Cython浅出:最常用知识点都在这儿了","date":"2023-09-17T04:30:38.000Z","updated":"2023-09-18T15:23:58.000Z","comments":true,"path":"2023/09/17/Cython浅出:最常用知识点都在这儿了/","link":"","permalink":"https://ben-xj.github.io/2023/09/17/Cython%E6%B5%85%E5%87%BA%EF%BC%9A%E6%9C%80%E5%B8%B8%E7%94%A8%E7%9F%A5%E8%AF%86%E7%82%B9%E9%83%BD%E5%9C%A8%E8%BF%99%E5%84%BF%E4%BA%86/","excerpt":"众所周知,Python是一门“极慢”的语言,无奈它写起来真的很快,各种库用起来太顺手了,以至于形成了良性的生态循环。这也导致越来越多的人用起了Python(主要是有很多代码可以抄啊…)。 但是在某些领域,对代码运行效率的要求还是挺高的,比如本人所在的优化算法领域。那我又想拥有Python的快速开发能力,又想获得较高的运行时效率,这怎么办?","text":"众所周知,Python是一门“极慢”的语言,无奈它写起来真的很快,各种库用起来太顺手了,以至于形成了良性的生态循环。这也导致越来越多的人用起了Python(主要是有很多代码可以抄啊…)。 但是在某些领域,对代码运行效率的要求还是挺高的,比如本人所在的优化算法领域。那我又想拥有Python的快速开发能力,又想获得较高的运行时效率,这怎么办? 有很多的加速方案,比如pybind11、numba、Cython等,个人一番体验下来觉得最简单的就是Cython啦,绝对是可以以最低成本获得不错效果的加速手段(之一?)。 这篇文章就简单介绍下Cython的一些核心用法,我也录了相关的系列视频在B站,建议关注我的B站Cython系列,其中包含完整的代码示例。 首先,Cython是什么?Cython 是一个功能强大的工具,它允许你以 Python 语言为基础编写代码,并通过一些优化技巧将其转化为 C 代码,从而提高运行时效率。文章标题只有浅出,没有深入,因为我自以为并没有很深入了解Cython,只是希望介绍一些 Cython 的核心用法,帮大家以最低成本(相对小的代码修改)获得不错的加速效果,具体包括指定变量类型、边界检查优化、内存视图优化以及 cdef、def 和 cpdef 的区别。Cython还有一些高级用法,比如直接给C/C++代码加wrapper,个人认为已经偏离Python太远了,非必要就不研究了。 基础配置 当你开始使用 Cython 进行项目加速时,需要了解一些基础配置和工作流程。在本部分,我们将介绍 Cython 的安装,创建 setup.py 文件以及将 Cython的.pyx 文件转换为 .c 并编译为扩展模块的过程。这部分可参考之前的文章Accelerate Your NumPy Matrix Operations with Cython。 安装 Cython 首先,你需要安装 Cython。你可以使用 pip 来安装 Cython: 1pip install Cython 创建 pyx 文件 Cython的模块需要以.pyx为后缀,所以我们需要创建一个.pyx文件,比如multiply.pyx,内容如下,这个代码可以直接把Python的代码复制过来(没错,一个字都不改也ok,当然这样加速效果有限): 12345678910111213def cnp.ndarray[double, ndim=2] elementwise_multiply( cnp.ndarray[double, ndim=2] A, cnp.ndarray[double, ndim=2] B): cdef int nrows = A.shape[0] cdef int ncols = A.shape[1] cdef cnp.ndarray[double, ndim=2] result = np.zeros((nrows, ncols), dtype=np.float64) cdef int i, j for i in range(nrows): for j in range(ncols): result[i, j] = A[i, j] * B[i, j] return result 创建 setup.py 文件 setup.py 文件是用于构建和安装你的 Cython 扩展模块的关键文件。一般放在根目录,便于对整个项目进行管理,以下是一个简单的 setup.py 示例: 123456789101112131415161718from setuptools import setup, Extensionfrom Cython.Build import Cythonizeimport numpy as npext_modules = [ Extension("acceleration.multiply", ["acceleration/Cython/multiply.pyx"], include_dirs=[np.get_include()]), Extension("acceleration.knapsack", ["acceleration/Cython/knapsack.pyx"], include_dirs=[np.get_include()])]setup( name='Fluent Python', ext_modules=Cythonize(ext_modules),) 在这个示例中,我添加了两个Cython模块,multiply和knapsack。写法上,Extension的第一个参数是编译后扩展模块的路径,第二个参数是.pyx文件的路径,第三个参数是需要包含的头文件路径,这里我用了numpy的头文件。 setup函数的name参数是项目名称,ext_modules参数是需要编译的模块,这里用了Cythonize函数。 编译和安装 你可以通过 setup.py 文件来编译和安装你的扩展模块。在项目根目录下运行以下命令: 1Python setup.py build_ext --inplace 这将编译扩展模块并将其安装到指定目录下,而生成的.c文件在相应的.pyx同级目录下。 扩展模块在windows下是.pyd文件,在linux下是.so文件,比方我用的是windows,所以生成的文件是类似于multiply.cp39-win_amd64.pyd和knapsack.cp39-win_amd64.pyd。 使用 Cython 扩展模块 现在,你可以在 Python 中正常导入和使用你的 Cython 扩展模块(把.pyd或.so文件当成是一个Python的模块就行)。例如,如果你的扩展模块名称是 your_module,可以这样导入它: 1import your_module 然后,你可以使用其中定义的函数和类,它们已经被编译成 C 代码,因此在性能上比纯 Python 代码更高效。 Cython 的核心用法 在上一部分,我们介绍了 Cython 的基础配置和工作流程。在本部分,我们将介绍 Cython 的一些核心用法,包括指定变量类型、边界检查优化、内存视图优化以及 cdef、def 和 cpdef 的区别。 指定变量类型 Python 是一门动态类型语言,这意味着变量的类型在运行时确定。这种灵活性使得代码编写和调试变得非常容易,但也导致了运行效率较低。Cython 允许你为变量和函数参数指定静态类型,这样编译器就能更好地优化你的代码。 例如,考虑以下 Python 函数: 12def add(a, b): return a + b 在 Cython 中,你可以使用类型声明来指定参数的类型: 12def add(int a, int b): return a + b 这样,Cython 编译器可以生成更高效的 C 代码,无需在运行时进行类型检查。 这里列举一下Python和Cython的类型对应关系如下[1]: 当然除了这些基础类型外,Cython还支持从C++标准库中导入一些类型,或者导入numpy的数组类型,可以看看我的B站视频。 边界检查优化 Python 的列表和数组通常会在访问元素时执行边界检查,以确保不会访问超出范围的元素。这会导致额外的性能开销。在 Cython 中,你可以使用数组的 “boundscheck” 属性和 “wraparound” 属性来控制边界检查。 1234567# 在Cython中关闭边界检查cimport [email protected](False)@Cython.wraparound(False)def access_element(my_list): return my_list[10] 通过关闭边界检查,你可以显著提高代码的执行速度,但需要手动确保访问的索引不会超出数组的实际范围。 内存视图优化 Cython 提供了内存视图(memoryview)的支持,它允许你有效地访问和操作数组的内存。内存视图可以加速数组的操作,尤其是多维数组的索引及切片操作。 12345cimport Cythondef process_array(double[:] arr): for i in range(arr.shape[0]): arr[i] = arr[i] * 2 double[:] arr 定义了一个内存视图,该视图可以访问以 arr 为基础的双精度浮点数数组。[:] 表示可以访问整个数组。 arr.shape[0] 返回数组的长度,允许你在循环中迭代整个数组。 在循环中,你可以直接访问内存视图 arr 的元素,并执行操作,而不需要生成临时对象。 一般来说,Python的切片操作是通过生成一个slice对象,再把该对象传入一个函数来实现的,内存视图允许你以一种更接近底层的方式操作数据,内存视图的优点在于它们不会复制数据,而是在原始数据的基础上执行操作。这减少了内存使用量和数据复制开销,因此在处理大型数据集时,内存视图可以显著提高性能。 cdef、def 和 cpdef 的区别 在 Cython 中,有三种不同的函数声明方式:cdef、def 和 cpdef。 cdef 声明的函数是纯 C 函数,只能从 Cython 代码中调用,不可从 Python 代码中访问。 def 声明的函数是 Python 函数,可以从 Python 代码中调用,但会带来一些性能开销。 cpdef 声明的函数是混合函数,既可以从 Cython 代码中调用,也可以从 Python 代码中调用,其底层其实生成了两个函数版本。 选择适当的声明方式取决于你的需求,如果需要最大的性能,可以使用 cdef 声明,如果需要与 Python 交互,可以使用 cpdef。 以上是 Cython 的一些核心用法,它们可以帮助你在不牺牲开发速度的情况下提高 Python 代码的运行效率。上述示例可能并不完整,如果你对 Cython 感兴趣,可以关注我的Cython系列视频,其中包括更多实际案例和示范。 其他资料 [1] Welcome to Cython’s Documentation — Cython 3.0.2 documentation [2] PyVideo.org https://pyvideo.org/search.html?q=Cython Cython [Book] [3] Cython: The Best of Both Worlds [4] Proceedings of the Python in Science Conference (SciPy): Cython tutorial [5] Cython 3.0: Compiling Python to C, the next generation - YouTube Ref [1] Language Basics — Cython 3.0.2 documentation","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"cython","slug":"cython","permalink":"https://ben-xj.github.io/tags/cython/"},{"name":"python加速","slug":"python加速","permalink":"https://ben-xj.github.io/tags/python%E5%8A%A0%E9%80%9F/"}]},{"title":"vim最常用命令","slug":"vim最常用命令","date":"2023-08-25T11:24:21.000Z","updated":"2023-08-26T15:00:04.000Z","comments":true,"path":"2023/08/25/vim最常用命令/","link":"","permalink":"https://ben-xj.github.io/2023/08/25/vim%E6%9C%80%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/","excerpt":"Vim中的最常用命令 本指南系统地介绍了Vim中的修改、移动、搜索、多窗口等功能的使用方法, 整合了数10个示例,旨在帮助Vim初学者快速掌握必备的Vim编辑命令。 本文提供了一份较全的常用命令查询手册,如果希望根据使用频率来学习,可来我的B站频道 观看视频教程:Vim最常用命令指南。 文章结构如下: 一、修改命令(基础) 二、移动命令(基础) 三、组合编辑命令(用得贼多) 四、搜索和定位命令 五、多窗口命令 六、Visual模式 七、文件操作命令 每类命令都以示例讲解使用场景,力求深入浅出,可以作为Vim新手的实践指南,帮助各位快速上手Vim。","text":"Vim中的最常用命令 本指南系统地介绍了Vim中的修改、移动、搜索、多窗口等功能的使用方法, 整合了数10个示例,旨在帮助Vim初学者快速掌握必备的Vim编辑命令。 本文提供了一份较全的常用命令查询手册,如果希望根据使用频率来学习,可来我的B站频道 观看视频教程:Vim最常用命令指南。 文章结构如下: 一、修改命令(基础) 二、移动命令(基础) 三、组合编辑命令(用得贼多) 四、搜索和定位命令 五、多窗口命令 六、Visual模式 七、文件操作命令 每类命令都以示例讲解使用场景,力求深入浅出,可以作为Vim新手的实践指南,帮助各位快速上手Vim。 一、编辑命令(基础) 1. 插入(i) 在当前光标位置的字符之前进行插入。 使用方法:快捷键i 例如: 123456操作前: abc^操作:i test操作后:testabc 其中,^表示当前光标位置,后续示例中也会使用该符号表示光标位置。 2. 追加(a) 在当前光标位置的字符之后进行插入。 使用方法:快捷键a 例如: 123456操作前:abc^操作:a ba操作后: ababc 3. 替换(s) 删除当前光标位置的字符,并进入插入模式。 使用方法:快捷键s 例如: 123456操作前:abc ^操作:s x操作后:axc 4. 行首插入(I) 在当前行的行首插入。 使用方法:快捷键Shift+i 例如: 123456操作前: include <stdio.h> ^操作:Shift+i #操作后:#include <stdio.h> 5. 行尾插入(A) 在当前行的行尾插入。 使用方法:快捷键Shift+a 例如: 123456操作前:int x = 1 ^操作:Shift+a ;操作后: int x = 1; 6. 替换整行(S) 删除当前整行,并进入插入模式。 使用方法:快捷键Shift+s 例如: 123456操作前:int x = 1; ^操作:Shift+s int y = 2;操作后:int y = 2; 7. 换行(o) 在当前行之下插入新行。 使用方法:快捷键o 例如: 1234567操作前: int x = 1; ^操作:o操作后:int x = 1;// ……这是一个新行 8. 上插行(O) 在当前行之上插入新行。 使用方法:快捷键Shift+o 例如: 123456789操作前:int main() { }^操作:Shift+o操作后:int main() {} 9. 删除字符(x) 删除当前光标位置的字符。 例如: 123456操作前:int x = 1; ^操作:x操作后:int x= 1; 10. 复制、粘贴1行(yy/p) yy复制当前行, 移动到指定位置后, p粘贴复制的内容到当前行之下(或shift+p粘贴到当前行之上)。p表示Paste,即粘贴。 例如: 1234567891011操作前: def __init__(self): ^ self.__startTime = time.time() self.__endTime = 0操作:yy j p// 复制当前行,并向下移动一行,粘贴复制的内容操作后: def __init__(self): self.__startTime = time.time() def __init__(self): self.__endTime = 0 11. 剪切1行(dd) dd剪切当前行, 同样可配合p进行粘贴,也可以不粘贴,就当是删除当前行。 12. 剪切1行并进入插入模式(cc) cc剪切当前行, 并进入插入模式。等于dd + i。 二、移动命令(基础) 1. 上下左右移一个字符(k、j、h、l) 使用方法:快捷键k、j、h、l 例如右移 l: 123456原位置:int x = 1; ^操作后:int x = 1; ^ 2. 下个单词词首(w/W) 移动到下个单词的开头。 使用方法:快捷键w 例如: 123456原位置:def __init__(self): ^操作后:def __init__(self): ^ 另外,快捷键W可以跳过标点符号,只要是连在一起的字母数字字符都会被视为一个单词。 例如: 12345678910原位置:def __init__(self): ^ self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]操作后:def __init__(self): self._cards = [Card(rank, suit) for suit in self.suits ^ for rank in self.ranks] 3. 本单词词尾(e/E) 移动到当前单词的末尾,如果本身就在单词末尾,则移动到下个单词的末尾。 使用方法:快捷键e 例如: 123456原位置:def __init__(self): ^操作后:def __init__(self): ^ 类似的,快捷键E可以跳过标点符号,只要是连在一起的字母数字字符都会被视为一个单词。 例如: 123456原位置:def __init__(self): ^操作后:def __init__(self): ^ 4. 本单词词首(b/B) 移动到当前单词的开头,如果本身就在单词开头,则移动到上个单词的开头。 和w/W类似,快捷键b/B可以跳过标点符号,只要是连在一起的字母数字字符都会被视为一个单词。同样的概念不举例了。 5. 移动到行首(0) 将光标移动到当前行的第一个字符。 使用方法:快捷键0 例如: 123456原位置:def init(self): ^操作后:def init(self):^ 6. 移动到行尾($) 将光标移动到当前行的最后一个字符。 使用方法:快捷键$ 例如: 123456原位置:def init(self): ^操作后:def init(self): ^ 7. 移动到文件首(gg) 将光标移动到文件的第一行第一个字符。 使用方法:快捷键gg 8. 移动到文件尾(G) 将光标移动到文件的最后一行第一个字符。 使用方法:快捷键G 9. 移动到指定字符(f/F) f向右移动到指定字符,F向左移动到指定字符。 使用方法: f{char}:向前移动到指定字符 F{char}:向后移动到指定字符 例如: 123456789原位置:def init(self): ^操作:f )def init(self): ^继续操作:F edef init(self): ^ 三、组合编辑命令(用得贼多) 把编辑命令和移动命令组合起来使用,可以实现更强大的编辑功能。 1. 删除指定区域(d) 删除当前光标位置到指定位置的字符。 使用方法: d + 移动命令 例1: 1234567891011原代码:def __init__(self): self.__startTime = time.time() self.__endTime = 0 ^操作:d $ // 删除光标位置到行尾的字符操作后:def __init__(self): self.__startTime = time.time() ^ 例2: 1234567891011原代码:def __init__(self): self.__startTime = time.time() self.__endTime = 0 ^操作:d 2 w // 删除光标位置到下2个单词词首的字符操作后:def __init__(self): self.__startTime = time.time() __endTime = 0 // 删除了self. 这被视为2个单词 ^ 例3: 12345678原代码:def __init__(self): ^ self.__startTime = time.time() self.__endTime = 0操作:d 2 d // 删除2行操作后: self.__endTime = 0 2. 改变指定区域© 删除当前光标位置到指定位置的字符,并进入插入模式。基本相当于d + 移动命令 + i,就不举例了。 3. i和a表示范围 我们经常遇到光标在一对符号之间的情况,比如在括号内部,或者在引号内部,具体位置无所谓,这时候可以使用i和a来表示范围。i表示inside, 即符号内部;a表示around,即包括符号内部和符号本身。配合d、c、y等命令使用,可以快速删除、复制、修改符号内部的内容。 例1: 123456原代码:def __init__(self): ^操作:d i ( // 删除括号内部的内容,这里还可以写成d i ),效果一样操作后:def __init__(): 例2: 123456原代码:def __init__(self): ^操作:y a ( // 复制括号内部的内容,这里还可以写成y i ),效果一样操作后:def __init__(self): // (self)这6个字符被复制了 四、搜索和定位命令 1. 搜索(/) 用于进入Vim的搜索模式,可以向前或向后搜索关键词。 使用: /搜索词 例如: 1/python -> 进入搜索模式,并匹配到第一个python 2. 向下搜索匹配(n) 在搜索模式下,可重复向下搜索匹配项。 使用: n 例如: 12/python -> 进入搜索模式,并匹配到第一个pythonn -> 找到下一个python 3. 向上搜索匹配(N) 在搜索模式下,可重复向上搜索匹配项。 使用: N 例如: 12/python -> 进入搜索模式,并匹配到第一个pythonN -> 找到上一个python 4. 书签功能(m) 命令 m[a-zA-Z] 命令会用选定的字母标记当前光标所在位置。 m 可以理解为 mark 使用: m+标记 -> 做标记 `+标记 -> 跳转到标记处 例如: 12345678910111213141516操作前:class StopWatch: ^ def __init__(self): self.__startTime = time.time() self.__endTime = 0 def start(self): self.__startTime = time.time() def stop(self): self.__endTime = time.time()操作1: ma // 将光标位置标记为 a操作2: G // 跳转到文件最后一行操作3: `a // 跳转到 a 标记处操作后:光标回到原来位置 五、多窗口命令 1. 窗口拆分(vs/sp) vs垂直拆分窗口(v表示vertical),sp水平拆分窗口。 vs的效果是将当前窗口分为两个垂直窗口,sp的效果是将当前窗口分为两个水平窗口。 2. 快速窗口跳转(Ctrl+w+w) 一般我们最多也就开个2、3个窗口,Ctrl+w+w可以在窗口间快速跳转。 六、Visual模式 Visual模式就相当于普通编辑器的选中功能,可以高亮选中文本,再进行编辑操作。 1. 进入Visual模式(v) 按下v键进入Visual模式,高亮当前光标所在字符。 2. 选中行(V) 按下shift+v键可直接选中整行。 3. 选中块(Ctrl+v) 按Ctrl+v可实现块选择, 即选中一个矩形区域内的字符。 4. 编辑操作 Visual模式下选中合适的区域,配合一些编辑命令进行编辑操作, 可以批量修改选中文本。常用的组合命令举例: 123v + d : 删除选中文本v + y : 复制选中文本v + c : 修改选中文本 七、文件操作命令 1. 打开文件(e) e可以在Vim中打开指定文件。 使用 :e 文件名 2. 保存文件(:w) :w可以保存当前文件。 3. 退出(:q) :q可以退出vim。 一般是和:w配合使用,先保存再退出,:wq可以合并为:x。 内容很长很干,慢慢练吧兄弟。","categories":[{"name":"Linux","slug":"Linux","permalink":"https://ben-xj.github.io/categories/Linux/"}],"tags":[{"name":"vim","slug":"vim","permalink":"https://ben-xj.github.io/tags/vim/"}]},{"title":"一文搞懂Python排序:sorted() vs list.sort()","slug":"python-sorted","date":"2023-07-23T02:13:34.000Z","updated":"2023-07-23T08:35:52.000Z","comments":true,"path":"2023/07/23/python-sorted/","link":"","permalink":"https://ben-xj.github.io/2023/07/23/python-sorted/","excerpt":"","text":"Python排序详解:sorted() vs list.sort() 在Python中排序数据时,我们通常会使用sorted()和list.sort()这两个函数。它们存在一些关键的区别,适用于不同的场景。本文将通过详细的示例阐述两者的差异,以及何时使用哪个函数更加合适。 list.sort() 的特点 list.sort()是列表对象的一个方法,作用是就地(in-place)对列表进行排序。也就是说,它直接修改了原列表,没有返回值: 123nums = [3, 1, 2]nums.sort() print(nums) # [1, 2, 3] list.sort()支持一些可选参数来自定义排序: reverse=True 倒序排序 key 根据自定义函数结果排序 例如: 1234567nums = [3,-2,1]nums.sort(reverse=True)print(nums) # [3, 1, -2] 倒序nums.sort(key=abs)print(nums) # [1,-2, 3] 根据绝对值排序 list.sort()只能用于列表,不能用于其他可迭代对象。它通过下标排序,稳定性不确定,相同元素的相对顺序可能会改变。例如: 1234567891011121314151617181920212223from dataclasses import dataclass@dataclassclass User: name: str age: intusers = [ User('John', 25), User('Alice', 25), User('Bob', 24)]# 原始顺序为 John, Alice, Bobusers.sort(key=lambda x: x.age) print([u.name for u in users])# 结果可能为:# ['Bob', 'John', 'Alice']# 或者# ['Bob', 'Alice', 'John'] 按照年龄排序,John和Alice的年龄相同,但是这是两个不同的人,list.sort()可能不会保留原顺序。 list.sort()主要适用于:就地排序列表,不需要保留原顺序。 sorted() 的特点 sorted()是一个全局的内置函数,可以对任意可迭代对象进行排序,返回一个新列表。原列表不变: 12345nums = [3, 1, 2] new_nums = sorted(nums)print(new_nums) # [1, 2, 3]print(nums) # [3, 1, 2] 没变 sorted()也可以接受 reverse 和 key 自定义排序: 12345new_nums = sorted(nums, reverse=True) # 倒序print(new_nums) # [3, 2, 1]new_nums = sorted(nums, key=str) # 按字符串排序print(new_nums) # [1, 2, 3] sorted() 是一个稳定排序,相同元素的相对顺序会保持不变。 主要适用于: 需要保留原列表顺序的场景 对不可变对象如 tuple 进行排序 链式调用多个排序操作 需要自定义排序逻辑的场景 例如: 123456789101112131415161718from pprint import pprintusers = [{'name':'John', 'age':20}, {'name':'John', 'age':15}, {'name':'Lisa', 'age':25}]# 根据年龄排序by_age = sorted(users, key=lambda u: u['age']) # 再根据名字排序by_age_name = sorted(by_age, key=lambda u: u['name'])pprint(by_age_name)# ------------- Result -----------# [{'age': 15, 'name': 'John'},# {'age': 20, 'name': 'John'},# {'age': 25, 'name': 'Lisa'}] 使用 attrgetter 和 itemgetter 代替 lambda 函数 在 key 参数中传入 lambda 函可以实现自定义排序,但是使用 operator 模块的 attrgetter 和 itemgetter 可以使代码更简洁: itemgetter 其实就是重载了[]下标操作符,可以用于获取序列的下标和字典的键: 123456789from pprint import pprintfrom operator import itemgetterusers = [{'name':'John', 'age':20}, {'name':'John', 'age':15}, {'name':'Lisa', 'age':25}]by_age_name = sorted(users, key=itemgetter( 'name','age'))pprint(by_age_name) attrgetter 可以用于获取对象属性: 123456789101112from operator import attrgetterfrom pprint import pprintusers = [ User('John', 25), User('Alice', 25), User('Bob', 24)]# 根据年龄属性排序 by_age = sorted(users, key=attrgetter('age'))pprint(by_age) 它们提供了一种更优雅和高效的提取对象属性和字典键的方式。 attrgetter 和 itemgetter 性能如何? 我们可以写个简单的测试来比较一下在sorted()中使用lambda和attrgetter的性能。 1234567891011121314151617181920212223242526272829303132333435import timeitclass Person: def __init__(self, name, age): self.name = name self.age = agepeople = [ Person("Diana", 40), Person("Frank", 45), Person("Alice", 30), Person("Bob", 25), Person("Charlie", 35), Person("Eve", 20)]# Using lambda function to sort by 'age'lambda_time = timeit.timeit( stmt="sorted(people, key=lambda person: person.age)", setup="from __main__ import people", number=100000)# Using attrgetter to sort by 'age'attrgetter_time = timeit.timeit( stmt="sorted(people, key=attrgetter('age'))", setup="from __main__ import people; from operator import attrgetter", number=100000)print(f"Using lambda: {lambda_time:.6f} seconds")print(f"Using attrgetter: {attrgetter_time:.6f} seconds")# Using lambda: 0.055244 seconds# Using attrgetter: 0.047022 seconds 可以看到,使用 attrgetter 的性能比 lambda 函数更好,因为底层是C语言实现的。 总结 list.sort() 用于就地排序列表,更简单直接 sorted() 更通用更灵活,可以保留原顺序 attrgetter 和 itemgetter 可以简化 key 函数,同时提高性能 根据实际需求选择合适的排序函数,可以让代码更高效和可读!","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"built-ins","slug":"built-ins","permalink":"https://ben-xj.github.io/tags/built-ins/"},{"name":"sorting","slug":"sorting","permalink":"https://ben-xj.github.io/tags/sorting/"}]},{"title":"深入浅出Python生成器","slug":"Python生成器","date":"2023-07-22T08:26:21.000Z","updated":"2023-07-22T08:28:04.000Z","comments":true,"path":"2023/07/22/Python生成器/","link":"","permalink":"https://ben-xj.github.io/2023/07/22/Python%E7%94%9F%E6%88%90%E5%99%A8/","excerpt":"Understanding Python Generators and Efficient Sequences Introduction Python’s generators are a powerful feature that allows developers to create memory-efficient and lazy-evaluated sequences. Unlike regular sequences, such as lists, generators produce values on-the-fly, making them ideal for processing large datasets or infinite sequences. In this article, we will explore the concept of generators in Python, how to create them using generator functions and comprehensions, and understand their benefits over traditional sequences.","text":"Understanding Python Generators and Efficient Sequences Introduction Python’s generators are a powerful feature that allows developers to create memory-efficient and lazy-evaluated sequences. Unlike regular sequences, such as lists, generators produce values on-the-fly, making them ideal for processing large datasets or infinite sequences. In this article, we will explore the concept of generators in Python, how to create them using generator functions and comprehensions, and understand their benefits over traditional sequences. 1. What are Generators? Generators are a special type of iterable in Python that use lazy evaluation to generate values one at a time. They are defined using functions that contain the yield keyword. When a generator function is called, it returns a generator object without executing the entire function body. Instead, the values are generated only when requested through iteration. 2. Generator Functions Generator functions are the primary method of creating generators. By defining a function with the yield keyword, we can produce values on-the-fly, reducing memory consumption and improving performance. Here’s an example of a generator function that yields squares of numbers: 1234def squares_generator(limit): for i in range(1, limit + 1): yield i ** 2 Usage: 1234567# Create the generatorgen = squares_generator(5)# Iterate over the generator and print the squaresfor square in gen: print(square) Output: 123451491625 3. Using Generators We can utilize generators in various ways. For instance, we can iterate over them using a for loop, access elements using next(), or convert them into a list using list(). Since generators yield elements on demand, they are more memory-efficient and faster for large datasets. Usage: 1234567891011# Create the generatorgen = squares_generator(5)# Using next() to access elements one by oneprint(next(gen)) # Output: 1print(next(gen)) # Output: 4# Convert the generator to a listsquare_list = list(gen)print(square_list) # Output: [9, 16, 25] 4. Generator Comprehensions Similar to list comprehensions, Python offers generator comprehensions using parentheses instead of square brackets. Generator comprehensions allow us to create generators in a more concise and readable manner. Here’s an example: 123# Create a generator for even numbers from 1 to 10even_numbers_gen = (x for x in range(1, 11) if x % 2 == 0) Usage: 1234# Iterate over the generator and print the even numbersfor even_number in even_numbers_gen: print(even_number) Output: 12345246810 5. Infinite Series with Generators Generators shine when dealing with infinite sequences, such as the Fibonacci series. Since generators produce values on-the-fly, they can generate an infinite sequence without consuming excessive memory. For example: 123456def fibonacci_generator(): a, b = 0, 1 while True: yield a a, b = b, a + b Usage: 1234567# Create the Fibonacci generatorfib_gen = fibonacci_generator()# Print the first 10 Fibonacci numbersfor _ in range(10): print(next(fib_gen)) Output: 123456789100112358132134 6. Differences between range and Generators Although the range function in Python is often used in loops, it does not return a generator by default. However, you can convert a range object into a generator using generator comprehensions or the iter() function. While range objects are efficient for representing ranges of integers, generators are more flexible and memory-efficient for handling dynamic or infinite sequences. Conclusion Python generators offer an elegant and memory-efficient approach to deal with sequences, especially when working with large datasets or infinite series. They are defined using generator functions or comprehensions, allowing developers to produce values on-the-fly as they are needed. By leveraging generators in your Python code, you can optimize memory consumption and improve the performance of your applications. Understanding generators is a valuable skill for any Python developer looking to handle data streams or create efficient sequences in their programs.","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"generator","slug":"generator","permalink":"https://ben-xj.github.io/tags/generator/"}]},{"title":"Linux/Unix常用命令: grep","slug":"Grep","date":"2023-05-16T12:10:08.000Z","updated":"2023-05-16T12:34:44.000Z","comments":true,"path":"2023/05/16/Grep/","link":"","permalink":"https://ben-xj.github.io/2023/05/16/Grep/","excerpt":"grep是Linux/Unix系统中非常常用的命令,它用来在文本文件中查找指定的模式并输出文本行。 以下均以or-tools文件夹中的 Dependencies.txt文件为例,其内容如下:","text":"grep是Linux/Unix系统中非常常用的命令,它用来在文本文件中查找指定的模式并输出文本行。 以下均以or-tools文件夹中的 Dependencies.txt文件为例,其内容如下: 1234567891011Protobuf=v21.12abseil-cpp=20230125.0Cbc=2.10.7Cgl=0.60.5Clp=1.17.7Clp=1.17.7Osi=0.108.7CoinUtils=2.11.6Eigen=3.4.0Re2=2021-11-01Scip=v803 以下是grep命令的常用用法: 0. 递归查找 1grep -r pattern directory 使用-r选项可以递归查找指定目录下所有文件,而不仅仅是当前目录。 例:我们在or-tools外层文件夹中执行以下命令: 1grep -r Clp=1.17.7 or-tools/ 即可找到Clp=1.17.7出现的两行。 接下来我们进入or-tools文件夹,直接对Dependencies.txt文件进行操作。 1. 简单模式匹配 1grep pattern file 这个最简单的用法,会在指定的文件中查找匹配pattern的所有行。 例:我们找到所有包含Clp的行。 1grep Clp Dependencies.txt 2. 忽略大小写匹配 1grep -i pattern file 使用-i选项可以忽略大小写来查找匹配。 例:我们找到所有包含clp的行,忽略大小写。 1grep -i clp Dependencies.txt 3. 显示匹配行数 1grep -c pattern file 使用-c选项可以统计匹配的行数。 例:我们统计一下Clp出现的次数。 1grep -c Clp Dependencies.txt 不同的选项可以组合使用,比如我们可以忽略大小写,统计一下clp出现的次数。 1grep -ci clp Dependencies.txt 4. 输出不匹配的行 1grep -v pattern file 使用-v选项可以输出不匹配pattern的所有行。 例:我们输出一下不包含Clp的行。 1grep -v Clp Dependencies.txt 5. 输出匹配行的前后若干行 1grep -A n -B m pattern file 使用-A和-B选项可以输出匹配pattern的行的前后n和m行。而-C选项则可以输出前后n行。 例:我们输出一下包含Clp的行的前后一行。 1grep -A 1 -B 1 Clp Dependencies.txt 还有很多其他选项和使用方法,可以通过 man grep命令查看更多帮助和用法。","categories":[{"name":"Linux","slug":"Linux","permalink":"https://ben-xj.github.io/categories/Linux/"}],"tags":[{"name":"linux","slug":"linux","permalink":"https://ben-xj.github.io/tags/linux/"},{"name":"grep","slug":"grep","permalink":"https://ben-xj.github.io/tags/grep/"}]},{"title":"Powering Up Your Code: Parallel Programming with three Python packages","slug":"python parallel tools","date":"2023-05-05T13:44:10.000Z","updated":"2023-05-14T14:15:48.000Z","comments":true,"path":"2023/05/05/python parallel tools/","link":"","permalink":"https://ben-xj.github.io/2023/05/05/python%20parallel%20tools/","excerpt":"Introduction Parallel computing is a crucial aspect of modern-day computing that enables programs to perform computations faster and more efficiently. Python has several libraries that allow developers to write parallel programs, including Joblib, Ray, and Multiprocessing. In this blog post, we will explore the usage of these libraries and how they can help write efficient parallel programs.","text":"Introduction Parallel computing is a crucial aspect of modern-day computing that enables programs to perform computations faster and more efficiently. Python has several libraries that allow developers to write parallel programs, including Joblib, Ray, and Multiprocessing. In this blog post, we will explore the usage of these libraries and how they can help write efficient parallel programs. Choice 1: Joblib Joblib is a Python library that allows for easy parallelization of CPU-bound tasks. It provides a simple and lightweight interface to parallelize functions using threads or processes. Joblib is easy to use and requires no prior knowledge of multi-processing. To use Joblib, you need to import the Parallel and delayed functions from the joblib module. The Parallel function is used to create a parallel object, and the delayed function is used to specify which function to parallelize. Here is an example: 1234567891011from joblib import Parallel, delayedimport time def compute_square(n): time.sleep(1) return n ** 2if __name__ == '__main__': inputs = range(10) results = Parallel(n_jobs=2)(delayed(compute_square)(i) for i in inputs) print(results) In the example above, we define a function compute_square that takes an input and returns its square. We then use Joblib’s Parallel function to create a parallel object with two parallel jobs and apply it to the compute_square function using the delayed function. Finally, we print the results. Also, joblib supports several backends for parallel processing. Here are some of the available backends for joblib Parallel: “loky” - The default backend that is recommended for most users. It uses the “Loky” process-based backend and allows for inter-process communication. “threading” - This backend uses Python’s built-in threading module to run tasks in parallel. “multiprocessing” - This backend uses Python’s built-in multiprocessing module, which spawns new processes to execute tasks in parallel. “dask” - This backend uses the Dask library to distribute tasks across multiple nodes in a cluster or on a single machine. “ray” - This backend uses the Ray library to parallelize functions across multiple cores or multiple machines. Choice 2: Ray Ray is a powerful Python library for building distributed applications. It makes it easy to parallelize Python code across multiple CPUs or GPUs. Ray provides a simple to use API for parallelizing embarrassingly parallel and data-intensive workloads. To use Ray, you need to import the ray module and use the ray.remote decorator to decorate a function that you want to parallelize. When you call the function, Ray will automatically create a worker process to execute the function. Here is an example: 1234567891011121314import rayimport timeray.init()@ray.remotedef compute_square(n): time.sleep(1) return n ** 2if __name__ == '__main__': inputs = [1, 2, 3, 4, 5] results = ray.get([compute_square.remote(i) for i in inputs]) print(results) In the example above, we define a compute_square function that will sleep for one second and return the square of an input number. We use the @ray.remote decorator to specify that the function is going to be executed remotely. In the main block, we call the remote function using the ray.get method, and finally, we print the results. Choice 3: Multiprocessing Multiprocessing is a Python library that allows developers to write parallel programs using processes. It provides a simple and easy-to-use interface to spawn multiple processes to take advantage of multi-core CPUs. To use Multiprocessing, you need to import the multiprocessing module, and then create a Process object for each process you want to spawn. In each Process object, you pass the function you want to execute, along with its arguments. Here is an example: 1234567891011121314151617181920212223from multiprocessing import Processfrom multiprocessing import Valueimport timedef compute_square(n, result: Value): time.sleep(1) result = n**2if __name__ == '__main__': inputs = [1, 2, 3, 4, 5] results = [Value('f', 0.) for i in range(5)] processes = [ Process(target=compute_square, args=(inputs[i], results[i])) for i in range(5) ] for p in processes: p.start() for p in processes: p.join() print([v.value for v in results]) In the example above, we define a compute_square function that will sleep for one second and return the square of an input number. In the main block, we create a Process object for each input number, and then we start each process using the start method. Finally, we wait for all processes to complete using the join method. Conclusion In this blog post, we explored three Python libraries, Joblib, Ray, and Multiprocessing that you can use to write parallel programs in Python. These libraries provide a simple and easy-to-use interface to parallelize computations, which can help you write programs that run faster and more efficiently. When deciding which library to use, it’s essential to consider the type of program you’re writing and the specific requirements of your application.","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"parallel programming","slug":"parallel-programming","permalink":"https://ben-xj.github.io/tags/parallel-programming/"},{"name":"joblib","slug":"joblib","permalink":"https://ben-xj.github.io/tags/joblib/"},{"name":"ray","slug":"ray","permalink":"https://ben-xj.github.io/tags/ray/"},{"name":"multiprocessing","slug":"multiprocessing","permalink":"https://ben-xj.github.io/tags/multiprocessing/"}]},{"title":"MapStruct and Lombok not working together","slug":"MapStruct-and-Lombok-not-working-together","date":"2023-05-05T12:49:56.000Z","updated":"2023-05-05T13:14:08.000Z","comments":true,"path":"2023/05/05/MapStruct-and-Lombok-not-working-together/","link":"","permalink":"https://ben-xj.github.io/2023/05/05/MapStruct-and-Lombok-not-working-together/","excerpt":"Problem When attempting to learn mapstruct as a new tool, I discovered that it does not seamlessly integrate with lombok annotations such as @AllArgsConstructor, as it suggests that the constructor does not exist. However, once I manually create the constructor, everything operates as intended. Clearly, the lombok annotation is not functioning as expected.","text":"Problem When attempting to learn mapstruct as a new tool, I discovered that it does not seamlessly integrate with lombok annotations such as @AllArgsConstructor, as it suggests that the constructor does not exist. However, once I manually create the constructor, everything operates as intended. Clearly, the lombok annotation is not functioning as expected. Cause The reason why it does not work is because Maven only uses the MapStruct processor and not the Lombok one. The annotationProcessorPaths tells maven which processors it should use. Simple solution: add maven dependency: Don’t forget the lombok-mapstruct-binding dependency 123456789101112131415<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${org.mapstruct.version}</version></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version></dependency> add necessary annotation processor paths to maven plugin: add lombok related paths 123456789101112131415161718192021222324252627<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <!-- depending on your project --> <target>1.8</target> <!-- depending on your project --> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </path> <!-- other annotation processors --> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.26</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> </configuration></plugin> And, voila! Everything’s working fine now. ref https://stackoverflow.com/questions/47676369/mapstruct-and-lombok-not-working-together","categories":[{"name":"Java","slug":"Java","permalink":"https://ben-xj.github.io/categories/Java/"}],"tags":[{"name":"java","slug":"java","permalink":"https://ben-xj.github.io/tags/java/"},{"name":"lombok","slug":"lombok","permalink":"https://ben-xj.github.io/tags/lombok/"},{"name":"mapstruct","slug":"mapstruct","permalink":"https://ben-xj.github.io/tags/mapstruct/"},{"name":"maven","slug":"maven","permalink":"https://ben-xj.github.io/tags/maven/"}]},{"title":"pip包管理基本使用","slug":"pip包管理","date":"2023-04-29T14:06:56.000Z","updated":"2023-04-29T14:13:00.000Z","comments":true,"path":"2023/04/29/pip包管理/","link":"","permalink":"https://ben-xj.github.io/2023/04/29/pip%E5%8C%85%E7%AE%A1%E7%90%86/","excerpt":"","text":"1. 镜像加速 在我们使用pip进行Python包安装时,如果我们需要使用镜像站来加速下载和安装,可以执行以下命令: 1.1 临时使用 1pip install -i https://mirrors.sjtug.sjtu.edu.cn/pypi/web/simple some-package 需要注意的是,simple不能少,而且是https而不是http。 1.2 长期使用 如果我们希望将该镜像站设为默认的源地址,可以先升级pip到最新版本,然后执行以下命令: 12pip install pip -Upip config set global.index-url https://mirrors.sjtug.sjtu.edu.cn/pypi/web/simple 如果我们连接pip默认源的网络连接较差,也可以使用以下命令临时使用这个镜像站来升级pip: 1pip install -i https://mirrors.sjtug.sjtu.edu.cn/pypi/web/simple pip -U 2. 依赖导入和导出 在Python项目中,我们通常会使用多个第三方包,这些包可以通过pip进行安装。而在开发过程中,我们可能需要将当前环境中的所有包信息导出到文件中,或从文件中读取所有包信息并安装这些包。 我们可以使用以下两个命令来实现这个功能: 将当前环境中的所有包信息输出到文件中: 1pip freeze > requirements.txt 使用一个文件安装所有包信息: 1pip install -r requirements.txt 通过这两个命令,我们可以更方便地管理第三方包,提高项目开发的效率。","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"pip","slug":"pip","permalink":"https://ben-xj.github.io/tags/pip/"}]},{"title":"From C++ to Python: How to Use Pybind11 for Cross-Language Interoperability","slug":"pybind11 basic","date":"2023-04-29T12:44:10.000Z","updated":"2023-04-29T13:13:42.000Z","comments":true,"path":"2023/04/29/pybind11 basic/","link":"","permalink":"https://ben-xj.github.io/2023/04/29/pybind11%20basic/","excerpt":"Introduction Pybind11 is a lightweight header-only library that allows you to expose C++ functions and classes to Python. It simplifies the process of creating Python bindings for C++ code and allows seamless interoperability between C++ and Python. In this article, we will discuss how to use Pybind11 to use C++ functions and classes in Python with a runnable example code.","text":"Introduction Pybind11 is a lightweight header-only library that allows you to expose C++ functions and classes to Python. It simplifies the process of creating Python bindings for C++ code and allows seamless interoperability between C++ and Python. In this article, we will discuss how to use Pybind11 to use C++ functions and classes in Python with a runnable example code. Prerequisites To follow along with this article, you should have: Basic knowledge of C++ and Python Basic knowledge of Python’s C API Installation Pybind11 can be installed via pip by running the following command: 1pip install pybind11 If you prefer to install Pybind11 manually, you can download it from GitHub and build it using CMake. Example Let’s say we have a simple C++ class called Calculator that has two member functions add and subtract: 12345678910class Calculator {public: Calculator() {} int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; }}; We would like to create a Python wrapper for this class so that we can use it in Python. Here’s how we can do this using Pybind11: 1234567891011121314151617181920#include <pybind11/pybind11.h>#include <pybind11/stl.h>class Calculator {public: Calculator() {} int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; }};PYBIND11_MODULE(calculator, m) { pybind11::class_<Calculator>(m, "Calculator") .def(pybind11::init<>()) .def("add", &Calculator::add) .def("subtract", &Calculator::subtract);} Explanation Let’s break down this code. We start by including the pybind11 header file. Then, we define our Calculator class as before. Next, we use the PYBIND11_MODULE macro to create a Python module called calculator. This macro takes two arguments: the name of the module and an instance of pybind11::module class that represents the module. In this case, we define the module as m. We then use the pybind11::class_ template to define the Calculator class as a Python class. The first argument to pybind11::class_ is the Python name of the class ("Calculator"). The second argument is the C++ class that we want to expose (Calculator). We then define the add and subtract member functions using the .def method. Finally, we need to build this module into a shared library so that we can load it into Python. We can do this using CMake: 1234567cmake_minimum_required(VERSION 3.0)project(calculator)find_package(pybind11 REQUIRED)pybind11_add_module(calculator calculator.cpp) This will build a shared library called calculator.so (on Linux) or calculator.pyd (on Windows). We can now load this module into Python and use it like any other Python module: 12345import calculatorc = calculator.Calculator()print(c.add(1, 2)) # Output: 3print(c.subtract(2, 1)) # Output: 1 Conclusion In this article, we have learned how to use Pybind11 to create Python bindings for C++ classes and functions. Pybind11 simplifies the process of creating Python bindings and allows seamless interoperability between C++ and Python. By following the example code provided in this article, you should be able to start creating your own Python bindings for your C++ code.","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"cpp","slug":"cpp","permalink":"https://ben-xj.github.io/tags/cpp/"},{"name":"pybind11","slug":"pybind11","permalink":"https://ben-xj.github.io/tags/pybind11/"}]},{"title":"pulp不同求解器设置参数","slug":"pulp不同求解器设置参数","date":"2023-04-26T12:23:27.000Z","updated":"2023-04-28T14:55:12.000Z","comments":true,"path":"2023/04/26/pulp不同求解器设置参数/","link":"","permalink":"https://ben-xj.github.io/2023/04/26/pulp%E4%B8%8D%E5%90%8C%E6%B1%82%E8%A7%A3%E5%99%A8%E8%AE%BE%E7%BD%AE%E5%8F%82%E6%95%B0/","excerpt":"Pulp provides an easy-to-use syntax and interface for formulating and solving LP problems, including support for a wide range of problem types and solvers. It is widely used in operations research, supply chain management, logistics, and other industries for making optimization decisions.","text":"Pulp provides an easy-to-use syntax and interface for formulating and solving LP problems, including support for a wide range of problem types and solvers. It is widely used in operations research, supply chain management, logistics, and other industries for making optimization decisions. 1234567891011121314151617181920212223from pulp import *# Use CBC solverprob.solve(PULP_CBC_CMD(msg=True, timeLimit=1, options=["startalg", "barrier"]))# Use cplex solverprob.solve( CPLEX_CMD(msg=True, timeLimit=1, # interactive cmd options=["set emphasis mip 3", "set barrier algorithm 3"]))# Use gurobi solverprob.solve( GUROBI_CMD(msg=True, timeLimit=1, threads=4, options=[("Method", 2), ("MIPGap", 0.2)]))# Use scip solver, latest version of pulp only# support single thread onlyprob.solve(SCIP_CMD(msg=True, timeLimit=1, options=["branching/clamp=0.4"]))","categories":[{"name":"优化","slug":"优化","permalink":"https://ben-xj.github.io/categories/%E4%BC%98%E5%8C%96/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"pulp","slug":"pulp","permalink":"https://ben-xj.github.io/tags/pulp/"},{"name":"solver","slug":"solver","permalink":"https://ben-xj.github.io/tags/solver/"},{"name":"mip","slug":"mip","permalink":"https://ben-xj.github.io/tags/mip/"}]},{"title":"Accelerate Your NumPy Matrix Operations with Cython","slug":"Accelerate Your NumPy Matrix Operations with Cython","date":"2023-03-31T00:44:10.000Z","updated":"2023-04-28T14:54:50.000Z","comments":true,"path":"2023/03/31/Accelerate Your NumPy Matrix Operations with Cython/","link":"","permalink":"https://ben-xj.github.io/2023/03/31/Accelerate%20Your%20NumPy%20Matrix%20Operations%20with%20Cython/","excerpt":"Introduction Python is widely used for scientific computing, data analysis, and machine learning tasks due to its ease of use and rich ecosystem. NumPy, a popular library for numerical computations in Python, provides a powerful array object and a variety of functions to operate on these arrays. However, performance can sometimes be a bottleneck when working with large datasets or complex operations.","text":"Introduction Python is widely used for scientific computing, data analysis, and machine learning tasks due to its ease of use and rich ecosystem. NumPy, a popular library for numerical computations in Python, provides a powerful array object and a variety of functions to operate on these arrays. However, performance can sometimes be a bottleneck when working with large datasets or complex operations. Cython, a superset of the Python language, allows you to write Python code with optional C-like syntax and static types, which can then be compiled to C and executed as a native extension. This can lead to significant performance improvements compared to pure Python code. In this blog post, we will demonstrate how to use Cython with NumPy to optimize matrix operations, and compare the performance of pure Python and Cython-accelerated implementations. Prerequisites To follow along with the examples in this post, make sure you have both Cython and NumPy installed: pip install cython numpy Example: Element-wise Matrix Multiplication Let’s start by implementing element-wise matrix multiplication using Cython with NumPy. Step 1: Create a Cython file Create a Cython file called matrix_mult_cython.pyx with the following code: 123456789101112131415# matrix_mult_cython.pyximport numpy as npcimport numpy as cnpcpdef cnp.ndarray[double, ndim=2] elementwise_multiply(cnp.ndarray[double, ndim=2] A, cnp.ndarray[double, ndim=2] B): cdef int nrows = A.shape[0] cdef int ncols = A.shape[1] cdef cnp.ndarray[double, ndim=2] result = np.zeros((nrows, ncols), dtype=np.float64) cdef int i, j for i in range(nrows): for j in range(ncols): result[i, j] = A[i, j] * B[i, j] return result Note: In Cython, the cimport statement is used to import C-level declarations from other Cython modules or libraries. It is similar to the regular Python import statement, but it specifically deals with importing C-level functions, types, and other constructs that are not part of the Python runtime. In the provided example, the line cimport numpy as cnp is used to import the Cython definitions for the NumPy library. This allows us to interact with NumPy arrays more efficiently, leading to performance improvements. The cnp alias is used in the same way as np for regular Python NumPy imports, but it refers to the C-level NumPy constructs. Step 2: Compile the Cython module Create a setup.py file to build the Cython module: 123456789101112131415# setup.pyfrom setuptools import setup, Extensionfrom Cython.Build import cythonizeimport numpy as npext_modules = [ Extension("matrix_mult_cython", ["matrix_mult_cython.pyx"], include_dirs=[np.get_include()]) # Add the NumPy header files]setup( name='Matrix Multiplication Cython Example', ext_modules=cythonize(ext_modules), zip_safe=False,) Compile the Cython module by running the following command in your terminal: python setup.py build_ext --inplace Note: The zip_safe parameter is an option indicating whether the package can be safely installed and run from a zip archive without being extracted to the file system. When zip_safe is set to True, it means that the package can be installed and run directly from a zip archive without any issues. However, when set to False, it indicates that the package needs to be extracted to the file system before being executed. In the case of Cython-compiled extensions, it is generally recommended to set zip_safe=False. This is because Cython generates compiled C extensions (shared libraries or DLLs) that need to be accessed by the operating system’s dynamic loader, which often cannot read files from a zip archive. Step 3: Use the Cython module in your Python code Now, you can use the compiled Cython module in your Python code: 12345678910111213# main.pyimport numpy as npfrom matrix_mult_cython import elementwise_multiplydef main(): A = np.random.rand(1000, 1000) B = np.random.rand(1000, 1000) result = elementwise_multiply(A, B) print(result)if __name__ == "__main__": main() Run your Python code: python main.py Performance Comparison To compare the performance before and after using Cython, we can implement the same element-wise multiplication using pure Python with NumPy and then measure the execution time for both the pure Python and Cython-accelerated implementations. Pure Python Implementation Add a pure Python implementation of element-wise multiplication in main.py: 1234567891011def elementwise_multiply_python(A, B): assert A.shape == B.shape, "Both matrices must have the same shape." nrows, ncols = A.shape result = np.zeros((nrows, ncols), dtype=np.float64) for i in range(nrows): for j in range(ncols): result[i, j] = A[i, j] * B[i, j] return result Timing the Implementations Add timing code to main.py to measure the execution time of both the pure Python and Cython-accelerated implementations: 1234567891011121314151617181920212223import timedef main(): A = np.random.rand(1000, 1000) B = np.random.rand(1000, 1000) # Time the pure Python implementation start_python = time.time() result_python = elementwise_multiply_python(A, B) end_python = time.time() elapsed_python = end_python - start_python # Time the Cython-accelerated implementation start_cython = time.time() result_cython = elementwise_multiply(A, B) end_cython = time.time() elapsed_cython = end_cython - start_cython print(f"Pure Python: {elapsed_python:.5f} seconds") print(f"Cython-accelerated: {elapsed_cython:.5f} seconds")if __name__ == "__main__": main() Run the Python code: python main.py You should see the execution time of both the pure Python implementation and the Cython-accelerated implementation. Typically, the Cython-accelerated implementation should be significantly faster, as it leverages C-level array access and efficient looping. This is the result on my machine: Conclusion In this blog post, we demonstrated how to use Cython with NumPy to optimize matrix operations, specifically element-wise matrix multiplication. We also compared the performance of pure Python and Cython-accelerated implementations, showing that Cython can provide significant performance improvements. Cython is a powerful tool for optimizing Python code that relies on numerical computations, especially when used in conjunction with libraries like NumPy. By taking advantage of C-level array access and efficient looping, you can achieve substantial speedups in your scientific computing, data analysis, and machine learning tasks.","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"cython","slug":"cython","permalink":"https://ben-xj.github.io/tags/cython/"}]},{"title":"2. 基于Django Rest框架构建API","slug":"基于Django-Rest框架构建API","date":"2022-12-31T09:58:24.000Z","updated":"2023-04-26T14:05:28.000Z","comments":true,"path":"2022/12/31/基于Django-Rest框架构建API/","link":"","permalink":"https://ben-xj.github.io/2022/12/31/%E5%9F%BA%E4%BA%8EDjango-Rest%E6%A1%86%E6%9E%B6%E6%9E%84%E5%BB%BAAPI/","excerpt":"1. 什么是API? 简单看一下百科的解释: API之主要目的是提供应用程序与开发人员以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实现。API是一种接口,故而是一种抽象。 应用程序接口(英语:ApplicationProgrammingInterface,简称:API),又称为应用编程接口,就是软件系统不同组成部分衔接的约定。","text":"1. 什么是API? 简单看一下百科的解释: API之主要目的是提供应用程序与开发人员以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。提供API所定义的功能的软件称作此API的实现。API是一种接口,故而是一种抽象。 应用程序接口(英语:ApplicationProgrammingInterface,简称:API),又称为应用编程接口,就是软件系统不同组成部分衔接的约定。 简单来说,我们写程序是为了帮用户完成某件事,用户不需要知道我们是怎么完成的。对于用户来说,只需发个指令,譬如,“我想导航到萧山”,那么程序能把路线告诉用户即可。API是什么呢,就是接受用户指令,并返回程序结果的一个工具。 2. 安装djangorestframework包 作为网络开发程序员,我们要为用户提供API 并告诉用户如何使用我们的软件。用于开发API的工具有很多,在Django项目中,一般使用djangorestframework包来开发API。 djangorestframework包直接使用pip安装即可 1pip install djangorestframework 3. 建立Django项目 在本文中,我们通过建立一个电影网站,让用户 获取、修改以及增加新的电影信息,以熟悉Django API的构建。 可以参考[[基本Django项目构建]]一文建立起项目,简单列举一下相关命令。 12345django-admin startproject movie_apicd movie_apipython manage.py startapp movie # 这里记得在配置文件中加入moviepython manage.py migratepython manage.py runserver 这样就可以跑起来一个空项目了。 因为本文只关注API的构建,这里只建立一个数据模型,其他的网页浏览视图、模板就不做了。 3.1 建立Model 在movie/models.py中建立电影数据类, 123456789from django.db import models# Create your models here.class Movie(models.Model): name = models.CharField(max_length=200) year = models.IntegerField() def __str__(self): return f'{self.name} ({self.year})' 对数据模型更改后,要进行迁移 12python manage.py makemigrationspython manage.py migrate 使用python manage.py shell进行项目的shell添加一些数据 12345678910111213>>> from movie.models import Movie>>> Movie.objects.create(name="The Shawshank Redemption", year=1994)<Movie: The Shawshank Redemption (1994)>>>> Movie.objects.create(name="The Godfather", year=1972)<Movie: The Godfather (1972)>>>> Movie.objects.create(name="The Dark Knight", year=2008)<Movie: The Dark Knight (2008)>>>> Movie.objects.create(name='The Godfather: Part II', year=1974)<Movie: The Godfather: Part II (1974)>>>> Movie.objects.create(name='12 Angry Men', year=1957)<Movie: 12 Angry Men (1957)>>>> Movie.objects.all()<QuerySet [<Movie: The Shawshank Redemption (1994)>, <Movie: The Godfather (1972)>, <Movie: The Dark Knight (2008)>, <Movie: The Godfather: Part II (1974)>, <Movie: 12 Angry Men (1957)>]> 4. 构建API 首先在movie_api/settings.py文件找到INSTALLED_APPS, 注册rest_framework,现在这个列表应该如下, 12345INSTALLED_APPS = [ ... # 其他已有值 'movie', 'rest_framework',] 为了避免与网站基本内容混淆,可以项目根目录下建立一个专门的api文件夹,并在其中建立一个空的__init__.py文件,表明这是一个包。 4.1 建立序列化器 我们把变量从内存中变成可存储或传输的过程称之为序列化。——廖雪峰 也就是说,从数据库中把数据读到我们的Model类型的变量中后,还要经过序列化,才能顺利传输到客户端(浏览器),供用户浏览使用。 在api文件夹下建立serializers.py文件,内容如下 1234567from rest_framework import serializersfrom movie.models import Movieclass MovieSerializer(serializers.ModelSerializer): class Meta: model = Movie fields= '__all__' 这里建立了一个Movie专用的序列化器,其中序列化的数据包括所有字段。 4.2 建立视图并绑定URL 4.2.1 获取所有电影 在api文件夹下建立views.py文件 1234567891011from rest_framework.decorators import api_viewfrom movie.models import Moviefrom .serializers import MovieSerializerfrom rest_framework.response import Response@api_view(['GET'])def get_movies(request): movies = Movie.objects.all() serializer = MovieSerializer(movies, many=True) return Response(serializer.data) 这里通过装饰器来设置请求方法,这里只是获取,用GET即可。 注意在一个普通的网站中,获取了电影列表后,应该传输给前端的模板,以供渲染,但在API中,我们进行序列化,以供传输。 然后绑定url,在api文件夹下建立urls.py文件, 123456from django.urls import pathfrom . import viewsurlpatterns = [ path('', views.get_movies, name='get_movies')] 如文章[[基本Django项目构建]]中提到的,还没有被django项目所识别,因此,需要在movie_api/urls.py文件中进行引用,以让项目进行识别。 123456from django.urls import path, includeurlpatterns = [ path('admin/', admin.site.urls), path('movies/', include('api.urls')),] 这样,运行项目后,我们就可以通过网址http://127.0.0.1:8000/movies/访问电影列表api了,效果如下: 4.2.2 新增电影 新增电影条目可以保持与电影列表的网址相同,只需要在视图中增加一个POST请求方法即可。修改api/views.py中相关函数如下, 1234567891011121314from rest_framework import status@api_view(['GET', 'POST'])def get_movies(request): if request.method == 'GET': movies = Movie.objects.all() serializer = MovieSerializer(movies, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = MovieSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 要注意的是,一旦数据有变动,要使用is_valid进行数据的验证并使用save保存,这里包括类型、长度等的验证。 再次访问网址http://127.0.0.1:8000/movies/,可以看到下方多出了一个输入框,以增加电影条目。 4.2.3 获取某个电影的信息 这里也是获取内容,与[[#4 2 1 获取所有电影]]类似,首先在api/views.py中添加视图函数, 12345@api_view(['PUT'])def get_movie_detail(request, id): movie = Movie.objects.get(pk=id) serializer = MovieSerializer(movie) return Response(serializer.data) 然后在api/urls.py中绑定网址, 123urlpatterns = [ path('<int:id>', views.get_movie_detail, name='get_movie_detail'),] 即可通过http://127.0.0.1:8000/movies/1 访问id为1的电影信息了。 4.2.4 修改或删除某个电影的信息 修改或删除也是针对某个电影,所以网址与[[#4 2 3 获取某个电影的信息]]可以相同,不过请求方法需要设置为PUT和DELETE,修改相应的视图函数如下: 123456789101112131415@api_view(['GET', 'PUT', 'DELETE'])def get_movie_detail(request, id): movie = Movie.objects.get(pk=id) if request.method == 'GET': serializer = MovieSerializer(movie) return Response(serializer.data) elif request.method == 'PUT': serializer = MovieSerializer(movie, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': movie.delete() return Response(status=status.HTTP_204_NO_CONTENT) 这里增加了对请求方法PUT和DELETE的支持,在函数体中,针对不同的请求类型,有不同的处理。 修改后页面效果如下,可以进行内容的修改和条目的删除。 5. 回顾 简单回顾一下,在一个普通的网站项目基础上,首先建立了专门的API文件夹,在其中首先建立序列化器以进行数据转化传输,然后建立了各类视图,并通过不同请求方法进行数据的增、删、改、查(即CRUD操作)API的构建。 可以看到,API的视图函数与一般网站视图函数的主要区别在于,API的视图函数是从数据库获取数据后进行序列化再传输,而一般网站视图函数则是获取数据后传递给前端模板以供展示。","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"django","slug":"django","permalink":"https://ben-xj.github.io/tags/django/"},{"name":"后端框架","slug":"后端框架","permalink":"https://ben-xj.github.io/tags/%E5%90%8E%E7%AB%AF%E6%A1%86%E6%9E%B6/"},{"name":"api","slug":"api","permalink":"https://ben-xj.github.io/tags/api/"}]},{"title":"1. 基本Django项目构建","slug":"基本Django项目构建","date":"2022-12-31T09:53:37.000Z","updated":"2023-04-29T11:38:24.000Z","comments":true,"path":"2022/12/31/基本Django项目构建/","link":"","permalink":"https://ben-xj.github.io/2022/12/31/%E5%9F%BA%E6%9C%ACDjango%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA/","excerpt":"1. 创建django项目 可通过如下命令创建名为myproject的django项目,","text":"1. 创建django项目 可通过如下命令创建名为myproject的django项目, 123django-admin startproject myprojectcd myprojectpython manage.py migrate 备注 python manage.py migrate意思是把数据模型(Python中定义的Model)和数据库同步。 python manage.py makemigrations是当模型的相关代码发生变动时,对变动进行提交保存,后接migrate 2. 创建app 1python manage.py startapp base # 这里base就是app的名字 创建完成后要注册app,在setting.py中找到INSTALLED_APPS,加入app名 1234INSTALLED_APPS = [ 'base', ...] 一个django项目的结构如下 3. 创建数据模型(Model) 在models.py中,建立数据模型,类似于pojo,即一个对象包含哪些字段,这也被称为Schema。 123456from django.db import models# Create your models here.class Item(models.Model): name = models.CharField(max_length=200) created = models.DateTimeField(auto_now_add=True) 如上所述,数据模型变动后,要进行迁移 12python manage.py makemigrationspython manage.py migrate makemigrations后,即建立了数据模型和数据库的联系,可以通过python manage.py sqlmigrate base 0001生成sql语句,但这只是供查看确认,并不执行,migrate才是执行。 临时加入数据 可以另外开一个shell进行一些操作,比如添加数据 1python manage.py shell 这条命令相比直接运行python,可以导入该django项目的环境变量。 在shell中添加数据 12345678910111213>>> from base.models import Item>>> Item.objects.create(name='item1')<Item: Item object (1)>>>> Item.objects.create(name='item2')<Item: Item object (2)>>>> Item.objects.create(name='item3')<Item: Item object (3)>>>> items = Item.objects.all()>>> print(items)<QuerySet [<Item: Item object (1)>, <Item: Item object (2)>, <Item: Item object (3)>]># 也可以这样>>> item = Item(name='item4')>>> item.save() 4. 创建后端逻辑(View) 在views.py文件中完成 比如最简单的, 12def home(request): return HttpResponse("home page") 这样后续执行该逻辑时,网页上就显示了home page这行字。 当然,更一般的,后端会提供一些数据处理,并显示在定义好的前端模板上,这样就要和前端模板绑定。比如现在要把所有的物品显示在前端页面上,那么后端就要从数据库拉取所有的items, 123def get_items(request): items = Item.objects.all() return render(request, 'items.html', {'items': items}) 这样就可以把items数据传递给items.html这个前端模板。 5. 创建前端模板(templates) 在base文件夹下创建templates文件夹,再在templates文件夹下创建base文件夹,并在其中新建items.html文件,即base/templates/base/items.html,这样设置后,在django项目中,我们可以通过base/items.html定位到这个模板。 Django框架中存在模板寻找器,可搜索每个app的特定文件夹。 文件内容如下 12345678910111213141516<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Items</title></head><body> <ul> {% for item in items %} <li>{{item.name}}</li> {% endfor %} </ul></body></html> 大意就是把各个物品的名字显示成一个无序列表。 6. 绑定网址 以上已经完成了后端与数据库、前端与后端的数据传递,那么用户如何访问这样一个网页呢?就需要在urls.py中绑定好网址和后端。 在base文件夹下新建urls.py文件,内容如下 1234567from . import views from django.urls import pathurlpatterns = [ path("items/", views.get_items), path("", views.home)] 但这个url目前只在base这个app下,并没有被django项目所识别,因此,需要在myproject/urls.py文件中进行引用,以让项目进行识别。 123456from django.urls import include # 这是新增的行urlpatterns = [ path('admin/', admin.site.urls), path('base/', include('base.urls')) # 这是新增的行] 7. 运行 最后,执行python manage.py runserver即可运行网站,打开http://127.0.0.1:8000/base/items/ 就显示了物品列表如下。 8. 参考 Django Crash Course - Introduction + Python Web Development Tutorial Django REST Framework Oversimplified","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"django","slug":"django","permalink":"https://ben-xj.github.io/tags/django/"},{"name":"后端框架","slug":"后端框架","permalink":"https://ben-xj.github.io/tags/%E5%90%8E%E7%AB%AF%E6%A1%86%E6%9E%B6/"},{"name":"api","slug":"api","permalink":"https://ben-xj.github.io/tags/api/"}]},{"title":"tmux够用命令","slug":"tmux够用命令","date":"2022-12-31T00:44:10.000Z","updated":"2023-05-16T12:33:36.000Z","comments":true,"path":"2022/12/31/tmux够用命令/","link":"","permalink":"https://ben-xj.github.io/2022/12/31/tmux%E5%A4%9F%E7%94%A8%E5%91%BD%E4%BB%A4/","excerpt":"Tmux is a terminal multiplexer for Unix-like systems. It allows users to create and manage multiple terminal sessions within a single terminal window or console. Tmux provides many features that are useful for working in a command-line environment. For example, it allows users to detach and reattach sessions, which means that users can start a session, disconnect from it and then reconnect to it later. This feature is particularly useful for long-running tasks that continue even after the user has logged out or disconnected from the network.","text":"Tmux is a terminal multiplexer for Unix-like systems. It allows users to create and manage multiple terminal sessions within a single terminal window or console. Tmux provides many features that are useful for working in a command-line environment. For example, it allows users to detach and reattach sessions, which means that users can start a session, disconnect from it and then reconnect to it later. This feature is particularly useful for long-running tasks that continue even after the user has logged out or disconnected from the network. 1. Session 会话 可以理解为一个连接,tmux其实是提供了一个终端服务,这个服务可以允许我们创建多个终端会话。 1.1 创建匿名和命名的会话 12tmux newtmux new -s <session-name> 创建后会自动进入该会话的窗口(下一节详细说明窗口)。 1.2 离开会话 1ctrl+b d 即离开当前的会话,回到系统的终端窗口。tmux会话的一大优点是不会随着终端gui的关闭而停止,会话仍保持后台运行,后续可通过attach命令重新进入。 1.3 查看会话列表及进入会话 我们可以同时运行多个会话,互不干扰,查看会话列表的命令为 1tmux ls 第一列就是会话的名字,进入指定会话命令为 1tmux attach -t <session-name> 这里-t表示target。 1.4 退出会话(删除) 1234# 会话内exit# 会话外/内tmux kill-session -t <session-name> 这是彻底退出会话,不会保留后台。 1.5 重命名会话 1tmux rename-session -t <session-name> <new-name> 2. Window 窗口 每次进入会话看到的都是一个会话窗口,而实际上tmux允许我们在一个session开启多个窗口,窗口可以简单理解为一个个tab页。 2.1 新窗口 1ctrl+b c 这个动作开启了一个新窗口,并自动进入新窗口。可以通过下方状态栏观察。 2.2 窗口跳转 那如果我想跳回去之前的窗口,可以通过命令 1ctrl+b <window-name> 2.3 窗口重命名 这时候我们发现,这些窗口名都是数字,开多了自己都不知道往哪找想要的窗口了,那么,可以把窗口改个容易识别的名字,这样就知道每个窗口在做什么啦。 1ctrl+b , 2.4 关闭窗口 最后,当不再使用某个窗口,可以关掉 1ctrl+d或exit 3. Pane 面板 最后的最后,如果你的屏幕足够大,一个窗口只能同时跑一个命令不是很浪费?tmux提供了多面板支持,可以把当前窗口一分为2、3、4… 3.1 水平划分 1ctrl+b % 效果如下 3.2 垂直划分 1ctrl+b " 效果如下 当然,水平和垂直划分可以随意组合 3.3 pane间切换 这么多面板,怎么跳到指定的那一个,当然不是用鼠标点,我们还是用ctrl+b命令,结合上下左右方向键就可以切换了。 3.4 关闭pane 如果觉得太凌乱,就关掉几个pane吧,命令和关窗口一样。 以上。","categories":[{"name":"Linux","slug":"Linux","permalink":"https://ben-xj.github.io/categories/Linux/"}],"tags":[{"name":"shell","slug":"shell","permalink":"https://ben-xj.github.io/tags/shell/"},{"name":"tmux","slug":"tmux","permalink":"https://ben-xj.github.io/tags/tmux/"}]},{"title":"5. 半正定锥","slug":"半正定锥","date":"2022-04-17T12:19:23.000Z","updated":"2023-04-29T12:37:32.000Z","comments":true,"path":"2022/04/17/半正定锥/","link":"","permalink":"https://ben-xj.github.io/2022/04/17/%E5%8D%8A%E6%AD%A3%E5%AE%9A%E9%94%A5/","excerpt":"1. 几个符号 1.1 对称方阵的集合","text":"1. 几个符号 1.1 对称方阵的集合 Sn={X∈Rn×n∣X=XT}\\mathbf{S}^{n}= \\{ X \\in \\mathbf{R}^{n \\times n} \\mid X=X^{T} \\} Sn={X∈Rn×n∣X=XT} S for symmetric 1.2 对称半正定方阵的集合 S+n={X∈Sn∣X⪰0}\\mathbf{S}^{n}_{+}= \\{X \\in \\mathbf{S}^{n} \\mid X \\succeq 0 \\} S+n={X∈Sn∣X⪰0} ⪰\\succeq⪰表示矩阵的特征值≥0\\ge 0≥0 1.3 对称正定方阵的集合 S++n={X∈Sn∣X≻0}\\mathbf{S}^{n}_{++}= \\{X \\in \\mathbf{S}^{n} \\mid X \\succ 0 \\} S++n={X∈Sn∣X≻0} 1.4 证明对称半正定方阵为凸锥 半正定矩阵有: xTAx≥0x^TAx \\ge 0 xTAx≥0 代入凸锥的定义即可证 xT(θ1A+θ2B)x=θ1xTAx+θ2xTBx≥0x^{T}\\left(\\theta_{1} A+\\theta_{2} B\\right) x=\\theta_{1} x^{T} A x+\\theta_{2} x^{T} B x \\geq 0 xT(θ1A+θ2B)x=θ1xTAx+θ2xTBx≥0 1.5 对比 Sn\\mathbf{S}^{n}Sn、S+n\\mathbf{S}^{n}_+S+n是凸锥(当然也是凸集); S++n\\mathbf{S}^{n}_{++}S++n是凸集,不是凸锥,因为不包含0点。","categories":[{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"}]},{"title":"4. 多面体和单纯形","slug":"多面体和单纯形","date":"2022-04-17T12:16:41.000Z","updated":"2023-04-29T12:43:28.000Z","comments":true,"path":"2022/04/17/多面体和单纯形/","link":"","permalink":"https://ben-xj.github.io/2022/04/17/%E5%A4%9A%E9%9D%A2%E4%BD%93%E5%92%8C%E5%8D%95%E7%BA%AF%E5%BD%A2/","excerpt":"1. 多面体(Polyhedron) 多面体是一系列线性等式和不等式的解集。","text":"1. 多面体(Polyhedron) 多面体是一系列线性等式和不等式的解集。 P={x∣ajTx≤bj,j=1,…,m,cjTx=dj,j=1,…,p}\\mathcal{P}=\\{x \\mid a_{j}^{T} x \\leq b_{j}, j=1, \\ldots, m, c_{j}^{T} x=d_{j}, j=1, \\ldots, p\\} P={x∣ajTx≤bj,j=1,…,m,cjTx=dj,j=1,…,p} 向量形式为 P={x∣Ax⪯b,Cx=d}\\mathcal{P}= \\{x \\mid A x \\preceq b, C x=d \\}P={x∣Ax⪯b,Cx=d} 从定义可以看出,多面体就是超平面和半空间的交集。 有界的多面体称为Polytope。 2. 单纯形(Simplex) 2.1 定义 假设k+1k+1k+1个点v0,…,vk∈Rnv_0, \\ldots, v_k \\in R^nv0,…,vk∈Rn仿射独立,即v1−v0,…,vk−v0v_1-v_0, \\ldots, v_k-v_0v1−v0,…,vk−v0线性不相关,则与这k+1k+1k+1个点相关的单纯形 即为这些点的凸包: C=conv{v0,…,vk}={θ0v0+⋯+θkvk∣θ⪰0,1Tθ=1}\\begin{align} C & = \\operatorname{conv}\\{v_{0}, \\ldots, v_{k}\\} \\\\ & = \\{\\theta_{0} v_{0}+\\cdots+\\theta_{k} v_{k} \\mid \\theta \\succeq 0, \\mathbf{1}^{T} \\theta = 1\\} \\end{align} C=conv{v0,…,vk}={θ0v0+⋯+θkvk∣θ⪰0,1Tθ=1} 2.2 例子 以二维空间为例 若给两个不同的点,则构成的单纯形为一条线段 若给三个不同的点,则构成的单纯形为一个三角形 若给四个以上不同的点,则不可能仿射独立,不能构成单纯形 2.3 证明单纯形是多面体 思路: 把单纯形中的点表示成多面体的形式 线性不相关->满秩 设单纯形为CCC,则CCC中的点可表示为 x=θ0v0+θ1v1+⋯+θkvkx=\\theta_{0} v_{0}+\\theta_{1} v_{1}+\\cdots+\\theta_{k} v_{k} x=θ0v0+θ1v1+⋯+θkvk 其中θ⪰0,1Tθ=1\\theta \\succeq 0, \\mathbf{1}^{T} \\theta = 1θ⪰0,1Tθ=1,要注意的是θ\\thetaθ是可变的,决定了xxx的取值。 对上式进行变换,得 x=v0+θ1(v1−v0)+⋯+θk(vk−v0)=v0+By\\begin{align} x &= v_{0}+\\theta_{1} (v_{1}-v_{0})+\\cdots+\\theta_{k} (v_{k}-v_{0})\\\\ &=v_0 +By \\end{align} x=v0+θ1(v1−v0)+⋯+θk(vk−v0)=v0+By 其中 B=[v1−v0⋯vk−v0]∈Rn×ky=(θ1,…,θk)\\begin{align} B & = \\left[\\begin{array}{lll} v_{1}-v_{0} & \\cdots & v_{k}-v_{0} \\end{array}\\right] \\in \\mathbf{R}^{n \\times k}\\\\ y & = \\left(\\theta_{1}, \\ldots, \\theta_{k}\\right) \\end{align}By=[v1−v0⋯vk−v0]∈Rn×k=(θ1,…,θk) 注意这里的yyy不是θ\\thetaθ,少了一个元素。y⪰0,1Ty≤1y \\succeq 0,\\mathbf{1}^{T} y \\le 1y⪰0,1Ty≤1。显然可以用yyy的约束条件来得到对xxx的约束,那么下一步要做的就是把yyy独立出来。 由于BBB中各向量线性无关,则rank(B)=krank(B)=krank(B)=k,因此,存在非奇异矩阵A=(A1,A2)∈Rn×nA=(A_1, A_2) \\in R^{n \\times n}A=(A1,A2)∈Rn×n使得, AB=[A1A2]B=[I0]A B=\\left[\\begin{array}{l} A_{1} \\\\ A_{2} \\end{array}\\right] B=\\left[\\begin{array}{l} I \\\\ 0 \\end{array}\\right] AB=[A1A2]B=[I0] 在xxx的表达式左边乘上矩阵AAA,可得 A1x=A1v0+y,A2x=A2v0A_{1} x=A_{1} v_{0}+y, \\quad A_{2} x=A_{2} v_{0}A1x=A1v0+y,A2x=A2v0 代入yyy的约束,可得 A2x=A2v0,A1x⪰A1v0,1TA1x≤1+1TA1v0A_{2} x=A_{2} v_{0}, \\quad A_{1} x \\succeq A_{1} v_{0}, \\quad \\mathbf{1}^{T} A_{1} x \\leq 1+\\mathbf{1}^{T} A_{1} v_{0} A2x=A2v0,A1x⪰A1v0,1TA1x≤1+1TA1v0 符合多面体的定义,证毕。","categories":[{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"}]},{"title":"3. 球和椭球","slug":"球和椭球","date":"2022-04-17T05:49:31.000Z","updated":"2023-04-29T12:43:54.000Z","comments":true,"path":"2022/04/17/球和椭球/","link":"","permalink":"https://ben-xj.github.io/2022/04/17/%E7%90%83%E5%92%8C%E6%A4%AD%E7%90%83/","excerpt":"1. 球(Ball) 1.1 定义 球有两种形式的定义","text":"1. 球(Ball) 1.1 定义 球有两种形式的定义 1.1.1 定义一 B(xc,r)={x∣∥x−xc∥2≤r}={x∣(x−xc)T(x−xc)≤r2}\\begin{align} B\\left(x_{c}, r\\right) & = \\{x \\mid\\left\\|x-x_{c}\\right\\|_{2} \\leq r\\}\\\\& = \\{x \\mid\\left(x-x_{c}\\right)^{T}\\left(x-x_{c}\\right) \\leq r^{2}\\} \\end{align} B(xc,r)={x∣∥x−xc∥2≤r}={x∣(x−xc)T(x−xc)≤r2} 其中xcx_cxc为球心,rrr为半径。 1.1.2 定义二 B(xc,r)={xc+ru∣∥u∥2≤1}B\\left(x_{c}, r\\right)=\\{x_{c}+r u \\mid\\|u\\|_{2} \\leq 1\\} B(xc,r)={xc+ru∣∥u∥2≤1} 从直观上看,我们都知道球一定是个凸集。下面分别通过两种定义进行证明: 1.2 球为凸集的证明 1.2.1 利用定义一证明 ∥θx1+(1−θ)x2−xc∥2=∥θ(x1−xc)+(1−θ)(x2−xc)∥2≤θ∥x1−xc∥2+(1−θ)∥x2−xc∥2≤r.\\begin{aligned} \\|\\theta x_{1}+(1-\\theta) x_{2}-x_{c}\\|_{2} &=\\|\\theta (x_{1}-x_{c} )+(1-\\theta) (x_{2}-x_{c} ) \\|_{2} \\\\ & \\leq \\theta \\|x_{1}-x_{c} \\|_{2}+(1-\\theta) \\|x_{2}-x_{c} \\|_{2} \\\\ & \\leq r . \\end{aligned} ∥θx1+(1−θ)x2−xc∥2=∥θ(x1−xc)+(1−θ)(x2−xc)∥2≤θ∥x1−xc∥2+(1−θ)∥x2−xc∥2≤r. 这里关键就是用到了三角不等式 1.2.2 利用定义二证明 θ(xc+ru1)+(1−θ)(xc+ru2)=xc+r(θu1+(1−θ)u2)\\theta(x_c+ru_1)+(1-\\theta)(x_c+ru_2)=x_c+r\\left(\\theta u_1+(1-\\theta)u_2\\right) θ(xc+ru1)+(1−θ)(xc+ru2)=xc+r(θu1+(1−θ)u2) 那么只需要保证 ∥θu1+(1−θ)u2∥2≤1\\|\\theta u_1+(1-\\theta)u_2\\|_{2} \\le 1 ∥θu1+(1−θ)u2∥2≤1 同样用三角不等式容易证明。 2. 椭球(Ellipsoid) 2.1 定义 同样,也有两种定义形式 2.1.1 定义一 E={x∣(x−xc)TP−1(x−xc)≤1}\\mathcal{E}=\\{x \\mid\\left(x-x_{c}\\right)^{T} P^{-1}\\left(x-x_{c}\\right) \\leq 1\\} E={x∣(x−xc)TP−1(x−xc)≤1} 其中P=PT≻0P=P^{T} \\succ 0P=PT≻0,即对称且正定。椭球的半轴就是矩阵PPP的特征值的方根。 特别地,当P=r2IP=r^2 IP=r2I,该点集为一个半径为rrr的球。 2.1.2 定义二 E={xc+Au∣∥u∥2≤1}\\mathcal{E}=\\{x_{c}+A u \\mid\\|u\\|_{2} \\leq 1\\} E={xc+Au∣∥u∥2≤1} 这里A=P1/2A=P^{1/2}A=P1/2。","categories":[{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"}]},{"title":"2. 超平面和半空间","slug":"超平面和半空间","date":"2022-04-17T05:47:34.000Z","updated":"2023-04-26T14:06:30.000Z","comments":true,"path":"2022/04/17/超平面和半空间/","link":"","permalink":"https://ben-xj.github.io/2022/04/17/%E8%B6%85%E5%B9%B3%E9%9D%A2%E5%92%8C%E5%8D%8A%E7%A9%BA%E9%97%B4/","excerpt":"1. 超平面(hyperplane) 形如{x∣aTx=b}(a≠0)\\{x \\mid a^Tx=b \\}(a \\ne 0){x∣aTx=b}(a=0)的就是超平面","text":"1. 超平面(hyperplane) 形如{x∣aTx=b}(a≠0)\\{x \\mid a^Tx=b \\}(a \\ne 0){x∣aTx=b}(a=0)的就是超平面 可以看成是一系列点的集合,这些点与向量aaa的内积为一个固定的常数。而bbb则是该超平面相对于原点的偏移量,原定义可以写作 {x∣aT(x−x0)=0}\\{ x \\mid a^T(x-x_0)=0 \\} {x∣aT(x−x0)=0} 其中x0x_0x0为超平面上一点。 2. 半空间(halfspace) 超平面可以把RnR^nRn分割为两个半空间,形如{x∣aTx≤b}(a≠0)\\{x \\mid a^Tx \\le b \\}(a \\ne 0){x∣aTx≤b}(a=0)的就是半空间 用定义可证,半空间也是一个凸集([[1. 仿射集-凸集-凸锥#凸集 convex set]]) 3. 子空间(subspace) 要区分子空间和半空间。 所谓子空间,或者空间,即存在以下性质的点集合:对于x1,x2∈Vx_1, x_2 \\in Vx1,x2∈V,有 αx1+βx2∈V,α,β∈R\\alpha x_1 + \\beta x_2 \\in V, \\quad \\alpha,\\beta \\in R αx1+βx2∈V,α,β∈R","categories":[{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"}]},{"title":"批量爬取大学课件","slug":"批量爬取大学课件","date":"2022-04-16T01:36:22.000Z","updated":"2023-04-26T14:06:14.000Z","comments":true,"path":"2022/04/16/批量爬取大学课件/","link":"","permalink":"https://ben-xj.github.io/2022/04/16/%E6%89%B9%E9%87%8F%E7%88%AC%E5%8F%96%E5%A4%A7%E5%AD%A6%E8%AF%BE%E4%BB%B6/","excerpt":"国外很多大学的课件放在一个专门的页面上,如下图所示,那么很容易通过一个爬虫批量下载下来。 思路就是识别页面中以pdf结尾的链接,然后进行下载。","text":"国外很多大学的课件放在一个专门的页面上,如下图所示,那么很容易通过一个爬虫批量下载下来。 思路就是识别页面中以pdf结尾的链接,然后进行下载。 单线程版本 123456789101112131415import requestsfrom bs4 import BeautifulSoupurl = 'https://inst.eecs.berkeley.edu/~ee127/fa19/Lectures/'page = requests.get(url).contentsoup = BeautifulSoup(page, 'html.parser')links = soup.find_all('a')for link in links: href = link.get('href') if href.endswith('.pdf'): file_url = url + href with open(href, 'wb') as f: f.write(requests.get(file_url).content) 下载25个文件,费时180秒左右。 多线程版本 对于这种国外网站,常常下载速度较慢,这种IO密集型的任务使用多线程就非常有必要了。 123456789101112131415161718192021222324from threading import Threadimport requestsfrom bs4 import BeautifulSoupdef download(url, href): r = requests.get(url + href) with open(href, 'wb') as f: f.write(r.content)url = 'https://inst.eecs.berkeley.edu/~ee127/fa19/Lectures/'page = requests.get(url).contentsoup = BeautifulSoup(page, 'html.parser')links = soup.find_all('a')threads = []for link in links: href = link.get('href') if href.endswith('.pdf'): t = Thread(target=download, args=(url, href)) threads.append(t) t.start()for t in threads: t.join() 这时,下载同样的文件,只需12秒左右,效果还是很明显的。","categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"}],"tags":[{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"爬虫","slug":"爬虫","permalink":"https://ben-xj.github.io/tags/%E7%88%AC%E8%99%AB/"}]},{"title":"1. 仿射集、凸集、凸锥","slug":"仿射集 凸集 凸锥","date":"2022-04-16T00:44:10.000Z","updated":"2023-04-26T14:05:06.000Z","comments":true,"path":"2022/04/16/仿射集 凸集 凸锥/","link":"","permalink":"https://ben-xj.github.io/2022/04/16/%E4%BB%BF%E5%B0%84%E9%9B%86%20%E5%87%B8%E9%9B%86%20%E5%87%B8%E9%94%A5/","excerpt":"1. 仿射集(affine set) 1.1 直线(line)","text":"1. 仿射集(affine set) 1.1 直线(line) 通过两个点x1≠x2x_1 \\ne x_2x1=x2,可构造一条直线 y=θx1+(1−θ)x2y=\\theta x_1 + (1-\\theta) x_2 y=θx1+(1−θ)x2 其中θ∈R\\theta \\in Rθ∈R。若令θ∈[0,1]\\theta \\in [0,1]θ∈[0,1],则为一条线段。 这个式子可以简单变换为 y=x2+θ(x1−x2)y=x_2 + \\theta(x_1 - x_2) y=x2+θ(x1−x2) 表示以x2x_2x2为基准点,向x1−x2x_1-x_2x1−x2方向构造的一系列新的点。 把θ\\thetaθ看作变量,上式其实就是对θ\\thetaθ的线性变换加上一个常数,这就是仿射.(仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。) 1.2 仿射组合(affine combination) 给定若干点xi(i=1,…,k)x_i(i=1,\\ldots,k)xi(i=1,…,k),定义 y=θ1x1+θ2x2+⋯+θkxky=\\theta_1 x_1 + \\theta_2 x_2 + \\cdots + \\theta_k x_k y=θ1x1+θ2x2+⋯+θkxk 为这些点的仿射组合。其中θi∈R\\theta_i \\in Rθi∈R 且θ1+θ2+⋯+θk=1\\theta_1 + \\theta_2 + \\cdots + \\theta_k=1θ1+θ2+⋯+θk=1。 1.3 仿射集(affine set) 一个集合CCC被称为仿射集,其充分条件是“经过其中任意两点的直线仍在此集合中”。即对任意x1,x2∈Cx_1, x_2 \\in Cx1,x2∈C, y=θx1+(1−θ)x2y=\\theta x_1 + (1-\\theta) x_2 y=θx1+(1−θ)x2 也在集合CCC中,其中θ∈R\\theta \\in Rθ∈R,则CCC为仿射集。 设x0∈Cx_0 \\in Cx0∈C,则 V=C−x0={x−x0∣x∈C}V=C-x_0=\\left\\{x-x_0 | x \\in C\\right\\} V=C−x0={x−x0∣x∈C} 是一个与C相关的[[子空间(subspace)]] 例子1 线性方程组{x∣Ax=b}\\{x \\mid A x=b\\}{x∣Ax=b}的解集CCC一定是仿射集。反之,每个仿射集都可以表示为一个线性方程组的解集。 根据定义,CCC对应的子空间为{x∣Ax=0}\\{x \\mid A x=0\\}{x∣Ax=0},即AAA的化零空间(nullspace)。 1.4 仿射包(affine hull) 任意集合CCC,构造尽可能小的仿射集。 即集合CCC中所有点的仿射组合称为关于CCC的仿射包( aff C\\text { aff } C aff C,包是指包含、包裹之意)。 aff C={θ1x1+⋯+θkxk∣x1,…,xk∈C,θ1+⋯+θk=1}\\text { aff } C=\\left\\{\\theta_{1} x_{1}+\\cdots+\\theta_{k} x_{k} \\mid x_{1}, \\ldots, x_{k} \\in C, \\theta_{1}+\\cdots+\\theta_{k}=1\\right\\} aff C={θ1x1+⋯+θkxk∣x1,…,xk∈C,θ1+⋯+θk=1} 2. 凸集(convex set) 2.1 凸组合(convex combination) 给定若干点xi(i=1,…,k)x_i(i=1,\\ldots,k)xi(i=1,…,k),定义 y=θ1x1+θ2x2+⋯+θkxky=\\theta_1 x_1 + \\theta_2 x_2 + \\cdots + \\theta_k x_k y=θ1x1+θ2x2+⋯+θkxk 其中θi≥0\\theta_i \\ge 0θi≥0 且θ1+θ2+⋯+θk=1\\theta_1 + \\theta_2 + \\cdots + \\theta_k=1θ1+θ2+⋯+θk=1,yyy称作x1,x2,…,xkx_1, x_2, \\ldots, x_kx1,x2,…,xk的一个凸组合。 2.2 凸集(convex set) 一个集合CCC被称为凸集,其充分条件是“经过其中任意两点的线段仍在此集合中”。即对任意x1,x2∈Cx_1, x_2 \\in Cx1,x2∈C, y=θx1+(1−θ)x2y=\\theta x_1 + (1-\\theta) x_2 y=θx1+(1−θ)x2 也在集合CCC中,其中θ∈[0,1]\\theta \\in [0,1]θ∈[0,1],则CCC为凸集。可见,凸集的要求比仿射集低,任何仿射集都是凸集。 2.3 凸包(convex hull) 对任意集合CCC,集合CCC中所有点的凸组合称为凸包,可记作convC\\operatorname{conv} CconvC。 convC={θ1x1+⋯+θkxk∣xi∈C,θi≥0,i=1,…,k,θ1+⋯+θk=1}\\operatorname{conv} C=\\left\\{\\theta_{1} x_{1}+\\cdots+\\theta_{k} x_{k} \\mid x_{i} \\in C, \\theta_{i} \\geq 0, i=1, \\ldots, k, \\theta_{1}+\\cdots+\\theta_{k}=1\\right\\} convC={θ1x1+⋯+θkxk∣xi∈C,θi≥0,i=1,…,k,θ1+⋯+θk=1} 3. 凸锥(convex cone) 3.1 锥(cone) 对于集合CCC中任意点xxx和任意常数θ≥0\\theta \\ge 0θ≥0,都有θx∈C\\theta x \\in Cθx∈C,则CCC称为锥。 注: 一条任意射线不一定是锥 一条端点在0点的射线是锥 两条端点在0点的射线是锥 3.2 锥组合(conic combination) 简单理解,conic 就是非负(或者单边)的意思。 给定若干点xi(i=1,…,k)x_i(i=1,\\ldots,k)xi(i=1,…,k),定义 y=θ1x1+θ2x2+⋯+θkxky=\\theta_1 x_1 + \\theta_2 x_2 + \\cdots + \\theta_k x_k y=θ1x1+θ2x2+⋯+θkxk 其中θi≥0\\theta_i \\ge 0θi≥0 ,yyy称作x1,x2,…,xkx_1, x_2, \\ldots, x_kx1,x2,…,xk的一个锥组合。 3.3 凸锥(convex cone) 若从凸锥组合仍属于原集合,则称为凸锥。 即对任意x1,x2∈Cx_1, x_2 \\in Cx1,x2∈C, y=θ1x1+θ2x2y=\\theta_1 x_1 + \\theta_2 x_2 y=θ1x1+θ2x2 也在集合CCC中,其中θi≥0\\theta_i \\ge 0θi≥0,则CCC为凸锥。显然,凸锥的要求包含对凸集的要求,任何凸锥都是凸集。 注: 两条端点在0点的射线不是凸锥 两条端点在0点的射线及其构成的扇形区域是凸锥 3.4 锥包(conic hull) 对任意集合CCC,集合CCC中所有点的锥组合称为锥包。 {θ1x1+⋯+θkxk∣xi∈C,θi≥0,i=1,…,k}\\left\\{\\theta_{1} x_{1}+\\cdots+\\theta_{k} x_{k} \\mid x_{i} \\in C, \\theta_{i} \\geq 0, i=1, \\ldots, k\\right\\} {θ1x1+⋯+θkxk∣xi∈C,θi≥0,i=1,…,k} 4. 特殊集合对比 4.1 点 一个点一定是仿射集和凸集,但不一定是锥,只有原点可以单独构成一个凸锥。 4.2 空集 空集既是仿射集,又是凸集和凸锥。","categories":[{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"}]}],"categories":[{"name":"Python","slug":"Python","permalink":"https://ben-xj.github.io/categories/Python/"},{"name":"Linux","slug":"Linux","permalink":"https://ben-xj.github.io/categories/Linux/"},{"name":"Java","slug":"Java","permalink":"https://ben-xj.github.io/categories/Java/"},{"name":"优化","slug":"优化","permalink":"https://ben-xj.github.io/categories/%E4%BC%98%E5%8C%96/"},{"name":"中科大凸优化课程笔记","slug":"中科大凸优化课程笔记","permalink":"https://ben-xj.github.io/categories/%E4%B8%AD%E7%A7%91%E5%A4%A7%E5%87%B8%E4%BC%98%E5%8C%96%E8%AF%BE%E7%A8%8B%E7%AC%94%E8%AE%B0/"}],"tags":[{"name":"cython","slug":"cython","permalink":"https://ben-xj.github.io/tags/cython/"},{"name":"python加速","slug":"python加速","permalink":"https://ben-xj.github.io/tags/python%E5%8A%A0%E9%80%9F/"},{"name":"vim","slug":"vim","permalink":"https://ben-xj.github.io/tags/vim/"},{"name":"python","slug":"python","permalink":"https://ben-xj.github.io/tags/python/"},{"name":"built-ins","slug":"built-ins","permalink":"https://ben-xj.github.io/tags/built-ins/"},{"name":"sorting","slug":"sorting","permalink":"https://ben-xj.github.io/tags/sorting/"},{"name":"generator","slug":"generator","permalink":"https://ben-xj.github.io/tags/generator/"},{"name":"linux","slug":"linux","permalink":"https://ben-xj.github.io/tags/linux/"},{"name":"grep","slug":"grep","permalink":"https://ben-xj.github.io/tags/grep/"},{"name":"parallel programming","slug":"parallel-programming","permalink":"https://ben-xj.github.io/tags/parallel-programming/"},{"name":"joblib","slug":"joblib","permalink":"https://ben-xj.github.io/tags/joblib/"},{"name":"ray","slug":"ray","permalink":"https://ben-xj.github.io/tags/ray/"},{"name":"multiprocessing","slug":"multiprocessing","permalink":"https://ben-xj.github.io/tags/multiprocessing/"},{"name":"java","slug":"java","permalink":"https://ben-xj.github.io/tags/java/"},{"name":"lombok","slug":"lombok","permalink":"https://ben-xj.github.io/tags/lombok/"},{"name":"mapstruct","slug":"mapstruct","permalink":"https://ben-xj.github.io/tags/mapstruct/"},{"name":"maven","slug":"maven","permalink":"https://ben-xj.github.io/tags/maven/"},{"name":"pip","slug":"pip","permalink":"https://ben-xj.github.io/tags/pip/"},{"name":"cpp","slug":"cpp","permalink":"https://ben-xj.github.io/tags/cpp/"},{"name":"pybind11","slug":"pybind11","permalink":"https://ben-xj.github.io/tags/pybind11/"},{"name":"pulp","slug":"pulp","permalink":"https://ben-xj.github.io/tags/pulp/"},{"name":"solver","slug":"solver","permalink":"https://ben-xj.github.io/tags/solver/"},{"name":"mip","slug":"mip","permalink":"https://ben-xj.github.io/tags/mip/"},{"name":"django","slug":"django","permalink":"https://ben-xj.github.io/tags/django/"},{"name":"后端框架","slug":"后端框架","permalink":"https://ben-xj.github.io/tags/%E5%90%8E%E7%AB%AF%E6%A1%86%E6%9E%B6/"},{"name":"api","slug":"api","permalink":"https://ben-xj.github.io/tags/api/"},{"name":"shell","slug":"shell","permalink":"https://ben-xj.github.io/tags/shell/"},{"name":"tmux","slug":"tmux","permalink":"https://ben-xj.github.io/tags/tmux/"},{"name":"凸优化","slug":"凸优化","permalink":"https://ben-xj.github.io/tags/%E5%87%B8%E4%BC%98%E5%8C%96/"},{"name":"爬虫","slug":"爬虫","permalink":"https://ben-xj.github.io/tags/%E7%88%AC%E8%99%AB/"}]}