Gale-Shapley Algorithm Stability Test - python

I'm a beginner in python coding and am trying to figure out how to test the stability of the Gale-Shapley Algorithm. I understand that for a stable pairing to be made, this means that there's no situation whereby there's 2 people who prefers each other over their assigned partner.
The data of participants' preferences is as follows:
preference = [["boy1",1,3,2,4], ["boy2",1,2,4,3],["boy3",1,2,3,4],["boy4",2,3,1,4],["girl1",2,1,3,4],["girl2",4,3,2,1],["girl3",1,2,3,4],["girl4",3,4,2,1]]
For example, for preference[0], boy1's ranking for girl1 is 1, girl2 is 3, girl3 is 2, girl 4 is 4. This means that the list goes: ["boy1", (ranking of girl1), (ranking of girl2), (ranking of girl3), (ranking of girl 4)].
An example of a solution of pairings is as follows:
solution1 = [["boy1","girl1"],["boy2","girl3"],["boy3","girl2"],["boy4","girl4"]
I'm trying to come up with a function that produces true if solution is stable and false if the solution isn't stable, given the preference, solution and number of couples.
I've tried using pandas and numpy but I keep getting stuck with many for loops and if and problems with indexing as I'm not very familiar with any of these python libraries. I'm now trying to go back to basic and see if it's possible to do it. However, as I'm doing it, I realize that I kept using for loops and it won't be as efficient. Below is my incomplete code, please do advise on what I should do to improve the efficiency of this incomplete code - and if it's possible to execute my current incomplete code once it's complete. Please do suggest any python libraries that I can use too, any suggestions are greatly appreciated!
def teststability(n, preference, solution):
for i in solution[i]:
fpo = solution[i][1][1]
for j in preference[j]:
if solution[i][0] == preference[j][0]:
rank = preference[j][fpo]
if rank == 1:
continue
else:
for k in pref[j][k]:
if pref[j][k] < rank:
lst.append("girl"+str(k))
else:
continue

You don't Pandas or Numpy for this, as it's a classic algorithmic SAT problem, and not one of data. (If you need to apply a given solution algorithm to a large array of pairs, then Pandas might be useful.)
The algorithm is implemented in the QuantEcon/MatchingMarkets package.
Lastly, I'd note that it's a little confusing that you're using lists made of strings and integers. I'd suggest dict of male-to-female and female-to-male preferences, eg:
female_prefs = {1: [2, 1, 3, 4], 2: [4, 3, 2, 1], 3: [1, 2, 3, 4], 4: [3, 4, 2, 1]}

Related

Python intersection of 2 arrays without using loops/functions

I have some problems with this task:
write in recursive functions which (NOTE: you can't use loops.):
3.1 Will display on the screen the common part of two sorted arrays
3.2 Will write the back of the word/array on the screen
Right now I have rest of the exercise:
firstArray = [1, 2, 3, 4, 5]
secondArray = [4, 5, 6, 7, 8]
#1 function - print first element
def printFirstElement():
firstElemenet = firstArray[0]
print(firstElemenet)
printFirstElement()
#2 function - print all without first element
def printAllWithouthFirstElemenet():
arrayWithoutFirstElement = firstArray[1:]
print(arrayWithoutFirstElement)
printAllWithouthFirstElemenet()
#3 functin - return information if array is empty
def checkArrayEmptiness():
if firstArray:
print("Array has somehting")
else:
print("Array is empty")
checkArrayEmptiness()
##rest code should be here
I really don't have idea what I could write more, someone could help me?
Edit 1
Without ready-made solutions
You can use python set.
Something like:
print(set(firstArray).intersection(secondArray))
In most cases it will be smart to use Python built in solutions, as they are more efficient for the general case.
But, in case you do need it, try looking at this duplicate question: Finding List Intersection using Python List Slices & recursion

Python: Is this array element replacement correct?

I wanted to change all the negative values of an array to be 0. Will the following expression do what I expect?
import numpy as np
x = np.array([3, -3], [5, 2], [1, -5])
x[x < 0] = 0
I know this could be done manually, but I want to know that because I need it for a larger personal project.
In short, yes it will, if you provide a valid array. However, the array you are trying to construct is not valid, as np.array does not accept multiple array-like parameters. Maybe you meant to write this instead?
x = np.array([[3, -3], [5, 2], [1, -5]])
Note the extra pair of brackets surrounding your arguments to create a 2D array.
As others pointed out though, please don't ask simple questions like this on StackOverflow which can easily be confirmed with less than a minute of your own trial and error in a Python shell. The intent is generally to ask about specific problems you run into, and to show your attempts at a solution, so you can then be guided into accomplishing what you want.

Python: graph redundant nodes (without Networkx)

We've been given standard beginner's python problem as a homework exercise, but my research into it shows people always use Networkx to solve these graph type node problems, whereas we're not allowed to use the Networkx built-in to solve it. I'm hoping for advice on a nice way to tackle this please.
There are five nodes (named 1,2,3,4,5) and the order is this:
1 goes nowhere
2 only goes to 1
3 goes to 1 and 5 (but 5 is closer which makes the 3 to 1 path redundant)
4 goes to 1 and 2 (but 2 is closer so 4-1 is redundant)
5 goes to 2
This is the example data to read in (note this is just one data set - it has to work with other pairs too):
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)', 'R(3,1)', 'R(4,1)']
This is the non-redundant pair output:
['R(3,5)', 'R(4,2)', 'R(5,2)', 'R(2,1)']
My attempt so far has been to split into two lists for start node and end node:
start_value = []
end_value = []
for i in range(len(partial_order)):
start_value.append(int(partial_order[i][2]))
for i in range(len(partial_order)):
end_value.append(int(partial_order[i][4]))
dictionary = dict(zip(start_value, end_value))
Output:
[3, 4, 5, 2, 3, 4]
[5, 2, 2, 1, 1, 1]
{3: 1, 4: 1, 5: 2, 2: 1}
I thought if I put it into a dictionary, I can try something from there, but my dictionary only shows 3:1 instead of 3:[1,5]. It is the 3-5 pair that I need to keep since it is closer, so 3-1 is redundant. Thanks for any tips on how to progress without Networkx.
This is one of pages I was reading - I'm trying to set up graph dictionary like that so I can try out their find_shortest_path function, to see if that gives me a solution.
https://www.python.org/doc/essays/graphs/
UPDATE:
I ended up abandoning the dictionary idea and zipping the two lists together then performed a whole bunch of if statements to get it working.
But I really would like to hear anyone's solution for something more Pythonic (so long as it doesn't use packages like Networkx). Happy coding.

