當前位置:網站首頁>從PlatEMO中提取真實PF前沿

從PlatEMO中提取真實PF前沿

2022-05-13 17:52:35武科大許志偉

從PlatEMO中提取真實PF前沿

覺得有用的話,歡迎一起討論相互學習~

我的微博我的github我的B站

  • 眾所周知,我是Jmetal的重度愛好者,最近實驗遇到一些難以解决的困難,當我在進行超多目標優化實驗即MaOP時,需要M=10及以上的PF,然而在benchmark中沒有提供,而且Jmetal不支持通過均勻取點的方式生成PF。因此,經過老師的指導,我們選擇使用在PlatEMO中運行完相應目標數量的benchmark problem後,將通過均勻踩點得到的真實PF提取出來作為在Jmetal上進行實驗的真實PF.

觀察platEMO中PF數據結構

  • 首先進入Test模塊,選擇好自己的算例和目標數量,此處設置目標數量為10,然後使其繼續運行,直到完成迭代次數。
  • 選擇data-source模式為True PF,此時圖中顯示的在此目標數量下test problem的真實前沿
  • 此時我們獲得了真實前沿,但是還需要其中的散點數據,只有將這些數據保存出來,才能在Jmetal中畫出前沿
  • 此時選中–>open in new figure and save to workspace
  • 即會出現這樣的小窗口,在主窗口選擇打開變量Data{},其中打開的即是對應圖形中真實PF的信息。

  • 點開第一個單元格,可以看到數據的保存格式,錶示平行坐標圖的橫軸,是從1-10然後從10-1的不斷重複的序列,第二個單元格中存儲的是對應的目標函數值


  • 因此為了將其轉換成Jemtal可使用的標准PF形式,即每一列錶示一個目標,每一行錶示一個PF上的點。需要將目前的數據格式做如下的處理,即
  1. 將每十列重新分為一行
  2. 單數行索引順序保持不變,雙數行索引順序倒置

准備處理數據

  • 新建一個excel錶格保存數據,注意,如果直接將一整行進行保存,可能出現excel中列不够的情况,因此需要先將矩陣在platEMO中轉置後變成一列再複制到Excel中。由於目標數是10是固定的,因此只需要對目標對應的函數值進行處理。


  • 嗯,現在再對數據做第一個處理,將數據每十行變成一列
    使用excel公式=INDEX($A:$A,ROW(A1)*10-10+COLUMN(A1))
    在單元格選中,然後向右拖10行,然後選中行,向下拉滿
    處理好後的數據如圖所示:
  • 但是其雙數行還是從10-1的目標索引進行排列,為了保持一致,其雙數行需要變成從1-10的目標索引進行排列

對雙數行進行處理

  • 因為現在雙數行的索引模式是倒序的,因此需要將其變為順序模式,為此,首先將數據複制一遍,成為沒有公式的純數據。

  • 然後將其保存為csv文件格式,方便之後進行處理,excel另存為csv(逗號分割)。

  • 寫一個python 脚本對test1.csv文件進行處理。

import csv

# 源文件名
filename = "./test1.csv"
pf_file = "./test1.pf"

singular_line = []  # 單數行
double_line = []  # 雙數行

num_obj = 10  # 目標個數,這錶示其中列的個數

singular_data = [[] for i in range(num_obj)]  # 單數行保存為一個num_obj列的二維數組
double_data = [[] for i in range(num_obj)]  # 單數行保存為一個num_obj列的二維數組

# 將文件中的信息保存到singular_data和double_data這兩個列錶中
with open(filename, 'r', encoding='utf-8') as f:
    i = 1
    for line in f.readlines():
        if i % 2 == 0:
            double_line.append(line)
        else:
            singular_line.append(line)
        i = i + 1
f.close()

# 再將兩個列錶中的數據進行處理,將雙數行中的數據換順序保存
# 單數行直接保存
for Sum in singular_line:

    # print(Sum.split("\n")[0].split(",")[0:])
    sum_eva_index = Sum.split("\n")[0].split(",")[0:]

    for i in range(num_obj):
        # print(sum_eva_index[i]) # test
        singular_data[i].append(float(sum_eva_index[i]))

# 雙數行反向後保存
for Sum in double_line:
    sum_eva_index = Sum.split("\n")[0].split(",")[0:]
    for i in range(num_obj):
        # print("i", i)
        double_data[i].append(float(sum_eva_index[num_obj - i - 1]))  # 注意,即使num_obj是目標數量,但是索引是從num_obj-1開始的

# 將數據寫入CSV文件中
# 將數據寫入csv日志文件中
with open(pf_file, 'w') as f:
    for i in range(len(singular_data[0])):  # 3504
        for j in range(len(singular_data)):  # 10
            # f.write([singular_data[0][i], singular_data[1][i], singular_data[2][i], singular_data[3][i],
            # singular_data[4][i], singular_data[5][i], singular_data[6][i], singular_data[7][i],
            # singular_data[8][i], singular_data[9][i]])
            f.write(str(singular_data[j][i]))
            # 用制錶符做分割
            if j!=(len(singular_data)-1):
                f.write("\t")
        # 換行符
        f.write("\n")
    for i in range(len(double_data[0])):  # 3504
        for j in range(len(double_data)):  # 10
            f.write(str(double_data[j][i]))
            # 用制錶符做分割
            if j!=(len(double_data)-1):
                f.write("\t")
        # 換行符
        f.write("\n")
    f.close()

# with open(pf_file, "w", newline='') as f:
# writer = csv.writer(f)
#
# # print(len(singular_data)) # 10
# # print(len(singular_data[0])) # 3504
# # 遍曆行
# for i in range(len(singular_data[0])): # i 取(0,1,2...)
# writer.writerow([singular_data[0][i], singular_data[1][i], singular_data[2][i], singular_data[3][i],
# singular_data[4][i], singular_data[5][i], singular_data[6][i], singular_data[7][i],
# singular_data[8][i], singular_data[9][i]])
#
# # 再寫雙數行
# for i in range(len(double_data[0])): # i 取(0,1,2...)
# writer.writerow([double_data[0][i], double_data[1][i], double_data[2][i], double_data[3][i],
# double_data[4][i], double_data[5][i], double_data[6][i], double_data[7][i],
# double_data[8][i], double_data[9][i]])
#
# f.close()

最終結果

  • 可以來看看最終結果,這裏使用30行數據為例,test1.csv單數行被改到test1.pf的前15行,而轉換順序後的test1.csv的雙數行被改到test1.pf的後15行。

版權聲明
本文為[武科大許志偉]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/133/202205131742272918.html

隨機推薦