Why does Paxos ensure that consensus is reached and does not change? - algorithm

I have been reading about single-decree Paxos (primarily looking at Paxos Made Simple) yet am confused about if a consensus among Acceptors is guaranteed to not change after being reached.
According to James Aspnes's notes,
So now we suppose that some value v is eventually accepted by a majority T with number n. Then we can show by induction on proposal number that all proposals issued with higher numbers have the same value (even if they were issued earlier).
However, I am confused since I believe I have a counterexample, shown below. Feel free to jump to step 12 since that is where simple steps can illustrate the problem. I have included steps 1-12 in case it is not possible to reach the state in step 12.
Consider the following behavior. Borrowing notation from Contradiction in Lamport's Paxos made simple paper.
That is, X(n:v, m), means Acceptor X has largest accepted proposal n:v, where n is proposal number and v is value, and m is the largest numbered prepare response to which Acceptor X has responded.
Say we have 3 Acceptors A, B, C. Let Px be a proposer, or even multiple proposers, who keeps sending proposals since they don't find out about any consensus being reached.
Px broadcasts prepare(1)
A and B respond with promise, state is A(:, 1), B(:, 1)
Px receives promises from A and B, confirms majority and broadcasts accept(1:'foo')
Only A receives this accept, state is now A(1:'foo', 1), B(:, 1), C(:,)
Py broadcasts prepare(2)
B, C respond with promises, state is now A(1:'foo', 1), B(:, 2), C(:,2)
Py receives promises from B and C, confirms majority and broadcasts accept(2:'bar')
Only B receives this accept, state is A(1:'foo', 1), B(2:'bar', 2), C(:,2)
Pz broadcasts prepare(3)
A and C response with promise, state is A(1:'foo', 3), B(2:'bar', 2), C(:,3)
Pz receives promises from A and C, confirms majority, notes that 1:'foo' is the largest numbered accepted value, and broadcasts accept 3:'foo'
Only C receives this accept, state is A(1:'foo', 3), B(2:'bar', 2), C(3:'foo', 3)
-- A consensus has been reached! 'foo' is the value decided upon --
Pn doesn't know about this, broadcasts prepare(4)
A and B response with promise, state is A(1:'foo', 4), B(2:'bar', 4), C(3:'foo', 3)
Pn receives promises from A and B, confirms majority, notes that 2:'bar' is the largest numbered accepted value, and broadcasts accept 4:'bar'
A receives this broadcast, state is A(4:'bar', 4), B(4:'bar', 4), C(3:'foo', 3).
-- A consensus has been reached! 'bar' is the value decided upon --
To be clear, steps 4, 8, 12, don't necessarily mean that the other nodes "failed", but I think it can just the proposer in question is taking a really long time to deliver the messages. Thus this shouldn't be a case where more than N acceptors crash in out of 2N + 1.
The top-voted answer in Contradiction in Lamport's Paxos made simple paper suggests that Proposers only sent accept messages to Acceptors who promised them and an acceptor accepting a value means updating the maxBal. Both of these are satisfied in the above example, yet it shows how consensus can flip-flop between two different values. Am I missing something here?

I am going to copy&paste a statement straight from Paxos article in wikipedia: "consensus is achieved when a majority of Acceptors accept the same identifier number (rather than the same value)".
So in your step 12 "state is A(1:'foo', 3), B(2:'bar', 2), C(3:'foo', 3) -- A consensus has been reached! 'foo' is the value decided upon" - there is no consensus yet; even if there is a majority in the value.
p.s.
thanks for the questions, this is a nice highlight on the consensus definition in Paxos!

Related

How to apply Disjoint Set Union in the following algorithm?

