So I'm trying to go through a book used to teach different types of models and algorithms and I came upon this issue. My code is below. Essentially it generates a text output of a graph. Individual points are referred to as "vertices" and the lines connecting them are "edges". What I'm currently trying to do is check if an edge exists between two vertices.
class Graph(dict):
def __init__(self, vs=[], es=[]):
for v in vs:
self.add_vertex(v)
for e in es:
self.add_edge(e)
def add_vertex(self, v):
self[v] = {}
def add_edge(self, e):
v,w = e
self[v][w] = e
self[w][v] = e
def get_edge(self, v, w):
g = dict(self)
keys = g.keys()
return type(keys[0])
def remove_edge(self, e):
pass
def vertices(self):
keys = self.keys()
return keys
class Vertex(object):
def __init__(self, label=''):
self.label = label
def __repr__(self):
return 'Vertex(%s)' % repr(self.label)
__str__ = __repr__
class Edge(tuple):
def __new__(cls, e1, e2):
return tuple.__new__(cls, (e1, e2))
def __repr__(self):
return 'Edge(%s, %s)' % (repr(self[0]), repr(self[1]))
__str__ = __repr__
v = Vertex('v')
w = Vertex('w')
e = Edge(v, w)
print e
g = Graph([v,w],[e])
print g
edge = Graph.get_edge(g, 'v', 'w')
print edge
The issue is here:
def get_edge(self, v, w):
g = dict(self)
keys = g.keys()
return type(keys[0])
I cannot access the values in the dictionary because I can't use the keys, the return type line shows why:
Output:
Edge(Vertex('v'), Vertex('w'))
{Vertex('v'): {Vertex('w'): Edge(Vertex('v'), Vertex('w'))}, Vertex('w'):{Vertex('v'): Edge(Vertex('v'), Vertex('w'))}}
<class '__main__.Vertex'>
The issue is the keys aren't strings, integers, or really anything I can reference, they're generated from calling the Vertex class. Is there some way I could reference the keys that I'm missing? My goal is to have the method return the Edge requested if it exists.
Related
I'm trying to do an academic project (I cannot use any of the libraries from python) to construct a graph data structure from teh data in a csv file.
First I'm reading the csv file and put the information into a dictionary, using:
def github_csv():
with open('Github1.csv', 'r') as csv_file:
data = csv.DictReader(csv_file)
next(data)
for row in data:
print(row)
The output is:
{'follower': '9236', 'followed': '1570'}
{'follower': '13256', 'followed': '9236'}
{'follower': '9236', 'followed': '13256'}
My first doubt is there any way to put it like this:
'9236': ['1570', '13256']
'13256': ['9236']
Then how can I assign the key value to a vertex and corresponding values for another vertex and then create the edges?
My graph class is:
class Graph:
def __init__(self, directed=False):
self._directed = directed
self._number = 0
self._vertices = {}
def insert_vertex(self, x):
v = Vertex(x)
self._vertices[v] = {}
self._number = len(self._vertices)
return v
def insert_edge(self, u, v, x=None):
e = Edge(u, v, x)
self._vertices[u][v] = e
self._vertices[v][u] = e
EDIT:
class Vertex:
__slots__ = "_element"
def __init__(self, x):
self._element = x
def vertice(self):
return self._element
def __eq__(self, other):
if isinstance(other, Vertex):
return self._element == other.vertice()
return False
def __repr__(self):
return '{0}'.format(self._element)
def __hash__(self):
return hash(id(self))
class Edge:
__slots__ = '_origin', '_destination', '_weight'
def __init__(self, u, v, p=None):
self._origin = u
self._destination = v
self._weight = p
def __hash__(self):
return hash((self._origin, self._destination))
def __repr__(self):
if self._weight is None:
return '({0}, {1})'.format(self._origin, self._destination)
return '({0}, {1}, {2})'.format(self._origin, self._destination, self._weight)
def endpoints(self):
return self._origin, self._destination
def opposite(self, v):
return self._origin if v is self._destination else self._origin
def cost(self):
return self._weight
def show_edge(self):
print('(', self._origin, ', ', self._destination, ') com peso', self._weight)
Regarding the first question:
lista = [{'follower': '9236', 'followed': '1570'},
{'follower': '13256', 'followed': '9236'},
{'follower': '9236', 'followed': '13256'}]
rel_dict = {}
for d in lista:
if d["follower"] in rel_dict.keys():
rel_dict[d["follower"]].append(d["followed"])
else:
rel_dict[d["follower"]] = [d["followed"]]
rel_dict:
{'9236': ['1570', '13256'], '13256': ['9236']}
EDIT2 (with Vertex and Edge definition):
To add these data to the graph:
graph = Graph()
for k,v in rel_dict.items():
k_vertex = graph.insert_vertex(k)
for v_item in v:
v_item_vertex = graph.insert_vertex(v_item)
graph.insert_edge(k_vertex, v_item_vertex)
Assuming you get row as the dictionaries you've mentioned,
edges_dict = {}
def github_csv():
with open('Github1.csv', 'r') as csv_file:
data = csv.DictReader(csv_file)
next(data)
for row in data:
edges_dict[ row['follower'] ].append(row['followed'])
This should give you an edges_dict dictionary of lists as required.
With Python and JsonPickle, How do I serialize the object with a Certain Casing, eg Camel Case, Pascal, etc? The following answer below does it manually, however looking for a specific Jsonpickle solution, since it can handle complex object types .
JSON serialize a class and change property casing with Python
https://stackoverflow.com/a/8614096/15435022
class HardwareSystem:
def __init__(self, vm_size):
self.vm_size = vm_size
self.some_other_thing = 42
self.a = 'a'
def snake_to_camel(s):
a = s.split('_')
a[0] = a[0].lower()
if len(a) > 1:
a[1:] = [u.title() for u in a[1:]]
return ''.join(a)
def serialise(obj):
return {snake_to_camel(k): v for k, v in obj.__dict__.items()}
hp = HardwareSystem('Large')
print(json.dumps(serialise(hp), indent=4, default=serialise))
Here's my attempt.
from importlib import import_module
import inspect
import json
import jsonpickle
import re
def snake_to_camel(s):
a = s.split('_')
a[0] = a[0].lower()
if len(a) > 1:
a[1:] = [u.title() for u in a[1:]]
return ''.join(a)
def camel_to_snake(s):
snake = []
snake_len = len(s)
for idx, char in enumerate(s):
snake.append(char.lower())
if idx < snake_len - 1:
if char.islower() and s[idx+1].isupper():
snake.append('_')
return ''.join(snake)
def debug_output(obj):
output = '{}({})'
attrs = [attr + '=' + repr(getattr(obj, attr)) for attr in vars(obj)]
return output.format(obj.__class__.__name__, ', '.join(attrs))
class SoftwareSystem:
def __init__(self):
self.software_rating = 'Awesome!'
# Making debug output friendly
def __repr__(self):
return debug_output(self)
class HardwareSystem:
def __init__(self, vm_size):
self.vm_size = vm_size
self.some_other_thing = 42
self.a = 'a'
# Making debug output friendly
def __repr__(self):
return debug_output(self)
#jsonpickle.handlers.register(HardwareSystem, base=True)
#jsonpickle.handlers.register(SoftwareSystem, base=True)
class SystemHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
for k, v in obj.__dict__.items():
data[snake_to_camel(k)] = jsonpickle.encode(v)
return data
def restore(self, obj):
# Gets reference to class
# https://stackoverflow.com/a/55559852/152016
module_path, class_name = obj['py/object'].rsplit('.', 1)
module = import_module(module_path)
class_ = getattr(module, class_name)
# Dealing with __init__ params (except first)
params = inspect.getargs(class_.__init__.__code__)
params = params.args[1:]
# Preparing dict keys
l_obj = {}
for k, v in obj.items():
l_obj[camel_to_snake(k)] = v
# Instantiating constructor params
data = {}
for k, v in l_obj.items():
if k in params:
data[k] = v
result = class_(**data)
# Setting other jsonpickled object attributes
for k, v in l_obj.items():
if not k in params:
setattr(result, k, v)
return result
hw = HardwareSystem(100)
sw = SoftwareSystem()
hw.software_instance = sw
json_str = jsonpickle.encode(hw)
print(json_str)
decoded = jsonpickle.decode(json_str)
print(hw)
This has some assumptions:
Following your original snake_to_camel function, I've put up a camel_to_snake on decoding, that assumes only the first uppercase letter after a lowercase letter will have prepended the _ char (so awesomeABC will translate to awesome_abc, and therefore if you translate it back again it will be incorrectly awesomeAbc)
The above code encodes/decodes properties added after __init__ (see for example hw.software_instance above).
You can nest objects. I've only tried a single object nested.
I've added auxiliary debug_output/__repr__ functions, you may throw these away (or customize :))
I have the following code:
class Player:
def __init__(self, N, V, F, L, T):
self._Name = N
self._VPs = V
self._Fuel = F
self._Lumber = L
self._PiecesInSupply = T
def AddPiecesInSupply(self, T):
modify = T+1
modify.T
return T
I have been given code and been asked to make changes. "self._PiecesInSupply = T" is a protected attribute. I have been asked to create a method to allow "self._PiecesInSupply = T" to be modified so I created the code:
def AddPiecesInSupply(self, T):
modify = T+1
modify.T
return T
This is how I call Player.AddPiecesInSupply
Player.AddPiecesInSupply(0)
however the value 0 is being passed to the parameter self not T. Any ideas on how to pass the value 0 to T?
Thanks
Maybe you want something like this:
class Player:
def __init__(self, N, V, F, L, T):
self._Name = N
self._VPs = V
self._Fuel = F
self._Lumber = L
self._PiecesInSupply = T
def AddPiecesInSupply(self, T):
self._PiecesInSupply += T
return T
player = Player('name','VPs',1,2,3)
player.AddPiecesInSupply(0)
print(player._PiecesInSupply)
The following code does not work.
def set_view_counts(self):
"""
Initializes the view counts for all of the Concept objects in the ConceptModel. See Concept for a
description of why this parameter is optional.
"""
for node in self.nodes():
p = PageviewsClient().article_views("en.wikipedia", [node.concept.replace(' ', '_')])
p = [p[key][node.concept.replace(' ', '_')] for key in p.keys()]
p = int(sum([daily_view_count for daily_view_count in p if daily_view_count])/len(p))
node.properties['view_count'] = p
When I check the contents of my node.properties dictionaries I find 4560, 4560, 4560, 4560.
The following code does.
def set_view_counts(self):
"""
Initializes the view counts for all of the Concept objects in the ConceptModel. See Concept for a
description of why this parameter is optional.
"""
for node in self.nodes():
p = PageviewsClient().article_views("en.wikipedia", [node.concept.replace(' ', '_')])
p = [p[key][node.concept.replace(' ', '_')] for key in p.keys()]
p = int(sum([daily_view_count for daily_view_count in p if daily_view_count])/len(p))
node.properties = p
When I check properties I find 11252, 7367, 3337, 4560.
What's going on here?
We would need to see more of your code, but I put some meat around your function, guessing what you could have written to reproduce your bug:
class Node:
def __init__(self, props={}):
self.properties = props
class G:
def __init__(self):
self.n = [Node(), Node(), Node(), Node()]
def nodes(self):
return self.n
def set_view_counts(self):
p = 0
for node in self.nodes():
node.properties['view_count'] = p
p = p + 1
def __repr__(self):
r = ''
for node in self.nodes():
r += node.properties.__repr__()
return r
g = G()
g.set_view_counts()
print g
With this, I get:
{'view_count': 3}{'view_count': 3}{'view_count': 3}{'view_count': 3}
This is because of the default value on the props parameter in Node.__init__. The same dict (the one used as the default value) is shared by all Nodes. Fix this by removing the default value.
I'm looking for a convenient way to remove an instance of a class object which is contained in two dictionaries. When I delete the object instance from one dict, I should automatically be deleted in the second dict. Is this anyhow possible?
class node():
def __init__(self, vID):
self.vID = vID
def __hash__(self):
return hash(self.vID)
def __eq__(self, other):
return self.vID == other.vID
class structure():
def __init__(self):
self.point_index_a = {}
self.point_index_b = {}
def add_point(self,x,y):
x_object = node(x)
self.point_index_a[x_object] = None
self.point_index_b[x_object] = None
def a_iter(self):
for k,v in self.point_index_a.iteritems():
print k,v
def b_iter(self):
for k,v in self.point_index_b.iteritems():
print k,v
mg = structure()
mg.add_point(1, 8)
mg.add_point(3, 4)
# point index a
for k,v in mg.point_index_a.iteritems():
print k,v
# point index b
for k,v in mg.point_index_b.iteritems():
print k,v
to_del = mg.point_index_a.iterkeys().next()
del to_del
# point index a, object to_del still exists in both dicts
for k,v in mg.point_index_a.iteritems():
print k,v
# point index b
for k,v in mg.point_index_b.iteritems():
print k,v
I would implement as follows:
class structure():
...
def remove(self, point):
del self.point_index_a[point]
del self.point_index_b[point]