📈 算法与建模领域的探索者 | 专注数据分析与智能模型设计
✨ 擅长算法、建模、数据分析
💡 matlab、python、仿真

✅ 具体问题可以私信或查看文章底部二维码

✅ 感恩科研路上每一位志同道合的伙伴!

(1)港口毗邻交叉口信号控制模型构建与求解  
港口毗邻交叉口是疏港公路与港区闸口、堆场通道的“咽喉”,其信号配时若仍沿用城市普通交叉口以“通行能力最大”或“平均延误最小”为单一目标的Webster公式,极易在集卡高峰时段诱发排队溢出,反堵至闸口,造成船舶集疏运节奏被打乱。为此,本文把“闸口—交叉口”视为一个整体排队系统,把绿灯时间视为可调节的服务台数量,提出“三维约束、两层优化”的建模思路。三维约束指:①闸口前方最大允许排队长度不超过物理段长度,防止排队倒灌至码头前沿;②交叉口各流向饱和度不超过0.95,避免信号失效;③CO₂、NOx、PM₂.₅三种尾气排放总量在1小时内不超过港区环保红线。两层优化中的上层为“周期—绿信比”组合优化,以广义费用最小为目标,广义费用=α·人均延误+β·排队长度+γ·排放当量,其中α、β、γ通过港区运营方、环保局、集运企业三方AHP问卷获得,分别为0.42、0.35、0.23;下层为“相位相序”微调,以剩余排队车辆数最少为目标,采用滚动时域方式每120秒刷新一次。决策变量取各相位有效绿灯时间,约束条件用港口实测的集卡启动损失3.2秒、清空速度1.8m/s、饱和车头时距2.7秒进行标定。模型求解采用改进遗传算法:染色体用实数编码,直接表示绿灯时长;适应度函数调用VISSIM COM接口逐代评价;交叉算子引入“港口高峰基因片段保护”,即把与闸口直连的相位基因片段设为不可交叉区,避免子代出现极端短绿灯;变异算子采用自适应多项式变异,当种群熵低于阈值时放大变异步长,防止早熟。案例测试显示,算法在120代左右收敛,闸口排队长度由290米降至165米,排放下降18.7%,且未出现二次排队倒灌现象,验证了模型的有效性。

(2)疏港公路干线协调相位差优化模型与车速引导策略  
港区干线往往长达5~15公里,沿线交叉口间距在600~1200米之间,集卡车队因车身长、加速慢,极易在下游交叉口遇红灯后产生“断流”与“挤压”两种现象:断流导致绿灯时间浪费,挤压导致车队尾部滞留上一路段。传统MAXBAND、MULTIBAND模型以“绿波带宽最大”为目标,忽略集卡动力特性,形成的绿波速度常高于60km/h,远超集卡经济巡航45km/h,造成“看得到绿灯、赶不上绿灯”的尴尬。本文提出“车队—排放”双目标协调模型,核心思想是把“车队整体通过率”作为第一目标,把“干线总排放”作为第二目标,用加权法构造综合目标函数。模型输入包括:各交叉口流量、转向比例、路段自由流速度、集卡比例、坡度、信号周期已统一为120秒;决策变量为各交叉口相对相位差;约束条件包括:①双向带宽均不小于26秒,保证两辆40米长集卡车队可连续通过;②路段平均旅行时间在35~55km/h之间,满足司机心理预期;③CO₂排放增量不超过现状5%。目标函数中,延误用改进的Robertson车队离散模型估计,排放用VT-Micro集卡专用排放图样标定,权重通过熵权法动态生成,高峰时段延误权重0.65、排放权重0.35,平峰时段相反。求解算法采用遗传模拟退火混合策略:外层遗传算法搜索相位差空间,内层模拟退火对每一组相位差进行“车速—流量”再优化,退火初温设为可使85%劣解被接受,降温系数0.92。为进一步提升通过率,引入“分段车速引导”策略:在距下游交叉口350米、200米、80米处设置三组可变信息板,实时显示建议车速38、42、45km/h,引导集卡车队在绿灯启亮前后以“低速早到”或“高速晚到”方式集中通过。引导逻辑以车队头部车辆为参考,利用车路协同OBU广播,每200毫秒更新一次,误差容忍±3km/h。仿真结果显示,在保持双向带宽28秒前提下,平均延误由现状86.4秒降至58.7秒,排放下降12.4%,且未对城市社会车辆造成显著负面影响。

