簡體   English   中英

在Networkx中添加節點時在Python NumPy中取整

[英]Rounding in Python NumPy when adding nodes in Networkx

我從哪里得到尾隨0或9? 我檢查每一步都沒有出現舍入問題,並且得到了正確的結果。 但是,當我將此數字添加到圖形中時,會出現舍入問題。

我的完整代碼如下:

from __future__ import division
from math import sqrt
import networkx as nx
import numpy as np
from decimal import Decimal

n=4   #n is the nummber of steps in the graph.
a = np.array([ 1.1656,  1.0125,  0.8594])

g=nx.DiGraph() #I initiate the graph

#f2 checks for equal nodes and removes them
def f2(seq): 
    checked = []
    for e in seq:
        if (e not in checked):
            checked.append(e)
    return np.asarray(checked)

root = np.array([1])
existing_nodes = np.array([1])
previous_step_nodes = np.array([1])
nodes_to_add =np.empty(0)
clean = np.array([1])

for step in range(1,n):
    nodes_to_add=np.empty(0)
    for values in previous_step_nodes:
        nodes_to_add = np.append(nodes_to_add,values*a)

    print "--------"
    print "*****nodes to add ****" + str(f2(np.round(nodes_to_add,4)))
    print "clean = " + str(clean) + "\n"
    #Up to here, the code generates the nodes I will need 

    # This for loop makes the edges and adds the nodes.
    for node in clean:
        for next_node in np.round(node*a,4):
            print str(node ) + "     "  + str( next_node)
            g.add_edge(np.round(node,4), np.round(next_node,4))
#            g.add_edge(Decimal(np.round(node,4)).quantize(Decimal('1.0000')), Decimal(np.round(next_node,4)).quantize(Decimal('1.0000')))

    previous_step_nodes = f2(nodes_to_add)
    clean = f2(np.round(previous_step_nodes,4))
#    g.add_nodes_from(clean)

    print "\n step" + str(step) + " \n"
    print " Current Step :" + "Number of nodes = " + str(len(f2(np.round(previous_step_nodes,4))))
    print clean

print "How many nodes are there ? " +str(len(g.nodes()))

這段代碼可以正常工作,並打印出非常整潔的圖形描述,這正是我想要的。 但是,當我打印節點列表時,要檢查圖僅包含我需要的節點數,我得到:

How many nodes are there ? 22
[1, 0.88109999999999999, 1.0143, 1.038, 0.74780000000000002, 
1.1801999999999999, 1.3755999999999999, 1.0142, 0.8609, 
0.88100000000000001, 0.85940000000000005, 1.1656,
1.1950000000000001, 1.0125, 1.5835999999999999, 1.0017, 
0.87009999999999998, 1.1676,
0.63480000000000003, 0.73860000000000003, 1.3586, 1.0251999999999999]

這顯然是使我的程序無用的問題。 0.88109999999999999和0.88100000000000001是同一節點。

因此,在檢查了數天的stackoverflow之后,我得出一個結論,解決該問題的唯一方法是使用Decimal()。 所以,我更換了:

g.add_edge(np.round(node,4), np.round(next_node,4))

g.add_edge(Decimal(np.round(node,4)).quantize(Decimal('1.0000')), 
           Decimal(np.round(next_node,4)).quantize(Decimal('1.0000')))

但是,結果卻不是我所期望的:因為

0.88109999999999999 = 0.8811
0.88100000000000001 =0.8810, 

因此Python仍將它們視為不同的數字。

理想情況下,我寧願不使用Decimal()來使代碼復雜化,並且希望截斷小數,以便0.88109999999999999 = 0.88100000000000001 = 0.8810,但是我不知道如何解決此問題。

感謝您的答復,我更新了我的代碼。 我建議使用f2作為:

def f2(seq): 
    near_equal = lambda x, y: abs(x - y) < 1.e-5
    checked = []
    for e in seq:
        if all([not near_equal(e, x) for x in checked]):
            checked.append(e)
    return np.asarray(checked)

