第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--碳中和

前言

"全球校园人工智能算法精英大赛"是江苏省人工智能学会举办的面向全球具有正式学籍的全日制高等院校及以上在校学生举办的算法竞赛。其中的算法巅峰赛属于产业命题赛道,这是第3赛季,这次优化题的主题是 "碳中和"。


AIC·算法巅峰赛赛题及竞赛规则


题目描述

给你 N 个任务 和 M 台服务器,需要决定:

  • 哪些任务要执行
  • 每个执行的任务分配到哪台服务器

核心约束

  1. 功耗约束
    每台服务器的实际总功耗 ≤ 该服务器的功耗上限
  2. 热量约束
    每台服务器的实际承受总热量 ≤ 该服务器的热量阈值
  3. 热量传导规则
    服务器排成一排,相邻服务器会互相传导热量:

怎么理解热量约束和热量传达规则

服务器 p 承受的热量 = 服务器 p 任务的热量总和 + 左邻热量和 × K + 右邻热量和 × K 服务器 p 承受的热量 = 服务器p 任务的热量总和 + 左邻热量和 × K + 右邻热量和 × K 服务器p承受的热量=服务器p任务的热量总和+左邻热量和×K+右邻热量和×K

注: 左右两侧服务器的特殊情况,非环。

核心目标

在满足所有限制条件下,最大化总收益。

输入数据

第一行

复制代码
N M K

N:任务数量(1-4000)

M:服务器数量(1-800)

K:热量传导系数(0.0-1.0)

任务数据(N行,每行3个数字)

复制代码
收益 功耗 热量

服务器数据(M行,每行2个数字)

复制代码
功耗上限 热量阈值

输出格式

输出 N 个数字,用空格分隔:

复制代码
a_1, a_2, a_3, ..., a_n

a i ∈ 0 , m a_i \in 0, m ai∈0,m 其中0: 该任务i不执行, 1-M: 该任务 i分配到几号服务器

sample

输入

复制代码
3 2 1.0
10 3 4
8 4 3
5 2 2
5 7
7 8

输出

复制代码
1 2 0

解释

复制代码
有 3 个任务,2 台服务器,K=1.0(100%传导)
服务器1:最多用5功耗,承受7热量
服务器2:最多用7功耗,承受8热量

任务1(功耗3,热量4)→ 服务器1
任务2(功耗4,热量3)→ 服务器2
任务3不执行

检查约束:
服务器1:功耗3 ≤ 5 ✅,热量4 ≤ 7 ✅
服务器2:功耗4 ≤ 7 ✅,热量3 ≤ 8 ✅

考虑传导:
服务器1总热量:自己4 + 邻居传导3×1.0 = 7(刚好等于阈值7)✅
服务器2总热量:自己3 + 邻居传导4×1.0 = 7 ≤ 8 ✅
总收益:10 + 8 = 18 ✅

思路分析

该问题属于带约束的多维度资源分配优化问题,是组合优化问题。

该问题可以视为 二维费用的 0-1 多重背包的变形问题。


高分思路

贪心策略

  1. 任务task按照收益从高到低排序
  2. 按需为每个 task寻找第一个满足约束限制的服务器 server 节点,进行分配
python3 复制代码
# task按收益从高到低排序
tasks.sort(key=lambda x: -x.val)

# 遍历每个任务
for task in tasks:
	for server in servers:
		# 如果该服务器,添加该任务后,依旧满足约束
		if server.satisfy(task):
			# 该 task 被赋予给 该 server
			task -> server 
			break

就这么一个简单的思路,最后分数为 400+,赛时前 15 名。


多策略混合

保留原先的贪心策略主框架,做一些策略抽象

python3 复制代码
sort_stragety  #排序策略
choice_strategy # 挑选策略

# task按 策略 sort_strategy 排序
tasks.sort(key=sort_stragety)

# 遍历每个任务
for task in tasks:
	candidate_list = []
	for server in servers:
		# 如果该服务器,添加该任务后,依旧满足约束
		if server.satisfy(task):
			candidate_list.append(server)
	
	# 如果存在候选服务器列表
	if candidate_list:
	    # 按挑选策略,选择具体的svr
		svr = choice_strategy(candidate_list)
		task -> svr # 把 task 赋予某个 server 执行	

这里抽象了 2 个策略,sort_stragety/choice_strategy

任务的排序策略

  • 按收益值从高到低 排序
  • 按收益/功耗 比值,从高到低 排序
  • 按收益/热度 比值,从高到低 排序
  • 按收益/功耗热度的比值,从高到低 排序

