如何用Tuple合并4个决策变量数组为二维数组并在OPL IDE中显示
OPL合并决策变量为二维数组并实现可视化
需求说明
现有4个决策变量数组,需合并为一个二维数组(行对应Nrows,列对应Nchannels),并实现可视化。原始参数代码如下:
int Nbeams=21; // 待分配到二维数组的波束数量 int Nchannels=16; // 列数(通道数) int Nrows=4; // 行数 range rows = 1..Nrows; range beams = 1..Nbeams; dvar int No_beams_in_each_row[rows] = [6,6,6,4]; dvar int first_beam_in_each_row [rows] = [1,7,13,19]; dvar int beam_firstchannel[beams] = [1,3,5,7,9,11,1,3,5,7,9,11,1,3,5,7,9,11,1,5,9,13]; dvar int beam_nomusedchannel[beams] = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4]; dvar int beam_row[beams] = [1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4];
完整解决方案
以下提供两种可视化方式,先通过约束将现有变量合并为二维数组,再分别实现OPL IDE内视图和Python外部可视化:
int Nbeams=21; // 待分配到二维数组的波束数量 int Nchannels=16; // 列数(通道数) int Nrows=4; // 行数 range rows = 1..Nrows; range beams = 1..Nbeams; range channels = 1..Nchannels; dvar int No_beams_in_each_row[rows] = [6,6,6,4]; dvar int first_beam_in_each_row [rows] = [1,7,13,19]; dvar int beam_firstchannel[beams] = [1,3,5,7,9,11,1,3,5,7,9,11,1,3,5,7,9,11,1,5,9,13]; dvar int beam_nomusedchannel[beams] = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4]; dvar int beam_row[beams] = [1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4]; // 定义二维数组:row×channel,存储对应位置的波束编号(0表示未占用) dvar int beam_in_channel[rows][channels] in 0..Nbeams; subject to { // 约束:根据波束的行、起始通道、占用通道数填充二维数组 forall(b in beams) { let r = beam_row[b]; let start_c = beam_firstchannel[b]; let num_c = beam_nomusedchannel[b]; // 确保波束占用的通道不超出范围 start_c + num_c - 1 <= Nchannels; forall(c in start_c..start_c + num_c - 1) { beam_in_channel[r][c] == b; } } // 约束:未被占用的位置设为0 forall(r in rows, c in channels) { if (not exists(b in beams: beam_row[b]==r && c >= beam_firstchannel[b] && c < beam_firstchannel[b]+beam_nomusedchannel[b])) { beam_in_channel[r][c] == 0; } } } // --- 方式1:在OPL IDE中通过Gantt视图展示二维数组 --- tuple sequence_like { int start; int end; string label; int type; }; // 为每一行生成Gantt视图所需的序列数据 {sequence_like} channel_beam_view[r in rows] = {<c-1, c, (beam_in_channel[r][c]==0 ? " " : "Beam " + beam_in_channel[r][c]), beam_in_channel[r][c]> | c in channels}; execute show_in_opl_ide { channel_beam_view; // 在OPL IDE的"Output"标签下可查看Gantt视图 } // --- 方式2:调用Python生成热力图可视化 --- tuple BeamChannelSolution { int row; int channel; int beam_id; }; {BeamChannelSolution} beam_channel_solution = {<r, c, beam_in_channel[r][c]> | r in rows, c in channels}; execute display_with_python { // 生成Python可视化脚本 var python = new IloOplOutputFile("c:/temp/beam_channel_display.py"); python.writeln("import matplotlib.pyplot as plt"); python.writeln("import numpy as np"); python.writeln("grid = np.array(["); // 逐行写入二维数组数据 for(var r in rows) { python.write("["); for(var c in channels) { python.write(beam_in_channel[r][c]); if (c != channels.last()) python.write(", "); } python.writeln("],"); } python.writeln("])"); python.writeln("plt.figure(figsize=(12, 4))"); python.writeln("im = plt.imshow(grid, cmap='viridis', aspect='auto')"); python.writeln("plt.colorbar(im, label='Beam ID (0 = 未占用)')"); python.writeln("plt.xticks(ticks=np.arange(channels.size()), labels=np.arange(1, channels.size()+1))"); python.writeln("plt.yticks(ticks=np.arange(rows.size()), labels=np.arange(1, rows.size()+1))"); python.writeln("plt.xlabel('通道')"); python.writeln("plt.ylabel('行')"); python.writeln("plt.title('波束在-行通道网格上的分布')"); python.writeln("plt.show()"); python.close(); // 执行脚本,需替换为你的Python实际安装路径 IloOplExec("C:/Python39/python.exe c:/temp/beam_channel_display.py"); }
说明
- 二维数组构建:通过约束将
beam_row、beam_firstchannel、beam_nomusedchannel三个变量映射到beam_in_channel[row][channel]二维数组,实现数据合并。 - OPL IDE视图:生成Gantt序列数据后,在OPL IDE的Output标签中选中
channel_beam_view即可查看二维分布。 - Python可视化:自动生成Python脚本并执行,生成带标签的热力图,直观展示波束在各行各通道的分布情况,注意替换脚本中的Python路径为实际安装路径。
内容的提问来源于stack exchange,提问作者MO MO MA
相关产品推荐
相关产品推荐