(1 point) Suppose you have a set of N people who all do not know each other, and you have to process
a sequence of queries of the following kinds:
Type 1: MakeFriends(x,y) - x and y become friends with each other
Type 2: AreFriends(x,y) - output 1 if x and y are friends, and output 0 otherwise
In particular, for every pair of people, we need to maintain a state indicating whether they are friends
or not, and update this state based on queries of type 1, and report the state for queries of type 2.
Since you have learned about the disjoint sets data structures in your algorithms course, you decide to
store the set of N people as N singleton sets to begin with. For each query of type 1, you perform a
union operation, and for each query of type 2, you perform a find operation.
What can you say about this algorithm?
A. It may not always produce an accurate answer.
B. It works with O(lg∗n), O(lg∗n) amortized response time to both queries.
C. It works with O(n), O(n) worst-case response time to both queries.
D. The correctness of the approach depends on how DSU is implemented.
If we get the following sequence of queries: MakeFriends(1,2), MakeFriends(2,3), AreFriends(1,3), the answer to the last query with our approach (irrespective of how DSU is implemented)
will be 1, while the correct answer is 0.
Is the above explanation correct
Let's imagine two sets S1 and S2, where S1 contains elements 1, 2, 3, and S2 contains elements 4, 5, 6. These two sets don't have any elements in common, so they're disjoint.
Each set can be viewed as a tree that has a single root. Let's say the root of S1 is 1 and the root of S2 is 4.
Now if UNION(2, 5) is called, it will essentially merge set S1 with set S2. In other words, all the elements will now be part of a single set, and the root can be either 1 or 4 depending on the implementation. If FIND(1,6) is called afterwards, it will return true, as 1 and 6 now belongs to the same set, even though there weren't any calls like UNION(1,6) that explicitly asked to join 1 and 6.
If we get the following sequence of queries: MakeFriends(1,2), MakeFriends(2,3), AreFriends(1,3), the answer to the last query with our approach (irrespective of how DSU is implemented) will be 1, while the correct answer is 0.
Coming back to this statement, MakeFriends(1,2) will create a set that includes the elements 1, 2. Calling MakeFriends(2, 3) will include 3 in the same set. As a result, AreFriends(1,3) will return true, even though there weren't any explicit calls that joined 1 and 3, similar to the example mentioned above. So this statement is correct.
In the multiple choice questions, A. It may not always produce an accurate answer is correct.

Minimize transaction costs for settling debts in a pool

