ORers‘ Bling Chat | 【高光聊天记录集锦-02】:运小筹读者群里那些热烈的讨论

注:为方便理解问题,整理过程中有筛选合并等,敬请谅解。

1.关于退化解的讨论

Discussant(按发言先后)

  1. X教授:某高校老师
  2. Z博士:运小筹主编
  3. L同学:某校研究生
  4. R同学:本次推文小编(打酱油的)
  5. Y同学:某校研究生
  6. L博士:运筹优化方向博士生
  • X教授:大家可以讨论一下,矩阵乘法的意义是什么?矩阵乘向量是在干嘛?这个和单纯形法有撒关系?然后就能更好的理解退化现象的本质了!
  • Z博士:是通过线性变换,在可行域的不同位置上跳动来搜索吗?
  • X教授:别!先一步一步来。首先矩阵乘向量是在干嘛?第二步,如果向量的维度和矩阵乘子的维度不匹配会怎样?分别会出现哪些情况?接着再说利用单纯形法的的基础是怎样的?
  • Z博士:这样的面试题我肯定挂!
  • X教授:放心,没有企业会问这样的问题。因为一般他们也不会去考虑这些“无聊”的基础问题。
  • L同学我面试的时候被问过😂(小编有话说:这题会考噢!)
  • R同学:我的拙见:矩阵代表着基的变换,而向量代表在某个基下的坐标,相乘后就得到相对于基变换前的基的坐标。
  • Z博士:代数上就是换到其他的空间?几何上就是实现一些形状变化?
  • L博士:矩阵乘以向量,就是对矩阵进行剪切+旋转吧。如果矩阵是[0, 1;1, 0]就相当于对向量进行旋转。如果是:[0, 2;2, 0]就是旋转+拉长。如果是:[1, 2;2, 0]这种的,就是剪切。
  • X教授:从表现上讲解:矩阵乘以向量就是将在[1,0;0,1]这个基础base下的一个向量map到另一个空间(乘上的那个矩阵)中去,并还是用以前的向量空间来描述,可以是拉伸,可以是压缩,也可以是旋转。然后通过放大镜后再去看火柴的成像,你的两次观察,其实都在空气这个介质中的。而那根火柴已经被加工一次了再放回空气中,所以就被形变了。如果说不是在原来的基中去观察,其实你在新的空间中,通过map之后你的坐标是不会变的。所以这里的前提一定要明确:矩阵的乘法产生的新的映射结果都是指在原来的基中的新坐标,而不是在新的空间中的坐标。接着咱们再看,比如一个23的矩阵,乘上一个31的向量,是意味着什么呢?它得到的结果肯定就是一个2*1的坐标了。对吧?
  • R同学:对。
  • X教授:那对应的实际意义是什么呢?
  • Y同学:把三维向量投影到了二维空间里?
  • X教授:yes。
  • Y同学:那么把三维的东西投影到二维空间之后,会产生一个怎样的结果?
  • Y同学:原有信息损失,部分特征无法表达,不能唯一确定的。
  • X教授:very good!用哲学的思维讲就是:蚂蚁永远不能明白人类在干嘛?因为只能看到平面,由于信息的缺失,导致那一个维度的空间变成自由维度。所以就提供了单纯形法旋转的基础了。这个时候,我们要还原出来向量的本身信息,只能固定部分维度。但到底固定哪些维度最好就说不清楚,就得看目标函数是去哪个低纬度空间中可以产生更好的结果。所以本质就是这样,这个要说清楚最好是可以通过一次讲解会比较清楚。我简单提一下,就是这样,不知道大家明白了吗?
  • Z博士:基本明白!等着听退化哈哈哈!
  • R同学:理解了!
  • X教授:退化等一下,哈哈!然后刚刚的情况如果反一反会是怎样呢?或者这样子问好了,通过升维,会产生怎样的结果呀?把这些点想象成是一个高维空间的轮廓投影下来的,点意味着是什么?是线的交点,对不?
  • R同学:对!
  • X教授:那么将这个面上的点拉起来之后,是不是可能这个点是根本不存在的?比如两根线分别出于两个平行的超平面,只是不同方向,但因为降维了,导致这两个线被误以为相交了。但其实这个是不存在的,如果用约束来理解它是什么,这两个线会相交,但实际不会相交。所以通过升维,其实是将问题简单化了。因为将一些误以为有关系的约束,就可以去掉了。这就是为什么,如果大家有做分布式鲁棒之类的一些研究的话,会看到大佬们很常见的使用到了升维的技巧来简化模型,它的动机就是来自于这样的。我记得好像ML里面也常用这个技巧,但我对机器学习非常小白,所以不敢妄加评论。
  • L博士:核函数,通过核函数将低维数据映射到高维空间。
  • X教授:嗯,所以我个人感觉inverse optimisation也是这样的一个动机产生的。我们要解一个线性方程组,首先就是这每一个维度的超平面的信息,而这个超平面一定程度上是极大受约束于你被给定的线性空间的,也就是这个乘上的矩阵 。
  • L博士:所以是由于降维,导致一些维度被删除,使得多维空间中本来不相交的超平面相交了。而这些【并不实际存在的】超平面相交,产生了【假的】corner point,使得单纯形法迭代过程中,出现找不到下一个入基变量的情况嘛?其实解空间的维度是没问题的,只是由于约束矩阵A的关系,将解空间映射到了低维空间去,导致出现了这些【误判】嘛?
  • X教授:对哒!
  • L博士:也就出现了退化?就像这样吧!(如下图)AB和CD在高维解空间根本没有构成corner point,但是弄到2维空间,出来一个corner point。
    图一
  • X教授:是滴!俗称鬼打墙,因为根本没有那个点。从而被误认为能构成一个基,但其实并不存在那样的一个基。所以你在一个迷幻空间中变来变去,发现最后回到了原地,越把这些东西和易经结合起来看,就越觉得国学太妙了。其实风水就是矩阵,哈哈!过多的,我就不说了。免得被误认为我搞封建迷信,哈哈哈哈哈!!!!
  • L博士:哈哈,但是simplx在构造主元(pivot)的时候,沿着高维空间解x构成的高维空间的低维映射空间X’里的多面体边缘转悠,结果就走到这个不存在的corner point这里了,结果就被困住了,是这样子的不?
  • X教授:对的,所以像branch-and-price里面的退化其实也是类似的。你有一个基出现了是0,你的对偶就可以是好多不同的情况。
  • L博士:这有点像前些天《开端》里面,一个人睡着另一个人没睡着,先睡着的人会进入那个空间,有点这个意思,哈哈哈!
  • Z博士:这个也可以从互补松弛性解释吧!
  • X教授:嗯,可以的。
  • Z博士:我之前就是这么理解的,没从什么空间映射角度来…‘’通俗地讲 bound不住了,哈哈哈哈……
  • X教授:只是给大家提供一个浅薄的个人见解。
  • Z博士:不浅薄,很高深!我现在还没完全理解呢哈哈哈……
  • X教授:希望对映射比较模糊的初学同学们能有帮助!

