基于or-tools的护士排班问题建模求解

news2024/12/23 0:13:58

基于or-tools的护士排班问题建模求解

  • 护士排班问题(Nurse Rostering Problem,NRP)
  • ortools官网例题1:A nurse scheduling problem
    • 代码解析
    • 完整代码
  • ortools官网例题2:Scheduling with shift requests
    • 代码解析
    • 完整代码

)

护士排班问题(Nurse Rostering Problem,NRP)

护士排班问题(Nurse Rostering Problem,NRP)或护士排程问题( nurse scheduling problem,NSP)是员工调度问题(Employee Scheduling)的一种。医院需要反复为护理人员制作值班表,通常情况下,护理人员要花费大量的时间来编制值班表,特别是在有许多工作人员提出要求的情况下,而且在处理对当前值班表的临时更改时可能会花费更多的时间。由于人工调度繁琐、耗时,以及其他种种原因,护士排班问题(NRP)或护士排程问题(NSP)引起了人们的广泛关注。

相关文献:

  • http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.1030.5363&rep=rep1&type=pdf
  • https://arxiv.org/pdf/1804.05002.pdf

ortools官网例题1:A nurse scheduling problem

or-tools官网给出了一个使用CP-SAT求解器解决NRP的算例(https://developers.google.cn/optimization/scheduling/employee_scheduling#java_4):
医院主管需要满足一个为期 3 天的护士计划,让其在 3 天内满足 4 个护士的条件,但需满足以下条件:

  1. 每个班次(shift)分为三个 8 小时。
  2. 每天,每个班次都会分配给一名护士,而每个护士都不例外。
  3. 在这 3 天时间里,每个护士都至少分配到两次班次。

∑ s = 1 S x n d s = 1 , ∀ d = 1 , 2 , ⋯   , D ; n = 1 , 2 , ⋯   , N ∑ s = 1 S x n d s ≤ 1 , ∀ S × D N ≤ ∑ d = 1 D ∑ n = 1 N x n d s ≤ S × D N + ( S × D ) % N , ∀ s = 1 , 2 , ⋯   , S \sum_{s=1}^Sx_{nds}=1, \quad \forall d=1,2,\cdots,D ; n=1,2,\cdots,N \\ \sum_{s=1}^Sx_{nds} \leq 1,\quad \forall \\ \frac{S \times D}{N} \leq \sum_{d=1}^D\sum_{n=1}^Nx_{nds} \leq \frac{S \times D}{N}+(S \times D)\%N, \quad \forall s=1,2,\cdots,S s=1Sxnds=1,d=1,2,,D;n=1,2,,Ns=1Sxnds1,NS×Dd=1Dn=1NxndsNS×D+(S×D)%N,s=1,2,,S

代码解析

1、导入ortools库

from ortools.sat.python import cp_model

2、构造数据

num_nurses = 4  # 护士人数
num_shifts = 3  # 每天有3个班次
num_days = 3  # 3天
all_nurses = range(num_nurses)
all_shifts = range(num_shifts)
all_days = range(num_days)

3、创建模型

model = cp_model.CpModel()

4、创建变量

# 如果将 班次s在d天分配给护士n,则等于 1
shifts = {}
for n in all_nurses:
    for d in all_days:
        for s in all_shifts:
            shifts[(n, d, s)] = model.NewBoolVar(f"shift_n{n}_d{d}_s{s}")

5、约束条件

# 每天每个班次都会分配给一名护士:每天每个班次分配的护士人数之和=1
for (int d : allDays) {
  for (int s : allShifts) {
    List<Literal> nurses = new ArrayList<>();
    for (int n : allNurses) {
      nurses.add(shifts[n][d][s]);
    }
    model.addExactlyOne(nurses);
  }
}
# 每个护士每天最多上一个班次
for n in all_nurses:
    for d in all_days:
        model.AddAtMostOne(shifts[(n, d, s)] for s in all_shifts)

每个护士上的班次尽可能均分,有4个护士,3天*3班次/天=9班次
则每个护士平均分配9 / 4 = 2.25班次,则每个护士至少上2个班次,至多上3个班次。

# Try to distribute the shifts evenly, so that each nurse works
# min_shifts_per_nurse shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of nurses, some nurses will
# be assigned one more shift.
min_shifts_per_nurse = (num_shifts * num_days) // num_nurses
if num_shifts * num_days % num_nurses == 0:
    max_shifts_per_nurse = min_shifts_per_nurse
else:
    max_shifts_per_nurse = min_shifts_per_nurse + 1
for n in all_nurses:
    shifts_worked = []
    for d in all_days:
        for s in all_shifts:
            shifts_worked.append(shifts[(n, d, s)])
    model.Add(min_shifts_per_nurse <= sum(shifts_worked))
    model.Add(sum(shifts_worked) <= max_shifts_per_nurse)

6、设置模型参数

# 在非优化模型中,可以启用对所有解决方案的搜索
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Enumerate all solutions.
solver.parameters.enumerate_all_solutions = True

7、调用回调函数

class NursesPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
    """Print intermediate solutions."""

    def __init__(self, shifts, num_nurses, num_days, num_shifts, limit):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self._shifts = shifts
        self._num_nurses = num_nurses
        self._num_days = num_days
        self._num_shifts = num_shifts
        self._solution_count = 0
        self._solution_limit = limit

    def on_solution_callback(self):
        self._solution_count += 1
        print(f"Solution {self._solution_count}")
        for d in range(self._num_days):
            print(f"Day {d}")
            for n in range(self._num_nurses):
                is_working = False
                for s in range(self._num_shifts):
                    if self.Value(self._shifts[(n, d, s)]):
                        is_working = True
                        print(f"  Nurse {n} works shift {s}")
                if not is_working:
                    print(f"  Nurse {n} does not work")
        if self._solution_count >= self._solution_limit:
            print(f"Stop search after {self._solution_limit} solutions")
            self.StopSearch()

    def solution_count(self):
        return self._solution_count

# Display the first five solutions.
solution_limit = 5
solution_printer = NursesPartialSolutionPrinter(
    shifts, num_nurses, num_days, num_shifts, solution_limit
)

8、调用求解器求解

solver.Solve(model, solution_printer)

完整代码

import numpy as np
from ortools.sat.python import cp_model
import collections

num_nurses = 4  # 护士人数
num_shifts = 3  # 每天有3个班次
num_days = 3  # 3天
all_nurses = range(num_nurses)
all_shifts = range(num_shifts)
all_days = range(num_days)

print(all_nurses)

model = cp_model.CpModel()

# 如果将 班次shift s 在d天分配给护士n,则等于 1
shifts = {}
for nurse in all_nurses:
    for day in all_days:
        for shift in all_shifts:
            shifts[(nurse, day, shift)] = model.NewBoolVar(f"nurse{nurse}_day{day}_shift{shift}")

# 每天每个班次都会分配给一名护士:每天每个班次分配的护士人数之和=1
# Each shift is assigned to a single nurse per day.
for day in all_days:
    for shift in all_shifts:
        model.AddExactlyOne(shifts[(nurse, day, shift)] for nurse in all_nurses)

# 每个护士每天最多上一个班次
for nurse in all_nurses:
    for day in all_days:
        model.AddAtMostOne(shifts[(nurse, day, shift)] for shift in all_shifts)

"""
每个护士上的班次尽可能均分,有4个护士,3天*每天3班次=9班次
则每个护士平均9 // 4 = 2
"""
# Try to distribute the shifts evenly, so that each nurse works
# min_shifts_per_nurse shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of nurses, some nurses will
# be assigned one more shift.
min_shifts_per_nurse = (num_shifts * num_days) // num_nurses
if num_shifts * num_days % num_nurses == 0:
    max_shifts_per_nurse = min_shifts_per_nurse
else:
    max_shifts_per_nurse = min_shifts_per_nurse + 1
for n in all_nurses:
    shifts_worked = []
    for d in all_days:
        for s in all_shifts:
            shifts_worked.append(shifts[(n, d, s)])
    model.Add(min_shifts_per_nurse <= sum(shifts_worked))
    model.Add(sum(shifts_worked) <= max_shifts_per_nurse)

# 在非优化模型中,可以启用对所有解决方案的搜索
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Enumerate all solutions.
solver.parameters.enumerate_all_solutions = True


class NursesPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
    """Print intermediate solutions."""
    """
    调用回调函数,打印中间结果
    """

    def __init__(self, shifts, num_nurses, num_days, num_shifts, limit):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self._shifts = shifts
        self._num_nurses = num_nurses
        self._num_days = num_days
        self._num_shifts = num_shifts
        self._solution_count = 0
        self._solution_limit = limit

    def on_solution_callback(self):
        self._solution_count += 1
        so = np.zeros(shape=(num_days, num_shifts), dtype=np.int64)

        print(f"Solution {self._solution_count}")
        for d in range(self._num_days):
            # print(f"Day {d}")
            for n in range(self._num_nurses):
                is_working = False
                for s in range(self._num_shifts):
                    if self.Value(self._shifts[(n, d, s)]):
                        is_working = True
                        # print(f"  Nurse {n} works shift {s}")
                        so[d][s] = n
                if not is_working:
                    # print(f"  Nurse {n} does not work")
                    pass
        if self._solution_count >= self._solution_limit:
            print(f"Stop    search after {self._solution_limit} solutions")
            self.StopSearch()

        print(f'        shift1  shift2  shift3')
        for i in range(len(so)):
            print(f'day{i + 1}', end='\t')
            for j in range(len(so[i])):
                print(f'nurse{so[i][j] + 1}', end='\t')
            print()

    def solution_count(self):
        return self._solution_count


# Display the first five solutions.显示前5个解
solution_limit = 5
solution_printer = NursesPartialSolutionPrinter(
    shifts, num_nurses, num_days, num_shifts, solution_limit
)
solver.Solve(model, solution_printer)

输出结果为:

ortools官网例题2:Scheduling with shift requests

例题2相比于例题1,增加了特定班次的护士需求,目标函数为最大化护士需求满足的人数(尽可能满足护士需求)。对于大多数调度问题,输出所有解不太可能,因此需要有一个目标函数。例题2和例题1约束条件相同。

代码解析

1、导入库

from ortools.sat.python import cp_model

2、导入数据
shift_requests 是一个5 * 7 * 3的矩阵,表示5个护士7天,每一天3个班次的值班需求。如shift[2][0][1]代表护士护士2在第0天想上班次1。

num_nurses = 5 
num_shifts = 3
num_days = 7
all_nurses = range(num_nurses)
all_shifts = range(num_shifts)
all_days = range(num_days)
shift_requests = [
    [[0, 0, 1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1]],
    [[0, 0, 0], [0, 0, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 0], [0, 0, 1]],
    [[0, 1, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 1, 0], [0, 0, 0]],
    [[0, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]],
    [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0]],
]