服务器的挑选策略

  • FF(First-Fit)
    选择第一个满足要求服务器
  • BF(Best-Fit)
    按最优策略,比如定义 加权 功耗利用率 + 热量利用率的函数,越高越好
  • RF(Random-Fit)
    随机挑选任一个满足要求的服务器
  • 概率放弃
    按一定概率放弃此次选择任务和服务器配对,否则采用上述几种策略挑选

而任务的排序策略+服务器的挑选策略,做一个组合搭配。

这样的混合策略得分为 440+,赛时前三。


模拟退火

模拟退火也可以做这题,但操作因子设计就很复杂,不太好实现。

这边以最简单的任务重分配操作因子 为例(纯展示)

python 复制代码
import math, random
from math import inf

class Task(object):
    def __init__(self, value, power, heat):
        self.value = value
        self.power = power
        self.heat = heat

class Server(object):
    def __init__(self, p_limit, h_limit):
        self.p_limit = p_limit
        self.h_limit = h_limit


N, M, K = input().split()
N, M, K = int(N), int(M), float(K)

tasks = []
for _ in range(N):
    value, power, heat = list(map(int, input().split()))
    tasks.append(Task(value, power, heat))

servers = []
for _ in range(M):
    p_limit, h_limit = list(map(int, input().split()))
    servers.append(Server(p_limit, h_limit))


def fitness(assigns):
    ans = 0
    tmp_power = [0] * M
    tmp_heat = [0] * M
    for i in range(N):
        id = assigns[i]
        if id >= 0:
            tmp_power[id] += tasks[i].power
            tmp_heat[id] += tasks[i].heat
            ans += tasks[i].value
    # check
    for i in range(M):
        if tmp_power[i] > servers[i].p_limit:
            return -inf
        heat = tmp_heat[i]
        if i > 0: heat += tmp_heat[i - 1] * K
        if i + 1 < M: heat += tmp_heat[i + 1] * K
        if heat > servers[i].h_limit:
            return -inf

    return ans

assigns = [-1] * N
current_score = 0

best_score = 0
best_ans = assigns[:]

a = 0.999
T = 1000
while T > 1e-6:

    # reassign
    idx = random.randint(0, N - 1)
    old = assigns[idx]
    assigns[idx] = random.randint(-1, M - 1)  #

    score = fitness(assigns)
    if score == -inf:
        # 不合法的方案立马拒绝
        assigns[idx] = old
        T = T * a
        continue

    delta = score - current_score
    if delta > 0 or random.random() < math.exp(delta / T):
        # accept
        current_score = score
        if current_score > best_score:
            best_score = current_score
            best_ans = assigns[:]
    else:
        # reject
        assigns[idx] = old

    T = T * a

print (*[v + 1 for v in best_ans])

这个大概可以拿 300+分,有点意外

这个操作因子,效率太低了,间接反映了比赛实际的数据相对较弱,容易得分。

具体更有效率的操作因子,可具体问问 AI 大模型。


写在最后

相关推荐
Mininglamp_2718几秒前
Claude Code 封禁中国开发者之后:本地 AI 编程工具的替代方案实测
开发语言·人工智能·windows·开源软件·ai-native
硅谷秋水8 分钟前
World Engine:迈向自动驾驶的后训练时代
人工智能·深度学习·机器学习·计算机视觉·语言模型·自动驾驶
RobinDevNotes8 分钟前
PentAGI:全自主 AI 渗透测试代理系统
人工智能
醉城夜风~13 分钟前
Java详解经典算法题:接雨水(三种实现方案+原理剖析)
java·开发语言·算法
明理的信封16 分钟前
AI 基础设施的“去 Python 化“:Rust 与 C# 的两条替代路径
人工智能·python·rust
ysa05103021 分钟前
【板子】ST表
c++·笔记·算法·板子
Tiansan666628 分钟前
郑州AI问答推广公司:如何用AI提升转化率
人工智能·郑州ai问答推广公司
龙亘川30 分钟前
开源本地 AI 智能体网关 OpenClaw 深度实践:架构解析、全场景部署与自动化落地指南
人工智能·架构·开源·openclaw
霍格沃兹测试开发学社测试人社区44 分钟前
为企业提供专业、灵活、高效的一体化测试支持
人工智能
xixixi777771 小时前
产业全景解读:太空算力、国产芯、国产大模型、6G 空天地、AI 可信身份、后量子安全多线全面突破
人工智能·安全·ai·大模型·数据中心·通信·运营商