看了这么多,可以先停下来喝口水冷静一下噢!这个话题还没结束,哈哈!

  • L博士:我画了一个简单的示意图(如下图),就是为什么就出现退化迭代不下去了,供大家参考,其实迭代方向应该在低维空间里面画的。图2
  • X教授:是的 高维空间能看见那里是一条大道走到黑
  • Z博士:就这样的,ab之间会出现迭代循环吧?(如下图)在这里插入图片描述
  • L博士:嗯嗯,那个b如果是从下一维空间投影下来的,那在这里就会产生退化。
  • L博士:对的,这里其实是这样的。
    假如x是5维,约束是3个线性独立的。因此基于约束来找解就会是在3维空间里面去找。我们给定一个初始基。
    然后首先:将x从5维压到3维(这3维就是基变量所在的那些维度,非基变量的维度被无情抹掉了),我们只看3维。在这3维里面,我们顺着一条binding的边,也就是可行域多面体的一条边走到下一个corner point。到了这个corner point,我们需要再次将眼光放到5维,看看我们接下来要从5维中选择哪3维作为下一个要探索的方向。
    循环这个过程:
    1.从初始Corner point出发,纬度是3维。
    2.从上一个corner point 走到选好的corner point,一直是3维。
    3.到达目标corner point之后,视角从3维变到5维。
    4.选好下一个3维空间以后,朝着目标corner point走的过程,一直保持3维loop以上过程,就是simplex的迭代。
    但是如果出现选好的下一个corner point是低维空间(也就是3维空间)的一个假的corner point,我们走到那个点以后,把视角切回到5维,发现,5维空间里没有任何超平面在这里相交,往下选下一个3维空间,他不知所措,所以这就是退化,哈哈哈
  • L博士:解决退化的思路,可以从避免走到这种fake corner point入手,从机制上避免走到这种死胡同去,中文版教材里面提到过一个方法:就是总是选择reduced cost<0的最小下标的决策变量作为下一个入基变量,是可以避免的 这也是一种比较好的思路 我也做过一些这个尝试,但是效果并不好。
  • Z博士:对的!这就和传统的基于dual的构造方法不一样了吧。但是你刚刚说的CG不收敛,如果是有限次迭代要求,那么不一定都是因为退化产生的。
  • L博士:CG在实际中,很多时候确实找不到新列了,SP的目标值小于0了,然后就只能停止了呀。但是由于原问题是MIP,所以最后求解final RMP的时候,这就有gap了。
  • Z博士:线性优化导论里边也提到了几种蛮不错的方法 扰动的、字典序的、布兰德规则的 当然我一个也没用过哈哈,我碰到的实际问题中就没见过退化的 但是你刚刚说的CG不收敛,如果是有限次迭代要求,那么不一定都是因为退化产生的。
  • L博士:究其原因,还是由于退化,导致dual variable的值没有取得很适合的,导致子问题没有把一些本来应该在RMP中作为基变量的列找出来,就早早使得程序终止了 根据我们的尝试,CG在很多算例上,gap都能到100%以上,非常不稳定的 退化的影响在很多问题上是非常大的 求得的解还不如启发式的,这也是处理退化的重要性所在。
  • Z博士:如果说你不限制求解的工作量,那么的确只有退化一个原因,因为其他的原因都能逐步走出来,只有退化,是走不出来的 但是我觉得在求解实际问题中不会不限制求解的工作量,所以我之前才提了其他的想法。anyway,不矛盾 我一个业界的朋友跟我讲过,这玩意有时候不靠谱哈哈哈 其实这时候感觉就不用simplex一路追到头,且不说退不退化,时间性价比太低… 于是乎 构造列的方法应该也就成了蛮多研究的创新点吧hh,加油加油,我们的work,有舞台了。