3、创建模型

model = cp_model.CpModel()

4、模型变量

shifts = {}
for n in all_nurses:
    for d in all_days:
        for s in all_shifts:
            shifts[(n, d, s)] = model.NewBoolVar(f"shift_n{n}_d{d}_s{s}")

5、约束条件

for d in all_days:
    for s in all_shifts:
        model.AddExactlyOne(shifts[(n, d, s)] for n in all_nurses)
for n in all_nurses:
    for d in all_days:
        model.AddAtMostOne(shifts[(n, d, s)] for s in all_shifts)
# Try to distribute the shifts evenly, so that each nurse works
# min_shifts_per_nurse shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of nurses, some nurses will
# be assigned one more shift.
min_shifts_per_nurse = (num_shifts * num_days) // num_nurses
if num_shifts * num_days % num_nurses == 0:
    max_shifts_per_nurse = min_shifts_per_nurse
else:
    max_shifts_per_nurse = min_shifts_per_nurse + 1
for n in all_nurses:
    num_shifts_worked = 0
    for d in all_days:
        for s in all_shifts:
            num_shifts_worked += shifts[(n, d, s)]
    model.Add(min_shifts_per_nurse <= num_shifts_worked)
    model.Add(num_shifts_worked <= max_shifts_per_nurse)

