################################ # 巡回セールスマン問題(分割法) # coded by Y.Suganuma ################################ ################################# # 距離の計算 # n_c : 都市の数 # p : 都市番号 # rg : 都市間の距離 # return : 距離 ################################# def kyori(n_c, p, rg) r = 0.0 n1 = p[0] for i1 in 1 ... n_c n2 = p[i1] r += rg[n1][n2] n1 = n2 end n2 = p[0] r += rg[n1][n2] return r end ######################### # クラスIterationの定義 ######################### class Iteration ################################### # コンストラクタ # n_city_i 都市の数 # max_try_i 最大試行回数 # sei_i 整数 or 実数 # sel_i エッジの選択方法 # neib_i 近傍 # fix_i 近傍の扱い方 # out_lvl_i 出力レベル # out_m_i 出力方法 # out_d_i 表示間隔 # o_file_i 出力ファイル名 # city_i 都市の位置データ ################################### def initialize(n_city_i, max_tri_i, sei_i, sel_i, neib_i, fix_i, out_lvl_i, out_m_i, out_d_i, o_file_i, city_i) # 値の設定 @_n_city = n_city_i # 都市の数 @_max_try = max_tri_i # 最大試行回数 @_seisu = sei_i # 位置データの表現方法 # =1 整数 # =-1 実数(距離を整数計算) # =-2 実数(距離を実数計算) @_sel = sel_i # エッジの選択方法 # =0 最良のものを選択 # =1 最初のものを選択 @_neib = neib_i # 近傍(2 or 3) @_fix = fix_i # =1 近傍を固定 # =0 近傍を可変 @_out_lvl = out_lvl_i # 出力レベル # =0 最終出力だけ # n>0 n世代毎に出力(負の時はファイル) @_out_m = out_m_i # 出力方法 # =-1 出力しない # =0 すべてを出力 # =1 評価値だけを出力(最終結果だけはすべてを出力) @_out_d = out_d_i # 表示間隔 @_o_file = o_file_i # 出力ファイル名 @_city = city_i # 都市の位置データ # 距離テーブルの作成 @_rg = Array.new(@_n_city) for i1 in 0 ... @_n_city @_rg[i1] = Array.new(@_n_city) end for i1 in 0 ... @_n_city-1 for i2 in i1+1 ... @_n_city x = @_city[i2][0] - @_city[i1][0] y = @_city[i2][1] - @_city[i1][1] @_rg[i1][i2] = Math.sqrt(x * x + y * y) if @_seisu > -2 @_rg[i1][i2] = @_rg[i1][i2].round() end end end for i1 in 1 ... @_n_city for i2 in 0 ... i1 @_rg[i1][i2] = @_rg[i2][i1] end end # 都市を訪れる順序(初期設定) @_seq = Array.new(@_n_city) @_seq_w1 = Array.new(@_n_city) @_seq_w2 = Array.new(@_n_city) @_seq_w3 = Array.new(@_n_city) @_seq_w4 = Array.new(@_n_city) @_seq_w5 = Array.new(@_n_city) for i1 in 0 ... @_n_city sw = 0 while sw == 0 ct = Integer(rand(0) * @_n_city) if ct >= @_n_city ct = @_n_city - 1 end @_seq[i1] = ct sw = 1 for i2 in 0 ... i1 if ct == @_seq[i2] sw = 0 break end end end end end ################ # 最適化の実行 ################ def Optimize () # 初期設定 n_tri = 0 max = Array.new(1) max[0] = kyori(@_n_city, @_seq, @_rg) if @_out_m >= 0 && @_out_lvl.abs() > 0 if @_seisu > -2 print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n") else print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n") end Output(@_out_lvl, n_tri, max[0]) end # 実行 sw = 1 for n_tri in 1 ... @_max_try+1 # 改善 sw = Change(max) # 出力 if @_out_d > 0 and n_tri%@_out_d == 0 if @_seisu > -2 print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n") else print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n") end end if @_out_m >= 0 && @_out_lvl.abs() > 0 if n_tri%@_out_lvl.abs() == 0 Output(@_out_lvl, n_tri, max[0]) end end if sw <= 0 break end end # 最終出力 if @_out_m >= 0 n_tri -= 1 if @_seisu > -2 print("***試行回数 " + String(n_tri) + " 距離 " + String(Integer(max[0])) + "\n") else print("***試行回数 " + String(n_tri) + " 距離 " + String(max[0]) + "\n") end Output(@_out_lvl, n_tri, max[0]) end return n_tri end ################################ # 出力 # sw >=0 出力先未定 # <0 ファイル # n_tri 現在の試行回数 # r 距離 ################################ def Output(sw, n_tri, r) k = 0 if sw >= 0 print(" 出力先は(0:出力なし,n:画面にn個づつ,-1:ファイル)? ") pr = Integer($stdin.gets()) else pr = -1 end if pr != 0 if pr > 0 out = $stdout $stdin.gets() else now = String(Time.now) out = open(@_o_file, "a") if @_seisu > -2 out.print("***試行回数 " + String(n_tri) + " 距離 " + String(int(r)) + " 時間 " + now + "\n") else out.print("***試行回数 " + String(n_tri) + " 距離 " + String(r) + " 時間 " + now + "\n") end end if @_out_m == 0 for i1 in 0 ... @_n_city n = @_seq[i1] if @_seisu > 0 out.write(" " + String(n) + " " + String(int(@_city[n][0])) + " " + String(int(@_city[n][1])) + "\n") else out.write(" " + String(n) + " " + String(@_city[n][0]) + " " + String(@_city[n][1]) + "\n") end if pr > 0 k += 1 if k == pr $stdin.gets() k = 0 end end end end if pr <= 0 out.close() end end end ####################################### # エッジの入れ替え # r_m 距離 # return =0 改善がなかった # =1 改善があった ####################################### def Change(r_m) max = r_m[0] max1 = 0.0 ch = 0 k1 = 0 k2 = 0 n1 = 0 n2 = 0 sw = 0 sw1 = 0 # 近傍を可変 if @_fix == 0 # 初期設定(k=2) k = 2 for i1 in 0 ... @_n_city @_seq_w4[i1] = @_seq[i1] @_seq_w3[i1] = 0 end # 評価 sw2 = 0 i0 = 0 while i0 < @_n_city-2 && sw2 < 2 if i0 == 0 n = @_n_city - 1 else n = @_n_city end i1 = i0 + 2 while i1 < n && sw2 < 2 # 相手の場所 k3 = i1 k4 = k3 + 1 if k4 > @_n_city-1 k4 = 0 end # 順番の入れ替え n3 = -1 for i2 in 0 ... @_n_city if @_seq_w4[i2] == @_seq[i0+1] n3 = i2 + 1 break end end nn = n3 n4 = -1 for i2 in 0 ... @_n_city if nn > @_n_city-1 nn = 0 end if @_seq_w4[nn] == @_seq[k3] || @_seq_w4[nn] == @_seq[k4] n4 = @_seq_w4[nn] break else nn += 1 end end if n4 == @_seq[k4] n4 = k3 k3 = k4 k4 = n4 end # 評価 @_seq_w1[0] = @_seq[k4] @_seq_w1[1] = @_seq[i0+1] n4 = -1 nn = 2 while n4 < 0 if n3 > @_n_city-1 n3 = 0 end @_seq_w1[nn] = @_seq_w4[n3] if @_seq_w4[n3] == @_seq[k3] n4 = 1 end nn += 1 n3 += 1 end @_seq_w1[nn] = @_seq[i0] nn += 1 n3 = -1 n4 = -1 for i2 in 0 ... @_n_city if @_seq_w4[i2] == @_seq[i0] n3 = i2 - 1 if n3 < 0 n3 = @_n_city - 1 end break end end while n4 < 0 if @_seq_w4[n3] == @_seq[k4] n4 = 1 else @_seq_w1[nn] = @_seq_w4[n3] nn += 1 n3 -= 1 if n3 < 0 n3 = @_n_city - 1 end end end r = kyori(@_n_city, @_seq_w1, @_rg) # 最適値の保存 if sw2 == 0 || r < max1 sw2 = 1 max1 = r n1 = k3 n2 = k4 k1 = i0 k2 = i0 + 1 for i2 in 0 ... @_n_city @_seq_w5[i2] = @_seq_w1[i2] end if @_sel > 0 && max1 < max sw2 = 2 end end i1 += 1 end i0 += 1 end # 最適値の保存と近傍の増加 if sw2 > 0 if max1 < max sw = 1 max = max1 for i1 in 0 ... @_n_city @_seq_w2[i1] = @_seq_w5[i1] end end if k < @_neib for i1 in 0 ... @_n_city @_seq_w4[i1] = @_seq_w5[i1] end @_seq_w3[k1] = 1 @_seq_w3[k2] = 1 @_seq_w3[n1] = 1 @_seq_w3[n2] = 1 k1 = n2 k += 1 else sw1 = 1 end else sw1 = 1 end # 実行(k>2) while sw1 == 0 # 評価 sw2 = 0 for i1 in 0 ... @_n_city # 相手の場所 k3 = i1 k4 = k3 + 1 if k4 > @_n_city-1 k4 = 0 end if @_seq_w3[k3] == 0 && @_seq_w3[k4] == 0 # 順番の入れ替え n3 = -1 for i2 in 0 ... @_n_city if @_seq_w4[i2] == @_seq[k2] n3 = i2 + 1 break end end nn = n3 n4 = -1 for i2 in 0 ... @_n_city if nn > @_n_city-1 nn = 0 end if @_seq_w4[nn] == @_seq[k3] || @_seq_w4[nn] == @_seq[k4] n4 = @_seq_w4[nn] break else nn += 1 end end if n4 == @_seq[k4] n4 = k3 k3 = k4 k4 = n4 end # 評価 @_seq_w1[0] = @_seq[k4] @_seq_w1[1] = @_seq[k2] n4 = -1 nn = 2 while n4 < 0 if n3 > @_n_city-1 n3 = 0 end @_seq_w1[nn] = @_seq_w4[n3] if @_seq_w4[n3] == @_seq[k3] n4 = 1 end nn += 1 n3 += 1 end @_seq_w1[nn] = @_seq[k1] nn += 1 n3 = -1 n4 = -1 for i2 in 0 ... @_n_city if @_seq_w4[i2] == @_seq[k1] n3 = i2 - 1 if n3 < 0 n3 = @_n_city - 1 end break end end while n4 < 0 if @_seq_w4[n3] == @_seq[k4] n4 = 1 else @_seq_w1[nn] = @_seq_w4[n3] nn += 1 n3 -= 1 if n3 < 0 n3 = @_n_city - 1 end end end r = kyori(@_n_city, @_seq_w1, @_rg) # 最適値の保存 if sw2 == 0 || r < max1 sw2 = 1 max1 = r n1 = k3 n2 = k4 for i2 in 0 ... @_n_city @_seq_w5[i2] = @_seq_w1[i2] end end end end # 最適値の保存と近傍の増加 if sw2 > 0 if max1 < max sw = 1 max = max1 for i1 in 0 ... @_n_city @_seq_w2[i1] = @_seq_w5[i1] end end if k < @_neib for i1 in 0 ... @_n_city @_seq_w4[i1] = @_seq_w5[i1] end @_seq_w3[n1] = 1 @_seq_w3[n2] = 1 k1 = n2 k += 1 else sw1 = 1 end else sw1 = 1 end end # 近傍を固定 else n3 = Integer(rand(0) * (@_n_city - 2)) if n3 > @_n_city-3 n3 = @_n_city - 3 end # 2近傍 i1 = 0 while i1 <= @_n_city-3 && ch == 0 if n3 == 0 n1 = @_n_city - 2 else n1 = @_n_city - 1 end i2 = n3 + 2 while i2 <= n1 && ch == 0 # 枝の場所((n3,n3+1), (k1,k2)) k1 = i2 if i2 == @_n_city-1 k2 = 0 else k2 = i2 + 1 end # 枝の入れ替え @_seq_w1[0] = @_seq[n3] k = 1 i3 = k1 while i3 > n3 @_seq_w1[k] = @_seq[i3] k += 1 i3 -= 1 end nn = k2 while nn != n3 @_seq_w1[k] = @_seq[nn] k += 1 nn += 1 if nn > @_n_city-1 nn = 0 end end # 評価 r = kyori(@_n_city, @_seq_w1, @_rg) if r < max max = r sw = 1 for i3 in 0 ... @_n_city @_seq_w2[i3] = @_seq_w1[i3] end if @_sel > 0 ch = 1 end end i2 += 1 end n3 += 1 if n3 > @_n_city-3 n3 = 0 end i1 += 1 end # 3近傍 if @_neib == 3 && ch == 0 i1 = 0 while i1 <= @_n_city-3 && ch == 0 n1 = @_n_city - 2 n2 = @_n_city - 1 i2 = n3 + 1 while i2 <= n1 && ch == 0 i3 = i2 + 1 while i3 <= n2 && ch == 0 # 枝の場所((n3,n3+1), (i2,i2+1), (k1,k2)) k1 = i3 if i3 == @_n_city-1 k2 = 0 else k2 = i3 + 1 end # 枝の入れ替えと評価 # 入れ替え(その1) @_seq_w1[0] = @_seq[n3] k = 1 i4 = i2 while i4 > n3 @_seq_w1[k] = @_seq[i4] k += 1 i4 -= 1 end i4 = k1 while i4 > i2 @_seq_w1[k] = @_seq[i4] k += 1 i4 -= 1 end nn = k2 while nn != n3 @_seq_w1[k] = @_seq[nn] k += 1 nn += 1 if nn > @_n_city-1 nn = 0 end end # 評価(その1) r = kyori(@_n_city, @_seq_w1, @_rg) if r < max max = r sw = 1 for i3 in 0 ... @_n_city @_seq_w2[i3] = @_seq_w1[i3] end if @_sel > 0 ch = 1 end end # 入れ替え(その2) @_seq_w1[0] = @_seq[n3] k = 1 i4 = k1 while i4 > i2 @_seq_w1[k] = @_seq[i4] k += 1 i4 -= 1 end for i4 in n3+1 ... i2+1 @_seq_w1[k] = @_seq[i4] k += 1 end nn = k2 while nn != n3 @_seq_w1[k] = @_seq[nn] k += 1 nn += 1 if nn > @_n_city-1 nn = 0 end end # 評価(その2) r = kyori(@_n_city, @_seq_w1, @_rg) if r < max max = r sw = 1 for i3 in 0 ...@_n_city @_seq_w2[i3] = @_seq_w1[i3] end if @_sel > 0 ch = 1 end end # 入れ替え(その3) @_seq_w1[0] = @_seq[n3] k = 1 for i4 in i2+1 ...k1+1 @_seq_w1[k] = @_seq[i4] k += 1 end i4 = i2 while i4 > n3 @_seq_w1[k] = @_seq[i4] k += 1 i4 -= 1 end nn = k2 while nn != n3 @_seq_w1[k] = @_seq[nn] k += 1 nn += 1 if nn > @_n_city-1 nn = 0 end end # 評価(その3) r = kyori(@_n_city, @_seq_w1, @_rg) if r < max max = r sw = 1 for i3 in 0 ... @_n_city @_seq_w2[i3] = @_seq_w1[i3] end if @_sel > 0 ch = 1 end end # 入れ替え(その4) @_seq_w1[0] = @_seq[n3] k = 1 for i4 in i2+1 ... k1+1 @_seq_w1[k] = @_seq[i4] k += 1 end for i4 in n3+1 ... i2+1 @_seq_w1[k] = @_seq[i4] k += 1 end nn = k2 while nn != n3 @_seq_w1[k] = @_seq[nn] k += 1 nn += 1 if nn > @_n_city-1 nn = 0 end end # 評価(その4) r = kyori(@_n_city, @_seq_w1, @_rg) if r < max max = r sw = 1 for i3 in 0 ... @_n_city @_seq_w2[i3] = @_seq_w1[i3] end if @_sel > 0 ch = 1 end end i3 += 1 end i2 += 1 end n3 += 1 if n3 > @_n_city-3 n3 = 0 end i1 += 1 end end end # 設定 if sw > 0 r_m[0] = max for i1 in 0 ... @_n_city @_seq[i1] = @_seq_w2[i1] end end return sw end attr("_seq", true) end ######################### # クラスPartitionの定義 ######################### class Partition ########################## # コンストラクタ # name ファイル名 ########################## def initialize(name) max = 0 # ファイルのオープン @_i_file = name # 入力ファイル名 inn = open(name, "r") # 基本データ s = inn.gets().split(" ") @_n_city = Integer(s[1]) # 都市の数 @_sel = Integer(s[3]) # エッジの選択方法 # =0 最良のものを選択 # =1 最初のものを選択 @_neib = Integer(s[5]) # 近傍(2 or 3) @_seisu = Integer(s[7]) # 位置データの表現方法 # =1 整数 # =-1 実数(距離を整数計算) # =-2 実数(距離を実数計算) s = inn.gets().split(" ") @_out_m = Integer(s[1]) # 出力方法 # =-1 ディスプレイ(経路長だけ) # =0 ディスプレイ # =1 ファイル # =2 ファイル(経路長だけ) @_o_file = "" if @_out_m > 0 @_o_file = s[3] end s = inn.gets().split(" ") @_n_p_x = Integer(s[2]) # x軸方向の分割数 @_n_p_y = Integer(s[4]) # y軸方向の分割数 @_max_try = Integer(s[6]) # 最大試行回数 @_fix = 1 # =1 近傍を固定 # =0 近傍を可変 if @_neib < 0 @_neib = -@_neib @_fix = 0 end # 都市の位置データ @_city = Array.new(@_n_city) for i1 in 0 ... @_n_city @_city[i1] = Array.new(2) s = inn.gets().split(" ") @_city[i1][0] = Float(s[0]) @_city[i1][1] = Float(s[1]) end # ファイルのクローズ inn.close() # 距離テーブルの作成 @_rg = Array.new(@_n_city) # 都市間の距離 for i1 in 0 ... @_n_city @_rg[i1] = Array.new(@_n_city) for i2 in i1+1 ... @_n_city x = @_city[i2][0] - @_city[i1][0] y = @_city[i2][1] - @_city[i1][1] @_rg[i1][i2] = Math.sqrt(x * x + y * y) if @_seisu > -2 @_rg[i1][i2] = rg[i1][i2].round() end end end for i1 in 0 ... @_n_city for i2 in 0 ... i1 @_rg[i1][i2] = @_rg[i2][i1] end end # 作業領域 @_state = Array.new(@_n_p_y) # 領域結合用ワーク @_n_seq = Array.new(@_n_p_y) # 各領域の都市数 @_n_seq1 = Array.new(@_n_p_y) # 各領域の都市数(ワーク) for i1 in 0 ... @_n_p_y @_state[i1] = Array.new(@_n_p_x) # 領域結合用ワーク @_n_seq[i1] = Array.new(@_n_p_x) # 各領域の都市数 @_n_seq1[i1] = Array.new(@_n_p_x) # 各領域の都市数(ワーク) end @_seq_w1 = Array.new(@_n_city) # 作業領域 for i1 in 0 ... @_n_city @_seq_w1[i1] = 0 end @_seq_w2 = Array.new(@_n_city) # 作業領域 @_p_x = Array.new(@_n_p_x) # x軸の分割点 @_p_y = Array.new(@_n_p_y) # y軸の分割点 # 都市の分割 min_x = @_city[0][0] max_x = @_city[0][0] min_y = @_city[0][1] max_y = @_city[0][1] for i1 in 1 ... @_n_city if @_city[i1][0] < min_x min_x = @_city[i1][0] else if @_city[i1][0] > max_x max_x = @_city[i1][0] end end if @_city[i1][1] < min_y min_y = @_city[i1][1] else if @_city[i1][1] > max_y max_y = @_city[i1][1] end end end s_x = (max_x - min_x) / @_n_p_x @_p_x[0] = min_x + s_x @_p_x[@_n_p_x-1] = max_x for i1 in 1 ... @_n_p_x-1 @_p_x[i1] = @_p_x[0] + i1 * s_x end s_y = (max_y - min_y) / @_n_p_y @_p_y[0] = min_y + s_y @_p_y[@_n_p_y-1] = max_y for i1 in 1 ... @_n_p_y-1 @_p_y[i1] = @_p_y[0] + i1 * s_y end @_seq = Array.new(@_n_p_y) # 経路 @_seq1 = Array.new(@_n_p_y) # 経路(ワーク) for i1 in 0 ... @_n_p_y @_seq[i1] = Array.new(@_n_p_x) @_seq1[i1] = Array.new(@_n_p_x) for i2 in 0 ... @_n_p_x @_seq[i1][i2] = Array.new(@_n_city) @_seq1[i1][i2] = Array.new(@_n_city) n = 0 for i3 in 0 ... @_n_city if @_seq_w1[i3] == 0 if @_city[i3][0] <= @_p_x[i2] && @_city[i3][1] <= @_p_y[i1] @_seq_w1[i3] = 1 @_seq_w2[n] = i3 n += 1 end end end @_n_seq1[i1][i2] = n if n > 0 for i3 in 0 ... n @_seq1[i1][i2][i3] = @_seq_w2[i3] end if n > max max = n end end end end # 作業領域 print("最大都市数 " + String(max) + "\n") @_city_i = Array.new(max) # 都市の位置データ(作業領域) for i1 in 0 ... max @_city_i[i1] = Array.new(2) end @_max = 0 # 最適経路の長さ end ################## # 最適化の実行 ################## def Optimize() r = 0 # 分割数と開始時間の出力 if @_out_m > 0 Output(0, r) end for i1 in 0 ... @_n_p_y for i2 in 0 ... @_n_p_x @_n_seq[i1][i2] = @_n_seq1[i1][i2] for i3 in 0 ... @_n_seq1[i1][i2] @_seq[i1][i2][i3] = @_seq1[i1][i2][i3] end end end # 分割毎の最適化 for i1 in 0 ... @_n_p_y for i2 in 0 ... @_n_p_x if @_n_seq[i1][i2] > 3 # 近傍の大きさ if @_n_seq[i1][i2] > 3 nb = @_neib else nb = 2 end # 都市位置データの設定 for i3 in 0 ... @_n_seq[i1][i2] k = @_seq[i1][i2][i3] @_city_i[i3][0] = @_city[k][0] @_city_i[i3][1] = @_city[k][1] end # 最適化 it = Iteration.new(@_n_seq[i1][i2], @_max_try, @_seisu, @_sel, nb, @_fix, 0, -1, 0, @_o_file, @_city_i) max = it.Optimize() # 結果の保存 for i3 in 0 ... @_n_seq[i1][i2] k = it._seq[i3] @_seq_w1[i3] = @_seq[i1][i2][k] end for i3 in 0 ... @_n_seq[i1][i2] @_seq[i1][i2][i3] = @_seq_w1[i3] end # 出力 if @_seisu > -2 r = Integer(kyori(@_n_seq[i1][i2], @_seq[i1][i2], @_rg)) else r = kyori(@_n_seq[i1][i2], @_seq[i1][i2], @_rg).round() print(" y " + String(i1+1) + " x " + String(i2+1) + " n_city " + String(@_n_seq[i1][i2]) + " range " + String(r) + " (trial " + String(max) + ")\n") end end end end # 経路の接続 r = Connect() # 出力 Output(@_n_city, r) end ######################## # 出力 # n_c 都市の数 # r 距離 ######################## def Output(n_c, r) k = 0 if @_out_m <= 0 print("距離 " + String(r) + "\n") out = $stdout $stdin.gets() else now = String(Time.now) out = open(@_o_file, "a") if n_c > 0 print("距離 " + String(r) + "\n") printf(out, " 距離 " + String(r) + " 時間 " + now + "\n") else printf("問題 " + @_i_file + " 分割 " + String(@_n_p_x) + " " + String(@_n_p_y) + " 時間 " + now + "\n") end end if n_c > 0 && (@_out_m == 0 || @_out_m == 1) for i1 in 0 ... n_c n = @_seq_w1[i1] if @_seisu > 0 out.print(" " + String(n) + " " + String(int(@_city[n][0])) + " " + String(int(@_city[n][1])) + "\n") else out.print(" " + String(n) + " " + String(@_city[n][0]) + " " + String(@_city[n][1]) + "\n") end if @_out_m == 0 k += 1 if k == 10 $stdin.gets() k = 0 end end end end if @_out_m > 0 out.close() end end ######################## # 分割された領域の接続 ######################## def Connect() min = 0 k1 = 0 k2 = 0 k3 = 0 k4 = 0 min_c = 0 r1 = 0 r2 = 0 r3 = 0 r4 = 0 s1 = 0 s2 = 0 sw = 1 # 領域が1つの場合 if @_n_p_x == 1 && @_n_p_y == 1 for i1 in 0 ... @_n_seq[0][0] @_seq_w1[i1] = @_seq[0][0][i1] end # 初期設定 else for i1 in 0 ... @_n_p_y for i2 in 0 ... @_n_p_x if @_n_seq[i1][i2] > 0 @_state[i1][i2] = 0 else @_state[i1][i2] = 1 end end end # 実行 while sw > 0 # 最小節点領域 min_c = @_n_city sw = 0 for i1 in 0 ... @_n_p_y for i2 in 0 ... @_n_p_x if @_state[i1][i2] == 0 && @_n_seq[i1][i2] < min_c sw = 1 r1 = i1 r2 = i2 min_c = @_n_seq[i1][i2] end end end # 結合する対象領域の決定 if sw > 0 sw = 0 for i1 in 0 ... @_n_p_y for i2 in 0 ... @_n_p_x if @_state[i1][i2] == 0 && (i1 != r1 || i2 != r2) # 節点の数>2 if @_n_seq[r1][r2] > 1 for i3 in 0 ... @_n_seq[r1][r2] k1 = @_seq[r1][r2][i3] if i3 == @_n_seq[r1][r2]-1 k2 = @_seq[r1][r2][0] else k2 = @_seq[r1][r2][i3+1] end wd1 = @_rg[k1][k2] for i4 in 0 ... @_n_seq[i1][i2] k3 = @_seq[i1][i2][i4] if i4 == @_n_seq[i1][i2]-1 k4 = @_seq[i1][i2][0] else k4 = @_seq[i1][i2][i4+1] end wd = wd1 + @_rg[k3][k4] wa1 = @_rg[k1][k3] + @_rg[k2][k4] wa2 = @_rg[k1][k4] + @_rg[k2][k3] if sw == 0 || wa1-wd < min min = wa1 - wd r3 = i1 r4 = i2 if i3 == @_n_seq[r1][r2]-1 s1 = 0 else s1 = i3 + 1 end if i4 == @_n_seq[i1][i2]-1 s2 = 0 else s2 = i4 + 1 end sw = -1 end if sw == 0 || wa2-wd < min min = wa2 - wd r3 = i1 r4 = i2 s1 = i3 if i4 == @_n_seq[i1][i2]-1 s2 = 0 else s2 = i4 + 1 end sw = 1 end end end # 節点の数=1 else k1 = @_seq[r1][r2][0] if @_n_seq[i1][i2] > 1 for i4 in 0 ... @_n_seq[i1][i2] k3 = @_seq[i1][i2][i4] if i4 == @_n_seq[i1][i2]-1 k4 = @_seq[i1][i2][0] else k4 = @_seq[i1][i2][i4+1] end wd = @_rg[k3][k4] wa1 = @_rg[k1][k3] + @_rg[k1][k4] if sw == 0 || wa1-wd < min min = wa1 - wd r3 = i1 r4 = i2 s1 = 0 if i4 == @_n_seq[i1][i2]-1 s2 = 0 else s2 = i4 + 1 end sw = 1 end end else k3 = @_seq[i1][i2][0] wa1 = @_rg[k1][k3] if sw == 0 || wa1 < min min = wa1 r3 = i1 r4 = i2 s1 = 0 s2 = 0 sw = 1 end end end end end end # 領域の結合 @_seq_w1[0] = @_seq[r1][r2][s1] k = 1 n = s2 for i1 in 0 ... @_n_seq[r3][r4] @_seq_w1[k] = @_seq[r3][r4][n] k += 1 n += 1 if n > @_n_seq[r3][r4]-1 n = 0 end end if sw > 0 n = s1 + 1 for i1 in 0 ... @_n_seq[r1][r2]-1 if n > @_n_seq[r1][r2]-1 n = 0 end @_seq_w1[k] = @_seq[r1][r2][n] k += 1 n += 1 end else n = s1 - 1 for i1 in 0 ... @_n_seq[r1][r2]-1 if n < 0 n = @_n_seq[r1][r2] - 1 end @_seq_w1[k] = @_seq[r1][r2][n] k += 1 n -= 1 end end # 状態の変更 @_n_seq[r1][r2] += @_n_seq[r3][r4] @_state[r3][r4] = 1 for i1 in 0 ... @_n_seq[r1][r2] @_seq[r1][r2][i1] = @_seq_w1[i1] end sw = 1 end end end if @_seisu > -2 r = Integer(kyori(@_n_city, @_seq_w1, @_rg)) else r = kyori(@_n_city, @_seq_w1, @_rg).round() end @_max = r return r end attr("_out_m", true) attr("_o_file", true) attr("_max", true) end # 入力ミス if ARGV[0] == nil print("***error ファイル名を入力して下さい\n") # 入力OK else # 問題数と入力データファイル名 line = gets() a = line.split(" ") nm = Integer(a[1]) aa = Array.new(nm) for i0 in 0 ... nm aa[i0] = gets() end for i0 in 0 ... nm # 各問題の実行 a = aa[i0].split(" ") i_file = a[1] n = Integer(a[3]) pt = Partition.new(i_file) mean = 0.0 max = -1 # 乱数の初期値を変える for i1 in 0 ... n print("\n+++++問題 " + i_file + " +++++\n") srand(1000 * i1 + 1234567); # 最適化 pt.Optimize() # 最適値とその平均の計算 mean += pt._max if max < 0 or pt._max < max max = pt._max end end # 結果 if pt._out_m <= 0 print(" -----最小 " + String(max) + " 平均 " + String(mean/n) + "-----\n") else out = open(pt._o_file, "a") out = open("out.txt", "a") printf(out, " -----最小 " + String(max) + " 平均 " + String(mean/n) + "-----\n") out.close() end end end =begin ------------------------ケーススタディデータ(data.txt)------ 問題の数 2 問題 data1.txt 繰り返し回数 2 問題 data2.txt 繰り返し回数 1 ---------------------データファイル(data1.txt)------------ 都市の数 50 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2 出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt 分割数 X 2 Y 2 最大試行回数 1000 86.950684 27.711487 82.357788 16.148376 29.791260 37.959290 27.493286 1.542664 90.893555 88.734436 40.109253 92.308044 87.445068 53.474426 24.893188 99.382019 11.633301 80.616760 61.532593 8.702087 30.645752 93.598938 4.714966 81.205750 86.669922 90.858459 84.127808 52.830505 96.893311 45.832825 4.458618 34.513855 53.503418 6.959534 45.394897 12.193298 23.687744 97.676086 61.624146 46.806335 49.633789 16.419983 82.833862 74.290466 48.529053 36.628723 13.711548 5.583191 12.561035 6.739807 33.944702 26.622009 8.917236 50.190735 98.220825 98.344421 79.785156 65.419006 36.227417 56.687927 42.352295 25.862122 52.651978 12.590027 88.806152 79.957581 27.182007 51.988220 86.334229 51.142883 14.505005 35.820007 77.124023 37.855530 44.308472 0.022888 78.363037 13.533020 21.279907 55.534363 82.238770 26.612854 25.106812 88.291931 55.938721 0.532532 10.476685 59.233093 41.650391 33.729553 7.077026 4.295349 56.561279 99.641418 19.595337 34.416199 92.858887 46.705627 27.719116 35.533142 ---------------------データファイル(data2.txt)------------ 都市の数 10 選択方法(0:最良,1:最初) 1 近傍(2or3) 2 整数 -2 出力(0:ディスプレイ,1:ファイル) -1 出力ファイル名 out1.txt 分割数 X 1 Y 1 最大試行回数 1000 8.695068 2.771149 8.235779 1.614838 2.979126 3.795929 2.749329 0.154266 9.089355 8.873444 4.010925 9.230804 8.744507 5.347443 2.489319 9.938202 1.163330 8.061676 6.153259 0.870209 =end