Pythonによるゲーム経済分析:シミュレーションシティの生産効率最適化

<br></br>統計学部の学生向けにPythonのデータ処理機能を理解してもらうため、モバイルゲーム「シミュレーションシティ」の工場生産をモデル化します。学生が非構造化データのモデリングと処理を通じてPythonを学習・理解できるように構成しました。この内容を、特に統計を学ぶ学生の方々(統計学生が日常的に直面する問題を考慮して準備しました)のために公開します。
まずは「シミュレーションシティ」というモバイルゲームについて

このゲームの大きな課題の一つは、レベルが上がるとゴールドが不足することです。ゲーム内でゴールドを獲得するには、基本的に商品を生産して販売する必要があります。我々の目的は、生産可能な商品を分析し、各商品の付加価値を計算し、各生産部門の生産能力を考慮して、単位時間あたりに生産できる価値が最も高い製品の組み合わせを見つけることです。

一、基本分析

すべての議論は、ゲームレベルが10の場合に基づいています。レベル10では、工場(鉄、木材、プラスチックなどの原材料を生産)、材料工場、工具工場、家具工場、農産物工場の5つの生産部門があります。各部門が生産する製品は、生産に時間を要し、それぞれ価格が設定されています。工場が生産する原材料を除き、他の部門が生産する製品はすべて原材料を合成する必要があります。これにより、各部門が生産する製品の基本情報を得ることができます(実際の経済計算でも、以下の表のような様々な形式の生データを取得し分析します)。

工場:鉄、木材、プラスチック、種子を生産

材料工場:木板と釘を生産、それぞれ2つの木材と2つの鉄を消費

工具工場:ハンマー、巻尺、シャベルを生産

家具工場:椅子を生産、2つの木材、1つのハンマー、1つの釘を消費

農産物工場:果物と野菜を生産、2つの種子を消費

データは少なくて単純ですが、このような広義の表構造データを処理することは練習の価値があります。

二、全製品の付加価値計算

# データ処理で最もよく使われるパッケージであるpandasとnumpyをインポート
import pandas as pd
import numpy as np

# 各部門が生産する異なる商品を格納する辞書を構築
# 各商品には価格、所要時間、構成要素の3つの属性がある
'''production_data={'tool_factory':{'hammer':{'value':450,'duration':1,'materials':['Fe','wood']}},
       'material_factory':{'nail':{'value':400,'duration':2,'materials':['Fe','Fe']}},
       'basic_factory':{'Fe':{'value':50,'duration':3,'materials':[]},'wood':{'value':1,'duration':1,'materials':[]},'seed':
           {'value':1,'duration':1,'materials':[]}}}
Excelのデータをこのような辞書に変換する必要がある
'''
# 各部門のデータはExcelの各シートに保存されており、read_excelのsheetパラメータをNoneにすると、キーがシート名のパネルが取得できる
data_sheets=pd.read_excel('production_data.xlsx',None)
production_data={}
for sheet_name in data_sheets.keys():
    print(sheet_name)

    current_df=pd.read_excel('production_data.xlsx',sheet_name,index_col =0)

    products={}
    for product_name in current_df.columns:
        attributes={}
        for idx in current_df.index:
            if idx=='materials':
                try:
                    attributes[idx]=current_df[product_name][idx].split(',')
                    print(attributes[idx])
                except:
                    attributes[idx]=['nan']
            else:
                attributes[idx]=current_df[product_name][idx]
        products[product_name]=attributes
    production_data[sheet_name]=products
# 後で使用しやすくするために、各製品がどの部門に属するかを格納する辞書を作成
product_to_factory={}
for factory in production_data:
    for product in production_data[factory]:
        product_to_factory[str(product)]=factory
# 各製品の付加価値を計算し、製品名を主キーとし、付加価値を属性として含む表を作成
result_data={}
production_time,product_value,added_value,product_name=[],[],[],[]
tool_usage,material_usage,basic_usage,farm_usage,furniture_usage=[],[],[],[],[]
for factory in production_data:
    for product in production_data[factory]:
        product_info=production_data[factory][product]
        for dept in production_data:
            time_allocation[dept] = 0
        production_time.append(production_data[factory][product]['duration'])
        product_value.append(production_data[factory][product]['value'])
        material_costs=[]
        time_allocation[product_to_factory[product]] = production_data[factory][product]['duration']
        if product not in production_data['basic_factory']:
            added_value.append(production_data[factory][product]['value']-np.sum([production_data[product_to_factory[mat]][mat]['value'] for mat in production_data[factory][product]['materials']]))
            for material in production_data[factory][product]['materials']:

                time_allocation[product_to_factory[material]] += production_data[product_to_factory[material]][material]['duration']
                if material in production_data['basic_factory']:
                    pass
                else:
                    for sub_material in production_data[product_to_factory[material]][material]['materials']:

                        time_allocation[product_to_factory[sub_material]] += production_data[product_to_factory[sub_material]][sub_material]['duration']
        else:
            added_value.append(production_data[factory][product]['value']-0)
        product_name.append(str(product))
