Skip to content

Commit

Permalink
Factoring out Neo4j base classes from application code.
Browse files Browse the repository at this point in the history
  • Loading branch information
John Paul Lewicke committed Sep 10, 2010
1 parent 228a9f9 commit bc3b666
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 71 deletions.
95 changes: 95 additions & 0 deletions accounts/app_classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require 'neo_classes'
require 'neo4j/extensions/graph_algo'
require 'neo4j/extensions/find_path'

#Various classes that provide an abstract way of managing the flow of credit between
#a source and a destination user.

#The CreditRelationship class tracks the direct credit that two users have placed in
#each other, such as the credit limits in place and the stock of credit between the two.

#The CreditPath class tracks the indirect credit present between two users via a
#chain of trusted intermediaries. A CreditPath thus consists of a number of
#CreditRelationships that are strung together in a network of trust. Since the
#availability of intermediate nodes may fluctuate over time, a CreditPath
#is inherently volatile.


class CreditRelationship
attr_accessor :source, :dest, :source_offer, :dest_offer

def initialize(source, dest)
@source = source
@dest = dest

@source_offer = @source.trustrel(@dest)
@dest_offer = @dest.trustrel(@source)
end

# How much more can dest draw from source?
def slack_givable
return @source_offer.usable + @dest_offer.amount_used
end

# How much more can source draw from dest?
def slack_returnable
return @dest_offer.usable + @source_offer.amount_used
end



#Deletes dummy :trusts relationships that we created and resets the
#:activelytrusts flag in both directions.
def save!()

#Kind of ugly at the moment -- TODO cleanup.

if (@source.activelytrusts.include?(@dest) and self.slack_givable <= 0.0)
@source.rels.outgoing(:activelytrusts)[@dest].delete
end
if (not @source.activelytrusts.include?(@dest) and self.slack_givable > 0.0)
@source.activelytrusts << @dest
end
if (@dest.activelytrusts.include?(@source) and self.slack_returnable <= 0.0)
@dest.rels.outgoing(:activelytrusts)[@source].delete
end
if (not @dest.activelytrusts.include?(@source) and self.slack_returnable > 0.0)
@dest.activelytrusts << @source
end


[@source_offer,@dest_offer].each do |o|
if o.empty?
o.del

end
end
end

#Transfers amount from @source to @dest.

def give!(amount)

if self.slack_givable < amount
raise "Cannot transfer amount."
end

debt_to_use = [amount, @dest_offer.amount_used].min
credit_to_use = [0, amount - debt_to_use].max

@dest_offer.amount_used -= debt_to_use
@source_offer.amount_used += credit_to_use
end

end


class CreditPath
attr_accessor :source, :dest

#Accepts either
def initialize(source, dest)

end
end

47 changes: 0 additions & 47 deletions accounts/classes.rb

This file was deleted.

21 changes: 12 additions & 9 deletions accounts/init.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "classes"
require "app_classes"

num_nodes = 200
num_edges_per = 10
Expand Down Expand Up @@ -29,15 +29,18 @@
end
num_edges_per.times do |i|
k = rand(num_nodes - num_edges_per * 2 - 2)
s = a[i + k]
o = a[i + k + 1]
while (s == o)
o = a[rand(10)]
dest = a[i + k]
source = a[i + k + 1]
while (dest == source)
source = a[rand(10)]
end
rel = o.trusts.new(s)
rel.max_credit_offered = rand(10) + 1
rel.max_credit_desired = rand(10) + 1
rel.credit_used = 0

rel = CreditRelationship.new(source, dest)
source_offer = rel.source_offer
source_offer.max_offered += 1.0
source_offer.max_desired += 1.0

rel.save!()
end
end
end
76 changes: 76 additions & 0 deletions accounts/neo_classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require 'Neo4j'

Neo4j::Config[:storage_path] = '/Users/jplewicke/rivulet/accounts/dbneo'
Lucene::Config[:storage_path] = '/Users/jplewicke/rivulet/accounts/dblucene'
Lucene::Config[:store_on_file] = true


#Neo4j-based classes. Objects with these types are the ones that are actually persisted
#in the Neo4j graph store. Changing the properties for them may require a special
#migration for ALL existing database data. Changing the few helper methods we
#have for them shouldn't have a similar impact, but it's best to be cautious here.

class CreditOffer
include Neo4j::RelationshipMixin

property :max_offered, :max_desired, :amount_used, :amount_held

def max
return [self.max_offered, self.max_desired].min
end

def usable
return self.max - self.amount_used
end

def empty?
return [self.max_offered, self.max_desired, self.amount_used,
self.amount_held] == [0,0,0,0]
end
end


class User
include Neo4j::NodeMixin

property :user_id
#property :secret

has_n(:trusts).relationship(CreditOffer)

has_n(:activelytrusts)

has_n(:trusted_by).relationship(CreditOffer).from(User)

index :user_id

def trustrel(dest)

if self.trusts.include?(dest)
puts "yippee"
rel = self.rels.outgoing(:trusts)[dest]
else
rel = self.trusts.new(dest)
rel.max_offered = 0.0
rel.max_desired = 0.0
rel.amount_used = 0.0
rel.amount_held = 0.0
end

return rel
end


def self.fromid(id)
ret = nil

result = User.find(:user_id => id)
result.each {|x| ret = x}

if ret == nil
raise "No such user found."
end
return ret
end

end
70 changes: 55 additions & 15 deletions accounts/path.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
require 'classes'
require 'app_classes'
require 'set'
require 'benchmark'
#require 'Neo4j'
require 'neo4j/extensions/graph_algo'
require 'neo4j/extensions/find_path'

def find_user(id)
ret = nil
Expand All @@ -15,34 +12,71 @@ def find_user(id)
end

def path_to_credits(users_path)
users_path.each_cons(2).collect {|pair| pair.first.rels.outgoing(:trusts)[pair.last]}
if users_path == nil
return []
else
return users_path.each_cons(2).collect {|pair| CreditRelationship.new(pair.first, pair.last)}
end
end

def credit_format(c)
return "#{c.source.user_id} to #{c.dest.user_id}: \t#{c.slack_givable} fr,\t #{c.slack_returnable} ra \t #{c.source.activelytrusts.include?(c.dest)} \t #{c.dest.activelytrusts.include?(c.source)}"
end


num_nodes = 500
num_nodes = 200

users = []

Neo4j::Transaction.run do
num_nodes.times do |i|
users[i] = find_user("User_#{i}")
users[i] = User.fromid("User_#{i}")
end
end

def find_all(num1, num2, users)
Neo4j::Transaction.run do
#puts "start"
res = users[num1].traverse.outgoing(:trusts).depth(13).path_to(users[num2])
#puts res.collect {|u| u.user_id}
#puts path_to_credits(res)
#puts path_to_credits(res).collect {|r| r.credit_limit }
return res.to_a
path = []
b = 0.0
3.times do
#puts "start"
path = users[num1].traverse.outgoing(:activelytrusts).depth(18).path_to(users[num2])
#puts res.collect {|u| u.user_id}
credits = path_to_credits(path)

max_transfer = credits.collect {|a| a.slack_givable}.min

#b += max_transfer

puts " +++++++++"
#puts credits.collect {|a| credit_format(a)}

#puts credits

credits.each do |c|
puts ""
puts credit_format(c)
c.give!(max_transfer)
puts credit_format(c)
c.save!
puts credit_format(c)
end

puts max_transfer
# puts b
puts " ---------++++++"

#puts credits.collect {|a| credit_format(a)}


puts "____________________________________________________________"
end
return path.to_a
end
end

tot = 0.0
reps = 1
reps = 100
times = {}
counts = {}
res = 0
Expand All @@ -52,8 +86,10 @@ def find_all(num1, num2, users)
times[i] = 0.0
end



reps.times do |i|
puts i
puts "Pass #%d" % (i + 1)
time = Benchmark.realtime do
i = rand(num_nodes)
j = (i + 1) % num_nodes
Expand All @@ -64,7 +100,11 @@ def find_all(num1, num2, users)
tot += time

end
puts ""

return

return
puts "Average time:"
puts tot / reps
puts ""
Expand Down
Loading

0 comments on commit bc3b666

Please sign in to comment.