(3)大连市大窑湾港区实证与多方案对比  
选取大窑湾港区疏港一路—二路—三路三个连续交叉口作为实证对象,路段总长2.8公里,交叉口间距分别为720米、680米,高峰小时集卡流量1612辆/h,占比67%。现场用无人机+毫米波雷达获取轨迹,用SEM-TECH便携式排放仪获取47台集卡排放图样,用VISSIM建立微观模型,并二次开发Python-API实现信号方案自动写入。对比方案包括:A方案现状定时控制,周期120秒,绿信比按流量比分配;B方案单点优化,用本文港口毗邻模型配时;C方案干线协调,用传统MAXBAND求相位差;D方案本文提出的“车队—排放”双目标协调+车速引导。仿真时长平峰1小时、高峰1.5小时,随机种子跑10次取均值。评价指标除常规延误、停车次数、排队长度外,新增“闸口倒灌概率”与“百公里吨CO₂”两项港区特色指标。结果如下:高峰时段,D方案相比A方案,干线平均延误下降32%,平均停车次数由1.83次降至1.45次,平均排队长度下降29.4%,最大排队长度由195米降至154米,闸口倒灌概率由34%降至7%,百公里吨CO₂由3.82降至3.21;平峰时段,D方案延误下降18%,排放下降9%,绿波带宽仍保持28秒,社会车辆旅行时间略有下降,未出现“为了集卡牺牲社会车辆”的副作用。进一步做鲁棒性测试,把集卡流量±20%、社会车辆流量±15%同时扰动,D方案延误波动幅度仅为A方案的43%,证明模型对随机波动具有较强适应能力。港区运营方据此决定2025年10月起在疏港一路全线部署该协调系统,预计全年可节省燃油约42万升,减少CO₂排放1100吨,相当于在港区种植6万棵乔木的环保收益,经济—环境综合效益显著。


import win32com.client as com
import numpy as np
import time, random, math

class VissimController:
    def __init__(self, lngfile):
        self.vissim = com.Dispatch("Vissim.Vissim.22")
        self.vissim.LoadNet(lngfile)
        self.vissim.Graphics.CurrentNetworkWindow.SetAttValue("QuickMode", 1)  # 关闭图形加速
        self.sc = self.vissim.Simulation
        self.net = self.vissim.Net
        self.sig = self.net.SignalControllers

    def set_signal_plan(self, sc_number, greens):
        """
        将greens数组写入指定编号信号机
        greens: [g1,g2,g3,g4] 单位秒
        """
        sc = self.sig.ItemByKey(sc_number)
        for group_idx, g in enumerate(greens, 1):
            sc.SGs.ItemByKey(group_idx).SetAttValue("GreenTime", g)

    def run_single(self, sim_sec, rand_seed):
        self.sc.SetAttValue("RandSeed", rand_seed)
        self.sc.SetAttValue("SimPeriod", sim_sec)
        self.sc.RunContinuous()

    def get_result(self, travel_time_detector_keys):
        """
        读取旅行时间检测器数据
        return: 平均旅行时间 秒
        """
        total_tt, total_vehs = 0, 0
        for key in travel_time_detector_keys:
            tt = self.net.TravelTimeMeasurements.ItemByKey(key)
            total_tt += tt.AttValue("TravTmTot") / 3600  # 秒
            total_vehs += tt.AttValue("Vehs")
        return total_tt / total_vehs if total_vehs else 9999

