def maxNeighbor(t0):
    toDo = copy.deepcopy(
        t0["root"][2])  #Start the to do list with the kids of root.
    bestTree = t0  #Use the inputs as the best tree and best score.
    bestScore = ps.scoreTree(t0)

    print "Neighbors:"
    while len(toDo) > 0:
        nextNode = toDo.pop()
        toDo.extend(copy.deepcopy(t0[nextNode][2]))
        if len(t0[nextNode][2]) > 0:
            t1, t2 = nniNeighbor(t0, nextNode)
            s1 = ps.scoreTree(t1)
            s2 = ps.scoreTree(t2)
            print "\t", convertNewick(t1, "root"), s1
            print "\t", convertNewick(t2, "root"), s2
            if s1 < bestScore:
                print s1, bestScore
                bestTree = t1
                bestScore = s1
            if s2 < bestScore:
                print s2, bestScore
                bestTree = t2
                bestScore = s2

    return bestTree, bestScore
def maxNeighbor(t0):
	import copy
	import parsimonyScore as ps
	toDo = copy.deepcopy(t0["root"][2])     #Start the to do list with the kids of root.
	bestTree = t0  #Use the inputs as the best tree and best score.
	bestScore = ps.scoreTree(t0)

	print "Neighbors:"
	while len(toDo) > 0:
		nextNode = toDo.pop()
		toDo.extend(copy.deepcopy(t0[nextNode][2]))
		if len(t0[nextNode][2]) > 0: 
			t1, t2 = nniNeighbor(t0,nextNode)
			s1 = ps.scoreTree(t1)
			s2 = ps.scoreTree(t2)            
			print "\t", convertNewick(t1, "root"), s1
			print "\t", convertNewick(t2, "root"), s2
			if s1 < bestScore and bestTree != t1:
				#print s1, bestScore
				bestTree = t1
				bestScore = s1
			if s2 < bestScore and bestTree != t2:
				#print s2, bestScore
				bestTree = t2
				bestScore = s2
			if s1 == bestScore and bestTree != t1:
				#print s1, bestScore,"E"
				bestTree = t1
				bestScore = s1
			if s2 == bestScore and bestTree != t2:
				#print s2, bestScore,"E"
				bestTree = t2
				bestScore = s2

	return bestTree, bestScore
def treeSample(sequences):
	import parsimonyScore as ps
	steps = 0
	bestTree = buildRandomTree(sequences)
	bestScore = ps.scoreTree(bestTree)
	for iteration in range(1000):
		## choose random tree
		newTree = buildRandomTree(sequences)
		## score the tree
		newScore = ps.scoreTree(newTree)
		#print convertNewick(newTree,"root")
		#print newScore
		if newScore < bestScore:
			bestScore = newScore
			bestTree = newTree
			steps += 1
	return steps,bestTree,bestScore
def treeSample(sequences):
    bestTree = buildRandomTree(sequences)
    bestScore = ps.scoreTree(bestTree)
    #For 1000 steps:
    for i in range(100):
        #Choose randomly a tree.
        newTree = buildRandomTree(sequences)
        #Score the tree.
        newScore = ps.scoreTree(newTree)

        #We'll add in a print to see what's going on:
        print convertNewick(newTree, "root"), newScore

        #If better score than <tt>bestScore</tt>,
        if newScore < bestScore:
            #choose it to be the current tree
            bestScore = newScore
            bestTree = newTree
    #Return best tree and score.
    return bestTree, bestScore
def treeSearch(sequences):
    #Choose randomly a tree to be bestSoFar.
    bestSoFar = buildRandomTree(sequences)
    #Score the tree, bestSoFar.
    bestScore = ps.scoreTree(bestSoFar)
    print "Start:", convertNewick(bestSoFar, "root"), bestScore
    #For 1000 steps:
    for i in range(5):
        #   Make a list of all the NNI neighbors of bestSoFar
        neighborBest, neighborScore = maxNeighbor(bestSoFar)
        #   if any of the NNI neighbors of bestSoFar have better score,
        if neighborScore < bestScore:
            #       choose it to be the current tree
            bestSoFar = neighborBest
            bestScore = neighborScore

        print "Best so far: ", convertNewick(bestSoFar, "root"), bestScore
    return bestSoFar, bestScore
if __name__ == "__main__":
    #Sample tree:
    tree = {
        "root": ["", "", ["i1", "i2"]],
        "i1": ["root", "", ["a", "i3"]],
        "i2": ["root", "", ["b", "c"]],
        "i3": ["i1", "", ["d", "e"]],
        "a": ["i1", "T A A A A", []],
        "b": ["i2", "A A A A G", []],
        "c": ["i2", "C A A A T", []],
        "d": ["i3", "A A A A A", []],
        "e": ["i3", "T A A A A", []]
    }

    print "\nTest tree:", convertNewick(tree, "root"), ":", ps.scoreTree(tree)

    #Sample list of (species, sequence) pairs:
    seqList = [("ape", "A A A A A"), ("baboon", "A A A A G"),
               ("chimp", "C A A A A"), ("dog", "T G G G G"),
               ("elephant", "T G A C A"), ("fox", "A A G G C")]

    #Test the tree sampling function:
    bestTree, bestScore = treeSample(seqList)
    print "\nBest from sample:", convertNewick(bestTree,
                                               "root"), ":", bestScore

    print "\n"
    t, s = treeSearch(seqList)
    print convertNewick(t, "root"), s