result_data['time']=production_time
result_data['value']=product_value
result_data['added_value'] = added_value
result_data['name']=product_name
<br></br>三、各商品の収益とコストの計算<br></br>我々の目的は、単位時間あたりにゴールドを最も早く稼げる生産組み合わせを見つけることです。椅子を生産する場合に何が消費されるかを考えてみましょう。まず、椅子工場の一定時間を占有し、次に1つのハンマー、1つの釘、2つの木材を消費します。椅子を1つ生産するごとに、実際には1つのハンマー、1つの釘、2つの木材を生産する必要があります。<br></br>したがって、椅子を材料のない抽象的な家具A(価格は椅子の付加価値、生産には家具工場で椅子を1つ生産する時間が必要)とその構成製品の集合、つまり{ハンマー、釘、2×木材、家具A}に分解できます。ハンマーと釘を生産するにはそれぞれ工具工場の一定時間、1つの木材と1つの鉄、材料工場の一定時間、2つの鉄が必要です。<br></br>ハンマーと釘をそれぞれ{工具A、木材、鉄}と{材料A、2×鉄}に分解できます。ここで工具Aは材料を消費しない抽象的な工具で、価格はハンマーの付加価値であり、その生産には工具工場でハンマーを1つ生産する時間が必要です。最後に、鉄と木材をそれぞれ{工場A、工場B}と等価に表現でき、それらの生産にはそれぞれ工場で鉄と木材を1つ生産する時間が必要です。すると、椅子は集合{工具A、材料A、家具A、3×工場A、3×工場B}に分解でき、この集合中の工具A、材料A、家具Aは椅子の生産がこれら3つの部門の生産時間を実際に占有することを示しています。<br></br>したがって、各製品を、それが各部門の時間を占有する集合として表現できます。
time_allocation={}
for dept in production_data:
    time_allocation[dept]=0

result_df=pd.DataFrame(result_data)

result_data={}
production_time,product_value,added_value,product_name=[],[],[],[]
tool_usage,material_usage,basic_usage,farm_usage,furniture_usage=[],[],[],[],[]
for factory in production_data:
    for product in production_data[factory]:
        product_info=production_data[factory][product]
        for dept in production_data:
            time_allocation[dept] = 0
        production_time.append(production_data[factory][product]['duration'])# ここではまず部門を直接占有する時間を記録
        product_value.append(production_data[factory][product]['value'])
        material_costs=[]
        time_allocation[product_to_factory[product]] = production_data[factory][product]['duration']
        if product not in production_data['basic_factory']:
            for material in production_data[factory][product]['materials']:

                time_allocation[product_to_factory[material]] += production_data[product_to_factory[material]][material]['duration']# ここでは部門を間接的に占有する時間を記録
                if material in production_data['basic_factory']:
                    pass
                else:
                    for sub_material in production_data[product_to_factory[material]][material]['materials']:

                        time_allocation[product_to_factory[sub_material]] += production_data[product_to_factory[sub_material]][sub_material]['duration']
        product_name.append(str(product))

        tool_usage.append(time_allocation['tool_factory'])
        material_usage.append(time_allocation['material_factory'])
        basic_usage.append(time_allocation['basic_factory'])
        farm_usage.append(time_allocation['farm_factory'])
        furniture_usage.append(time_allocation['furniture_factory'])
result_data['time']=production_time
result_data['value']=product_value
result_data['name']=product_name
result_data['tool_factory']=tool_usage
result_data['material_factory']=material_usage
result_data['basic_factory']=basic_usage
result_data['farm_factory']=farm_usage
result_data['furniture_factory']=furniture_usage
四、まとめ最終的に、各製品の付加価値と各部門の占有時間を含むデータフレームを得ることができました。

このデータフレームがあれば、抽出した情報に基づいて最適化を行い、与えられた部門の使用時間内で生産価値が最大になる製品の組み合わせを見つけることができます。この問題は本質的に制約条件下での最大値問題であるため、実際の状況では遺伝的アルゴリズム、ランダムフォレスト、ニューラルネットワークなど様々なアルゴリズムを選択できます。もちろん、この小規模な問題の場合は、収益が最大の組み合わせを列挙して選ぶことさえ可能です。

したがって、この記事は主にあまり構造化されていないデータを処理し、後のデータ分析をより簡単で便利にすることを目的としています。Pythonでデータ分析を学ぶ人々の役に立てば幸いです。

PS:最後に、練習用に今回使用したデータをブログのファイルに添付しました。ファイル名はsimcity_data.zipです。

タグ: Python データ分析 Pandas NumPy ゲーム経済

8月13日 13:45 投稿