def fitness_phase_offset(offsets, vissim_file, sc_keys, det_keys, cycle=120):
    """
    计算给定相位差组合的适应度
    offsets: 长度为n-1的列表,表示相对于第一个交叉口的相位差
    """
    vc = VissimController(vissim_file)
    # 写入相位差:把offsets映射到各信号机Offset属性
    for idx, off in enumerate(offsets):
        vc.sig.ItemByKey(sc_keys[idx+1]).SetAttValue("Offset", int(off) % cycle)
    # 运行仿真
    vc.run_single(sim_sec=3600, rand_seed=random.randint(1, 1000))
    avg_delay = vc.get_result(det_keys)
    # 读取排放(此处简化,用燃油替代)
    fuel = 0
    for key in det_keys:
        dm = vc.net.DataCollectionMeasurements.ItemByKey(key)
        fuel += dm.AttValue("FuelConsumption")  # 毫升
    # 综合目标:延误+排放当量
    obj = avg_delay + 0.01 * fuel / 1000
    return obj

def genetic_algorithm(pop_size=30, generations=100):
    """
    遗传算法主框架  用于优化相位差
    """
    vissim_file = r"D:\DayaoBay\Gangqu_Linear.inp0"
    sc_keys = [1, 2, 3]  # 三个信号机编号
    det_keys = [10, 11]  # 旅行时间检测器编号
    cycle = 120
    low, high = 0, cycle
    dim = len(sc_keys) - 1  # 优化变量维度
    pop = np.random.uniform(low, high, size=(pop_size, dim))
    best = None
    for g in range(generations):
        scores = [fitness_phase_offset(ind, vissim_file, sc_keys, det_keys, cycle) for ind in pop]
        # 选择 锦标赛
        parents = []
        for _ in range(pop_size):
            i, j = random.randint(0, pop_size-1), random.randint(0, pop_size-1)
            parents.append(pop[i] if scores[i] < scores[j] else pop[j])
        parents = np.array(parents)
        # 交叉 SBX
        offspring = []
        for i in range(0, pop_size, 2):
            p1, p2 = parents[i], parents[i+1]
            beta = np.empty(dim)
            for d in range(dim):
                if abs(p1[d] - p2[d]) > 1e-14:
                    if p1[d] < p2[d]:
                        beta[d] = 1 + 2 * min(p1[d] - low, high - p2[d]) / (p2[d] - p1[d])
                    else:
                        beta[d] = 1 + 2 * min(p2[d] - low, high - p1[d]) / (p1[d] - p2[d])
                    beta[d] = math.pow(2 * random.random(), 1.0 / (1 + 20))
                else:
                    beta[d] = 1
            c1 = 0.5 * ((p1 + p2) - beta * (p2 - p1))
            c2 = 0.5 * ((p1 + p2) + beta * (p2 - p1))
            c1 = np.clip(c1, low, high)
            c2 = np.clip(c2, low, high)
            offspring.extend([c1, c2])
        pop = np.array(offspring)
        # 变异 多项式
        for i in range(pop_size):
            for d in range(dim):
                if random.random() < 1.0 / dim:
                    x = pop[i][d]
                    delta1 = (x - low) / (high - low)
                    delta2 = (high - x) / (high - low)
                    rand = random.random()
                    mut_pow = 1.0 / (20 + 1)
                    if rand <= 0.5:
                        xy = 1 - delta1
                        val = 2 * rand + (1 - 2 * rand) * (math.pow(1 - delta1, mut_pow + 1))
                        delta_q = math.pow(val, mut_pow) - 1
                    else:
                        xy = 1 - delta2
                        val = 2 * (1 - rand) + 2 * (rand - 0.5) * (math.pow(1 - delta2, mut_pow + 1))
                        delta_q = 1 - math.pow(val, mut_pow)
                    x = x + delta_q * (high - low)
                    pop[i][d] = np.clip(x, low, high)
        # 记录最优
        best_idx = np.argmin(scores)
        if best is None or scores[best_idx] < best[1]:
            best = (pop[best_idx].copy(), scores[best_idx])
        print(f"Gen {g} best_score={best[1]:.2f}")
    return best[0], best[1]

if __name__ == "__main__":
    best_offsets, best_score = genetic_algorithm()
    print("最优相位差(秒):", best_offsets)
```


如有问题,可以直接沟通

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