recursive algorithm for 2D array in Python

a = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 8, 1, 2],
[6, 3, 1, 4],
]
I have a 2D array and given cell indexs(i,j).
for e.g. we are given x,y=(2,3) so this is for a[2][3].
What I want to do using dynamic programming or recursion(prefer) is that I will traverse the whole matrix (until a given condition satisfy) by moving up, down, left and right.
I mean , I will go from (x,y) to all 4 adjacent cell, and then do this recursively for all 4 cell(until some condition). but this is not guaranteed that all 4 cell will be covered(there is algorithm for that, if that satisfy then only I will move to that cell and further from that cell using same algo.
I'm able to implement algorithm but I'm having hard time to implement recursive solution in Python.
can you please suggest something, link to some similar recursive code.
I tried to find same on stackoverflow but not success. I'm not sure if this is violating the question posting rule, if so I will remove but please try to help me with this first.
What you are trying to do is very similar to a flood fill. Check the Wikipedia page to learn the algorithm. It is common enough that it should not be hard to find code for it in multiple languages.

Graph Theory: Finding all possible paths of 'n' length (with some constraints)

I was given a sample challenge question by one of my friends. I would like to hear some advice on how to best approach finding a solution.
The problem involves calculating all possible patterns of traversing a series of points on a grid-like scale. I will simply be given a number 'n' that represents how many times I must move, and I must determine the number of ways I can traverse the grid moving n times. The starting point can be any of the points so I must run my calculation on every starting point with my answer being the sum of the results of each starting point.
I am still a bit of a beginner is some regards to programming, and my best guess as to how to approach this problem is to use graph theory. I have started by creating a graph to represent the nodes as well as their neighbors. I am leaving this problem intentionally vague because I want to learn how to approach these kinds of problems rather than having some expert swoop in and simply solve the entire thing for me. Here is an example representation of my graph in Python 3 (a dictionary).
graph = {'a':['b','c']
'b':['a','e','f']
'c':['a','d']
'd':['c']
'e':['b','g'] and etc.
My real graph is significantly bigger with each node typically having at least 3-4 neighbors. Let's pretend the 'n' given is 6, meaning I need to return all possible valid paths that involve moving 6 times. I am allowed to revisit nodes, so a valid path could simply be a-b-a-b-a-b. Another example of a 'valid' path is a-b-a-c-d-c or e-b-a-c-a-b since we can start from any starting point.
I am at a bit of a loss as to how to best approach this problem. Recursion has crossed my mind as a possible solution where I traverse all possible paths and increment a counter each time I hit the 'end' of a path. Another possible solution I have considered is at each node, calculate the possible moves and multiply it with a running tally. For example, starting at 'a', I have two moves. If I navigate to 'b', I have 3 moves. If I navigate to 'c', I have 2 moves. At this point, I have 1*3*2 moves. This could be a completely wrong approach...just an idea I had.
The actual problem is a lot more complex with constraints for certain nodes (how many times you can visit it, rules against visiting it if a certain sequence of nodes were hit prior, etc.) but I will omit the details for now. What I will say is that given these constraints, my algorithm must know what the previous pattern of visited nodes was. At the 5th move, for example, I must be able to refer to the previous 4 moves at any time.
I would love to hear advice on how you would best approach solving the 'simpler' problem I outlined above.
Check out Depth First Search (DFS). Just off the top of my head: Use recursive DFS, use a counter for saving each node found after making 'n' moves. You would need to build an undirected graph representation of the given data, so that you could run the DFS algorithm on the graph.
Here's the simplest answer for the case you gave. Once you have you graph in the form of a "transition map" (which can just be a dictionary, like you've shown), then the following code will work:
def myDFS(trans_dict,start,length,paths,path=[]):
path=path+[start]
if len(path)==length:
paths.append(path)
else:
for node in trans_dict[start]:
myDFS(trans_dict,node,length,paths,path)
If you want the number of ways you can traverse the map with a path of a given length, then that would just be len(paths).
Example:
trans_dict = {0:[1,2],1:[2,3],2:[0,3],3:[3]}
paths = []
length = 3
for a in trans_dict:
myDFS(trans_dict,a,length,paths)
print paths # [[0, 1, 2], [0, 1, 3], [0, 2, 0], [0, 2, 3], [1, 2, 0], [1, 2, 3], [1, 3, 3], [2, 0, 1], [2, 0, 2], [2, 3, 3], [3, 3, 3]]
print len(paths) # 11
Answer was inspired by this Q&A: trying to find all the path in a graph using DFS recursive in Python

Categories

Resources