読者です 読者をやめる 読者になる 読者になる

クズと天才は紙一重

不定期更新です。主に日々の活動記録( ・ㅂ・)و ̑̑

ゲーム理論(同時手番ゲーム)

相手の戦略がわからないまま、自分の戦略を考えなくてはいけない同時手番ゲーム。

ゲーム理論で代表的な、協調ゲーム、チキンゲームを紹介します。

 

ゲーム理論の非協力ゲームでは、

プレイヤーは互いに合理的な判断で自分の利得を追求します。

ところが相手と協調することで自分の利得が上がることを知れば、

喜んで相手に協調するでしょう。

プレイヤー同士が交渉をして合意を取り付けるわけではなく、

あくまでも相手の行動に合わせるということなので、

協調ゲームは非協力ゲームの1つです。

 

身近な協調ゲームは、交差点の車の様子です。

相手が止まると分かれば、自分が進み、相手が進みそうなら、自分は止まる。

ちなみに、この時点でのナッシュ均衡は、

「自分が止まり、相手が進む」、「相手が止まり、自分が進む」という感じなので、

瞬時にどちらの均衡を選べばいいかわかりません。

そこで信号機が登場します。信号機によってプレイヤーを協調させるようにできます。

 

皆さんは「賢者の贈り物」という作品を知っていますか?

貧しい夫妻が相手にクリスマスプレゼントを買いたいと思いましたが、お金がなく、

妻は夫が大切にしている金の懐中時計を吊るす鎖を買うため、自分の髪を売り、

夫は妻が欲しがっていたクシを買うため、海中時計を売りました。というような、相手を思いやる気持ちから、贈り物のすれ違いが起きてしまう物語です。

これをゲーム理論的に考えると、

お互いに戦略を明かさなかったので、残念な結果のように見えますが、

夫婦が物質的な豊かさより、精神的な豊かさを優先するのであれば、

このゲームの利得は大きく変わり、この選択肢がナッシュ均衡に変化します。

 

 

直線の長い道の端と端から相手に向かい車を走らせ、

先にハンドルを切った方が負けというようなゲームがあります、

こんな感じのゲームがチキンゲームと呼ばれるものです。

戦略は「進む」と「逃げる」です。

ナッシュ均衡は、

「自分が進み、相手が逃げる」、「自分が逃げて、相手が進む」の2つです。

自分のとって、利得が大きいのは「自分が進み、相手が逃げる」です。

このようなチキンゲームには、必勝法が存在していて、

ハンドルを根元から抜いてしまうという選択をします。

そうすると、自分は逃げるという選択肢がなくなってしまうので、

2つあったナッシュ均衡は1つに絞られ、

「自分が進み、相手が逃げる」という結果に落ち着きます。

ゲーム理論には、このように自ら選択肢を削るというような戦略も存在します。

 

ゲーム理論(ナッシュ均衡)

ナッシュ均衡とは、

全てのプレイヤーが自分の戦略に満足して、結果に後悔しない状態のこと。

 

例)

プレイヤーは兄と弟の2人。

2人は祖父から合わせて100万円もらうことになりました。

2人は同時に0~100万までの好きな金額を1万単位で申告することができます。

そして、2人の合わせた額が100万以下なら、申告した金額をそのままもらえます。

もし、100万を超してしまったら、何ももらえません。

普通に考えたら、50万を申告するのが無難です。

兄も弟も自分の戦略に満足して、結果に後悔しない状態なので、ナッシュ均衡です。

しかし、もし弟が兄に多く譲ろうとして提示金額が35万、

兄は、無難に50万の提示金額になってしまうと、申告金はもらえますが、

後悔することになるでしょう、この状態はナッシュ均衡ではありません。

 

ナッシュ均衡は相手が減らさなくては自分の利得は増やせない、

単独では戦略変更ができない状態とも言えます。

 

もう一つの例をあげます。

大きな服を扱うお店の戦略という、ナッシュ均衡から見る店舗戦略です。

衣料品販売店が扱っている服のサイズはS~XLが一般的で、

それ以上のサイズが置いていないことが多いです。 

店が大サイズの服を置き、利用客が店に行くと店は売上が上がり利得10を得て、