5、目标函数

# pylint: disable=g-complex-comprehension
model.Maximize(
    sum(
        shift_requests[n][d][s] * shifts[(n, d, s)]
        for n in all_nurses
        for d in all_days
        for s in all_shifts
    )
)

这里python用了嵌套的列表推导式,转换成一般写法,更直观:

expr = 0
for n in all_nurses:
    for d in all_days:
        for s in all_shifts:
            expr += shift_requests[n][d][s] * shifts[(n, d, s)]
model.Maximize(expr)

6、调用求解器

solver = cp_model.CpSolver()
status = solver.Solve(model)

solver.Solve(model)返回的是求解状态(是否得到最优解、可行解等),这里可以从Java语法来看返回值类型,更直观,以上两行代码等价于:

CpSolver solver = new CpSolver();
CpSolverStatus status = solver.solve(model);

7、结果输出

if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
  System.out.printf("Solution:%n");
  for (int d : allDays) {
    System.out.printf("Day %d%n", d);
    for (int n : allNurses) {
      for (int s : allShifts) {
        if (solver.booleanValue(shifts[n][d][s])) {
          if (shiftRequests[n][d][s] == 1) {
            System.out.printf("  Nurse %d works shift %d (requested).%n", n, s);
          } else {
            System.out.printf("  Nurse %d works shift %d (not requested).%n", n, s);
          }
        }
      }
    }
  }
  System.out.printf("Number of shift requests met = %f (out of %d)%n", solver.objectiveValue(),
      numNurses * minShiftsPerNurse);
} else {
  System.out.printf("No optimal solution found !");
}

