当前位置: 首页 > news >正文

APS开源源码解读: 排程工具 optaplanner

抽象层次非常好,广义优化工具。用于排产没有复杂的落地示例

  • https://github.com/apache/incubator-kie-optaplanner/blob/main/optaplanner-examples/src/main/java/org/optaplanner/examples/projectjobscheduling/app/ProjectJobSchedulingApp.java
  • https://github.com/eugenp/tutorials/tree/master/timefold-solver
  • https://github.com/kisszhu/aps

安装

  • java
  • maven

配置

在这里插入图片描述

  • xml配置
  • solutionClass
  • entityClass
  • constraintProviderClass
    • 约束设置
  • termination: 5min
  • constructionHeuristic: FIRST_FIT
    • first fit
  • localSearch:

也即是说,先定义对象“entityClass”, 转化为约束“constraintProviderClass”,然后运用 constructionHeuristic + localSearch的方式进行求解

其中,一个整体的任务叫做project, 资源有可再生,非可再生。

工序叫做Job,job跟着若干project。每个工序有自己的资源,ResourceRequirement. 执行模式Execution Mode. 分配allocation.

  • resourceRequirement和allocation都要设置execution mode
  • 每个工序JOb, 有自己的resourceRequirement, executation mode, allocation

基本概念

  • PlanningSolution
    • 定义Problem,以及解
  • planning entity
    • Allocation
  • planing variable
    • executionMode
    • delay
  • shadow variable
    • predecessorsDoneDate
    • https://www.optaplanner.org/docs/optaplanner/latest/shadow-variable/shadow-variable.html
  • planning score
  • 核心的优化算法

约束

比如排产中的工序依赖关系

import org.timefold.solver.core.api.score.buildin.hardsoft.HardSoftScore;
import org.timefold.solver.core.api.score.stream.ConstraintProvider;
import org.timefold.solver.core.api.score.stream.Constraint;
import org.timefold.solver.core.api.score.stream.ConstraintStream;
import org.timefold.solver.core.api.score.stream.Joiners;public class JobShopConstraintProvider implements ConstraintProvider {@Overridepublic Constraint[] defineConstraints(ConstraintFactory constraintFactory) {return new Constraint[] {// Ensure operations follow the sequence within each jobconstraintFactory.from(Operation.class).join(Operation.class, Joiners.filteringEach(otherOp -> otherOp.getJob().equals(op.getJob()) && otherOp.getSequence() == op.getSequence() + 1)).penalize("Operations must follow sequence",HardSoftScore.ONE_HARD,(op, otherOp) -> 1),// Ensure machine constraints are respectedconstraintFactory.from(Operation.class).join(Operation.class, Joiners.filteringEach((op1, op2) ->op1.getMachine().equals(op2.getMachine()) &&op1.getEndTime() > op2.getStartTime() &&op1.getStartTime() < op2.getEndTime() &&!op1.equals(op2))).penalize("Machine cannot process two operations at once",HardSoftScore.ONE_HARD,(op1, op2) -> 1)};}
}

官方示例

入口在APP的main

public static void main(String[] args) {prepareSwingEnvironment();new ProjectJobSchedulingApp().init();}

init

public void init() {init(null, true);}public void init(Component centerForComponent, boolean exitOnClose) {solutionBusiness = createSolutionBusiness();solverAndPersistenceFrame = new SolverAndPersistenceFrame<>(solutionBusiness, createSolutionPanel(),createExtraActions());solverAndPersistenceFrame.setDefaultCloseOperation(exitOnClose ? WindowConstants.EXIT_ON_CLOSE : WindowConstants.DISPOSE_ON_CLOSE);solverAndPersistenceFrame.init(centerForComponent);solverAndPersistenceFrame.setVisible(true);}

其中,solution business
- SolverFactory.createFromXmlResource建立了solver

public SolutionBusiness<Solution_, ?> createSolutionBusiness() {SolutionBusiness<Solution_, ?> solutionBusiness = new SolutionBusiness<>(this,SolverFactory.createFromXmlResource(solverConfigResource));solutionBusiness.setDataDir(determineDataDir(dataDirName));solutionBusiness.setSolutionFileIO(createSolutionFileIO());solutionBusiness.setImporters(createSolutionImporters());solutionBusiness.setExporters(createSolutionExporters());solutionBusiness.updateDataDirs();return solutionBusiness;}

在APP类继承的solution中,示例采用的是schedule,也就是planningsolution,作为问题和排产结果

package org.optaplanner.examples.projectjobscheduling.domain;import java.util.List;import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
import org.optaplanner.core.api.domain.solution.PlanningScore;
import org.optaplanner.core.api.domain.solution.PlanningSolution;
import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty;
import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.projectjobscheduling.domain.resource.Resource;@PlanningSolution
public class Schedule extends AbstractPersistable {private List<Project> projectList;private List<Job> jobList;private List<ExecutionMode> executionModeList;private List<Resource> resourceList;private List<ResourceRequirement> resourceRequirementList;private List<Allocation> allocationList;private HardMediumSoftScore score;public Schedule() {}public Schedule(long id) {super(id);}@ProblemFactCollectionPropertypublic List<Project> getProjectList() {return projectList;}public void setProjectList(List<Project> projectList) {this.projectList = projectList;}@ProblemFactCollectionPropertypublic List<Job> getJobList() {return jobList;}public void setJobList(List<Job> jobList) {this.jobList = jobList;}@ProblemFactCollectionPropertypublic List<ExecutionMode> getExecutionModeList() {return executionModeList;}public void setExecutionModeList(List<ExecutionMode> executionModeList) {this.executionModeList = executionModeList;}@ProblemFactCollectionPropertypublic List<Resource> getResourceList() {return resourceList;}public void setResourceList(List<Resource> resourceList) {this.resourceList = resourceList;}@ProblemFactCollectionPropertypublic List<ResourceRequirement> getResourceRequirementList() {return resourceRequirementList;}public void setResourceRequirementList(List<ResourceRequirement> resourceRequirementList) {this.resourceRequirementList = resourceRequirementList;}@PlanningEntityCollectionPropertypublic List<Allocation> getAllocationList() {return allocationList;}public void setAllocationList(List<Allocation> allocationList) {this.allocationList = allocationList;}@PlanningScorepublic HardMediumSoftScore getScore() {return score;}public void setScore(HardMediumSoftScore score) {this.score = score;}// ************************************************************************// Complex methods// ************************************************************************}

Timefold 示例

Solver job接受到problem,开始run

@Deprecated(forRemoval = true, since = "1.6.0")default SolverJob<Solution_, ProblemId_> solve(ProblemId_ problemId,Solution_ problem, Consumer<? super Solution_> finalBestSolutionConsumer,BiConsumer<? super ProblemId_, ? super Throwable> exceptionHandler) {SolverJobBuilder<Solution_, ProblemId_> builder = solveBuilder().withProblemId(problemId).withProblem(problem);if (finalBestSolutionConsumer != null) {builder.withFinalBestSolutionConsumer(finalBestSolutionConsumer);}if (exceptionHandler != null) {builder.withExceptionHandler(exceptionHandler);}return builder.run();}
solverStatus = SolverStatus.SOLVING_ACTIVE;// Create the consumer thread pool only when this solver job is active.consumerSupport = new ConsumerSupport<>(getProblemId(), bestSolutionConsumer, finalBestSolutionConsumer,firstInitializedSolutionConsumer, exceptionHandler, bestSolutionHolder);Solution_ problem = problemFinder.apply(problemId);// add a phase lifecycle listener that unlock the solver status lock when solving startedsolver.addPhaseLifecycleListener(new UnlockLockPhaseLifecycleListener());// add a phase lifecycle listener that consumes the first initialized solutionsolver.addPhaseLifecycleListener(new FirstInitializedSolutionPhaseLifecycleListener(consumerSupport));solver.addEventListener(this::onBestSolutionChangedEvent);final Solution_ finalBestSolution = solver.solve(problem);consumerSupport.consumeFinalBestSolution(finalBestSolution);return finalBestSolution;

理解

在这里插入图片描述

  • https://www.optaplanner.org/docs/optaplanner/latest/shadow-variable/shadow-variable.html

  • build_solver/ default_solver_factory

    public Solver<Solution_> buildSolver(SolverConfigOverride<Solution_> configOverride) {Objects.requireNonNull(configOverride, "Invalid configOverride (null) given to SolverFactory.");var isDaemon = Objects.requireNonNullElse(solverConfig.getDaemon(), false);var solverScope = new SolverScope<Solution_>();var monitoringConfig = solverConfig.determineMetricConfig();solverScope.setMonitoringTags(Tags.empty());var metricsRequiringConstraintMatchSet = Collections.<SolverMetric> emptyList();if (!monitoringConfig.getSolverMetricList().isEmpty()) {solverScope.setSolverMetricSet(EnumSet.copyOf(monitoringConfig.getSolverMetricList()));metricsRequiringConstraintMatchSet = solverScope.getSolverMetricSet().stream().filter(SolverMetric::isMetricConstraintMatchBased).filter(solverScope::isMetricEnabled).toList();} else {solverScope.setSolverMetricSet(EnumSet.noneOf(SolverMetric.class));}var environmentMode = solverConfig.determineEnvironmentMode();var constraintMatchEnabled = !metricsRequiringConstraintMatchSet.isEmpty() || environmentMode.isAsserted();if (constraintMatchEnabled && !environmentMode.isAsserted()) {LOGGER.info("Enabling constraint matching as required by the enabled metrics ({}). This will impact solver performance.",metricsRequiringConstraintMatchSet);}var innerScoreDirector = scoreDirectorFactory.buildScoreDirector(true, constraintMatchEnabled);solverScope.setScoreDirector(innerScoreDirector);solverScope.setProblemChangeDirector(new DefaultProblemChangeDirector<>(innerScoreDirector));var moveThreadCount = resolveMoveThreadCount(true);var bestSolutionRecaller = BestSolutionRecallerFactory.create().<Solution_> buildBestSolutionRecaller(environmentMode);var randomFactory = buildRandomFactory(environmentMode);var configPolicy = new HeuristicConfigPolicy.Builder<>(environmentMode,moveThreadCount,solverConfig.getMoveThreadBufferSize(),solverConfig.getThreadFactoryClass(),solverConfig.getNearbyDistanceMeterClass(),randomFactory.createRandom(),scoreDirectorFactory.getInitializingScoreTrend(),solutionDescriptor,ClassInstanceCache.create()).build();var basicPlumbingTermination = new BasicPlumbingTermination<Solution_>(isDaemon);var termination = buildTerminationConfig(basicPlumbingTermination, configPolicy, configOverride);var phaseList = buildPhaseList(configPolicy, bestSolutionRecaller, termination);return new DefaultSolver<>(environmentMode, randomFactory, bestSolutionRecaller, basicPlumbingTermination,termination, phaseList, solverScope,moveThreadCount == null ? SolverConfig.MOVE_THREAD_COUNT_NONE : Integer.toString(moveThreadCount));}

solver的主流程

@Overridepublic final Solution_ solve(Solution_ problem) {if (problem == null) {throw new IllegalArgumentException("The problem (" + problem + ") must not be null.");}// No tags for these metrics; they are globalLongTaskTimer solveLengthTimer = Metrics.more().longTaskTimer(SolverMetric.SOLVE_DURATION.getMeterId());Counter errorCounter = Metrics.counter(SolverMetric.ERROR_COUNT.getMeterId());solverScope.setBestSolution(problem);solverScope.setSolver(this);outerSolvingStarted(solverScope);boolean restartSolver = true;while (restartSolver) {LongTaskTimer.Sample sample = solveLengthTimer.start();try {// solvingStarted will call registerSolverSpecificMetrics(), since// the solverScope need to be fully initialized to calculate the// problem's scale metricssolvingStarted(solverScope);runPhases(solverScope);solvingEnded(solverScope);} catch (Exception e) {errorCounter.increment();solvingError(solverScope, e);throw e;} finally {sample.stop();unregisterSolverSpecificMetrics();}restartSolver = checkProblemFactChanges();}outerSolvingEnded(solverScope);return solverScope.getBestSolution();}
  • run_phase /abstract_solver
protected void runPhases(SolverScope<Solution_> solverScope) {if (!solverScope.getSolutionDescriptor().hasMovableEntities(solverScope.getScoreDirector())) {logger.info("Skipped all phases ({}): out of {} planning entities, none are movable (non-pinned).",phaseList.size(), solverScope.getWorkingEntityCount());return;}Iterator<Phase<Solution_>> it = phaseList.iterator();while (!solverTermination.isSolverTerminated(solverScope) && it.hasNext()) {Phase<Solution_> phase = it.next();phase.solve(solverScope);// If there is a next phase, it starts from the best solution, which might differ from the working solution.// If there isn't, no need to planning clone the best solution to the working solution.if (it.hasNext()) {solverScope.setWorkingSolutionFromBestSolution();}}}
  • solver外面的phase, PhaseFactory

  • dostep
    局部搜索在当前解上尝试多个移动,并选择最佳的被接受的移动作为这一步。A step is the winning Move。在每一步,它尝试所有选定的移动,除非是选定的step,否则它不会进一步研究那个解。这就是局部搜索具有很高可扩展性的原因之一。

private void doStep(CustomStepScope<Solution_> stepScope, CustomPhaseCommand<Solution_> customPhaseCommand) {InnerScoreDirector<Solution_, ?> scoreDirector = stepScope.getScoreDirector();customPhaseCommand.changeWorkingSolution(scoreDirector);calculateWorkingStepScore(stepScope, customPhaseCommand);solver.getBestSolutionRecaller().processWorkingSolutionDuringStep(stepScope);}
  • 决定下一步
    • A MoveSelector which selects the possible moves of the current solution. See the chapter move and neighborhood selection.
    • An Acceptor which filters out unacceptable moves.
    • A Forager which gathers accepted moves and picks the next step from them.
  <localSearch><unionMoveSelector>...</unionMoveSelector><acceptor>...</acceptor><forager>...</forager></localSearch>

在这里插入图片描述
从底向上看,理解可能的move。如果是entity+value组合,或者是entity和entity进行新的组合。也许这就是叫做组合优化的原因?

相关文章:

APS开源源码解读: 排程工具 optaplanner

抽象层次非常好&#xff0c;广义优化工具。用于排产没有复杂的落地示例 https://github.com/apache/incubator-kie-optaplanner/blob/main/optaplanner-examples/src/main/java/org/optaplanner/examples/projectjobscheduling/app/ProjectJobSchedulingApp.javahttps://github…...

AMEYA360:村田量产用于汽车市场的高可靠性0603M铜电极负温度系数NTC热敏电阻

株式会社村田制作所开发了0603M尺寸(0.60.30.3mm)铜电极负温度系数(NTC)热敏电阻&#xff0c;型号分别是“NCU03XH103F6SRL”和“NCU03XH103F60RL”&#xff0c;该新品扩充了NCU系列的产品尺寸阵容&#xff0c;满足了汽车市场应用中电路板的高密度化和小型化、以及对电子部件的…...

代码随想录第十天|150.逆波兰表达式求值 239.滑动窗口的最大值 347.前K个高频元素

150.逆波兰表达式求解 思路&#xff1a;做过 使用stoi &#xff1a;字符串转数字 class Solution { public:int cal(int num1,int num2,char c){int res;if(c){resnum1num2;}if(c-){resnum2-num1;}if(c*){resnum1*num2;}if(c/){resnum2/num1;}return res;}int evalRPN(vector…...

[阅读笔记]《解读基金—我的投资观与实践》— 季凯帆

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…...

2.3之前

1. 2. freertos基础时钟:freertos自动的采用systick定时器,作为freertos基础时钟&#xff0c;systick定时器只有定时中断功能&#xff0c;1ms中断一次。...

处理器基础知识——cache

本文节选自书籍《大话处理器&#xff1a;处理器基础知识读本》 PDF版本可以访问我的网盘通过网盘分享的文件&#xff1a;大话处理器&#xff1a;处理器基础知识读本.pdf 提取码: 1234 0 什么是 Cache 随处可见的Cache–技术来源于生活 使用电脑的人对 Cachc 并不会陌生&#…...

操作系统的运行环境

1.处理器的运行模式 目态 也叫用户态&#xff0c; 执行非特权指令&#xff1a;不能直接访问系统中的软硬件资源&#xff0c;仅仅可以访问用户地址空间。 用户应用程序运行在目态。 管态 也叫内核态&#xff0c; 可执行除访管指令外的任意指令&#xff0c;包括特权指令&…...

如何在 Selenium 中获取网络调用请求?

引言 捕获网络请求对于理解网站的工作方式以及传输的数据至关重要。Selenium 作为一种 Web 自动化工具,可以用于捕获网络请求。本文将讨论如何使用 Selenium 在 Java 中捕获网络请求并从网站检索数据。 我们可以使用浏览器开发者工具轻松捕获网络请求或日志。大多数现代 Web…...

IP学习——oneday

1.什么是网络&#xff1f;为什么需要网络&#xff1f; 空间&#xff0c;时间&#xff1b;传统的邮件传输要考虑到距离&#xff0c;网络解决了空间距离&#xff08;太远&#xff09;、解决了时间问题&#xff08;旧音乐等&#xff09; 云:面向客户的虚拟化服务 运营商公司主营…...

2024 年高教社杯全国大学生数学建模竞赛 C 题 农作物的种植策略(详细思路+matlab代码+python代码+论文范例)

持续更新中,2024年数学建模比赛思路代码论文都会发布到专栏内,只需订阅一次! 完整论文+代码+数据结果链接在文末! 一、第一问 问题描述:假定各种农作物未来的预期销售量、种植成本、亩产量和销售价格相对于 2023 年保持稳定,每季种植的农作物在当季销售。如果某种作物每…...

软件工程知识点总结(1):软件工程概述

1 什么是软件&#xff1f; 定义&#xff1a;计算机系统中的程序及其文档。 ——程序是计算机任务的处理对象和处理规模的描述&#xff1b; ——文档是为了便于了解程序所需要的阐明性资料。 2 软件的特点&#xff1f; 软件是无形的&#xff0c;不可见的逻辑实体 ——它的正确与…...

热烈庆祝中国科学技术大学建校六六周年

卡西莫多的诗文集2022-2024.9月6-校庆国庆专版 欢迎分享 通过网盘分享的文件&#xff1a;卡西莫多的诗文集2022-2024.9月6-A5-校庆国庆专版.pdf 链接: 百度网盘 请输入提取码 提取码: umpm...

iptables持久化命令:netfilter-persistent save

在Linux上&#xff0c;使用netfilter-persistent命令可以保存iptables防火墙规则&#xff0c;确保它们在系统重启后仍然有效。以下是如何使用netfilter-persistent来保存iptables规则的步骤&#xff1a; 打开终端&#xff1a;首先&#xff0c;你需要打开Linux系统的终端。保存…...

elementUI table 给表头添加气泡显示(鼠标悬浮显示注释)

elementUI table 给表头添加气泡显示&#xff08;鼠标悬浮显示注释&#xff09; 前言&#xff1a;文档显示&#xff1a;&#xff08;使用插槽&#xff0c;我看看到底是怎么个事儿&#xff09;文档代码:修改后的效果&#xff1a;页面效果&#xff1a; 前言&#xff1a; 公司出现…...

Web3社交新经济,与 SOEX 实现无缝交易的高级安全性

出于充分的理由&#xff0c;安全性是交易中至关重要的考虑因素。每个人都应该确保自己的资金在交易时是安全的。由于 &#xff33;&#xff2f;&#xff25;&#xff38; 充当您与交易所的最佳连接&#xff0c;因此必须强调的是&#xff0c;该系统不会引发任何安全问题。 &a…...

Python和MATLAB(Java)及Arduino和Raspberry Pi(树莓派)点扩展函数导图

&#x1f3af;要点 反卷积显微镜图像算法微珠图像获取显微镜分辨率基于像素、小形状、高斯混合等全视野建模基于探测器像素经验建模荧光成像算法模型傅里叶方法计算矢量点扩展函数模型天文空间成像重建二维高斯拟合天体图像伽马射线能量和视场中心偏移角标量矢量模型盲解卷积和…...

使用isolation: isolate声明隔离混合模式

在CSS中&#xff0c;isolation 属性与混合模式&#xff08;如 mix-blend-mode 和 background-blend-mode&#xff09;并不直接相关&#xff0c;但它确实可以影响元素如何与其他元素进行渲染&#xff0c;尤其是在涉及到堆叠上下文&#xff08;stacking contexts&#xff09;和复…...

93. UE5 GAS RPG 应用负面效果表现

在上一篇文章里&#xff0c;我们实现了添加负面效果GE&#xff0c;并且在添加GE时&#xff0c;也会给角色应用一个负面效果标签作为标识。在这一篇里&#xff0c;我们将通过负面效果标签标识&#xff0c;应用角色身上展现对应的负面效果的表现。 我们将在这篇文章里添加一个自定…...

TCP 和 UDP 区别

UDP UDP&#xff08;用户数据报协议&#xff0c;User Datagram Protocol&#xff09;是一种无连接的网络传输协议&#xff0c;提供了简单的消息传送服务。UDP位于传输层&#xff0c;允许应用程序向其他主机发送封装在IP数据报中的消息&#xff0c;而无需先建立连接。由于UDP不…...

免费2024柜台租赁经营合同范本模板下载分享

今天看到这个合同范本都拿来卖钱,我直接分享出来2024年最新的范本模板随便下,免费的 柜台租赁经营合同GF—2013—0603.docx: https://url51.ctfile.com/f/20096151-1353625109-4285d2?p1605 (访问密码: 1605) 柜台租赁经营合同GF—2013—0603.pdf: https://url51.ctfile.com/…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

相关类相关的可视化图像总结

目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系&#xff0c;可直观判断线性相关、非线性相关或无相关关系&#xff0c;点的分布密…...