<前回の続き>
「 ソースは Git hub にある☆
まず 何が出力されるかを説明しよう☆」
Git hub: event-placement-ai
「 CSV形式で ここまでは作ってくれる☆
あとは 手打ちで 何とかしろだぜ☆」
best-position.csv
X,Y,BLOCK,TABLE,PARTICIPANT,GENRE_CODE
0,0,C,27,35,Gray
1,0,C,26,22,Blue
2,0,C,25,41,Red
3,0,C,24,18,Yellow
4,0,C,23,8,Blue
7,0,B,22,20,Yellow
8,0,B,21,23,Black
9,0,B,20,54,Orange
10,0,B,19,21,Red
13,0,A,18,1,Red
14,0,A,17,27,Blue
15,0,A,16,53,Green
16,0,A,15,31,Yellow
17,0,A,14,34,Pink
18,0,A,13,52,Red
19,0,A,12,49,Gray
0,1,C,28,30,Blue
19,1,A,11,4,Blue
0,2,C,29,7,Red
2,2,F,57,57,Green
3,2,F,56,48,White
4,2,F,55,24,Black
7,2,E,50,25,White
8,2,E,49,47,Brown
9,2,E,48,56,Blue
10,2,E,47,60,Blue
13,2,D,41,58,Yellow
14,2,D,40,5,Green
15,2,D,39,19,SkyBlue
16,2,D,38,10,Green
17,2,D,37,40,Blue
19,2,A,10,38,Orange
0,3,C,30,33,Blue
2,3,F,58,15,Blue
3,3,F,59,14,Green
4,3,F,60,32,Orange
7,3,E,51,11,Purple
8,3,E,52,39,White
9,3,E,53,36,Green
10,3,E,54,12,Red
13,3,D,42,28,Pink
14,3,D,43,2,Red
15,3,D,44,45,YellowGreen
16,3,D,45,3,Blue
17,3,D,46,6,Blue
19,3,A,9,50,Blue
0,4,C,31,51,Yellow
19,4,A,8,44,Green
0,5,C,32,46,Black
1,5,C,33,26,Yellow
2,5,C,34,17,Blue
3,5,C,35,16,Yellow
4,5,C,36,59,White
13,5,A,1,9,Green
14,5,A,2,13,Violet
15,5,A,3,42,Green
16,5,A,4,29,Green
17,5,A,5,43,Yellow
18,5,A,6,55,Violet
19,5,A,7,37,Red
「 この出力データを使って、さらに思考の材料にしてもいいわけだしな☆」
CCCCC..BBBB..AAAAAAA
C..................A
C.FFF..EEEE..DDDDD.A
C.FFF..EEEE..DDDDD.A
C..................A
CCCCC........AAAAAAA
「 ブロックは Rogue形式で示せだぜ☆ 半角1文字でなんとかしろ☆」
27,26,25,24,23, 0, 0,22,21,20,19, 0, 0,18,17,16,15,14,13,12
28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11
29, 0,57,56,55, 0, 0,50,49,48,47, 0, 0,41,40,39,38,37, 0,10
30, 0,58,59,60, 0, 0,51,52,53,54, 0, 0,42,43,44,45,46, 0, 9
31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8
32,33,34,35,36, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7
ID,GENRE_CODE
1,Red
2,Red
3,Blue
4,Blue
5,Green
6,Blue
7,Red
8,Blue
9,Green
10,Green
11,Purple
12,Red
13,Violet
14,Green
15,Blue
16,Yellow
17,Blue
18,Yellow
19,SkyBlue
20,Yellow
21,Red
22,Blue
23,Black
24,Black
25,White
26,Yellow
27,Blue
28,Pink
29,Green
30,Blue
31,Yellow
32,Orange
33,Blue
34,Pink
35,Gray
36,Green
37,Red
38,Orange
39,White
40,Blue
41,Red
42,Green
43,Yellow
44,Green
45,YellowGreen
46,Black
47,Brown
48,White
49,Gray
50,Blue
51,Yellow
52,Red
53,Green
54,Orange
55,Violet
56,Blue
57,Green
58,Yellow
59,White
60,Blue
「 参加者は番号に ジャンルコードを対応付けろだぜ☆
ジャンルコードは HTML/CSS で使われる色の名前☆」
# Shuffule
random.shuffle(par_id_list)
random.shuffle(flo_id_list)
「 参加者番号と、テーブル番号を 対応付けながら 先頭から順に並べろだぜ☆」
「 ブロックに 同じジャンルコードで まとめてくれるところまで やってくれてもいいんじゃない?」
import random
from my_lib.html_generator.css_builder import new_csv
from my_lib.html_generator.html_builder import new_html
from my_lib.entry_list import read_entry_lists
from my_lib.mapper import write_mappings
from my_lib.position import new_position
from my_lib.build_floor_map import convert_map
from evaluation import evaluate
# Location.
best_position_file = "./event-placement-ai/output-data/best-position.csv"
# Read a cloor map.
convert_map()
par_id_list, flo_id_list = read_entry_lists()
print("Info : Participants count: {}".format(len(par_id_list)))
print("Info : Table count: {}".format(len(flo_id_list)))
max_score = -1
best_pos_df = None
for i in range(0, 10):
# Shuffule
random.shuffle(par_id_list)
random.shuffle(flo_id_list)
write_mappings(par_id_list, flo_id_list)
pos_df = new_position()
# Evaluation
score = evaluate(pos_df)
if max_score < score:
max_score = score
best_pos_df = pos_df
new_html(best_pos_df)
new_csv(best_pos_df)
best_pos_df.to_csv(best_position_file, index=False)
print("Info : Finished.")
「 とりあえず ループで10回 回して 一番評価値の多い配置を返すなら
外側の形は こうだな☆」
evaluation.py
def evaluate(pos_df):
return 0
def evaluate(pos_df):
# 評価値
value = 0
# Block は A~F とする。
# GenreCode は色々。
block_dict = {}
for _index, row in pos_df.iterrows():
# x = row["X"]
# y = row["Y"]
block = row["BLOCK"]
# table_id = row["TABLE"]
# participant_id = row["PARTICIPANT"]
genre_code = row["GENRE_CODE"]
if not(block in block_dict):
block_dict[block] = {}
if not(genre_code in block_dict[block]):
block_dict[block][genre_code] = 0
block_dict[block][genre_code] += 1
# 集計
for _block_name, genre_code_dict in block_dict.items():
for _genre_code_name, count in genre_code_dict.items():
value += count ** 2
break
return value
「 ループで 10回 トライすると こう☆
評価値は 99 ぐらいかだぜ☆ Cブロックに少し 青 が固まっているな☆」
「 もう1回 1000回 トライで 評価値119☆ 黄色と青が 固まっているような気もするが……☆」
「 シャッフルするのではなく、1つずつ 入れ替えて 少しずつ 良くしていくのが
いいんじゃないか☆?」
「 そもそも その評価関数は わたしたちの目的に沿ってるのかだぜ☆?」
「 シャッフルして ラッキーパンチを待っていては くじ運頼りになってしまう☆
わたしたちは もう少しマシな探し方を知っているだろう☆」
import random
import pandas as pd
from my_lib.html_generator.css_builder import new_csv
from my_lib.html_generator.html_builder import new_html
from my_lib.entry_list import read_entry_lists
from my_lib.mapper import new_mappings
from my_lib.position import new_position
from my_lib.build_floor_map import convert_floor_map
from evaluation import evaluate
# Location.
block_file = "./event-placement-ai/input-data/block.txt"
table_file = "./event-placement-ai/input-data/table.txt"
best_position_file = "./event-placement-ai/output-data/best-position.csv"
position_file = "./event-placement-ai/auto-generated/position.csv"
floor_file = "./event-placement-ai/auto-generated/floor.csv"
participant_file = "./event-placement-ai/input-data/participant.csv"
mappings_file = "./event-placement-ai/auto-generated/mappings.csv"
# Read a floor.
floor_df = convert_floor_map(block_file, table_file)
floor_df.to_csv(floor_file, index=False)
par_id_list, flo_id_list = read_entry_lists()
# print("Info : Participants count: {}".format(len(par_id_list)))
# print("Info : Table count: {}".format(len(flo_id_list)))
# Shuffule at first.
random.shuffle(par_id_list)
flo_id_list.sort()
# random.shuffle(flo_id_list)
max_value = -1
for i in range(0, 1000):
# Swap.
size = len(par_id_list)
index1 = random.randint(0, size-1)
index2 = random.randint(0, size-1)
# print("size={}, index1={}, index2={}".format(size, index1, index2))
temp = par_id_list[index1]
par_id_list[index1] = par_id_list[index2]
par_id_list[index2] = temp
mappings_df = new_mappings(par_id_list, flo_id_list)
mappings_df.to_csv(mappings_file, index=False)
# floor_df = pd.read_csv(floor_file,
# sep=',', engine='python')
participant_df = pd.read_csv(participant_file)
# mappings_df = pd.read_csv(mappings_file,
# sep=',', engine='python')
pos_df = new_position(floor_df,
participant_df, mappings_df)
"""
output
------
X,Y,BLOCK,PARTICIPANT,TABLE,GENRE_CODE
0,0,C,1,27,Red
1,0,C,2,26,Red
2,0,C,3,25,Blue
3,0,C,4,24,Blue
4,0,C,5,23,Green
"""
pos_df.to_csv(position_file, index=False)
# Evaluation
value = evaluate(pos_df)
print("Info : i={}, Value={}, Max={}".format(i, value, max_value))
if max_value < value:
# Update and output.
max_value = value
new_html(pos_df, 0, 0, max_value)
new_csv(pos_df, 0, 0)
pos_df.to_csv(best_position_file, index=False)
else:
# Cancel swap.
temp = par_id_list[index2]
par_id_list[index2] = par_id_list[index1]
par_id_list[index1] = temp
print("Info : Finished.")
「 2か所を選んで 交換し、評価値が上がれば採用、そうでなければ 元に戻す、
ということを ちまちま 繰り返そうぜ☆」
「 確実だが 時間がかかるぜ☆
最悪、机の数の2乗ぐらい 回数が かかるんじゃないか☆?」
「 緑、赤、青は 自分にあったブロックを選んでいるようにみえるが、まぐれ だからな☆
最初に 自分に合わないブロックに集まってしまうと、
そこから出ようとしなくなるのは 想像付くぜ☆」
「 例えば このように、 赤 が小さいブロックに陣取ってしまうと、もう修正がきかない☆
これを 極大の丘に登る という☆
わたしたちは 最大の丘に登りたい んだぜ☆」
「 ひとまず 1000回で探索を終了するのではなく、どこを1つ交換しても評価値が上がらなくときに
終了するように変更しようぜ☆?」
「 じゃあ ランダムに2か所選んで交換するのではなく、机の数の2乗÷2 の組み合わせを あらかじめ作って
シャッフルするの?」
「 机の数が 300 なら 90000 の組み合わせがあるのか……☆
じゃあ やっぱ ランダム・ヒットで☆」
import os
import random
import pandas as pd
from my_lib.html_generator.css_builder import new_csv
from my_lib.html_generator.html_builder import new_html
from my_lib.html_generator.json_builder import new_json
from my_lib.entry_list import new_entry_lists_from_mappings
from my_lib.entry_list import read_entry_lists
from my_lib.mapper import new_mappings
from my_lib.position import new_position
from my_lib.build_floor_map import convert_floor_map
from evaluation import evaluate
# Location.
block_file = "./event-placement-ai/input-data/block.txt"
table_file = "./event-placement-ai/input-data/table.txt"
best_position_file = "./event-placement-ai/output-data/best-position.csv"
position_file = "./event-placement-ai/auto-generated/position.csv"
floor_file = "./event-placement-ai/auto-generated/floor.csv"
participant_file = "./event-placement-ai/input-data/participant.csv"
best_mappings_file = "./event-placement-ai/auto-generated/best-mappings.csv"
# Read a floor.
floor_df = convert_floor_map(block_file, table_file)
floor_df.to_csv(floor_file, index=False)
if os.path.isfile(best_mappings_file):
tbl_id_list, par_id_list = new_entry_lists_from_mappings(
best_mappings_file)
else:
tbl_id_list, par_id_list = read_entry_lists(floor_file, participant_file)
# print("Info : Participants count: {}".format(len(par_id_list)))
# print("Info : Table count: {}".format(len(tbl_id_list)))
# Sort table.
tbl_id_list.sort()
# random.shuffle(tbl_id_list)
# Shuffule at first.
# random.shuffle(par_id_list)
prod_num = 0
time_num = 0
retry = True
max_value = -1
while retry:
retry = False
for i in range(0, 1000):
time_num += 1
# Random swap.
size = len(par_id_list)
index1 = random.randint(0, size-1)
index2 = random.randint(0, size-1)
# print("size={}, index1={}, index2={}".format(size, index1, index2))
temp = par_id_list[index1]
par_id_list[index1] = par_id_list[index2]
par_id_list[index2] = temp
mappings_df = new_mappings(tbl_id_list, par_id_list)
participant_df = pd.read_csv(participant_file)
pos_df = new_position(floor_df,
participant_df, mappings_df)
"""
output
------
X,Y,BLOCK,PARTICIPANT,TABLE,GENRE_CODE
0,0,C,1,27,Red
1,0,C,2,26,Red
2,0,C,3,25,Blue
3,0,C,4,24,Blue
4,0,C,5,23,Green
"""
pos_df.to_csv(position_file, index=False)
# Evaluation
value = evaluate(pos_df)
print("Info : i={}, Value={}, Max={}".format(i, value, max_value))
if max_value < value:
# Update and output.
max_value = value
new_html(pos_df, prod_num, time_num, max_value)
new_csv(pos_df, prod_num, time_num)
new_json(pos_df, prod_num, time_num, max_value)
mappings_df.to_csv(best_mappings_file, index=False)
pos_df.to_csv(best_position_file, index=False)
retry = True
else:
# Cancel swap.
temp = par_id_list[index2]
par_id_list[index2] = par_id_list[index1]
par_id_list[index1] = temp
print("Info : Finished.")
「 あれっ、ループの中で ファイル読込してしまっている☆
遅いわけだぜ☆」
「 評価値が 409 にもなると、ランダムでは 1000回 入れ替えても 評価値が上がらなかったぜ☆」
「 テーブル番号順で 同じ色が連続したら 評価値1点 追加しない?」
「 評価関数が 机の数 分だけ重たくなるぜ☆ まあ O(n) なら軽微か……☆」
evaluation.py
def evaluate(pos_df):
# 評価値
value = 0
# block_dict[block][genre_code] = value
block_dict = {}
for _index, row in pos_df.iterrows():
# x = row["X"]
# y = row["Y"]
block = row["BLOCK"]
# table_id = row["TABLE"]
# participant_id = row["PARTICIPANT"]
genre_code = row["GENRE_CODE"]
if not(block in block_dict):
block_dict[block] = {}
if not(genre_code in block_dict[block]):
block_dict[block][genre_code] = 0
block_dict[block][genre_code] += 1
# 集計。ブロックに同じ色が集まっているほど高評価。
for _block_name, genre_code_dict in block_dict.items():
for _genre_code_name, count in genre_code_dict.items():
value += count ** 2
break
# 集計。テーブル番号順にして、同じ色が連続したら 1点加点。
sorted_pos_df = pos_df.sort_values(by=["TABLE"], ascending=True)
# print(sorted_pos_df.head(5))
table_ordered_list = sorted_pos_df[["TABLE", "GENRE_CODE"]].values.tolist()
# print("table_ordered_list: {}".format(table_ordered_list))
prev_genre_code = None
for entry in table_ordered_list:
if prev_genre_code == entry[1]:
value += 1
# print("prev_genre_code: {}, entry[1]: {}, value: {}".format(
# prev_genre_code, entry[1], value))
else:
prev_genre_code = entry[1]
return value
「 2個つながっている黒のところに 青を持っていかないのは、入れ替えても 同点だからね。
連続していたら1点追加じゃなくて、連続していた数だけ追加 にしたら
もっと つながると思うわよ?」
# 集計。テーブル番号順にして、同じ色が連続したら、連続した数だけ加点。
continue_bonus = 0
sorted_pos_df = pos_df.sort_values(by=["TABLE"], ascending=True)
# print(sorted_pos_df.head(5))
table_ordered_list = sorted_pos_df[["TABLE", "GENRE_CODE"]].values.tolist()
# print("table_ordered_list: {}".format(table_ordered_list))
prev_genre_code = None
for entry in table_ordered_list:
if prev_genre_code == entry[1]:
continue_bonus += 1
value += continue_bonus
# print("prev_genre_code: {}, entry[1]: {}, value: {}".format(
# prev_genre_code, entry[1], value))
else:
prev_genre_code = entry[1]
continue_bonus = 0
「 49のグレーと 19のスカイブルーが入れ替わって欲しいんだけど、
テーブル1つ1つずつのランダムじゃなくて、ジャンルコードが連続するテーブルの両端以外のテーブルは除いたあとでのランダムって
できないの?」
「 できるが、仕事帰りに ゆったりするはずの わたしの休みが 消し飛ぶ……☆」
「 ダメだ今日中に 終わんね☆
ランダムなスワップだけでは 評価関数で ごり押しするにも すぐ上限がくる☆
次回から ランダムをやめて 探索部を作り込んでいこうぜ☆」
「 探索部を書く前に、ブロックの中のジャンルコードの両端の2つの机、あるいは単独の1つの机を ピックアップするモジュールを作りたい☆
絵を描いて説明すると……☆」
「 すべての机から ランダムに2つ選ぶのではなく、
上図の赤丸で示した机から ランダムに2つ選びたい☆」
「 連続するジャンルコードの 始端と終端、または 単独のジャンルコード を選べばいいのよ」
import os
import random
import pandas as pd
from my_lib.html_generator.css_builder import new_csv
from my_lib.html_generator.html_builder import new_html
from my_lib.html_generator.json_builder import new_json
from my_lib.entry_list import new_entry_lists_from_mappings
from my_lib.entry_list import read_entry_lists
from my_lib.mapper import new_mappings
from my_lib.position import new_position
from my_lib.build_floor_map import convert_floor_map
from evaluation import evaluate
# Location.
block_file = "./event-placement-ai/input-data/block.txt"
table_file = "./event-placement-ai/input-data/table.txt"
participant_file = "./event-placement-ai/input-data/participant.csv"
position_file = "./event-placement-ai/auto-generated/position-{}-{}-{}.csv"
floor_file = "./event-placement-ai/auto-generated/floor.csv"
best_mappings_file = "./event-placement-ai/auto-generated/best-mappings.csv"
# Read a floor.
floor_df = convert_floor_map(block_file, table_file)
floor_df.to_csv(floor_file, index=False)
participant_df = pd.read_csv(participant_file)
if os.path.isfile(best_mappings_file):
tbl_id_list, par_id_list = new_entry_lists_from_mappings(
best_mappings_file)
# print("len(tbl_id_list): {}".format(len(tbl_id_list)))
# print("len(par_id_list): {}".format(len(par_id_list)))
# print("tbl_id_list: {}".format(tbl_id_list))
# print("par_id_list: {}".format(par_id_list))
genre_code_list = []
for i in range(0, len(tbl_id_list)):
temp_df = participant_df[participant_df.ID == par_id_list[i]]
temp_df = temp_df['GENRE_CODE']
# print(temp_df.head(5))
# print("temp_df.values.tolist()[0]: {}".format(
# temp_df.values.tolist()[0]))
genre_code_list.append(temp_df.values.tolist()[0])
# print("len(genre_code_list): {}".format(len(genre_code_list)))
# print("genre_code_list: {}".format(genre_code_list))
else:
tbl_id_list, par_id_list, genre_code_list = read_entry_lists(
floor_file, participant_df)
# print("Info : Participants count: {}".format(len(par_id_list)))
# print("Info : Table count: {}".format(len(tbl_id_list)))
# テーブル番号を崩さずスキャンしたいので、ソートしない。
# tbl_id_list.sort()
# random.shuffle(tbl_id_list)
# Shuffule at first.
# random.shuffle(par_id_list)
prod_num = 0
var_num = 0
progress_num = 0
retry = True
max_value = -1
def pick_up_index_list(tbl_id_list, genre_code_list):
"""
index_list = []
for i in range(0, len(par_id_list)):
index_list.append(i)
return index_list
"""
order_list = [0] * len(tbl_id_list)
index = 0
for tbl_id in tbl_id_list:
order_list[tbl_id-1] = index
index += 1
# print("order_list: {}".format(order_list))
index_list = []
prev_genre_code = None
prev_index = -1
# 同じジャンルコードが連続しているところは、始点と終点だけを取る。
for index in order_list:
genre_code = genre_code_list[index]
# print("prev_genre_code: {}, genre_code: {}".format(
# prev_genre_code, genre_code))
if prev_genre_code == None:
prev_genre_code = genre_code
# Index of start.
index_list.append(index)
elif prev_genre_code != genre_code:
prev_genre_code = genre_code
# print("start: {}, end: {}".format(
# start, current-1))
if index_list[len(index_list)-1] != prev_index:
# Index of previous end.
index_list.append(prev_index)
# Index of start.
index_list.append(index)
prev_index = index
# print("len(genre_code_list)-1: {}".format(len(genre_code_list)-1))
index_list.append(order_list[len(order_list)-1])
# print("index_list: {}".format(index_list))
# # 並び順を崩さないようにすること。
# # result = list(set(index_list))
# # print("result: {}".format(result))
return index_list
def choice_index():
# Pick up table.
picked_up_index_list = pick_up_index_list(tbl_id_list, genre_code_list)
# print("picked_up_index_list: {}".format(picked_up_index_list))
# Random swap.
size = len(picked_up_index_list)
index11 = random.randint(0, size-1)
index12 = random.randint(0, size-1)
index1 = picked_up_index_list[index11]
index2 = picked_up_index_list[index12]
# print("size={}, index1={}, index2={}".format(size, index1, index2))
# print("Choiced index1={}, index2={}".format(index1, index2))
return index1, index2
def swap_par(index1, index2, par_id_list, genre_code_list):
"""
テーブルIDは固定し、参加者IDを入れ替えます。
"""
temp_par_id = par_id_list[index1]
temp_genre_code = genre_code_list[index1]
par_id_list[index1] = par_id_list[index2]
genre_code_list[index1] = genre_code_list[index2]
par_id_list[index2] = temp_par_id
genre_code_list[index2] = temp_genre_code
return
while retry:
retry = False
for i in range(0, 1000):
progress_num += 1
index1, index2 = choice_index()
swap_par(index1, index2, par_id_list, genre_code_list)
mappings_df = new_mappings(tbl_id_list, par_id_list)
pos_df = new_position(floor_df,
participant_df, mappings_df)
# Evaluation
value = evaluate(pos_df)
print("Info : i={}, Value={}, Max={}".format(i, value, max_value))
if max_value < value:
# Update and output.
max_value = value
new_html(pos_df, prod_num, var_num, progress_num, max_value)
new_csv(pos_df, prod_num, var_num, progress_num)
new_json(pos_df, prod_num, var_num, progress_num, max_value)
mappings_df.to_csv(best_mappings_file, index=False)
pos_df.to_csv(position_file.format(
prod_num, var_num, progress_num), index=False)
retry = True
else:
# Cancel swap.
swap_par(index2, index1, par_id_list, genre_code_list)
"""
temp = par_id_list[index2]
par_id_list[index2] = par_id_list[index1]
par_id_list[index1] = temp
"""
print("Info : Finished.")
「 人工知能どころか 機械学習も無しの ただのアルゴリズムで 結構揃うものだ……☆」
「 ブロックで切れてないので、上図の黄色はつながっている☆」
「 じゃあ一旦、初期配置をシャッフルするぜ☆
少しずつ良くしていくような最適化は、一度付いた癖は 直らないからな☆」
「 白はもっと くっつきそうなものだが☆
赤も 極大 に登りあがってしまった☆」
「 じゃあ 初期配置をまた シャッフルして……、って
ぜんぜん シャッフルされてないじゃないか☆!」
「 ぜんぜん テストもせずに エクステンド(増築)してるからな☆
結果の正当性も疑わしいものだぜ☆」
「 少し異なるとか、同じとか、初期配置が どれほどの影響があるか分からないが、ランダム配置であることは重要だろう☆」
「 1個浮いている緑は 橙色のところに移したいけど、そうすると橙色が離れてしまうから、
2か所の交換だけではなく、3か所同時交換 とか有効そうじゃない?」
「 ランダムな組み合わせが爆発して どうでもいいところで 3か所同時交換するばかりに なる気もするが……☆」
「 同じジャンルコード動詞で スワップ しても スワップしたことにならないので、
違う色動詞で スワップするようにしなさい」
def choice_index():
# Pick up table.
picked_up_index_list = pick_up_index_list(tbl_id_list, genre_code_list)
# print("picked_up_index_list: {}".format(picked_up_index_list))
# リトライ回数が多すぎると、終わりたいときに、逆に終わらないかもしれない。
retry = 3
genre_code1 = None
genre_code2 = None
while genre_code1 == genre_code2 and 0 < retry:
# Random choice at first.
size = len(picked_up_index_list)
index11 = random.randint(0, size-1)
index1 = picked_up_index_list[index11]
genre_code1 = genre_code_list[index1]
# 同じ色はなるべく選ばない。
index12 = random.randint(0, size-1)
index2 = picked_up_index_list[index12]
genre_code2 = genre_code_list[index2]
retry -= 1
# print("size={}, index1={}, index2={}".format(size, index1, index2))
# print("Choiced index1={}, index2={}".format(index1, index2))
return index1, index2
「 しかし 緑が1個浮いている気がするが、くっつけなかったのかだぜ☆?」
「 10と55を ピンポイントで入れ替えるのは 確率が低いんじゃない?
それか 改造したコードがエンバグしたか」
「 いったい どういう確率なのかも ページに表示したいよな☆」
「 JSONを Java Script で読み込んで、writeln したらどうだぜ☆?」
placement-0-0-5412.json
{
"test": 0,
"variation": 0,
"progress": 5412,
"value" : 614
}
「 web-server を立ててたら読めるんだが、プログラマーでない読者に サーバー立てろとか言っても むずかしいだろうしな……☆」
def new_json(test_number, variation_number, progress_num, value):
return """
{{
"test": {0},
"variation": {1},
"progress": {2},
"value" : {3}
}}
""".format(test_number, variation_number, progress_num, value)
「 じゃあ JSONのテキストを書く部分だけを、モジュールに切りだそう☆」
import pandas as pd
def write_json(test_number, variation_number, progress_num, json):
# Location.
json_file = "./event-placement-ai/auto-generated/placement-{}-{}-{}.json"
try:
file = open(json_file.format(
test_number, variation_number, progress_num), 'w', encoding='utf-8')
file.write(json)
except Exception as e:
print(e)
finally:
file.close()
return
def new_json(test_number, variation_number, progress_num, value):
return """
{{
"test" : {0},
"variation" : {1},
"progress" : {2},
"value" : {3}
}}
""".format(test_number, variation_number, progress_num, value)
「 京アニ爆発事件の生き残りも 1人減った☆ まだ分からなさそうだぜ☆
あたまに集中力が入らん☆
これだけ 書き直すのに 5時間ぐらいかかった……☆」
「 もうプログラムするのも嫌だ☆(^~^) 仕事に行くのも嫌だぜ☆(^~^)」
「 場所を入れ替えて 等価値 だったら 入れ替えないからな☆
ずれることもないし、動かないぜ☆」
「 入れ替えではなく、挿入だったら もっと かき混ぜれるのかだぜ☆? 例えば……☆」
「 同じブロックで 離れ離れ になっているブロックは 挿入でくっつけるとか☆」
participants = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
blocks = ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C']
print("participants: {}.".format(participants))
print("blocks: {}.".format(blocks))
def shift_smaller():
"""
ブロック単位でシフトします。[1,2,3,4]を、[2,3,4,1]にする動きです。
"""
prev_block = None
# テーブルID順に並んでいるとします。
for i in range(0, 10):
print("i:{}, blocks[i]: {}, prev_block: {}.".format(
i, blocks[i], prev_block))
if prev_block == blocks[i]:
# Swap.
temp = participants[i-1]
participants[i-1] = participants[i]
participants[i] = temp
prev_block = blocks[i]
shift_smaller()
print("participants: {}.".format(participants))
participants: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
blocks: ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C'].
i:0, blocks[i]: A, prev_block: None.
i:1, blocks[i]: A, prev_block: A.
i:2, blocks[i]: A, prev_block: A.
i:3, blocks[i]: B, prev_block: A.
i:4, blocks[i]: B, prev_block: B.
i:5, blocks[i]: B, prev_block: B.
i:6, blocks[i]: B, prev_block: B.
i:7, blocks[i]: C, prev_block: B.
i:8, blocks[i]: C, prev_block: C.
i:9, blocks[i]: C, prev_block: C.
participants: [2, 3, 1, 5, 6, 7, 4, 9, 10, 8].
「 こういうのは 小さなプログラムを書いて、まずテストだぜ☆」
def shift_bigger():
"""
ブロック単位でシフトします。[1,2,3,4]を、[4, 1, 2, 3]にする動きです。
"""
prev_block = None
# テーブルID順に並んでいるとします。
for i in reversed(range(0, 10)):
print("i:{}, blocks[i]: {}, prev_block: {}.".format(
i, blocks[i], prev_block))
if prev_block == blocks[i]:
# Swap.
temp = participants[i]
participants[i] = participants[i+1]
participants[i+1] = temp
prev_block = blocks[i]
participants: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
blocks: ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C'].
i:9, blocks[i]: C, prev_block: None.
i:8, blocks[i]: C, prev_block: C.
i:7, blocks[i]: C, prev_block: C.
i:6, blocks[i]: B, prev_block: C.
i:5, blocks[i]: B, prev_block: B.
i:4, blocks[i]: B, prev_block: B.
i:3, blocks[i]: B, prev_block: B.
i:2, blocks[i]: A, prev_block: B.
i:1, blocks[i]: A, prev_block: A.
i:0, blocks[i]: A, prev_block: A.
participants: [3, 1, 2, 7, 4, 5, 6, 10, 8, 9].
def shift_smaller():
"""
ブロック単位でシフトします。[1,2,3,4]を、[2,3,4,1]にする動きです。
"""
prev_block = None
# テーブルID順に並んでいるとします。
for index, block in enumerate(block_list):
# for index, row in floor_df.iterrows():
if prev_block == block:
swap_participant(
index-1, index, par_id_list, genre_code_list)
prev_block = block
return
def shift_bigger():
"""
ブロック単位でシフトします。[1,2,3,4]を、[4, 1, 2, 3]にする動きです。
"""
prev_block = None
index = len(block_list)-1
# テーブルID順に並んでいるとします。
for block in reversed(block_list):
# print("shift_bigger: index={}, block={}.".format(index, block))
if prev_block == block:
swap_participant(
index, index+1, par_id_list, genre_code_list)
prev_block = block
index -= 1
return
「 pandas の API がトンチンカンなんで、結局リストに出してシフト☆」
「 テーブル1個ずつのシフトではなく、かたまりで シフトしないとな☆ ごそっと☆」
「 先頭から 連続するジャンルコードのテーブル数を数えるモジュールが欲しいな☆
名前は count_joined_genre_code とかかだぜ☆?」
「 つまり 上図の赤丸のところを数えるんだぜ☆
10、4、14、1、8、4 みたいな感じ☆」
genre_code_list = ['green', 'green', 'blue', 'red', 'red',
'blue', 'yellow', 'black', 'black', 'black']
block_list = ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C']
def count_joined_genre_code():
"""
TODO 同じブロック内での、連続するジャンルコードの数。
"""
count = 0
result_dict = {}
prev_block = None
prev_genre_code = None
for idx in range(0, len(block_list)):
block = block_list[idx]
genre_code = genre_code_list[idx]
if prev_block != block or prev_genre_code != genre_code:
if prev_block not in result_dict:
result_dict[prev_block] = []
result_dict[prev_block].append(count)
count = 1
else:
count += 1
prev_block = block
prev_genre_code = genre_code
# last
if prev_block not in result_dict:
result_dict[prev_block] = []
result_dict[prev_block].append(count)
return result_dict
result_dict = count_joined_genre_code()
print("result_dict: {}.".format(result_dict))
result_dict: {None: [0], 'A': [2, 1], 'B': [2, 1, 1], 'C': [3]}.
「 サンプル・プログラムを作って試しながら 動くまで持っていくのが 開発だぜ☆
作っているプログラムに いきなり拡張するのは テストがしにくいからな☆」
「 先頭の10個抜いて、うしろを 10個詰めて、空いた10個のところに先頭の10個を埋めたいぜ☆」
「 スワップを使ってばかりではなく、スタックとムーブをそろそろ作るべきでは☆?」
participants = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
blocks = ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B']
print("participants: {}.".format(participants))
print("blocks: {}.".format(blocks))
def for_block_asc(callback_head_block, callback_same_block):
"""
ブロックの切れ目が分かるループです。昇順。
"""
# テーブルID順に並んでいるとします。
prev_block = None
for i in range(0, len(blocks)):
if prev_block == blocks[i]:
callback_same_block(i, blocks[i])
else:
callback_head_block(i, blocks[i])
prev_block = blocks[i]
return
def for_block_desc(callback_tail_block, callback_same_block):
"""
ブロックの切れ目が分かるループです。降順。
"""
# テーブルID順に並んでいるとします。
prev_block = None
for i in reversed(range(0, len(blocks))):
if prev_block == blocks[i]:
callback_same_block(i, blocks[i])
else:
callback_tail_block(i, blocks[i])
prev_block = blocks[i]
return
print("Info : for_block_asc.")
for_block_asc(
lambda i, block:
print("Head: i={}, block={}.".format(i, block)),
lambda i, block:
print("Same: i={}, block={}.".format(i, block))
)
print("Info : for_block_desc.")
for_block_desc(
lambda i, block:
print("Tail: i={}, block={}.".format(i, block)),
lambda i, block:
print("Same: i={}, block={}.".format(i, block))
)
print("Info : Finished.")
participants: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
blocks: ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B'].
Info : for_block_asc.
Head: i=0, block=A.
Same: i=1, block=A.
Same: i=2, block=A.
Same: i=3, block=A.
Same: i=4, block=A.
Same: i=5, block=A.
Same: i=6, block=A.
Same: i=7, block=A.
Head: i=8, block=B.
Same: i=9, block=B.
Info : for_block_desc.
Tail: i=9, block=B.
Same: i=8, block=B.
Tail: i=7, block=A.
Same: i=6, block=A.
Same: i=5, block=A.
Same: i=4, block=A.
Same: i=3, block=A.
Same: i=2, block=A.
Same: i=1, block=A.
Same: i=0, block=A.
Info : Finished.
「 block_list とか tbl_id_list のような よく使うリストを ひとかたまりにできないかだぜ☆?」
「 それこそ position クラスに まとめられないのかだぜ☆?」
position-0-0-666.csv
X,Y,BLOCK,TABLE,PARTICIPANT,GENRE_CODE
13,5,A,1,57,Green
14,5,A,2,10,Green
15,5,A,3,53,Green
「 pandas が扱いやすければ 何も工夫しなくていいんだが、 API がトンチンカンだからな……☆
position クラスを自作するしかないのか……☆」
<書きかけ>
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント