12

I have an instance 'graph_main' of a class BipartiteGraph which I've defined. All I need now is to keep this instance untouched but create another instance 'graph1' of this class that is identical to 'graph_main'. But for some reason the graph_main also keeps changing while I am not working with it at all. I am new to Python, like couple of weeks new. So if there is relevant documentation that you can point me towards to learn the scope of objects in Python, I will appreicate it.

MWE:

import numpy
import testBipartiteUtils
import random
#These are Bipartite graph parameters
N=30 #No of Bit Nodes
K=10 #No of Check Nodes 
rdeg=2 

graph_main = testBipartiteUtils.BipartGraph([])

for NodeIndex in range(0, K):
    graph_main.addBitNode(NodeIndex)#Adding Bit Node. No edges added

for NodeIndex in range(0, N):
    graph_main.addChkNode(NodeIndex)#Adding Check Node. No edges added

    attachments=random.sample(range(0,K),rdeg) 
    for j in attachments:
        graph_main.addEdge([j,NodeIndex])

for z in range(0,10):
    chan=[]
    for i in range(0,N):
        chan.append(0)

graph1=graph_main **#creating a new object identical to graph_main?**

PeelGraph=testBipartiteUtils.Peeling(graph1,chan)
PeelGraph.zeroStep()
print "graph_main Nodes are-",len(graph_main.BitNodes),len(graph_main.ChkNodes)
print "graph1 Nodes are-",len(graph1.BitNodes),len(graph1.ChkNodes)

del PeelGraph
print "z=",z

I am providing my Utils file in case someone wants to run it and see but I highly doubt that would be necessary. So I am expecting an output of constant number of Bit and Check Nodes in graph_main (it is a bipartite graph class) for each simulation since I am not changing it. Here I am assuming graph1=graph_main creates a new object identical to the existing graph_main. Is that correct and my mistake lies elsewhere?

testBipartiteUtils.py

import numpy

 class Edge:

 def __init__(self, n1, n2):
    """Constructor. Takes bit and check node IDs as arguments"""
    self.node1=n1
    self.node2=n2

def getNodes(self):
    """Returns a list containing the bit and check nodes for this edge"""
    return [self.node1, self.node2]

def hasNodes(self, n1, n2):
    """Takes two node IDs. Returns true if the IDs match the two nodes of this edge in that order."""
    if(self.node1==n1 and self.node2==n2):
        return True

    return False


 class BitNode:
""" Basic node class."""

def __init__(self, name):
    """Constructor. Takes a node ID"""
    self.ID=name
    self.neighbors=[]
    self.degree= 0

def addNeighbors(self, nbs):
    """Adds a list of neighbors to the current list. Takes a list of node IDs"""
    for i in range(0, len(nbs)):
        if(not nbs[i] in self.neighbors):
            self.neighbors.append(nbs[i])
            self.degree+=1

def getID(self):
    """Returns node ID"""
    return self.ID

def getNeighbors(self):
    """Returns list of neighbor IDs"""
    return self.neighbors


 class ChkNode:

def __init__(self, name):
    """Constructor. Takes a node ID"""
    self.ID=name
    self.neighbors=[]
    self.chan = int(-1)
    self.degree= 0


def addNeighbors(self, nbs):
    """Adds a list of neighbors to the current list. Takes a list of node IDs"""
    for i in range(0, len(nbs)):
        if(not nbs[i] in self.neighbors):
            self.neighbors.append(nbs[i])
            self.degree+=1

def getID(self):
    """Returns node ID"""
    return self.ID

def getNeighbors(self):
    """Returns list of neighbor IDs"""
    return self.neighbors


 class BipartGraph:
def __init__(self, eds):
    """Constructor. Takes a list of edge primitives, which is a list of two node IDs.
    Iterates through the edges, creates nodes for unique node IDs, and adds all edges and nodes.
    """
    self.size = 0
    self.BitNodes = []
    self.ChkNodes = []
    self.edges = []
    for i in range(0, len(eds)):
        self.addEdge(eds[i])


