#!/usr/bin/env ruby1.9 require "pp" require "set" class Hash def to_s_rank to_a.sort.map{|k,v| "%s %.3f\n" % [k, v] }.join end end class Graph def initialize @forw = Hash.new{|ht,k| ht[k] = {}} @back = Hash.new{|ht,k| ht[k] = {}} end def link!(f,t,v=1.0) return if v == 0.0 @forw[f][t] = v @back[t][f] = v end class << self def scenario_1 graph = new (1..10).each{|i| (i..10).each{|j| graph.link!("g%02d" % i, "b%02d" % j) graph.link!("b%02d" % i, "g%02d" % j) } } graph end def scenario_2 graph = new (1..10).each{|i| ([i-1,1].max..10).each{|j| graph.link!("g%02d" % i, "b%02d" % j) graph.link!("b%02d" % i, "g%02d" % j) } } graph end def scenario_3 graph = new (1..10).each{|i| (i..10).each{|j| graph.link!("g%02d" % i, "b%02d" % j) graph.link!("b%02d" % i, "g%02d" % j) } if i != 1 graph.link!("g%02d" % i, "b%02d" % (i-1), 0.5) graph.link!("b%02d" % i, "g%02d" % (i-1), 0.5) end } graph end def scenario_4 graph = new (1..3).each{|gh| (1..3).each{|ge| (1..3).each{|bh| (1..3).each{|be| gs = "g#{gh}#{ge}" bs = "b#{bh}#{be}" if gh <= bh && ge <= be graph.link!(gs, bs) end if gh <= bh && ge == be graph.link!(bs, gs) end } } } } graph end def scenario_5 graph = new (18..48).each{|g| (18..48).each{|b| if b >= g-4 && b <= g+6 graph.link!("g#{g}", "b#{b}") elsif b >= g-8 && b <= g+10 graph.link!("g#{g}", "b#{b}", 0.5) end if g <= b+4 if g >= ((b - 23) * 0.56 + 18) graph.link!("b#{b}", "g#{g}") else graph.link!("b#{b}", "g#{g}", 0.5) end end } } graph end def scenario_6 graph = new ez = Hash[(18..48).map{|a| [a, [[17-0.4*a, 5].min, 1].max.to_i]}] (18..48).each{|g| ez[g].times{|gi| (18..48).each{|b| ez[b].times{|bi| bs = "b#{b}-#{bi}" gs = "g#{g}-#{gi}" if b >= g-4 && b <= g+6 graph.link!(gs, bs) elsif b >= g-8 && b <= g+10 graph.link!(gs, bs, 0.5) end if g <= b+4 if g >= ((b - 23) * 0.56 + 18) graph.link!(bs, gs) else graph.link!(bs, gs, 0.5) end end } } } } graph end end def reciprocity graph = Graph.new @forw.each{|f, ts| ts.each{|t, tv| tu = @forw[t][f] || 0.0 graph.link! f, t, [tv, tu].min } } graph end def date graph = Graph.new @forw.each{|f, ts| ts.each{|t, tv| tu = @forw[t][f] || 0.0 u = [tv, tu].min x = [tv, tu].max - u graph.link! f, t, (u + 0.2 * x) } } graph end def rank at = 0.10 vals = Hash.new(1.0) 100.times{ new_vals = Hash.new(at) @forw.each{|f,ts| u = vals[f] * (1 - at) / ts.map{|t,tv| tv}.inject(&:+) ts.each{|t,tv| new_vals[t] += tv * u } } vals = new_vals } vals end def to_s (@forw.keys + @back.keys).uniq.sort.map{|f| "#{f} -> " + @forw[f].to_a.sort.map{|t,tv| if tv == 1.0 t else "#{t}^#{tv}" end }.join(" ") + " <- " + @back[f].to_a.sort.map{|t,tv| if tv == 1.0 t else "#{t}^#{tv}" end }.join(" ") + "\n" }.join end end def print_graph_transforms!(graph) puts "Graph:" puts graph puts "Reciprocity:" puts graph.reciprocity puts "Date:" puts graph.date end def print_graph_ranks!(graph) #puts "AttractiveRank:" #puts graph.rank.to_s_rank #puts "ReciprocityRank:" #puts graph.reciprocity.rank.to_s_rank puts "DateRank:" puts graph.date.rank.to_s_rank end print_graph_transforms!(Graph.scenario_6) puts "" print_graph_ranks!(Graph.scenario_6)