2022-06-14至2022-08-11 关于复现MKP算法的总结与反思
Prerequisite
自2022年6月14日至2022年8月11日的时间内,我致力于完成A Hybrid Approach for the 0–1 Multidimensional Knapsack problem 论文的复现工作,此次是我第一次进行组合优化方向的学习工作,下面介绍该工作内容发展过程以及该工作结束后的总结反思。
Introduction of — A Hybrid Approach for the 0–1 Multidimensional Knapsack problem
01 knapsack
众所周知的01背包问题,formulation如下所示

MKP 01
将knapsack 01问题可归约为MKP 01
即现在不仅仅是一个单独的属性容量限制,有多个属性容量限制,在满足所有容量限制的情况下要使得背包中的物品价值最大。

method introduction
A Hybrid Approach for the 0–1 Multidimensional Knapsack problem是结合 linear programming & Tabu Search ,实现一个优化的启发式算法来解决MKP01

该方法分为两个步骤,具体如下:
Phase 1: simplex phase
计算解决松弛的MKP来得到一个带小数的最优解
此阶段需要用到整数规划,此处用的是IBM的商业求解器CPLEX


Phase 2: TS phase
在Phase1得到的最优解附近利用禁忌算法搜索
- Search Space Reduction to gain the Neighborhood

2)Tabu management: Tabu list 通过RCS和running list来实现更新
running list:记录当前所有的迭代
RCS:每一次更新running list后,RCS就会通过回溯running list得到当前需要禁忌的对象,以更新tabu list。
3)Evaluation Function
评价函数:MKP中每一个解的评价函数的值是该解超出约束的值
Complish the Code
之前只是看着题目刷题,第一次做照着方法写代码的工作,下面是在coding时遇到的技术学习:
1)增强了C和部分C++语言的掌握能力,如多维数组排序、复杂函数调用、vector容器使用等,能够自主实现所需求的功能。
2)掌握对CPLEX的使用
3)目前debug仅仅只会通过cout和exit一起来间接查看错误点。
Problems
下图表示某一个instance的效果,其中p1的z*表示论文要求效果,p2的z_min表示目前所达到效果。

以下几点为当时推测问题点:
随机数

1、delta[k] = 2 * (u + q - k)
2、delta_max ≈ delta[k]
论文中未给出delta_max具体为多少,因此猜测:
delta_max = delta[k] + rand
经过不断尝试随机值后,效果有一定的改善,但该随机值并未固定。这是每换一个例子且得到效果差时,我第一个进行不断调整的数。
k值的计算
利用在introduction中提及的k值计算方法,paper中得到的值为130(instance 1),与我们得到的值有[1,10]的差距,因此继续检查k的计算方法,其中涉及到z(如下图所示),在paper中仍未给出具体的计算方法,因此一直在自行调整。