Suppose a group of friends shared some expenses across a month, and need to settle debts at the end. Each friend has a certain amount of money they should give/receive (the sum of debts and receivable amounts is zero), but everything must be settled with direct transfers (no central pool, only money from one person to another), and each transfer has a cost.
For example, suppose 3 people, A, B and C.
Person A must pay $100
Person B must receive $50
Person C must receive $50
The cost of each transaction can be described by the following matrix(the person in the row paying to the person in the column).
Given these costs, the optimal solution would be
Person A transfers $100 to Person B
Person B transfers $50 to Person C
This settles all debts with a transaction cost of 2. How can I generalize this?
All I could find searching was for simplifying chain debts (person A owes person B that owes person C, so person A owes person C).
The closest I found is this, but it doesn't have costs for transactions.
Backstory(if anyone is interested):
We live in a house with 8 people, and each month we pay bills from our own money and annotate it in a spreadsheet so at the end of the month we share the expenses fairly. However we have accounts on different banks, and some of these require fees for transferring money to other banks, so we prefer to keep transactions from the same bank.
I found another, simpler solution. We're still talking about transfer costs which are proportional to the transferred amount. You can build a simple graph with just as many nodes as people and run the network simplex algorithm. Python example:
import networkx as nx
G = nx.DiGraph()
G.add_node('A', demand=-100) # A has to send 100
G.add_node('B', demand=50) # B will receive 50
G.add_node('C', demand=50) # C will receive 50
G.add_edge('A', 'B', weight=1)
G.add_edge('A', 'C', weight=5)
G.add_edge('B', 'A', weight=1)
G.add_edge('B', 'C', weight=1)
G.add_edge('C', 'A', weight=2)
G.add_edge('C', 'B', weight=2)
print nx.network_simplex(G)
outputs (150, {'A': {'C': 0, 'B': 100}, 'C': {'A': 0, 'B': 0}, 'B': {'A': 0, 'C': 50}})
In case, the bank charges a percentage of the transferred amount, your task is finding a min-cost max flow.
Your graph should have 5 layers.
(direction)
| Source layer: S
| / | \
| Exchange: A --- B --- C (complete graph)
| \ | /
V Sink : T
The source is connected to the nodes A, B, C ... The capacity of S -> A is how much A has to pay, and 0 if A does not own money. The cost of the edge is 0.
In the exchange layer A, B, C... are all connected to each other (complete graph).
The capacity of A -> B is infinite and the cost is how much you have to pay after transferring $1 from A to B (same for all pairs).
The nodes are connected to the sink. The capacity of A -> Sink is how much A will receive, and 0 if A does not receive money. The cost of the edge is 0.
Run a min-cost max flow algorithm on the above graph from the root source to the root sink, such as Edmonds-Karp + cycle-canceling. You are probably better off finding a library (such as the Boost Graph Library for C++), instead of implementing the algorithms yourself.
After #j_random_hacker explained this problem is np-hard in the comments, I lost all hope of making a pretty solution and set out to do one that works.
Following #user3386109's suggestion, also in the comments, I based myself on minpaths to solve the problem. So I began by using the [Floyd-Warshall algorithm] to find the minimum cost to get money from a person to another for every pair. This yields a matrix of the minimum cost for transferring money from the person in the row to the person in the column. I also applied the modification(it is available in the Wikipedia article in the Path Reconstruction section) to obtain a matrix that yields the next node(next hop, the actual person you must send your money if want to reach the person in the column with minimal cost) for the person in the row to transfer money to the person in the column.
Example of the initialized matrixes, and the result after running the algorithm(The important elements that changed have a red dot):
I then decided to make simple Branch-and-Bound recursion. Every recursion call would receive a list of debts, a matrix for all transactions so far and the cost to reach this state. It must return TODO. We keep a global for the best solution found, and at the beginning of the recursion call check if the cost to reach this state is already worst than the global best, if it is, we return an "infinite" cost to signal this is not a solution we need to consider.
Then we select someone that owes money in the debt list and for each person that must receive money, we create copies of the debt list and transaction matrix, and simulate the transaction of the maximum amount of money between these two people(If A must pay 100 but C only needs to receive 50, the maximum is 50). The transactions matrix is modified by increasing all transaction in the minpath for these two people by the amount transferred. The cost is incremented if we increased an element that was previously zero. We then call the recursion. If the debt list reaches 0, a solution was found, the global minimum cost is updated and the cost returned is 0.
In a previous version, I spawned a recursion for each pair of owing/receiving person. This yielded horrible performance, and proved unnecessary, since the order of transactions doesn't matter, and any debts that weren't yet settled we be treated at lower levels of recursion.
This algorithm seemed correct, but there was still a problem!
In the following example:
Person A must pay 40$
Person B must pay 40$
Person C must pay 20$
Person D must receive 100$
The algorithm as it is now, makes A, B, C each make a transfer to D. The actual best way would be to choose one of A, B or C to transfer all the money to D in only one payment.
In this example, person A,B and C all have the same extremely high cost to transfer to D, and the next hop for all of them to get money to D is to go directly to D. However, the optimal solution would be to make everyone transfer all their money to a single person n transfer it to D all in one go. The algorithm is failing to recognize that since someone already made a transfer to person D, the cost of this transaction is 0, and so we should use this new path. To address this issue, I included a matrix for costs and a matrix for paths in the recursion, at the beginning of the recursion we set all costs of transfers that have already been made in this recursion branch to 0, and run Floyd-Warshall algorithm again. The recursion uses these matrixes instead of the global ones and passes them on. Sure, it means multiplying complexity by V^3, but it's the only way I found to solve this issue.
The algorithm seems to be working now, but I will probably keep trying to improve it, especially in code readability. The complete code is available at:
My gitlab project, inside the calculations folder
Sorry for the long answer and delay in posting it, but I found important to document my work thoroughly.

Speeding up LCS algorithm for graph construction

Referencing 2nd question from INOI 2011:
N people live in Sequence Land. Instead of a name, each person is identified by a sequence of integers, called his or her id. Each id is a sequence with no duplicate elements. Two people are said to be each other’s relatives if their ids have at least K elements in common. The extended family of a resident of Sequence Land includes herself or himself, all relatives, relatives of relatives, relatives of relatives of relatives, and so on without any limit.
Given the ids of all residents of Sequence Land, including its President, and the number K, find the number of people in the extended family of the President of Sequence Land.
For example, suppose N = 4 and K = 2. Suppose the President has id (4, 6, 7, 8) and the other three residents have ids (8, 3, 0, 4), (0, 10), and (1, 2, 3, 0, 5, 8). Here, the President is directly related to (8, 3, 0, 4), who in turn is directly related to (1, 2, 3, 0, 5, 8). Thus, the President’s extended family consists of everyone other than (0, 10) and so has size 3.
Limits: 1 <= n <= 300 & 1 <= K <= 300. Number of elements per id: 1-300
Currently, my solution is as follows:
For every person, compare his id to all other id's using an algorithm same as LCS, it can be edited to stop searching if k elements aren't there etc. etc. to improve it's average case performance. Time complexity = O(n^2*k^2)
Construct adjacency list using previous step result.
Use BFS. Output results
But the overall time complexity of this algorithm is not good enough for the second subtask. I googled around a little bit, and found most solutions to be similar to that of mine, and not working for larger subtask. The only thing close to a good solution was this one -> Yes, this question has been asked previously. The reason I'm asking essentially the same question again is that that solution is really tough to work with and implement. Recently, a friend of mine told me about a much better solution he read somewhere.
Can someone help me create a better solution ?
Even pointers to better solution would be great.