完整代码

"""Nurse scheduling problem with shift requests."""
from ortools.sat.python import cp_model


def main():
    # This program tries to find an optimal assignment of nurses to shifts
    # (3 shifts per day, for 7 days), subject to some constraints (see below).
    # Each nurse can request to be assigned to specific shifts.
    # The optimal assignment maximizes the number of fulfilled shift requests.
    num_nurses = 5
    num_shifts = 3
    num_days = 7
    all_nurses = range(num_nurses)
    all_shifts = range(num_shifts)
    all_days = range(num_days)
    shift_requests = [
        [[0, 0, 1], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 1]],
        [[0, 0, 0], [0, 0, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [0, 0, 0], [0, 0, 1]],
        [[0, 1, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0], [0, 1, 0], [0, 0, 0]],
        [[0, 0, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 0, 0]],
        [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 0]],
    ]

    # Creates the model.
    model = cp_model.CpModel()

    # Creates shift variables.
    # shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
    shifts = {}
    for n in all_nurses:
        for d in all_days:
            for s in all_shifts:
                shifts[(n, d, s)] = model.NewBoolVar(f"shift_n{n}_d{d}_s{s}")

    # Each shift is assigned to exactly one nurse in .
    for d in all_days:
        for s in all_shifts:
            model.AddExactlyOne(shifts[(n, d, s)] for n in all_nurses)

    # Each nurse works at most one shift per day.
    for n in all_nurses:
        for d in all_days:
            model.AddAtMostOne(shifts[(n, d, s)] for s in all_shifts)

    # Try to distribute the shifts evenly, so that each nurse works
    # min_shifts_per_nurse shifts. If this is not possible, because the total
    # number of shifts is not divisible by the number of nurses, some nurses will
    # be assigned one more shift.
    min_shifts_per_nurse = (num_shifts * num_days) // num_nurses
    if num_shifts * num_days % num_nurses == 0:
        max_shifts_per_nurse = min_shifts_per_nurse
    else:
        max_shifts_per_nurse = min_shifts_per_nurse + 1
    for n in all_nurses:
        num_shifts_worked = 0
        for d in all_days:
            for s in all_shifts:
                num_shifts_worked += shifts[(n, d, s)]
        model.Add(min_shifts_per_nurse <= num_shifts_worked)
        model.Add(num_shifts_worked <= max_shifts_per_nurse)

    # pylint: disable=g-complex-comprehension
    model.Maximize(
        sum(
            shift_requests[n][d][s] * shifts[(n, d, s)]
            for n in all_nurses
            for d in all_days
            for s in all_shifts
        )
    )

    # Creates the solver and solve.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    if status == cp_model.OPTIMAL:
        print("Solution:")
        for d in all_days:
            print("Day", d)
            for n in all_nurses:
                for s in all_shifts:
                    if solver.Value(shifts[(n, d, s)]) == 1:
                        if shift_requests[n][d][s] == 1:
                            print("Nurse", n, "works shift", s, "(requested).")
                        else:
                            print("Nurse", n, "works shift", s, "(not requested).")
            print()
        print(
            f"Number of shift requests met = {solver.ObjectiveValue()}",
            f"(out of {num_nurses * min_shifts_per_nurse})",
        )
    else:
        print("No optimal solution found !")

    # Statistics.
    print("\nStatistics")
    print(f"  - conflicts: {solver.NumConflicts()}")
    print(f"  - branches : {solver.NumBranches()}")
    print(f"  - wall time: {solver.WallTime()}s")


if __name__ == "__main__":
    main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1036606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比特币的蒙提霍尔问题

把钱放在嘴边 我们在比特币上建立了蒙提霍尔问题模拟。 如果您知道概率谜题的正确答案&#xff0c;不仅炫耀您的数学技能&#xff0c;还会获得金钱奖励。 它完全无需信任地在链上运行。 蒙提霍尔问题 蒙提霍尔问题&#xff08;三门问题&#xff09;是一个以蒙提霍尔命名的概率…

Redis桌面管理工具Redis Desktop Manager mac中文版功能特色

Redis Desktop Manager for Mac是一款实用的Redis可视化工具。RDM支持SSL / TLS加密&#xff0c;SSH隧道&#xff0c;基于SSH隧道的TLS&#xff0c;为您提供了一个易于使用的GUI&#xff0c;可以访问您的Redis数据库并执行一些基本操作&#xff1a;将键视为树&#xff0c;CRUD键…

计算机网络工程师多选题系列——操作系统

得多选者得天下啊同志们&#xff01; 摘录按照章节顺序&#xff0c;但事实上各章节习题有交叉。 1 操作系统 1.1 操作系统概论 操作系统的主要功能&#xff1a;进程管理、存储管理、文件管理、设备管理和用户接口。 操作系统的主要功能——设备管理&#xff1a;为用户程序提…

metinfo_5.0.4 EXP Python脚本编写

文章目录 metinfo_5.0.4EXP编写SQL注入漏洞 metinfo_5.0.4EXP编写 SQL注入漏洞 漏洞点&#xff1a;/about/show.php?langcn&id22 http://10.9.75.142/metInfo_5.0.4/about/show.php?langcn&id22验证漏洞(数字型注入) 状态码区分正确与错误 做比较的时候不能采用…

实现顺序表——实践报告

W...Y的主页 &#x1f60a; 代码仓库分享 &#x1f495; 目录 一、实验目的&#xff1a; 二、实验内容&#xff1a; 三、实验要求&#xff1a; 四.实验步骤&#xff08;给出每个函数的算法描述&#xff09;&#xff1a; 五.实验结果&#xff1a; 六.源代码 实验名称 &am…

【深度学习实验】前馈神经网络(五):自定义线性模型:前向传播、反向传播算法(封装参数)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 线性模型Linear类 a. 构造函数__init__ b. __call__(self, x)方法 c. 前向传播forward d. 反向传播backward 2. 模型训练 3. 代码整合 一、实验介绍 实现线性…

【计算机网络】IP协议(下)

文章目录 1. 特殊的IP地址2. IP地址的数量限制3. 私有IP地址和公网IP地址私有IP为什么不能出现在公网上&#xff1f;解决方案——NAT技术的使用 4. 路由5. IP分片问题为什么要进行切片&#xff1f;如何做的分片和组装&#xff1f;16位标识3位标志13位片偏移例子 细节问题如何区…

一文带你玩转logo:含义、获取、使用以及2000多知名logo大图资源

大家好&#xff01;logo是我们非常熟悉的一种事物&#xff0c;但是我发现很多场合的logo使用并不规范、高效&#xff0c;所以今天六分成长来带着大家了解一下关于logo的方方面面。 一、什么是logo&#xff1f; logo不是某一些英文单词的缩写&#xff0c;是一个完整的单词&…

uniapp如何判断是哪个(微信/APP)平台

其实大家在开发uniapp项目的时候长长会遇到这样一个问题&#xff0c;就是针对某些小程序&#xff0c;没发去适配相关的功能&#xff0c;所以要针对不同的平台&#xff0c;进行不同的处理。 #ifdef &#xff1a; if defined 仅在某个平台编译 #ifndef &#xff1a; …

机器学习实验一:使用 Logistic 回归来预测患有疝病的马的存活问题