至此整个讨论过程基本完结,那么你对解的退化现象的原因有没有新的认识呢?当然如果你有更好的想法欢迎在留言区讨论交流!

2.关于if约束线性化讨论

Discussant(按发言先后)

  1. Z同学: 某校研究生
  2. L博士:运小筹主编
  3. G同学:某校研究生
  4. R同学:本次小编(打酱油的)
  • Z同学:请问大家一个问题,我现在有x1 x2 x3三个变量,目前想添加一个约束,如果这三个变量同时大于等于0,则y大于等于0;如果这三个变量同时小于等于0,则y小于等于0。
  • L博士:最简单的方法,引入辅助变量,标记每个变量的正负, 然后,用Gurobi的indicator约束,加入if z 1 + z 2 + z 3 = 3 z_1 + z_2 + z_3 = 3 z1+z2+z3=3, then w = 1 w=1 w=1,或者你做线性化处理一下。
  • L博士:if x > = 0 x>=0 x>=0 then y = 1 y = 1 y=1,这种的线性化应该没问题吧!
    证明如下:
    原命题:if x > = 0 x>=0 x>=0, then y = 1 y = 1 y=1
    逆否命题:if y = 0 y=0 y=0, then x < 0 x<0 x<0==> x − ϵ < = 0 x - \epsilon<=0 xϵ<=0
    ==> x − ϵ − M y < = 0 x- \epsilon - My <=0 xϵMy<=0
    where epsilon is a small enough positive number
  • Z同学:原命题if x < 0 x<0 x<0, then y = 0 y= 0 y=0,逆否命题if y ≠ 0 y\ne0 y=0, then x > = 0 x>=0 x>=0接下来呢,画不出来瓢了…
  • L博士 y ≠ 0 y\ne 0 y=0, y y y是0-1变量呀,也就是 y = 1 y=1 y=1呀!
  • Z同学:接下来约束变为 x − M ( y − 1 ) > = 0 x-M(y-1)>=0 xMy1>=0
  • L博士:你这还是没学会呀! 定理的内容是符合形式:if 表达式如何如何(可以是任何线性表达式)
    then 0-1变量如何如何,像下面这个:
    原命题:if z 1 + z 2 + z 3 = 3 z_1 + z_2 + z_3 =3 z1+z2+z3=3, then w = 1 w=1 w=1
    逆否命题:if w = 0 w=0 w=0, then z 1 + z 2 + z 3 < = 2 z_1 + z_2 + z_3 <=2 z1+z2+z3<=2
    ==> z 1 + z 2 + z 3 − 2 − w < = 0 z_1 + z_2 + z_3 -2 - w<=0 z1+z2+z32w<=0
    where M takes value of 1 (the tightest upper bound of z 1 + z 2 + z 3 − 2 z_1 + z_2 + z_3 -2 z1+z2+z32 )
  • G同学:就是让0-1变量和大m相乘,在再用x去减右端项,然后小于等于0,都先变到这个形式上就好了,类似于万能公式。
  • Z同学:if x > = 0 x>=0 x>=0 then y = 1 y = 1 y=1与if y = 1 t h e n x > = 0 y=1 then x>=0 y=1thenx>=0是等价的吗?
  • L博士:不等价,逻辑不一样。
  • L博士:A: x > = 0 , B : y = 1 x>=0,B:y = 1 x>=0By=1
    A ==> B : if x > = 0 x>=0 x>=0 then y = 1 y = 1 y=1
    A<==B: if y = 1 y=1 y=1 then x > = 0 x>=0 x>=0
    这怎么能等价呢,哈哈
  • Z同学:可是x只有大于等于0和小于0两种情况,对应的就是y等于1。
  • R同学:原命题和逆否命题等价。
  • Z同学:逆否命题这个我明白,但是现在x与y的对应关系就只有两种,反过来说应该也成立的呀?如果优化结果中y等于1,就说明x就必须大于等于0。
  • G同学:不一定呀! 你只说了if x大于等于0的话y=1, 但是不代表y=1,x就一定大于等于0。
  • L博士
    第一种:if x > = 0 x>=0 x>=0 then y = 1 y = 1 y=1等价于逆否命题if y = 0 y = 0 y=0, then x < 0 x<0 x<0
    第二种if y = 1 y=1 y=1 then x > = 0 x>=0 x>=0
    第一种:if y = 0 y = 0 y=0, then x < 0 x<0 x<0 并没有约束 y = 1 y=1 y=1的时候的情况。 y = 1 y=1 y=1的时候,x可以大于0,可以小于0,都行的,都符合你的约束。因为你没约束。
    第二种:if y = 1 y=1 y=1 then$ x>=0 , 你 约 束 , , 你约束, ,y=1$的时候x必须非负。
    这两种显然不等价呀,可行域都完全不一样。
    只有你加入了其他能保证其他情况的约束,你说这些约束联合起来,他两等价还行。但是也不是这个的功劳,是其他约束的功劳。
  • L博士:但是实际中,上述解法可能会导致数值问题。所有MIP求解器都不允许<, >符号的出现,必须是=, >=, <=三者之一, 因此你需要引入一个“epsilon”, 但是这个引入,就有可能会导致数值问题, x - 0.00001 - M y <= 0, 如果这个M<100000, 就可能出问题。
  • Z同学:这是为啥捏? 直观上看不出问题呀!
  • L博士:比如 : x − 0.01 − 100 y < = 0 x -0.01 - 100 y <= 0 x0.01100y<=0,本来是想约束,如果 y = 0 , x < 0 y = 0, x < 0 y=0,x<0的。但是,如果 x = 0.005 x = 0.005 x=0.005,则 0.005 − 0.01 − 0 = − 0.005 < 0 0.005 - 0.01 - 0 = -0.005 <0 0.0050.010=0.005<0。你看,这不是 x = 0.005 > 0 x = 0.005 >0 x=0.005>0嘛, 它也满足你的约束,但是 x > 0 x>0 x>0,你没约束住呀!这就变成了, y = 0 , x = 0.005 y = 0, x = 0.005 y=0,x=0.005, 也满足你的约束。但是他不是你想要的 y = 0 , x < 0 y = 0, x < 0 y=0,x<0
  • Z同学:懂了,我这个epsilon和M需要合理选取. 说起这个,我也有个疑问,我引入了一个 ϵ \epsilon ϵ,与原问题应该就不等价了吧。我原问题的约束条件如果要求x大于0的话,现在让 x > = 0.000001 x>=0.000001 x>=0.000001,如果我的x算出来刚好就是0.000001,岂不是说明原问题的解是不存在的,因为无限逼近于0。
  • L博士:这个你没办法,谁叫你非要弄一个>0和<0的约束呢, 这个问题只能通过其他办法解决, 其他办法指的是:你自己想办法吧!
  • G同学:epsilon一般是问题的右端项,大m是左端的上界。在大于等于或小于等于里一般是没问题的,合理取值都是针对大m。但是如果你非要引入大于或小于的约束,就会出现刚刚师兄说的那种情况。所以要尽量避免这种情况。
  • Z同学:这是不是也可以用indicator约束直接处理呀!
  • L博士:对的, 使劲加GenConstr就行呀!