Minimum number of calls to be made?

There are 'n' number of detectives..each one knows an information, how many minimum calls should they make so all the detectives know all the n number of information ?
My answer: I came up with 2n-3 (that is, n-1 + n-2) solution where a detective calls n-1 other detectives and shares information mutually (in this way the last detective and the first has all the information). Then the remaining n-2 detectives who doesn't have the whole data calls either the first detective or the last to gain the remaining information.
(This is a question asked by my friend).
2n-3 is not correct.
Consider the case of n=4, 2n-3 would predict that 2*4-3=5 calls are needed.
However, we can do it in 4 calls via:
A calls B
C calls D
A calls C
B calls D

Is there a well understood algorithm or solution model for this meeting scheduling scenario?

I have a complex problem and I want to know if an existing and well understood solution model exists or applies, like the Traveling Salesman problem.
Input:
A calendar of N time events, defined by starting and finishing time, and place.
The capacity of each meeting place (maximum amount of people it can simultaneously hold)
A set of pairs (Ai,Aj) which indicates that attendant Ai wishes to meet with attendat Aj, and Aj accepted that invitation.
Output:
For each assistant A, a cronogram of all the events he will attend. The main criteria is that each attendants should meet as many of the attendants who accepted his invites as possible, satisfying the space constraints.
So far, we thought of solving with backtracking (trying out all possible solutions), and using linear programming (i.e. defining a model and solving with the simplex algorithm)
Update: If Ai already met Aj in some event, they don't need to meet anymore (they have already met).
Your problem is as hard as minimum maximal matching problem in interval graphs, w.l.o.g Assume capacity of rooms is 2 means they can handle only one meeting in time. You can model your problem with Interval graphs, each interval (for each people) is one node. Also edges are if A_i & A_j has common time and also they want to see each other, set weight of edges to the amount of time they should see each other, . If you find the minimum maximal matching in this graph, you can find the solution for your restricted case. But notice that this graph is n-partite and also each part is interval graph.
P.S: note that if the amount of time that people should be with each other is fixed this will be more easier than weighted one.
If you have access to a good MIP solver (cplex/gurobi via acedamic initiative, but coin OR and LP_solve are open-source, and not bad either), I would definitely give simplex a try. I took a look at formulating your problem as a mixed integer program, and my feeling is that it will have pretty strong relaxations, so branch and cut and price will go a long way for you. These solvers give remarkably scalable solutions nowadays, especially the commercial ones. Advantage is they also provide an upper bound, so you get an idea of solution quality, which is not the case for heuristics.
Formulation:
Define z(i,j) (binary) as a variable indicating that i and j are together in at least one event n in {1,2,...,N}.
Define z(i,j,n) (binary) to indicate they are together in event n.
Define z(i,n) to indicate that i is attending n.
Z(i,j) and z(i,j,m) only exist if i and j are supposed to meet.
For each t, M^t is a subset of time events that are held simulteneously.
So if event 1 is from 9 to 11, event 2 is from 10 to 12 and event 3 is from 11 to 13, then
M^1 = {event 1, event 2) and M^2 = {event 2, event 3}. I.e. no person can attend both 1 and 2, or 2 and 3, but 1 and 3 is fine.
Max sum Z(i,j)
z(i,j)<= sum_m z(i,j,m)
(every i,j)(i and j can meet if they are in the same location m at least once)
z(i,j,m)<= z(i,m) (for every i,j,m)
(if i and j attend m, then i attends m)
z(i,j,m)<= z(j,m) (for every i,j,m)
(if i and j attend m, then j attends m)
sum_i z(i,m) <= C(m) (for every m)
(only C(m) persons can visit event m)
sum_(m in M^t) z(i,m) <= 1 (for every t and i)
(if m and m' are both overlapping time t, then no person can visit them both. )
As pointed out by #SaeedAmiri, this looks like a complex problem.
My guess would be that the backtracking and linear programming options you are considering will explode as soon as the number of assistants grows a bit (maybe in the order of tens of assistants).
Maybe you should consider a (meta)heuristic approach if optimality is not a requirement, or constraint programming to build an initial model and see how it scales.
To give you a more precise answer, why do you need to solve this problem? what would be the typical number of attendees? number of rooms?

Resources