代码&#xff1a; import pandas as pd import numpy as np from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metrics import classification_report import matplotlib.pyplot as plt def train(): # …

机器学习---神经元模型

1. 生物学的启示 神经元在结构上由细胞体、树突、轴突和突触四部分组成。 细胞体是神经元的主体&#xff0c;由细胞核、细胞质和细胞膜3部分组成。细胞体的外部是细胞膜&#xff0c;将 膜内外细胞液分开。由于细胞膜对细胞液中的不同离子具有不同的通透性&#xff0c;这使得膜…

XXE 漏洞及案例实战

文章目录 XXE 漏洞1. 基础概念1.1 XML基础概念1.2 XML与HTML的主要差异1.3 xml示例 2. 演示案例2.1 pikachu靶场XML2.1.1 文件读取2.1.2 内网探针或者攻击内网应用&#xff08;触发漏洞地址&#xff09;2.1.4 RCE2.1.5 引入外部实体DTD2.1.6 无回显读取文件 3. XXE 绕过3.1 dat…

【操作系统】线程、多线程

为什么要引入线程&#xff1f; 传统的进程只能串行的执行一系列程序&#xff0c;线程增加并发度。同一个进程分为多个线程。 线程是调度的基本单元&#xff0c;程序执行流的最小单位&#xff0c;基本的CPU执行单元。 进程是资源分配的基本单位。 线程的实现方式 用户级线程 代…

Unity入门教程(上)

七、运行游戏 再次保存我们的项目文件&#xff08;返回步骤四&#xff09;。保存完成后&#xff0c;让我们把游戏运行起来。 1&#xff0c;确认游戏视图标签页右上方的Maximize on Play图标处于按下状态&#xff0c;然后点击画面上方的播放按钮&#xff08;位于工具栏中间的播…

C++类模板学习

之前已经学习了函数模板&#xff0c;在这里&#xff0c; C函数模板Demo - win32 版_c编写的opc da demo_bcbobo21cn的博客-CSDN博客 下面学习类模板&#xff1b; VC6&#xff1b; 做一个星星类&#xff0c;Star&#xff1b; Star.h&#xff1b; #if !defined(AFX_STAR_H_…

(十二)VBA常用基础知识:worksheet的各种操作之sheet移动

当前sheet确认 把sheet1移动到sheet3前边 Sub Hello()10Worksheets("Sheet1").Move Before:Worksheets("Sheet3") End Sub3. 把sheet2移动到sheet1后边 Sub Hello()11Worksheets("Sheet2").Move after:Worksheets("Sheet1") End Sub…

MissionPlanner编译过程

环境 windows 10 mission planner 1.3.80 visual studio 2022 git 2.22.0 下载源码 (已配置git和ssh) 从github上克隆源码 git clone gitgithub.com:ArduPilot/MissionPlanner.git进入根目录 cd MissionPlanner在根目录下的ExtLibs文件下是链接的其它github源码&#xff0…

pymysql简介以及安装

视频版教程 Python操作Mysql数据库之pymysql模块技术 前面基础课程介绍了使用文件来保存数据&#xff0c;这种方式虽然简单、易用&#xff0c;但只适用于保存一些格式简单、数据量不太大的数据。对于数据量巨大且具有复杂关系的数据&#xff0c;当然还是推荐使用数据库进行保存…

79、SpringBoot 整合 R2DBC --- R2DBC 就是 JDBC 的 反应式版本, R2DBC 是 JDBC 的升级版。

★ 何谓R2DBC R2DBC 就是 JDBC 的 反应式版本&#xff0c; R2DBC 是 JDBC 的升级版。 R2DBC 是 Reactive Relational Database Connectivity (关系型数据库的响应式连接) 的缩写 反应式的就是类似于消息发布者和订阅者&#xff0c;有消息就进行推送。R2DBC中DAO接口中方法的…

Rust vs C++ 深度比较

Rust由于其强大的安全性受到大量关注&#xff0c;被认为C在系统编程领域最强大的挑战者。本文从语言、框架等方面比较了两者的优缺点。原文: Rust vs C: An in-depth language comparison Rust和C的比较是开发人员最近的热门话题&#xff0c;两者之间有许多相似之处&#xff0c…