def testConceptNetworkAddNodeTwice(self): "One node added twice implies an incremented occ" cn = ConceptNetwork() node = Node("Salut") cn.addNode(node) cn.addNode(node) self.assertEqual(2, node.getOcc())
def testDumpLoad(self): "Test the saving of the Concept Network" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100,"From") conceptNetwork.fastPropagateActivations(state,2) av = state.getNodeActivationValue("To1") f = open("cntest.data","w") try: conceptNetwork.dump(f,0) finally: f.close() f = open("cntest.data") try: cnLoaded = pickle.load(f) finally: f.close() import os os.remove("cntest.data") # No state is dumped! self.assertRaises(KeyError,cnLoaded.getState,1) nodeLoaded = cnLoaded.getNode("To1") self.assertTrue(nodeLoaded)
def testConceptNetworkAddNodeTwice(self): "One node added twice implies an incremented occ" cn = ConceptNetwork() node = Node("Salut") cn.addNode(node) cn.addNode(node) self.assertEqual(2,node.getOcc())
def testDumpLoad(self): "Test the saving of the Concept Network" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100, "From") conceptNetwork.fastPropagateActivations(state, 2) av = state.getNodeActivationValue("To1") f = open("cntest.data", "w") try: conceptNetwork.dump(f, 0) finally: f.close() f = open("cntest.data") try: cnLoaded = pickle.load(f) finally: f.close() import os os.remove("cntest.data") # No state is dumped! self.assertRaises(KeyError, cnLoaded.getState, 1) nodeLoaded = cnLoaded.getNode("To1") self.assertTrue(nodeLoaded)
def testGetNodeStateTyped(self): "Test getting a node state with a type" cn = ConceptNetwork() node1 = Node("Salut.") cn.addNode(node1) state = State(1) cn.addState(state) state.setNodeActivationValue(100, "Salut.","basic") self.assertEqual(100, state.getNodeActivationValue("Salut.","basic"))
def testGetNodeStateTyped(self): "Test getting a node state with a type" cn = ConceptNetwork() node1 = Node("Salut.") cn.addNode(node1) state = State(1) cn.addState(state) state.setNodeActivationValue(100, "Salut.", "basic") self.assertEqual(100, state.getNodeActivationValue("Salut.", "basic"))
def testCoOccLink(self): "Twice the same link -> its co-occurrence is incremented" conceptNetwork = ConceptNetwork() nodeFrom = Node("from") nodeTo = Node("to") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo) conceptNetwork.addLink(nodeFrom, nodeTo) link = conceptNetwork.addLink(nodeFrom, nodeTo) self.assertEqual(2, link.getCoOcc())
def testFastPropagation(self): "Test the propagation" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100,"From","basic") conceptNetwork.fastPropagateActivations(state,2) self.assertEqual(True,state.getNodeActivationValue("To1") > 50)
def testFastPropagation(self): "Test the propagation" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100, "From", "basic") conceptNetwork.fastPropagateActivations(state, 2) self.assertEqual(True, state.getNodeActivationValue("To1") > 50)
def testConceptNetworkGetNodeTyped(self): "Test getting a node with a type" class TestNode(Node): __type = "test" __decay = 35 def __init__(self, symbol, occ = 1): Node.__init__(self, symbol, occ=occ) def getTypeName(self): return self.__type def getDecay(self): return self.__decay cn = ConceptNetwork() node1 = TestNode("Salut.") cn.addNode(node1) self.assertEqual(node1, cn.getNode("Salut.","test")) self.assertEqual("test", node1.getTypeName())
def testAging(self): """See if a old node state is removed when too old. When a NodeState has more than 50 propagations, and that it is set to zero, it has to disappear from the state of the ConceptNetwork.""" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100,"From","basic") for i in range(0,51): conceptNetwork.fastPropagateActivations(state,2) state.setNodeActivationValue(0, "From", "basic") self.assertRaises(KeyError,state.nodeState.__getitem__,("From","basic"))
def testAging(self): """See if a old node state is removed when too old. When a NodeState has more than 50 propagations, and that it is set to zero, it has to disappear from the state of the ConceptNetwork.""" conceptNetwork = ConceptNetwork() nodeFrom = Node("From") nodeTo1 = Node("To1") conceptNetwork.addNode(nodeFrom) conceptNetwork.addNode(nodeTo1) conceptNetwork.addLink(nodeFrom, nodeTo1) state = State(1) conceptNetwork.addState(state) state.setNodeActivationValue(100, "From", "basic") for i in range(0, 51): conceptNetwork.fastPropagateActivations(state, 2) state.setNodeActivationValue(0, "From", "basic") self.assertRaises(KeyError, state.nodeState.__getitem__, ("From", "basic"))
def testConceptNetworkGetNodeTyped(self): "Test getting a node with a type" class TestNode(Node): __type = "test" __decay = 35 def __init__(self, symbol, occ=1): Node.__init__(self, symbol, occ=occ) def getTypeName(self): return self.__type def getDecay(self): return self.__decay cn = ConceptNetwork() node1 = TestNode("Salut.") cn.addNode(node1) self.assertEqual(node1, cn.getNode("Salut.", "test")) self.assertEqual("test", node1.getTypeName())
class Ector: "The ECTOR class" def __init__(self, botname="Ector", username="******"): self.botname = botname self.username = username if os.path.exists("cn.pkl"): f = open("cn.pkl", "r") self.cn = pickle.load(f) f.close() else: self.cn = ConceptNetwork() self.loadUserState() self.prevsentences = "hello" def dump(self): """Save ECTOR. Save the ConceptNetwork in cn.pkl, and the state in usernameState.pkl""" # Save the ConceptNetwork f = open("cn.pkl", "w") self.cn.dump(f) f.close() # Save username's state if self.username: filename = self.__getStateId() f = open(filename, "w") state = self.cn.getState(self.username) pickle.dump(state, f) f.close() def showStatus(self): """Show Ector's status (ConceptNetwork stats, states)""" self.cn.showNodes() self.cn.showStates() def __getStateId(self): """Create a state id from the username""" return self.username + "_state.pkl" def setUser(self, username): """Change user's name. Create a new state, if it does not exist. """ self.username = username try: self.cn.getState(username) except: self.loadUserState() def loadUserState(self): """Load the state matching username""" if self.username: filename = self.__getStateId() if os.path.exists(filename): f = open(filename, "r") state = pickle.load(f) f.close() else: state = State(self.username) self.cn.addState(state) def addEntry(self, entry): """Add an entry into the Concept Network of Ector. Add an entry into the Concept Network of Ector. An entry may be constituted from several sentences. When file is not NULL, it is taken instead utterer. - entry entry to add Return the last sentenceNode of the entry. """ state = self.cn.getState(self.username) e = Entry(entry, self.username, self.botname) sentences = e.getSentences() lastSentenceNode = None #print "sentence received is", sentences if "Wrong." in sentences[0]: sentences = sentences[1:len(sentences)] for sentence in sentences: sentenceNode = self.addSentence(sentence) state.fullyActivate(sentence, "sentence") if lastSentenceNode: self.cn.addLink(lastSentenceNode, sentenceNode) lastSentenceNode = sentenceNode self.prevsentences = sentences print lastSentenceNode return lastSentenceNode for sentence in sentences: sentenceNode = self.addSentence(sentence) state.fullyActivate(sentence, "sentence") if lastSentenceNode: self.cn.addLink(lastSentenceNode, sentenceNode) lastSentenceNode = sentenceNode self.prevsentences = sentences return lastSentenceNode def addSentence(self, sentence): """Add a sentence into the Concept Network of Ector. Add a sentence into the Concept Network of Ector. Adds its tokens too. /* except when the sentence already exists (in this case, the occurrence is not incremented, nor are expression created -this should lead to the creation of expressions identical to the sentence). */ In the case where file exist, username is not taken into account, but file is, and is of type "file". - sentence sentence to add Return the node of the sentence added.""" state = self.cn.getState(self.username) # Activate the utterer, and add it to the concept network uttererNode = UttererNode(self.username) self.cn.addNode(uttererNode) state.fullyActivate(self.username, "utterer") # Add the sentence node to the concept network. sentenceNode = SentenceNode(sentence) self.cn.addNode(sentenceNode) #state.setNodeActivationValue(100, sentence, "sentence") state.fullyActivate(sentence, "sentence") # TODO: if the occurrence of the sentence node is only 1, # compute the expressions pass # Link it to the utterer node. self.cn.addBidirectionalLink(uttererNode, sentenceNode) # Add the tokens to the concept network, link them to the sentence e = Entry("None") tokens = e.getTokens(sentence) beginning = 1 middle = 0 end = 0 previousTokenNode = None i = 0 for token in tokens: i += 1 if i == len(tokens): end = 1 # Add the token node to the concept network tokenNode = TokenNode(token, 1, beginning, middle, end) self.cn.addNode(tokenNode) state.fullyActivate(token, "token") if beginning: beginning = 0 middle = 1 if middle and i == len(tokens) - 1: middle = 0 end = 1 # Link it to the previous node if previousTokenNode: self.cn.addLink(previousTokenNode, tokenNode) previousTokenNode = tokenNode # Link it to the sentence node self.cn.addBidirectionalLink(tokenNode, sentenceNode) return sentenceNode def propagate(self, times=1): """Propagate the activation in the state of the utterer""" state = self.cn.getState(self.username) for i in range(times): self.cn.fastPropagateActivations(state) def getActivatedSentenceNode(self): """Get one of the most activated sentences""" state = self.cn.getState(self.username) maximumAV = state.getMaximumActivationValue(self.cn, "sentence") sentences = state.getActivatedTypedNodes(self.cn, "sentence", maximumAV - 10) # TODO: compute a temperature according the state's activations temperature = Temperature(60) if sentences: sentenceNode = temperature.chooseWeightedItem(sentences) return sentenceNode else: return '' def showState(self, stateID): """Show the state matching stateID""" state = self.cn.getState(stateID) state.showNodes() def showLinks(self, stateId=None): """Show the links of the concept network, using stateID""" if stateId == None: stateId = self.username state = self.cn.getState(stateId) self.cn.showLinks(stateId) def generateForward(self, phrase, temperature): """Generate the end of a sentence, adding tokens to the list of token nodes in phrase.""" state = self.cn.getState(self.username) outgoingLinks = phrase[-1].outgoingLinks nextNodes = [] for link in outgoingLinks: toNode = link.getNodeTo() if toNode.getTypeName() == "token": av = state.getNodeActivationValue(toNode.getSymbol(), "token") if av == 0: av = 1 nbRepet = phrase.count(toNode) length = len(toNode.getSymbol()) # If the node is not present more than 3 times if nbRepet * length <= 5 * 3: repetition = 1 + nbRepet * nbRepet * length nextNodes += [(toNode, link.getCoOcc() * av / repetition)] # Stop condition if len(nextNodes) == 0: return phrase # Choose one node among the tokens following the one at the end # of the phrase chosenToken = temperature.chooseWeightedItem(nextNodes) phrase += [chosenToken] return self.generateForward(phrase, temperature) def generateBackward(self, phrase, temperature): """Generate the beginning of a sentence, adding tokens to the list of token nodes in phrase.""" state = self.cn.getState(self.username) incomingLinks = phrase[0].incomingLinks # previousNodes = [(link.getNodeFrom(), link.getCoOc()) # for link in incomingLinks # if link.getNodeFrom().getTypeName() == "token"] previousNodes = [] for link in incomingLinks: fromNode = link.getNodeFrom() if fromNode.getTypeName() == "token": av = state.getNodeActivationValue(fromNode.getSymbol(), "token") if av == 0: av = 1 nbRepet = phrase.count(fromNode) length = len(fromNode.getSymbol()) # If the node is not present more than 3 times if nbRepet * length <= 5 * 3: repetition = 1 + nbRepet * nbRepet * length previousNodes += [(link.getNodeFrom(), link.getCoOcc() * av)] # Stop condition if len(previousNodes) == 0: return phrase # Choose one node among the tokens preceding the one at the beginning # of the phrase chosenToken = temperature.chooseWeightedItem(previousNodes) phrase = [chosenToken] + phrase return self.generateBackward(phrase, temperature) def generateSentence(self, debug=False): """Get one node, generate a sentence from it forwards to the end of the sentence, and then generate backwards to the beginning of the sentence. Return a tuple containing the generated sentence as a string and the nodes of the sentence.""" # Choose a token node among the most activated state = self.cn.getState(self.username) maximumAV = state.getMaximumActivationValue(self.cn, "token") tokens = state.getActivatedTypedNodes(self.cn, "token", maximumAV - 10) # TODO: compute a temperature according the state's activations temperature = Temperature(60) chosenToken = temperature.chooseWeightedItem(tokens) phrase = [chosenToken] # Generate forwards phrase = self.generateForward(phrase, temperature) # Generate backwards phrase = self.generateBackward(phrase, temperature) strPhrase = [token.getSymbol() for token in phrase] if debug: return (("_".join(strPhrase)) + " (%s)" % chosenToken.getSymbol(), phrase) else: return (self.beautifySentence(" ".join(strPhrase)), phrase) def beautifySentence(self, sentence): """Beautify a string, which is a generated sentence, where tokens (words and punctuation) are separated by spaces. No need to get a space between a word and a comma.""" sentence = sentence.replace(" , ", ", ") sentence = sentence.replace(" .", ".") sentence = sentence.replace(" : ", ": ") sentence = sentence.replace(" !", "!") sentence = sentence.replace(" ?", "?") sentence = sentence.replace(" ' ", "'") sentence = sentence.replace(" ( ", " (") sentence = sentence.replace(" )", ")") sentence = sentence.replace(" - ", "-") return sentence def cleanState(self): """Clean the not activated nodes states in the state""" state = self.cn.getState(self.username) state.clean()
def testConceptNetworkGetNode(self): "Test getting a node from a Concept Network after adding it" cn = ConceptNetwork() node1 = Node("Salut") cn.addNode(node1) self.assertEqual(node1, cn.getNode("Salut","basic"))
def testConceptNetworkGetNode(self): "Test getting a node from a Concept Network after adding it" cn = ConceptNetwork() node1 = Node("Salut") cn.addNode(node1) self.assertEqual(node1, cn.getNode("Salut", "basic"))
class Ector: "The ECTOR class" def __init__(self,botname="Ector",username="******"): self.botname = botname self.username = username if os.path.exists("cn.pkl"): f = open("cn.pkl","r") self.cn = pickle.load(f) f.close() else: self.cn = ConceptNetwork() self.loadUserState() def dump(self): """Save ECTOR. Save the ConceptNetwork in cn.pkl, and the state in usernameState.pkl""" # Save the ConceptNetwork f = open("cn.pkl","w") self.cn.dump(f) f.close() # Save username's state if self.username: filename = self.__getStateId() f = open(filename,"w") state = self.cn.getState(self.username) pickle.dump(state,f) f.close() def showStatus(self): """Show Ector's status (ConceptNetwork stats, states)""" self.cn.showNodes() self.cn.showStates() def __getStateId(self): """Create a state id from the username""" return self.username + "_state.pkl" def setUser(self,username): """Change user's name. Create a new state, if it does not exist. """ self.username = username try: self.cn.getState(username) except: self.loadUserState() def loadUserState(self): """Load the state matching username""" if self.username: filename = self.__getStateId() if os.path.exists(filename): f = open(filename,"r") state = pickle.load(f) f.close() else: state = State(self.username) self.cn.addState(state) def addEntry(self,entry): """Add an entry into the Concept Network of Ector. Add an entry into the Concept Network of Ector. An entry may be constituted from several sentences. When file is not NULL, it is taken instead utterer. - entry entry to add Return the last sentenceNode of the entry. """ state = self.cn.getState(self.username) e = Entry(entry, self.username, self.botname) sentences = e.getSentences() lastSentenceNode = None for sentence in sentences: sentenceNode = self.addSentence(sentence) state.fullyActivate(sentence, "sentence") if lastSentenceNode: self.cn.addLink(lastSentenceNode,sentenceNode) lastSentenceNode = sentenceNode return lastSentenceNode def addSentence(self,sentence): """Add a sentence into the Concept Network of Ector. Add a sentence into the Concept Network of Ector. Adds its tokens too. /* except when the sentence already exists (in this case, the occurrence is not incremented, nor are expression created -this should lead to the creation of expressions identical to the sentence). */ In the case where file exist, username is not taken into account, but file is, and is of type "file". - sentence sentence to add Return the node of the sentence added.""" state = self.cn.getState(self.username) # Activate the utterer, and add it to the concept network uttererNode = UttererNode(self.username) self.cn.addNode(uttererNode) state.fullyActivate(self.username, "utterer") # Add the sentence node to the concept network. sentenceNode = SentenceNode(sentence) self.cn.addNode(sentenceNode) #state.setNodeActivationValue(100, sentence, "sentence") state.fullyActivate(sentence, "sentence") # TODO: if the occurrence of the sentence node is only 1, # compute the expressions pass # Link it to the utterer node. self.cn.addBidirectionalLink(uttererNode, sentenceNode) # Add the tokens to the concept network, link them to the sentence e = Entry("None") tokens = e.getTokens(sentence) beginning = 1 middle = 0 end = 0 previousTokenNode = None i = 0 for token in tokens: i += 1 if i == len(tokens): end = 1 # Add the token node to the concept network tokenNode = TokenNode(token, 1, beginning, middle, end) self.cn.addNode(tokenNode) state.fullyActivate(token, "token") if beginning: beginning = 0 middle = 1 if middle and i == len(tokens) - 1: middle = 0 end = 1 # Link it to the previous node if previousTokenNode: self.cn.addLink(previousTokenNode,tokenNode) previousTokenNode = tokenNode # Link it to the sentence node self.cn.addBidirectionalLink(tokenNode, sentenceNode) return sentenceNode def propagate(self,times=1): """Propagate the activation in the state of the utterer""" state = self.cn.getState(self.username) for i in range(times): self.cn.fastPropagateActivations(state) def getActivatedSentenceNode(self): """Get one of the most activated sentences""" state = self.cn.getState(self.username) maximumAV = state.getMaximumActivationValue(self.cn, "sentence") sentences = state.getActivatedTypedNodes(self.cn, "sentence", maximumAV - 10) # TODO: compute a temperature according the state's activations temperature = Temperature(60) if sentences: sentenceNode = temperature.chooseWeightedItem(sentences) return sentenceNode else: return '' def showState(self, stateID): """Show the state matching stateID""" state = self.cn.getState(stateID) state.showNodes() def showLinks(self, stateId=None): """Show the links of the concept network, using stateID""" if stateId == None: stateId = self.username state = self.cn.getState(stateId) self.cn.showLinks(stateId) def generateForward(self, phrase, temperature): """Generate the end of a sentence, adding tokens to the list of token nodes in phrase.""" state = self.cn.getState(self.username) outgoingLinks = phrase[-1].outgoingLinks nextNodes = [] for link in outgoingLinks: toNode = link.getNodeTo() if toNode.getTypeName() == "token": av = state.getNodeActivationValue(toNode.getSymbol(), "token") if av == 0: av = 1 nbRepet = phrase.count(toNode) length = len(toNode.getSymbol()) # If the node is not present more than 3 times if nbRepet * length <= 5 * 3: repetition = 1 + nbRepet * nbRepet * length nextNodes += [(toNode, link.getCoOcc() * av / repetition)] # Stop condition if len(nextNodes) == 0: return phrase # Choose one node among the tokens following the one at the end # of the phrase chosenToken = temperature.chooseWeightedItem(nextNodes) phrase += [chosenToken] return self.generateForward(phrase, temperature) def generateBackward(self, phrase, temperature): """Generate the beginning of a sentence, adding tokens to the list of token nodes in phrase.""" state = self.cn.getState(self.username) incomingLinks = phrase[0].incomingLinks # previousNodes = [(link.getNodeFrom(), link.getCoOc()) # for link in incomingLinks # if link.getNodeFrom().getTypeName() == "token"] previousNodes = [] for link in incomingLinks: fromNode = link.getNodeFrom() if fromNode.getTypeName() == "token": av = state.getNodeActivationValue(fromNode.getSymbol(), "token") if av == 0: av = 1 nbRepet = phrase.count(fromNode) length = len(fromNode.getSymbol()) # If the node is not present more than 3 times if nbRepet * length <= 5 * 3: repetition = 1 + nbRepet * nbRepet * length previousNodes += [(link.getNodeFrom(), link.getCoOcc() * av)] # Stop condition if len(previousNodes) == 0: return phrase # Choose one node among the tokens preceding the one at the beginning # of the phrase chosenToken = temperature.chooseWeightedItem(previousNodes) phrase = [chosenToken] + phrase return self.generateBackward(phrase, temperature) def generateSentence(self, debug=False): """Get one node, generate a sentence from it forwards to the end of the sentence, and then generate backwards to the beginning of the sentence. Return a tuple containing the generated sentence as a string and the nodes of the sentence.""" # Choose a token node among the most activated state = self.cn.getState(self.username) maximumAV = state.getMaximumActivationValue(self.cn, "token") tokens = state.getActivatedTypedNodes(self.cn,"token", maximumAV - 10) # TODO: compute a temperature according the state's activations temperature = Temperature(60) chosenToken = temperature.chooseWeightedItem(tokens) phrase = [chosenToken] # Generate forwards phrase = self.generateForward(phrase, temperature) # Generate backwards phrase = self.generateBackward(phrase, temperature) strPhrase = [token.getSymbol() for token in phrase] if debug: return (("_".join(strPhrase)) + " (%s)" % chosenToken.getSymbol(), phrase) else: return (self.beautifySentence(" ".join(strPhrase)), phrase) def beautifySentence(self, sentence): """Beautify a string, which is a generated sentence, where tokens (words and punctuation) are separated by spaces. No need to get a space between a word and a comma.""" sentence = sentence.replace(" , ", ", ") sentence = sentence.replace(" .", ".") sentence = sentence.replace(" : ", ": ") sentence = sentence.replace(" !", "!") sentence = sentence.replace(" ?", "?") sentence = sentence.replace(" ' ", "'") sentence = sentence.replace(" ( ", " (") sentence = sentence.replace(" )", ")") sentence = sentence.replace(" - ", "-") return sentence def cleanState(self): """Clean the not activated nodes states in the state""" state = self.cn.getState(self.username) state.clean()