3.GUROBI中取名的重要性

PS:前两天也看到有人在问,但是想不到在求解器中名字究竟要干啥,今天群里就来素材了。

Discussant(按发言先后)

  1. W同学: 某校研究生
  2. L博士:运小筹主编
  3. Z博士:运筹优化方向博士生
  4. R同学:本次小编(打酱油的)
  5. Y博士:运筹优化方向博士生
  • W同学:请问一下,在gurobi里如果对已有模型进行了拷贝,之后只求解copied model,为什么无法get values of the common variables呢?
  • L博士:你想获取的是原模型的还是copy模型的?
  • W同学:copy模型的, 但这个var是原模型和copy模型共有的。
  • L博士:那你这错误应该就在于:
    .addVar函数会做两个操作:
  1. 创建一个变量,跟model匹配(lazy update),
  2. 将这个变量返回,
    但是这个变量只跟原来的model绑定, 你要是用copy的model去get原模型返回的变量x的值, 那就识别不到了。因为,新copy的模型,与旧模型返回的var已经断开了联系。
    比如:你复印了两份试卷1. 原试卷2. 试卷的copy。你把原试卷给了同学A,然后就把试卷的copy答完了。但是你却问同学A,请问同学,你卷子上第一题的答案是什么啊?A同学显然一脸懵逼。
  • W同学:那如果我对新copy的model做optimize,那这里的x,是原模型的值还是copy的模型的值呢?
  • L博士:原模型啥也没有啊,你都没有解他呢!
  • W同学:对我就说有点不理解,试卷的copy里有第一题。然后我做了这个copy的第一题,为什么还能啥也没有呢?
  • L博士:原试卷是空的啊! 你都没作答呢,哈哈。
  • W同学:那我是不是得对copy的卷子的x做个重命名之类的, 不然c++识别不出来到底是哪道题。
  • L博士:对呀!所以你刚开始建模,一定要给变量起名字。不起名字的话,你copy了之后就找不到了。
  • W同学:好的,本想偷个懒,没想到还得重命名哈哈。
  • L博士:所以呢就是:1. 建立原模型,给变量起名字.2. copy模型.3.求解copy模型.4.获得copy模型的解,通过getVarByName,因为copy模型的时候,内部的变量名字也是在的,你用copy的模型用getVarByName他是可以识别的. 但是,如果你没起名字:1. 建模,把变量返回给A.2. copy模型.3. 求解copy模型.4. 你向A request 解.这个是错误的,A并不知道copy干了什么,他还是依旧没动.因为A是和原模型绑定了的,原模型求解了,A才会动,copy模型动,A是不知道的. 这个逻辑要理清楚,搞懂这些,这种报错就搞定了.。搞定了记得来群里回个话,哈哈,看看灵验不灵验。
  • Z博士:按照克隆人来理解就好啦,你给一个人系一个绳子,栓不住另一个人。不过我在好奇,model对象里存储变量的顺序是不是一样… 如果一样,那也应该可以直接提取,只要做好索引就行。
  • L博士:这个有时候会有问题,并且,按照顺序,我是不建议的. 这个太容易出错, 变量名最好一些.
  • Z博士:嗯嗯肯定起名字最好…就是我特别懒得打字哈哈哈. 不过自己做索引确实容易出错.
  • W同学:呜呜呜好了!!幸好我开始起名字了!!
  • Z博士:我每次最烦的就是变量约束起名字,比给孩子起名字还难.
  • R同学:写代码写变量最讨厌取名字了, 取拼音感觉怪怪的,取缩写又怕忘了,取英文全称有时候又太长。
  • L博士:可别拼音了, 太业余。
  • Y博士有一个专门给变量命名的网站:codelf, 想名字想得脑壳疼的话 可以用 codelf试试。

4.实现决策变量方差最小

PS:前几天美赛的时候就构建了一个这样的目标函数,但是这次聊天记录,让我直接格局打开了!!!

Discussant(按发言先后)

  1. T同学: 某校研究生
  2. Z博士:运筹优化方向博士生
  3. R同学:本次小编(没错又来打酱油了)
  4. K同学:某校研究生
  5. O同学:某校研究生
  • T同学:请问现在有一组决策变量,想设定一个目标函数,让每个决策变量尽可能均匀取值,应该如何设定呢?尽可能是线性表达式。
  • Z博士:决策变量有随机性吗? 均匀取值是说,一堆决策变量之间的额波动性小?
  • T同学:没有随机性,就是离散程度最小。
  • R同学:就是这些决策变量方差尽可能小是吧?
  • T同学:对,是这样
  • K同学:最小化(max - min)?
  • T同学:嗯嗯,感觉这样的确可以
  • Z博士:从统计学的方法呢,就是极差、方差啥的;然后如果这些变量是时间序列的话,那么可以借鉴一些量化金融里边的东西,比如基于股票技术指标构建。
  • K同学:其他方式感觉不太好处理。
  • O同学:设一个新的决策变量x_bar,添加一个约束x_bar==你其他决策变量的均值,然后目标函数就可以设为总偏差,绝对值可以线性化或者直接调求解器求解。
  • Z博士:嗯对的也可以,但是只用均值不够强,还可以加上其他分位点。如果一组数据本身波动很小,那么基本上所有元素都会接近每个quantile.如果你的变量序列中容易出现异常值,那么建议做一些尺度变换处理后再进行上述操作。
  • O同学:他这个问题更多是统计学上的问题,如何选取合适的统计量作为目标函数。
  • Z博士:嗯嗯对的,这不是运筹问题hhh. 选取统计量的时候, 有两种路子, 一种是选一个最合适的,但是可能数学性质不好,需要你线性化。
  • T同学:现在算出来后波动挺大的,所以想固定第一阶段的目标函数值,引入二阶段,让决策变量波动最小, 然后二阶段的目标函数就类似于一个方差的式子。
  • Z博士:总之,找波动性很小的必要条件, 尽量别用方差,会显著增加求解难度,甚至可能会让问题非凸。
  • O同学:其实不用两阶段这么麻烦,直接在你原模型加一条约束,就是你第二阶段目标函数小于等于某一个参数,这个参数就体现了你对决策变量波动的忍受程度。
  • T同学:主要我这个问题最优解有好多种取值方案,所以想保证第一阶段目标函数值不变然后在最优解集里寻找一个更好的, 在第一阶段加约束的话,最优目标值就可能达不到那么好了。
  • O同学:好吧,那确实按你这种方式处理更合适。
  • T同学:尺度变换处理指的是对变量序列先进行标准化类似的操作吗?
  • Z博士:类似,比如robust scaler。
  • T同学:明白,也就是说如果数据波动在一个值附近的话,我可以直接和这个值进行作差。
  • Z博士:那当然,但是一般情况下,你不知道他在哪个位置附近,甚至可能数据本身很分散或有异常值. 在不引入其他非线性操作(异常检测、平稳性检测)的情况下 ,我说的这种应该还算一种“heuristic”。
  • T同学:这里有一个小疑问,我这些x是待求的变量,但是robust scaler是对已知样本序列进行scaler的方法,也可以用吗?
  • Z博士:那你选一个能算出来的scaling方法就好了呀!
  • T同学:我是需要把scaling方法加入在约束条件中,然后目标函数对scaling后的决策变量进行处理吗?
  • Z博士:比如最大最小值标准化,那就是先写出标准化以后的每个变量的表达式(可以通过约束实现这一点)。然后再设计针对每个变量的极差目标。
  • T同学:感谢!我试一下哪种方式合理一点。感觉很多标准化方法引入约束后都是非线性的,会限制发挥。

5.招聘|会议

ps:选取部分有链接,获取更多资讯可加入读者群
会议部分:
1.https://mp.weixin.qq.com/s/8iLR-JLl2udPiEdtBLoFkg
2. https://mp.weixin.qq.com/s/e7XCMfHbSdiRD5VG79TITQ
3. https://mp.weixin.qq.com/s/11zoZCSVB5jt5jpj3SO1AA
招聘部分:
1.https://mp.weixin.qq.com/s/P3tQQpmATiEuSj5ZTU2X9g
2.https://mp.weixin.qq.com/s/39-huvrq9PF8hpSmRSpAHA

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值