0

Hi! I am new to Python and I am struggling for many hours so far with some problem regarding Shortest Path Algorithm implementation in Python.

I am expected to solve some task about finding shortest paths (graph problem) among given persons, and at the end find a common person who connects all of them.

I've made something like this so far:

import itertools
    
class centralperson():

def initialization(self,N,data,a,b,c):
    self.data = data
    self.N = N
    self.a = a
    self.b = b
    self.c = c
    self.list_of_values = [self.a,self.b,self.c]
    self.list_of_paths = []
    self.common_person = []

def makeGraph(self):
    
    # Create dict with empty list for each key
    graph = {key: [] for key in range(self.N)}
    self.graph = graph

    for key in self.graph:
        for x in self.data:
            if key in x:
                
                x = x.copy()
                x.remove(key)
                self.graph[key].extend(x)

def find_path(self,start, end):
    path = []
    path = path + [start]
    if start == end:
        return path
    if start not in self.graph.keys():
        raise ValueError('No such key in graph!')
    for node in self.graph[start]:
        if node not in path:
            newpath = self.find_path(self.graph, node, end, path)
            if newpath: return newpath
    return self.list_of_paths.append(path)


def findPaths(self):
    
    for pair in itertools.combinations(self.list_of_values, r=5):
        self.find_path(*pair)


def commonperson(self):
    
    list_of_lens = {}
    commonalities = set(self.list_of_paths[0]) & set(self.list_of_paths[1]) & set(self.list_of_paths[2])
    for i in self.list_of_values:
        list_of_lens[i] = (len(self.graph[i]))
    
    if len(commonalities)>1 or len(commonalities)<1:
        for k,v in list_of_lens.items():
            if v==1 and self.graph[k][0] in commonalities:
                output = self.graph[k]
                self.common_person.append(output)
    else:
        output = list(commonalities)
        self.common_person.append(output)
    return 

def printo(self):

    #return(self.common_person[0])
    return(self.list_of_paths,self.list_of_values)

Description of each function and inputs:

N -> number of unique nodes

a,b,c -> some arbitrarily chosen nodes to find common one among them

initialization -> just initialize our global variables used in other methods, and store the list of outputs

makeGraph -> makes an Adjacency List out of an input.

find_path -> find path between two given nodes (backtracking recursion)

findPaths -> it was expected to call find_path here for every combination of A,B,C i.e A->B, A->C, B->C

commonperson -> expected to find common person from the output of list_of_paths list

printo -> print this common person

Generally It works (I'think) when I'am running each function separately. But, when I try to make a huge class of it, it doesn't work :(

I think the problem is with this recursive function find_path. It is supposed to find a path between two person given, and append the result path to the list with all paths. Yet, as I have 3 different persons, and find_path is a recursive function with only 2 parameters.

Hence, I need to find all paths that connects them (3 paths) and append it to a bigger list list_of_paths. I've created a def findPaths to make use of itertools.combinations and in for loop cal function find_path for every combination of start and end argument of this function, but it seems not to work...

Can you help me with this? Also I don't know how to run all the def functions at once, because honestly I wouldn't like to run all instances of the class separately... My desired version is to:

Provide Input to a class i.e : N,data,a,b,c where N is number of unique nodes, data is just list of list with networks assigned, and A,B,C are my persons.

Get Output: which is a common person for all this 3 persons, (I planned to store it in common_person list.

Community
  • 1
  • 1
Rikudo
  • 25
  • 4

2 Answers2

0

The code inside you class should be indented, i.e.:

class centralperson:
    def __init__(self, ...):
        ...

    def makeGraph(self, ...):
        ...

instead of

class centralperson:
def __init__(self, ...):
    ...

def makeGraph(self, ...):
    ...

Try googling for 'python class examples'. I hope this helps!

It might also be useful to experiment with simpler classes before working on this problem.

Fons
  • 1,527
  • 12
  • 11
0
itertools.combinations(self.list_of_values, r=5)

returns an empty list, since self.list_of_values only has 3 elements, from which you cannot pick 5.

Perhaps you meant:

itertools.combinations(self.list_of_values, r=2)
Fons
  • 1,527
  • 12
  • 11
  • when I set to r=2 it gives an error: ```3 Persona.makeGraph() --> 4 Persona.findPaths() 5 Persona.printo() 43 for pair in itertools.combinations(self.list_of_values, r=2): --> 44 self.find_path(*pair) 34 for node in self.graph[start]: 35 if node not in path: ---> 36 newpath = self.find_path(self.graph, node, end, path) 37 if newpath: return newpath 38 return self.list_of_paths.append(path) TypeError: find_path() takes 3 positional arguments but 5 were given``` – Rikudo Jun 01 '19 at 16:19
  • Have a closer look at line 36. – Fons Jun 01 '19 at 16:29