def containsEdge(self, edgep):
    """Checks for an edge in the graph. Takes an edge primitive, which is a list of two node IDs. First ID is bit node, second ID is of Check node"""
    for e in self.edges:
        if(e.hasNodes(edgep[0], edgep[1])):
            return True


def getBitNode(self, name):
    """Checks if a given Bit Node ID exists in the graph. If not, it creates and adds a Bit Node for the given ID. Returns the Bit Node"""
    for i in range(0, len(self.BitNodes)):
        if(self.BitNodes[i].getID()==name):
            return self.BitNodes[i]
    newNode = BitNode(name)
    self.BitNodes.append(newNode)
    return self.BitNodes[len(self.BitNodes)-1]

def getChkNode(self, name):
    """Checks if a given Chk Node ID exists in the graph. If not, it creates and adds a Chk Node for the given ID. Returns the Chk Node"""
    for i in range(0, len(self.ChkNodes)):
        if(self.ChkNodes[i].getID()==name):
            return self.ChkNodes[i]
    newNode = ChkNode(name)
    self.ChkNodes.append(newNode)
    return self.ChkNodes[len(self.ChkNodes)-1]

def getEdges(self):
    """Returns list of edges"""
    return self.edges

def addBitNode(self, name):
    """Adds a Bit node, based on Bit node ID"""
    newNode = BitNode(name)
    self.BitNodes.append(newNode)

def addChkNode(self, name):
    """Adds a Check node, based on node ID"""
    newNode = ChkNode(name)
    self.ChkNodes.append(newNode)

def addEdge(self, edgep):
    """Adds an edge into the graph, and updates neighbors & degrees of relevant nodes.
    Takes an edge primitive, a list of two node IDs
    """
    if(not self.containsEdge(edgep)):
        no1 = self.getBitNode(edgep[0])
        no2 = self.getChkNode(edgep[1])
        newEdge = Edge(edgep[0], edgep[1])
        self.edges.append(newEdge)
        no1.addNeighbors([no2.getID()])
        no2.addNeighbors([no1.getID()])

 class Peeling:
"""peeling decoder on a Bipartite graph class.
"""
def __init__(self, G,chan):
    """Constructor. Takes a graph and channel output vector as arguments"""
    self.graph=G
    for i in range(0,len(self.graph.ChkNodes)):
        self.graph.ChkNodes[i].chan=chan[i]
    self.deg1Chks=[]

def zeroStep(self):
    self.graph.BitNodes.pop(0)

def peelIter(self):
    self.graph.ChkNodes.pop(0)
4
  • 1
    graph1=graph_main **#creating a new object identical to graph_main?** is actually creating a second reference to the object that graph_main refers to. Both of those variables now point to the exact same object. You'll want to make a .copy() method or similar to allow you to clone your object if you need a separate instance of it. Commented Feb 19, 2016 at 22:09
  • So this is similar to pointers in C++ where by you are assigning the pointer referencing graph_main to graph1 rather than creating a new variable like in MATLAB.. Commented Feb 21, 2016 at 5:51
  • 1
    Sort-of-but-not-quite. See robertheaton.com/2014/02/09/… for an explanation of the differences. As a rule of thumb, every single assignment operation in Python creates a new named reference (the variable name looking thing on the left side of the equation) to an object (the thing on the right). Even if foo is already defined, saying foo = bar replaces the old reference with a new reference with the same name. Commented Feb 22, 2016 at 19:54
  • Thanks. I think i get it but I am sure if I layoff python for a while and come back I will get confused. Can you point me to any other material that explains this stuff in detail? Commented Feb 26, 2016 at 17:07

2 Answers 2

17

Use the deepcopy function to create an identical instance with a new pointer (as opposed to a shallow copy, which is another variable pointing to the same object).

import copy

graph1= copy.deepcopy(graph_main)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. that works perfectly. But my problems are deeper than this as pointed out by Kirk- need to understand the differene of assignment and new named reference,
-8

I'm not sure about this but couldn't you just do this?...

x = ClassName(arguments, arguments...)

dup_of_x = x

Therefore, x stores x and dup_of_x also stores x

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.