並且我刪除了所有的numpy.round(),因為如果可以刪除“相似”的節點,那么我根本不需要任何舍入。

但是,python仍然無法區分節點:

g.nodes()打印出23個節點,當應該只有20個時:

有多少個節點? 23

[0.63474091729864457, 0.73858020442900385, 0.74781245698436638,
 0.85940689107605128, 0.86088399667008808, 0.86088399667008819,
 0.87014947721450187, 0.88102634567968308, 0.88102634567968319,
 1, 1.00171875, 1.0125, 1.0142402343749999, 1.02515625,
 1.0379707031249998, 1.1655931089239486, 1.1675964720799117,
 1.180163022785498, 1.1949150605703167, 1.358607295570996,
 1.3755898867656333, 1.3755898867656335, 1.5835833014513552]

這是因為:0.86088399667008808、0.86088399667008819; 0.88102634567968308、0.88102634567968319和1.3755898867656333、1.3755898867656335仍被視為不同的節點。

完整代碼:

from __future__ import division
from math import sqrt
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt

mu1 = 0.05; sigma1= 0.25
n=4

a0=1
a1 = 1 + mu1/n + sigma1*sqrt(3)/sqrt(2*n)
a2 = 1 + mu1/n
a3 = 1 + mu1 /n - sigma1*sqrt(3)/sqrt(2*n)
a = np.array([a1,a2,a3])

print " a = " + str(a)

g=nx.DiGraph() #I initiate the graph

def f2(seq): 
    near_equal = lambda x, y: abs(x - y) < 1.e-5
    checked = []
    for e in seq:
        if all([not near_equal(e, x) for x in checked]):
            checked.append(e)
    return np.asarray(checked)

root = np.array([1])
existing_nodes = np.array([1])
previous_step_nodes = np.array([1])
nodes_to_add =np.empty(0)
clean = np.array([1])

print "________________This Makes the Nodes____________________________________"
for step in range(1,n):
    nodes_to_add=np.empty(0)
    for values in previous_step_nodes:
        nodes_to_add = np.append(nodes_to_add,values*a)
    print "--------"    
    print "*****nodes to add ****" + str(f2(nodes_to_add))
    print "clean = " + str(clean) + "\n"
    #Up to here, the code generates the nodes I will need 

    # This for loop makes the edges and adds the nodes.
    for node in clean:
        for next_node in node*a:
            print str(node ) + "     "  + str( next_node)
            g.add_edge(node, next_node)

    previous_step_nodes = f2(nodes_to_add)
    clean = f2(previous_step_nodes)
#    g.add_nodes_from(clean)

    print "\n step" + str(step) + " \n"
    print " Current Step :" + "Number of nodes = " + str(len(f2(previous_step_nodes)))
    print clean

print "______________End of the Nodes_________________________________"
print "How many nodes are there ? " +str(len(g.nodes()))
print sorted(g.nodes())

結果:

有多少個節點? 23 0.63474091729864457,0.73858020442900385,0.74781245698436638,0.85940689107605128,0.86088399667008808,0.86088399667008819,0.87014947721450187,0.88102634567968308,0.88102634567968319,1,1.00171875,1.0125,1.0142402343749999,1.02515625,1.0379707031249998,1.1655931089239486,1.1675964720799117,1.180163022785498,1.1949150605703167,1.358607295570996,1.3755898867656333,1.3755898867656335,1.5835833014513552]

依靠浮點數之間的完全相等通常不是一個好主意,因為用於生成數字的同一組輸入會由於浮點表示形式,數學運算的順序等不同而產生不同的結果。

除非您要處理的節點非常接近,否則可以使用以下類似的方法修改f2函數(您可能希望將公差設為變量):

def f2(seq): 
    near_equal = lambda x, y: abs(x - y) < 1.e-8
    checked = []
    for e in seq:
        if all([not near_equal(e, x) for x in checked]):
            checked.append(e)
    return np.asarray(checked)

請注意,如果浮點數完全相等,則獲取刪除了重復項的列表的更簡單方法是

nodes_without_dupes = list(set(nodes_to_add)) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM