Uber vs. Lyft: Using Graphs for Evil
Uber and Lyft continue to lock horns trying to carve out dominance in the ride-sharing market. In a recent article, TechCrunch discussed the alleged nefarious activities of both Lyft and Uber in an attempt to not only beat one another at the ride-sharing game, but to sabotage their rivals along the way.
Let’s pretend that you’re a Lyft Agent of Evil. Your goal is to cause service disruptions by calling for Uber drivers and canceling at the last second. You’re not the type to do things in halves-- you want to be as evil as possible.
I decided to map out a small portion of San Francisco using intersections as nodes and the streets as relationships. The relationships between each intersection carry a property called "distance" which approximates in miles the distance between each intersection. (I used nice round numbers for this exercise, thus our map isn’t to scale.)
Click the Plus to see the Cypher
Where are our nefarious navigators?
match (l:lyft)-[:AT]-(p) return l.name as AGENT, p.name as LOCATION
Where are our unsuspecting Uber drivers?
match (u:uber)-[:AT]-(p) return u.name as DRIVER, p.name as LOCATION
Working alone, you can only cause so much disruption. Let’s get a baseline estimate of how evil you can be. Let’s say you’re in San Francisco on a Friday night. Standard prices put base fare at $3/ride + $0.30/per minute + $1.50 / mile. We’ll make some basic assumptions about our fraudulent foolery:
Assume that Uber drivers are able to pick up another fare immediately after the canceled fare
Assume that traffic / speed is a uniform 10 mph
What are the varying opportunity costs caused by evil agents by calling for a ride and canceling at the last second?
Uber’s platform is pretty great and will route the nearest driver to a given ride request—though it could be better cough if they used neo4j cough….if an "Agent" calls for an Uber driver, the nearest driver will be alerted and paired with that agent.
How many miles will a normal "call and cancel" take the driver out of his way?
MATCH p = (lyft)-[*0..10]-(b:uber) WHERE lyft.name = "lyftAgent001" RETURN p, reduce(dist=0, d in relationships(p) | dist + d.distance) AS totalDistance ORDER BY totalDistance ASC LIMIT 1
So, we’ve taken the driver 5 miles out of his way. Let’s see what that is in dollars:
Remember: uniform traffic at 10 mph, Base Fare $3 + $0.30/minute + $1.50/mile
RETURN 3+ (5 / .16667)* .3 + 5 * 1.5 AS Opportunity_Cost
or about ~$20
Let’s also assume that there are two other Lyft Agents of Evil around. Let’s see what they’re costing Uber drivers in time/money working alone:
Lyft Agent #2
MATCH p = (lyft)-[*0..10]-(b:uber) WHERE lyft.name = "lyftAgent002" RETURN p, reduce(dist=0, d in relationships(p) | dist + d.distance) AS totalDistance ORDER BY totalDistance ASC LIMIT 1
RETURN 3+ (3 / .16667)* .3 + 3 * 1.5 AS Opportunity_Cost
And the third agent, we’ll assume since they’re not working in concord that the Uber drivers return to their starting location after an Agent cancels their ride request:
MATCH p = (lyft)-[*0..10]-(b:uber) WHERE lyft.name = "lyftAgent003" RETURN p, reduce(dist=0, d in relationships(p) | dist + d.distance) AS totalDistance ORDER BY totalDistance ASC LIMIT 1
RETURN 3 + (5 / .16667)* .3 + 5 * 1.5 AS Opportunity_Cost
So in total, individual evil-doers cost Uber about $56 in this instance.
Doing evil by yourself isn’t fun. Why not coordinate with all of your fellow Lyft Agents of Evil? Let’s figure out what the optimum call order would be to maximize the amount of disruption and opportunity cost to the Uber drivers. We’re going to route de-optimize!
The three agents will work together to ensure that Uber makes the least fares in a given amount of time. This will comprise of tying up one driver with a short fare and forcing the other one to drive the longest path without actually picking anyone up.
What is the longest driving route between two Lyft Agents of Evil? Insofar as in what order should our ride-sharing cartel call Ubers to penalize the driver the most in opportunity costs. We’ll start by asking what is the longest path starting at an Uber driver, then to one Lyft Agent, and then to another Lyft Agent.
MATCH p = (a:uber)-[*0..5]-(b:lyft)-[*0..13]-(c:lyft) RETURN a.name as VICTIM, b.name as DRIVER_1, c.name as DRIVER_2, reduce(dist=0, d in relationships(p) | dist + d.distance) AS totalDistance ORDER BY totalDistance DESC LIMIT 1
RETURN 3+ (28 / .16667)* .3 + 28 * 1.5 AS Opportunity_Cost
Which costs the driver ~$95 in missed fare. This is the pickup order we want to force the Uber driver to take, canceling just when he arrives at both locations. This means LyftAgent002 should hail an Uber driver first. Agent 002 may take up to a $38 ride and as a whole they will still cost Uber drivers more in opportunity costs than working alone.
Was this page helpful?