SUMOで交通渋滞のエージェントシミレーション実験

基本は,
http://d.hatena.ne.jp/arupaka-_-arupaka/20131107/1383812174 を参考に。。
まず、道路
四角い道路

netgenerate --grid --grid.x-number=2 --grid.y-number=2 --grid.y-length=500 --grid.x-length=500 --output-file=jam.net.xml

次に交通 jam_flow.xml
1000秒に、車を100000台走らせる。
道路0/0to1/0の左したから 道路0/0to1/0 右下ヘ。
初速は最高に。終わりの速度は0に。
終わりの速度が0なのが渋滞を起こすポイント。

最短経路計算

duarouter -n jam.net.xml -f jam_flow.xml -o jam_flow.rou.xml

コンフィグファイル
cat jam.sumocfg

<configuration>
 	<input>
		<net-file value="jam.net.xml"/>
		<route-files value="jam_flow.rou.xml"/>
	</input>
	<time>

		<begin value="0"/>

		<end value="1000"/>

	</time>

 </configuration>

GUI 実行

sumo-gui -c jam.sumocfg

渋滞の有名な図を書く。
dumpで実行

sumo -c jam.sumocfg --netstate-dump jam.dump

  • rubyのnokogiriでxmlをスプレイピング

例えば,道路0/0to1/0の情報を標準出力

require 'rubygems'
require 'nokogiri'
text=Nokogiri::XML(open("jam.dump"));
a=(text/"edge[id=\"0/0to1/0\"]")
puts a

Hpricotだとうまくいかないので注意(/がうまく扱えない).

  • 流量計測

出力は,
流量は、 500-1500s time step 400m地点を1秒あたりを通過した車の数。
車の密度は。500-1500s にいる道路上にいる1m当たりの時間平均車の数。

require 'rubygems'
require 'nokogiri'


text=Nokogiri::XML(open("tmp.dump"));
car_number_sum=0;
#a=(text/"edge[id=\"0/0to1/0\"]")
#
#
#
#
#
#
counts=[];
500.times.each{|i|
	time=i+1000
#	puts time;

	a=(text/"timestep[time=\"#{time.to_s}.00\"]")
	car_number=(a/"vehicle").length
	
	(a/"vehicle").each{|i|

		id1=i["id"]
		pos=i["pos"]
		if pos.to_f>=400 then 
			counts.push(id1)		
	#		print id1," ",pos,"\n";
		end

	}

	car_number_sum=car_number_sum+car_number	
	
	#puts car_number;
}

	if not counts.empty? then				
		print counts.uniq!.length/500.0,",",car_number_sum/500.0/500.0,"\n"
	else

		print "0.0",",",car_number_sum/500.0/500.0,"\n"
	end
#puts a
  • 上記のフローでは、入り口と出口があるので、密度が一定以上増やせない!ということで、

グルグル流れれる車を作成。 (0/1to1/0 と 1/0to0/1 を100回回る)
まず参考までにルートファイル。 これを改変する。

<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/routes_file.xsd">
    <vehicle id="1_0" depart="0.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0"/>
    </vehicle>
    <vehicle id="1_1" depart="333.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0"/>
    </vehicle>
    <vehicle id="1_2" depart="667.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0"/>
    </vehicle>
</routes>

まず、五周させる。

<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.sf.net/xsd/routes_file.xsd">
    <vehicle id="1_0" depart="0.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0 0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0 0/0to1/0 1/0to0/0"/>
    </vehicle>
    <vehicle id="1_1" depart="333.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0"/>
    </vehicle>
    <vehicle id="1_2" depart="667.00" departSpeed="max" arrivalSpeed="0.00">
        <route edges="0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0  0/0to1/0 1/0to0/0"/>
    </vehicle>
</routes>

何周もするルートを生成するスクリプト

car_number=10000;
number_of_round=1000;

str="0/0to1/0 1/0to0/0"
number_of_round.times{|i|
	str=str+" "+"0/0to1/0 1/0to0/0"

}
#puts str
puts "<routes>"

car_number.times{|i|
puts "\t<vehicle id=\"#{i}\" depart=\"0.00\" departSpeed=\"max\" arrivalSpeed=\"0.00\">"
puts "\t\t<route edges=\"#{str}\"/>"
puts "\t</vehicle>"
}

puts "</routes>"

単位面積にたくさん車をつめこむ

netgenerate --grid --grid.x-number=3 --grid.y-number=3 --grid.y-length=500 --grid.x-length=500 --output-file=jam5.net.xml

car_number=1000;
number_of_round=10000;

str="0/0to1/0"
number_of_round.times{|i|
	str=str+" "+"1/0to2/0 2/0to1/0"

}
#puts str
puts "<routes>"

car_number.times{|i|
j=i*100
puts "\t<vehicle id=\"#{i}\" depart=\"#{j}\" departSpeed=\"max\" arrivalSpeed=\"0.00\">"
puts "\t\t<route edges=\"#{str}\"/>"
puts "\t</vehicle>"
}

puts "</routes>"
 <configuration>
 	<input>
		<net-file value="jam5.net.xml"/>
		<route-files value="jam_flow5.rou.xml"/>
	</input>
	<time>

		<begin value="0"/>

		<end value="40000"/>

	</time>

 </configuration>
 sumo -c jam5.sumocfg --netstate-dump jam5.dump

ログファイルが長くなった場合の対処,後ろのほうだけ切り出し:

i=`grep -n 99900 test.damp | awk -F":" '{print $1}'`
 echo "<sumo-netstate>" > tmp2
tail -n +$i >> tmp2

99900と99960の平均台数と平均流量をとるスクリプト

require 'rubygems'
require 'nokogiri'
require 'set'

#puts "kokomade1"
text=Nokogiri::XML(open("tmp2"));
car_number=0;
car_number_sum=0;
flow=0;
f1=open("test.dat","w")
#puts "kokomade2"
#a=(text/"edge[id=\"0/0to1/0\"]")
#
#
#
#
#
#
counts=[];
counts2=[];
past_car=[];
tmp_car=[]
#i2=100000/60
#
2.times.each{|i2|
	i=60*i2+99900
#	puts i2,i
#	time=i*100
#	puts time;
#	
#i=1002	
	a=(text/"timestep[time=\"#{i.to_i.to_s}.00\"]")
	#puts a
	#puts "kokodayo"
		
	a.each{|j|
		#puts j
		j2=(j/"edge")
	#	puts j2
		j2.each{|j3|
		#	puts j3["id"]
		#
			if j3["id"]=="2/0to1/0" then
				j5=(j3/"vehicle")
				if not j5.nil? then
					#puts j4.nil?
					#puts j4.length	
					car_number=car_number+(j5.length)
				end
				a123=Set.new(past_car.map{|i| i["id"]}) 
				a123b=Set.new(j5.map{|i| i["id"]}) 
				#puts "test1"
				#a123.each{|i| puts i}
				#puts "test2"
				#a123b.each{|i| puts i}
				#puts "test3"
				#Set.new(j5).each{|i| puts i}
				flow=(a123 & a123b).length
					
			end
			

			if j3["id"]=="1/0to2/0" then
				j4=(j3/"vehicle")
				
				if not j4.nil? then
					#puts j4.nil?
					car_number=j4.length
				end
				
				tmp_car=j4;
			end

			


		}
		past_car=tmp_car	
		
 puts i.to_s+","+car_number.to_s+","+flow.to_s

		f1.puts( i.to_s+","+car_number.to_s+","+flow.to_s)
		f1.flush	
#			puts j;
#		end
	}

}
#	f1.fush
if 2!=2 then
	car_number=(a/"vehicle").length
	
	(a/"vehicle").each{|i|

		id1=i["id"]
		pos=i["pos"]
		if pos.to_f>=400 then 
			counts.push(id1)		
	#		print id1," ",pos,"\n";
		end

	}

	car_number_sum=car_number_sum+car_number	
end	
	#puts car_number;
#}
if 2!=2 then
	if not counts.empty? then				
		print counts.uniq!.length,",",car_number_sum/500.0,"\n"
	else

		print "0.0",",",car_number_sum/500.0,"\n"
	end
end
#puts a

自動車を除くスクリプト

car_number=220;
#30000
number_of_round=10000;
remove_car=100

number_of_round_remove=2
str="0/0to1/0"

str2="0/0to1/0"
number_of_round.times{|i|
	str=str+" "+"1/0to2/0 2/0to1/0"
}


number_of_round_remove.times{|i|
	str2=str2+" "+"1/0to2/0 2/0to1/0"
}




#puts str
#puts str
puts "<routes>"

car_number.times{|i|

j=i*1
	if i>=100 and i<=remove_car+100 then 

		puts "\t<vehicle id=\"#{i}\" depart=\"#{j}\" departSpeed=\"max\" arrivalSpeed=\"0.00\">"
		puts "\t\t<route edges=\"#{str2}\"/>"
	else

		puts "\t<vehicle id=\"#{i}\" depart=\"#{j}\" departSpeed=\"max\" arrivalSpeed=\"0.00\" color=\"0,0,1\">"
		puts "\t\t<route edges=\"#{str}\"/>"
	end

puts "\t</vehicle>"
}




puts "</routes>"