質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

pythonの配列についての質問です。

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 386

score 7

こちらのコード(遺伝的アルゴリズムを用いたOneMax問題)なのですが、
#エリートを選択の部分で
elites = eva[:int(len(pop)*elite_rate)]
という一次元配列を作成しているにも関わらず、
#突然変異、交叉の部分では
child = mutate(elites[m][1])
や、
child = two_point_crossover(elites[m1][1], elites[m2][1])
と、二次元配列の扱いをしていることが理解できません。
どういうことなのでしょうか。

エラー発生しません。

import random
import copy

# パラメータ
gene_length = 10 # 遺伝子長
individual_length = 10 # 個体数
generation = 20 # 世代数
mutate_rate = 0.1 # 突然変異の確率
elite_rate = 0.2 # エリート選択の割合

def get_population():
    population = []
    for i in range(individual_length):
        population.append([random.randint(0,1) for j in range(gene_length)])
    return population


def fitness(pop):
    return sum(pop)


def evaluate(pop):
    pop.sort(reverse=True)
    return pop


def two_point_crossover(parent1, parent2):
    r1 = random.randint(0, gene_length-1)
    r2 = random.randint(r1, gene_length-1)
    child = copy.deepcopy(parent1)
    child[r1:r2] = parent2[r1:r2]
    return child


def mutate(parent):
    r = random.randint(0, gene_length-1)
    child = copy.deepcopy(parent)
    child[r] = 1 if child[r]==0 else 0
    return child


def main():
    # 初期個体生成
    pop = evaluate([(fitness(p), p) for p in get_population()])
    print('Generation: 0')
    print('Min : {}'.format(pop[-1][0]))
    print('Max : {}'.format(pop[0][0]))
    print('--------------------------')

    for g in range(generation):
        print('Generation: ' + str(g+1))

        # エリートを選択
        eva = evaluate(pop)
        elites = eva[:int(len(pop)*elite_rate)]

        # 突然変異、交叉
        pop = elites
        while len(pop) < individual_length:
            if random.random() < mutate_rate:
                m = random.randint(0, len(elites)-1)
                child = mutate(elites[m][1])
            else:
                m1 = random.randint(0, len(elites)-1)
                m2 = random.randint(0, len(elites)-1)
                child = two_point_crossover(elites[m1][1], elites[m2][1])
            pop.append((fitness(child), child))

        # 評価
        eva = evaluate(pop)
        pop = eva

        print('Min : {}'.format(pop[-1][0]))
        print('Max : {}'.format(pop[0][0]))
        print('--------------------------')
    print('Result : {}'.format(pop[0]))


if __name__ == '__main__':
    main()
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

evaやelitesに実際に何が入っているかprintで見てみましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

各行でprintするとわかりますが、
evaは、「評価値と、その遺伝子の内容のリストを要素とするタプル」のリストで、評価値の降順に並んでいます。
例([(6, [1, 1, 1, 0, 1, 1, 0, 1, 0, 0]),(5, [0, 1, 1, 0, 1, 1, 0, 1, 0, 0]),... ])

elites = eva[:int(len(pop)*elite_rate)]


で、evaから評価の良いものを一定割合だけ抽出しています。

elites[m][1]、というのは、「eliteの、indexがm番目のタプルのうち、遺伝子のリストの部分」を指しています。

>>> elites = [(6, [1, 1, 1, 0, 1, 1, 0, 1, 0, 0]),
...          (5, [0, 1, 1, 0, 1, 1, 0, 1, 0, 0]),
...          (4, [0, 0, 1, 0, 1, 1, 0, 1, 0, 0])]

>>> elites[1][1]

[0, 1, 1, 0, 1, 1, 0, 1, 0, 0]

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/07/22 18:58

    回答ありがとうございました

    キャンセル

checkベストアンサー

0

と、二次元配列の扱いをしていることが理解できません。

pop = evaluate([(fitness(p), p) for p in get_population()])という部分に注目して
コード内の各変数のデータ構造をよく確認し理解してください。

上記のコードにてpはある個体の遺伝子、fitness(p)は適応度を表しています。
そして(fitness(p), p)というタプルを内包表記でリスト化しています。
つまり各個体は、適応度と遺伝子の組をタプルで持っており、このタプルが1つの個体を表しています。
そして各個体のタプルをリストで持っています。

よってたとえばelites[m][1]m番目の個体の遺伝子を表しています。
またelites[m][0]は同じくm番目の個体の適応度を表しています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/07/22 18:58

    回答ありがとうございます。
    わかりやすい回答で、理解できました。

    キャンセル

0

a = [[1, 2], [3, 4], [5, 6]]

print(a[:2])


した時の結果が1次元のリストだと思いますか?

print(a[:2][0][1])


がエラーになると思いますか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る