Conclusion
虽然最终算法性能未完全复现,但是在此过程中仍然获得了启发式学习的知识、代码能力增强、自我学习能力增强等等。
1)精确算法和启发式算法的学习。例如在coding中就分别使用了CPLEX和Tabu Search。
2)文献的阅读。一开始,一些术语例如“relaxed”, "benchmark"等都不明白是什么,阅读进度很慢,我也很难理解内容。现采用方法:“先读abstarct(了解论文的大致方法)再分别去对应章节细读“。
3) Coding。第一次按照论文给出算法写的代码中,每一个函数里几乎都存在bug。其中总是在数组的长度上出现越界的情况上出错,最开始还找不到哪里出错,也不太会debug,甚至一行一行肉眼看代码来找问题点,后来学会用输出和assert来debug(当然现在是会用断点了)。
4) 碰到一些例子效果不好的情况,总是在一些小地方一直调,想掩盖代码的问题。但这样几乎是无济于事。
Code
下面放出当时的复现代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <time.h>
#include <vector>
#include <math.h>
#include <algorithm>
#include<ilcplex/ilocplex.h>
using namespace std;ILOSTLBEGINstring File_Name;
int **R;
int *P;
int *B;
int N;
int M;
int k ;
int randZ;
vector<float> x_bar;
int seed = 15;void Initializing() {int i;int j;ifstream FIC;ofstream FIC2;FIC.open(File_Name);if (FIC.fail()) {cout << "### Error open, File_Name " << File_Name << endl;exit(0);}FIC >> N >> M;P = new int [N];B = new int [N];R = new int *[M];for(i = 0; i < M; i++) {R[i] = new int [N];}while (! FIC.eof()){for(i = 0; i < N; i++) {FIC >> P[i];}for(i = 0; i < M; i++) {for(j = 0; j < N; j++) {FIC >> R[i][j];//[属性][物品]}}for(j = 0;j < M;j++) {FIC >> B[j];}}FIC.close();
}void Initializing2()
{int i,j;ifstream FIC;ofstream FIC2;FIC.open(File_Name);if (FIC.fail()){cout << "### Erreur open, File_Name " << File_Name << endl;exit(0);}FIC >> N >> M;P = new int [N];B = new int [N];R = new int *[M];for(i = 0; i < M; i++) {R[i] = new int [N];}while (! FIC.eof()){for(i = 0; i < N; i++) {FIC >> P[i];}for(j = 0; j < M; j++) {FIC >> B[j];}for(i = 0; i < M; i++) {for(j = 0; j < N; j++) {FIC >> R[i][j];}}}FIC.close();
}bool cmp1(float a[], float b[])
{return a[0] > b[0];
}bool cmp2(float a[], float b[])
{return a[0] < b[0];
}typedef IloArray<IloIntVarArray> IntVarMatrix;
typedef IloArray<IloNumVarArray> NumVarMatrix;
typedef IloArray<IloIntArray> IntMatrix;
typedef IloArray<IloNumArray> NumMatrix;int computeValue (vector<int> &x) {int value = 0;for(int i = 0; i < N; i++)value += x[i] * P[i];return value;
}int computeV_b(vector<int> &x) {vector<int> A(M, 0);int v_b = 0;for(int i = 0; i < M; i++) {for(int j = 0; j < N; j++) {A[i] += R[i][j] * x[j];}if(A[i] > B[i]) {v_b += A[i] - B[i];}}return v_b;
}void computeZ()
{float **M2 = new float*[N];int i;int num = rand() % (N / 10 + 1) + N / 10;//[N/10,N/5] instances:1-4,6-8
// int num = rand() % (N / 20 + 1) + N / 10;//[N/10,3*N/20] instance:5
// int num = rand() % (N / 144 + 1) + N / 8;// [8/N,19N/144] instances:9-10
// int num =rand() % (N / 224 + 1) + 15 * N / 112;//[15N/112,N/7] instance:11for(i = 0; i < N; i++) {M2[i] = new float[2];M2[i][0] = P[i];M2[i][1] = i;}sort(M2, M2 + N, cmp2);vector<int> x_1(N, 0);vector<int> x_2(N, 0);int v_b;int item = 0;do {x_1[M2[item][1]] = 1;v_b = computeV_b(x_1);if(v_b > 0) {x_1 = x_2;break;}else {x_2 = x_1;}item++;}while (item < num);randZ = computeValue(x_2);
}int computeK_max() {IloEnv env;IloModel model( env );IloInt i;IloInt j;IloNumVarArray X(env, N, 0, 1,ILOFLOAT);IloExpr k_max(env);IloNumArray x( env, N );for( i = 0; i < M; i++ ) {IloExpr v1( env );for( j = 0; j < N; j++ )v1 += (R[i][j] * X[j]);model.add( v1 <= B[i]);}IloExpr v2( env );for( i = 0; i < N; i++) {v2 += X[i] * P[i];k_max += X[i];}model.add( v2 >= randZ + 1);model.add(IloMaximize(env, k_max));IloCplex cplex(model);cplex.setOut(env.getNullStream());cplex.setParam(IloCplex::Param::RandomSeed,seed);cplex.setParam(IloCplex::Param::Threads, 1);cplex.solve();cplex.getValues(x, X);double obj = cplex.getObjValue();env.end();return ceil(obj);
}int computeK_min() {IloEnv env;IloModel model(env);IloInt i;IloInt j;IloNumVarArray X(env, N, 0, 1,ILOFLOAT);IloExpr k_min(env);IloNumArray x(env, N);for(i = 0; i < M; i++) {IloExpr v1(env);for( j = 0; j < N; j++ ) {v1 += (R[i][j] * X[j]);}model.add( v1 <= B[i]);}IloExpr v2( env );for(i = 0; i < N; i++) {v2 += X[i] * P[i];k_min += X[i];}model.add(v2 >= randZ + 1);model.add(IloMinimize(env, k_min));IloCplex cplex(model);cplex.setOut(env.getNullStream());cplex.setParam(IloCplex::Param::RandomSeed,seed);cplex.setParam(IloCplex::Param::Threads, 1);cplex.solve();cplex.getValues(x, X);double obj = cplex.getObjValue();env.end();return floor(obj);}float *computeX_bar() {IloEnv env;IloModel model(env);IloInt i;IloInt j;IloNumArray x(env, N);IloExpr value(env);IloNumVarArray X(env, N, 0.0, 1.0,ILOFLOAT);IloExpr sum(env);for (i = 0; i < M; i++) {IloExpr v(env);for( j = 0; j < N; j++ ) {v += (R[i][j] * X[j]);}model.add( v <= B[i] );}for(i = 0; i < N; i++)value += (P[i] * X[i]);for(i = 0; i < N; i++)sum += X[i];model.add(sum == k);model.add(IloMaximize(env, value));IloCplex cplex(model);cplex.setOut(env.getNullStream());cplex.setParam(IloCplex::Param::RandomSeed,seed);cplex.setParam(IloCplex::Param::Threads, 1);cplex.solve();cplex.getValues(x, X);env.end();float *x_bar = new float[N];for(i = 0; i < N; i++) {x_bar[i] = x[i];}return x_bar;
}void swap(float* &a) {for(int i = 0; i < N; i++)x_bar.push_back(a[i]);
}int computeSum(vector<int> &x) {int sum = 0;for(int i = 0; i < N; i++) {sum += x[i];}return sum;
}vector<int> computeXinit () {float **M = new float*[N];for(int i = 0; i < N; i++) {M[i] = new float[2];M[i][0] = x_bar[i];M[i][1] = i ;}sort(M, M + N, cmp1);int index[N];for(int i = 0; i < N; i++) {index[i] = M[i][1];}vector<int> x_init(N,0);for(int i = 0; i < k; i++) {x_init[index[i]] = 1;}return x_init;
}float computeBias(vector<int> &x) {float bias = 0;for(int l = 0; l < N; l++) {bias += abs(x[l] *1.0 - x_bar[l]);}return bias;
}int main(int argc, char **argv)
{string outfilename;string data_out;File_Name = "/Users/jiangtongjun/Library/Containers/com.tencent.xinWeChat/Data/Library/Application\ Support/com.tencent.xinWeChat/2.0b4.0.9/396ec1d845a72fdc3aaa185bb6f9c7eb/Message/MessageTemp/aef63e547d5e98cce87554f37a88a811/File/benchmark2/MK_GK7.DAT";srand(seed);
// Initializing();Initializing2();int erl = 0;int i;int j;int v_b;int z_min = 0;int z_max;int z;int iter = 0;int v_min;float bias;int bias_max;float bias_old;int i2 = 0;int j2 = 0;int flag;int h = 0;int *RL = new int[500000];int **tabu = new int*[N];int *x_best = new int[N];vector<int> RCS;vector<int> x_temp2;int *IW = new int[M];int *IW_new= new int[M];float *x = new float[N];float *xBar = new float[N];int z_old;int e = 1000;time_t now_time=time(NULL);tm* t_tm = localtime(&now_time);time_t mk_time_1 = mktime(t_tm);int l;for(i = 0; i < N; ++i) {tabu[i] = new int[N];}for(i = 0; i < N; ++i) {for(j = 0; j < N; ++j) {tabu[i][j] = -1;}}computeZ();k = computeK_max() - computeK_min() + 1;cout<<"k:"<<k<<endl;float *x_temp = computeX_bar();swap(x_temp);int u = 0;int q = 0;for(i = 0; i < N; ++i) {if((x_bar[i] > 0.0) && (x_bar[i] < 1.0)) {q++;}else if( x_bar[i] == 1.0 ) {u++;}}bias_max = 2 * (q + u - k) - 10;cout<<"bias_max:"<<bias_max<<endl;x_temp2 =computeXinit();for(i = 0; i < N; ++i) {x[i] = x_temp2[i];}for(i = 0; i < N; ++i) {xBar[i] = x_bar[i];}for(i = 0; i < M; ++i) {IW[i] = 0;for(j = 0; j < N; j++) {IW[i] += R[i][j] * x[j];}}z = computeValue(x_temp2);v_b = computeV_b(x_temp2);bias = computeBias(x_temp2);if (v_b == 0) {z_min = z;for (i = 0; i < N; ++i)x_best[i] = x[i];}else {z_min = 0;for( l = 0; l < N; ++l)x_best[l] = 0;}while ((v_min < INT_MAX) && (erl < 500000)) {v_min = INT_MAX;z_max = INT_MIN;for(i = 0; i < N; ++i) {for(j = i + 1; j < N; ++j) {if (x[i]+x[j] != 1) {continue;}if(tabu[i][j] != iter) {bias_old = bias;x[i] = 1 - x[i];x[j] = 1 - x[j];if(bias > bias_max - 2.0)bias = bias - abs(1 - x[i] * 1.0 - xBar[i]) - abs(1 - x[j] * 1.0 - xBar[j]) + abs(x[i] * 1.0 - xBar[i]) + abs(x[j] * 1.0 - xBar[j]);if(bias > bias_max) {x[i] = 1 - x[i];x[j] = 1 - x[j];bias = bias_old;continue;}z_old = z;if(x[i] == 1) {z = z + P[i];}else {z = z - P[i];}if(x[j] == 1) {z = z + P[j];}else {z = z - P[j];}if (z <= z_min) {x[i] = 1 - x[i];x[j] = 1 - x[j];z = z_old;bias = bias_old;continue;}v_b = 0;for(h = 0; h < M; ++h) {IW_new[h] = IW[h];if(x[i] == 1)IW_new[h] += R[h][i];elseIW_new[h] -= R[h][i];if(x[j] == 1)IW_new[h] += R[h][j];elseIW_new[h] -= R[h][j];if(IW_new[h] > B[h])v_b += IW_new[h] - B[h];}if((v_b < v_min) || ((v_b == v_min)&&(z > z_max))) {i2 = i;j2 = j;v_min = v_b;z_max = z;}x[i] = 1 - x[i];x[j] = 1 - x[j];z = z_old;bias = bias_old;}}}if (v_min != INT_MAX) {x[i2] = 1 - x[i2];x[j2] = 1 - x[j2];bias = bias - abs(1 - x[i2] * 1.0 - xBar[i2]) - abs(1 - x[j2] * 1.0 - xBar[j2]) + abs(x[i2] * 1.0 - xBar[i2]) + abs(x[j2] * 1.0 - xBar[j2]);z = z_max;for(h = 0; h < M; ++h) {if(x[i2] == 1) {IW[h] += R[h][i2];}else {IW[h] -= R[h][i2];}if(x[j2] == 1) {IW[h] += R[h][j2];}else {IW[h] -= R[h][j2];}}if (v_min == 0) {erl = 0;z_min = z;cout << "z_min :"<< z_min <<endl;for(i = 0; i < N; ++i) {x_best[i] = x[i];}}else {iter++;RL[erl++] = i2;RL[erl++] = j2;i = erl;while(i != 0) {--i;j = RL[i];flag = 0;if(find(RCS.begin(), RCS.end(), j) != RCS.end()) {RCS.erase(std::remove(RCS.begin(), RCS.end(), j), RCS.end());flag = 1;}if(flag == 0) {RCS.push_back(j);}if(RCS.size() == 2) {tabu[RCS[0]][RCS[1]] = iter;tabu[RCS[1]][RCS[0]] = iter;}}RCS.resize(0);}}time_t now_time=time(NULL);tm* t_tm = localtime(&now_time);time_t mk_time_2 = mktime(t_tm);if(mk_time_2 - mk_time_1 > 36000)break;if(iter > e) {cout << iter << " "<<erl <<endl;e += 1000;}}cout <<"Z_min:" << z_min << endl;
}
最后,感谢Dr.He
相关文章:
2022-06-14至2022-08-11 关于复现MKP算法的总结与反思
Prerequisite 自2022年6月14日至2022年8月11日的时间内,我致力于完成A Hybrid Approach for the 0–1 Multidimensional Knapsack problem 论文的复现工作,此次是我第一次进行组合优化方向的学习工作,下面介绍该工作内容发展过程以及该工作结…...
IBMMQ教程二(window版安装)
下载下载地址:https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/我这里选择的是9.1.0.0版本安装将下载完成的压缩包解压双击Setup.exe直接运行点击软件需求查看系统配置是否满足,右边绿色的对号说明满足需求,…...
Java | HashSet 语法
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的,即不会记录插入的顺序。 HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须…...
js学习4(运算符)
### 1.算数运算符: 、-、*、\、%(取余)、**(幂方) ## 优先级 同数学课程,可以加括号 ### 2.自增和自减 、--(即数值变量加一或减一) ### 3.赋值运算符 、、-、*、/、... ### 4.比较运…...
2月更新 | Visual Studio Code Python
我们很高兴地宣布,2023年2月版 Visual Studio Code Python 和 Jupyter 扩展现已推出!此版本包括以下改进:从激活的终端启动 VS Code 时的自动选择环境 使用命令 Python: Create Environmen 时可选择需求文件或可选依赖项 预发布:改…...
C++回顾(十八)—— 文件操作
18.1 I/O流概念和流类库结构 1 概念 程序的输入指的是从输入文件将数据传送给程序,程序的输出指的是从程序将数据传送给输出文件。 C输入输出包含以下三个方面的内容: (1)对系统指定的标准设备的输入和输出。即从键盘输入数据&am…...
以java编写员工管理系统(测试过 无问题)
一、系统结果的部分展示 二、题目以及相关要求 三、组成 1.该系统由 Employee 类 、commonEmployee类、Testemd类和managerEmployee类组成 2.Employee实现的代码 public class Employee {private String id;private String name;private String job;private int holiday…...
单例模式之懒汉式
在上篇文章中,我们讲了单例模式中的饿汉式,今天接着来讲懒汉式。 1.懒汉式单例模式的实现 public class LazySingleton {private static LazySingleton instance null;// 让构造函数为private,这样该类就不会被实例化private LazySingleto…...
1638_chdir函数的功能
全部学习汇总:GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 今天看一个半生不熟的小函数,chdir。说半生不熟,是因为这个接口一看就知道是什么功能。然而,这个接口如何用可真就没啥想法了。 …...
使用CEF 获得某头条请求,并生成本地文件的方法
目录 一、获得网站请求响应信息 1、响应过滤 2、匹配过滤URL的函数 3、获得请求响应后的处理...
二十、Django-restframework之视图集和路由器
一、视图集和路由器 REST框架包含了一个处理视图集的抽象,它允许开发人员集中精力建模API的状态和交互,并根据通用约定自动处理URL构造。 视图集类与视图类几乎相同,不同之处在于它们提供的是retrieve或update等操作,而不是get或…...
[深入理解SSD系列 闪存实战2.1.2] SLC、MLC、TLC、QLC、PLC NAND_固态硬盘闪存颗粒类型
闪存最小物理单位是 Cell, 一个Cell 是一个晶体管。 闪存是通过晶体管储存电子来表示信息的。在晶体管上加入了浮动栅贮存电子。数据是0或1取决于在硅底板上形成的浮动栅中是否有电子。有电子为0,无电子为1. SSD 根据闪存颗粒区分,固态硬盘有SLC、MLC、TLC、QLC、PLC 五种类型…...
论文阅读-MGTAB: A Multi-Relational Graph-Based Twitter Account DetectionBenchmark
目录 摘要 1. 引言 2. 相关工作 2.1. 立场检测 2.2.机器人检测 3.数据集预处理 3.1.数据收集和清理 3.2.专家注释 3.3. 质量评估 3.4.特征分析 4. 数据集构建 4.1.特征表示构造 4.2.关系图构建 5. 实验 5.1.实验设置 5.2.基准性能 5.3训练集大小的研究 5.4 社…...
基于libco的c++协程实现(时间轮定时器)
在后端的开发中,定时器有很广泛的应用。 比如: 心跳检测 倒计时 游戏开发的技能冷却 redis的键值的有效期等等,都会使用到定时器。 定时器的实现数据结构选择 红黑树 对于增删查,时间复杂度为O(logn),对于红黑…...
java多线程与线程池-04线程池与AQS
第7章 线程池与AQS java.util.concurrent包中的绝大多数同步工具,如锁(locks)和屏障(barriers)等,都基于AbstractQueuedSynchronizer(简称AQS)构建而成。这个框架提供了一套同步管理的通用机制,如同步状态的原子性管理、线程阻塞与解除阻塞,还有线程排队等。 在JD…...
优化模型验证关键代码25:样本均值近似技术处理两阶段随机旅行商问题及Gurobipy代码验证
大多数数学规划模型都会考虑到研究问题中存在的不确定性,针对这些不确定性,两种常用的处理方法是鲁棒优化和随机规划。这篇论文我们关注后者,也就是两阶段随机旅行商问题;利用套期保值算法计算不同规模TSP的可行解,同时比较了样本均值近似技术的解的情况,并计算了该问题的…...
老爸:“你做的什么游戏测试简直是不务正业!”——我上去就是一顿猛如虎的解释。
经常有人问我:游戏测试到底是干什么呢?是游戏代练?每天玩游戏?装备随便造,怪物随便秒,线上GM指令随便用?可以每天玩玩游戏,不用忙工作,太爽了?有时朋友不理解…...
JVM垃圾回收调优知识点整理
目录 1、JVM内存模型 1.2、堆及垃圾回收 1.3、JVM参数设置经验: 1.4、对象逃逸分析:...
linux安装mysql-8.0.31
1)、下载mysql-8.0.31压缩包两种方式 a.本地下载后上传服务器解压,下载地址:https://downloads.mysql.com/archives/community/ b.服务器使用命令下载,注意:路径在那,就下载到那个位置。 wget https://dev.mysql.com/…...
2023 年会是网络安全的关键年吗?
过去 12 个月对网络安全领域和周围的每个人来说再次充满挑战。和往年不同,感觉很不一样,攻击源源不断。过去,大型漏洞每季度发生一次,但在过去一年中,在某些情况下,我们几乎每周都会处理严重漏洞。 已知利…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