利用客も満足から利得10を得ます。

店が在庫を持たず、利用客も店舗に行かないと双方の利得は0。

店が在庫を持つのに利用客がこないと、店の利得は在庫費用がかかり-50、

利用客は影響なく0。

店が在庫を持たず、利用客が店に行くと、店は顧客のニーズに応えられず-5、

利用客も目当てのものがなく-5とします。

このゲームには、ナッシュ均衡が2つ存在します。

店が大サイズの服を置き、利用客が店に行く、または

店が在庫を持たず、利用客も店で買わない状態です。

本来、安定して固定されている均衡ですが、

このゲームに広告という戦略を加えると均衡が動きます。

店が大サイズの服があります。と告知することで

店が大サイズの服を置き、利用客が店に行くという均衡が選ばれるのです。

 

ナッシュ均衡はこのように複数の場合もあり、

自分にとって一番良いナッシュ均衡にたどり着くには、戦略の操作が必要になります。

また、必ずしも一番高い利得手にできるとも限りません。

 

今回は、ゲーム理論の1つである、ナッシュ均衡を軽く紹介しました。

今後も少しずつ、紹介して入れたらなと思います。

ゲーム理論

昔から、すごくゲーム理論が好きなので、紹介していこうかなと思います。

 

ゲーム理論とは

「ある特定の状況下において、お互いに影響を与え合う複数の主体の間で生じる戦略的な相互関係」「相互依存性の状況下での合理的意思決定や合理的配分方法」

について考えるための数学理論と言われています。

 

まあ、正直こう説明されても意味がわかりませんが、

簡単にいうと

「競争相手の行動を考え、自分が一番得する方法を合理的に決める」

と言った感じですかね。

相手も自分と同じように得をしたいと考えていて、

その行動を予測しながら、自分が得する行動を考えます。

なので、

ゲーム理論は相手の意思決定や行動を数理的に研究する学問です。

 

ゲーム理論には基本要素が3つあります。

1、プレイヤー

・自分の利潤が最大になるように行動する

・合理的にものを考え自分が損する行動を取らない

・勘違いや思い違いをしない

前提条件としてプレイヤーは、この基本的原理で行動します。

また、プレイヤーは、1対1の時もあれば、

企業対企業のようなケースも存在します。

2、戦略

プレイヤーが目的達成のためにどのような行動をするかという

行動予定のことです。

3、利得

プレイヤーの利益のことです。

利得はゲームによって違います。

 

また、ゲームにも種類があり

・同時手番ゲーム

相手と同時に行動を取るゲーム。

・逐次手番ゲーム

プレイヤーが順番に行動を取ることができるゲーム。

・非協力ゲーム

プレイヤー同士の協力、連携がないゲーム。

・協力ゲーム

複数のプレイヤーによる交渉、連携が可能であるゲーム。

・完全情報ゲーム

相手のとった行動や現在の行動が全て明らかになっているゲーム。

・非完全情報ゲーム

他のプレイヤーが行動するときに、

それまでの相手の行動や選択肢がわからないゲーム。

・定和ゲーム

プレイヤーの利潤の和が常に一定値となるゲーム。

・非定和ゲーム

プレイヤーの利潤の和が常に一定にならないゲーム。

細かくするともっとあったりするんですけど、大きく分けてこんな感じです。

 

ゲーム理論だと、有名なのは囚人のジレンマとかですかね、

少しずつ、ゲーム理論のことを書いていこうと思うので

いずれ触れることになると思います。

セレクトボックスをAjaxで動的に変える

Ajaxを使って動的にセレクトボックスを変える

config/routes.rbにパスを追加

 

resources bookshelfs do
  get 'ajax' => "bookshelfs#ajax", on: :collection
end

 

viewを編集

 

 = simple_form_for Bookshelf.new do |f|
#changeSelect onchange="entryChange();"
 = f.input :category, collection: @categories, input_html: {id: 'category_select'}
#firstBox
 = f.input :name, collection: @books, input_html: {id: 'name_select'}
 
javascript:
 function entryChange(){
  if(document.getElementById('category_select')){
   category = document.getElementById('category_select').value;
   if(category){
    $.ajax({
     type: 'get',
     url: "/<>bookshelfs/ajax",
     data: {category: category},
     dataType: 'html',
     success: function(data){
      $('#name_select').empty();
      $.each(JSON.parse(data), function(){
       $('#name_select')
        .append($("<option></option>")
         .attr("value",this[0])
         .text(this[1]));
      });
     }
    });
    document.getElementById('firstBox').style.display = "";
   }else{
    document.getElementById('firstBox').style.display = "none";
   }
  }
 }
window.onload = entryChange;

 

controller側を編集

def new
 @categories = [["IT","IT"],["経済","経済"]]
 @books = []
end
 
def ajax
 books = Book.where(category: params[:category])
 render json: books.map{|b| [b.name,b.name]} if request.xhr?
end

 

こんな感じでAjaxを使ってセレクトボックスを動的に変えることができます

 

Sidekiq

RailsのActiveJobには、未来に登録したJobをキャンセルするサポートがありません。

 

なので、Job実行にSidekiqを使い、キャンセルにSidekiqのAPIを使います。

 

Gemfileに以下を追加して、bundle install

gem 'sidekiq'

 

config/sidekiq.ymlに以下を記述

:concurrency: 25
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:queues:
 - default

 

Active JobがSidekiqを使用することを、config/application.rbに記述する。

config.active_job.queue_adapter = :sidekiq

 

キャンセルはこんな感じで行います。

 

require 'sidekiq/api'
job = ジョブ名.set(wait_until: Date.tomorrow.noon).perform_later(*args)
job.job_id #これでジョブを特定するIDがわかる

job_list = Sidekiq::ScheduledSet.new
job_list.find{ |job| job.arga[0]['job_id'] == job.job_id }.delete

 

ジョブ実行をSidekiqに変更したので、ローカル開発時は

redis-serverでRedisを立ち上げた後、

別ターミナルでbundle exec sidekiqでSidekiqを立ち上げて

Jobを使いましょう

Rails Active Job

Active Jobは、

時間差で処理を実行できるようなものです。

 

Jobの作成方法は、以下のコマンドを実行

rails g job ジョブ名

 

以下のようなジョブができます

class ジョブ名 < ActiveJob::Base
queue_as :default

def perform(*args)
 # 実行したいことを書く
end
end

 

*argsの部分に自由に引数を入れられます。

 

Jobを呼び出す方法

一週間後に実行したい場合

ジョブ名.set(wait: 1.week).perform_later(*args)

 

すぐに呼び出したい場合

ジョブ名.perform_now(*args)

 

特定の時間に呼び出したい場合

now_time = Time.now.to_i (現在時刻)
release_time = リリースする日時と時間
wait_time = (release_time - now_time)
ジョブ名.set(wait: wait_time.seconds).perform_later(*args)

wait_time.secondsで差分を秒に変換してJobをセットしています。

他にも、Jobオプションは、いろいろあるので調べてみてください

Line::Bot::APIでpush通知

Gamfileに以下を追加してbundle install

gem 'line-bot-api'

 

使いたいところに以下を記述するだけ

require 'line/bot'
client = Line::Bot::Client.new { |config|
config.channel_secret = "<SECRET_TOKEN>" config.channel_token = "<ACCESS_TOKEN>" } 
message={ type: 'text', text: '(送信したいメッセージ)' } user_id = uから始まるLINEの送信先識別子 response = client.push_message(user_id, mesage)

成功した場合200が返ってくる 

 

shellで確認可能

 

curl -X POST \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-d '{
"to": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"message":[
{
"type":"text",
"text":"(送信したいメッセージ)"
}
]
}' https://api.line.me/v2/bot/message/push

これは一人のユーザに対してなので、

Multicastを使いたい場合は以下のようにする

require 'line/bot'

client = Line::Bot::Client.new do |config|
config.channel_token = "#{ACCESS_TOKEN}"
end

user_ids = ['user1','user2']
message = {
type:'text',
text:'(送信したいメッセージ)'
}
response = client.multicast(user_ids, message)

 

Multicastはshellがうまく動作しないので省く