Подтвердить что ты не робот

Передача строки в agege в файле agraph.py. Проблема с networkx и pygraphviz

Учитывая этот начальный график:

import networkx as nx
G=nx.MultiGraph()
fromnodes=[0,0,1,1,1,1,1,2,3,4,5,5,5,7,8,9,10]
tonodes=[1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
dupedgeind=0
for x,y in zip(fromnodes,tonodes):
    if G.has_edge(x,y):
        dupedgeind=dupedgeind+1
        G.add_edge(x,y,key=dupedgeind)
    else:
        dupedgeind=0
        G.add_edge(x,y,key=dupedgeind)

Может ли кто-нибудь воссоздать эту ошибку?

pos=nx.nx_agraph.pygraphviz_layout(G,prog='sfdp')

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\networkx\drawing\nx_agraph.py", line 262, in pygraphviz_layout
    A=to_agraph(G)
  File "C:\Python27\lib\site-packages\networkx\drawing\nx_agraph.py", line 155, in to_agraph
    A.add_edge(u,v,key=str(key),**str_edgedata)
  File "C:\Python27\lib\site-packages\pygraphviz\agraph.py", line 484, in add_edge
    eh = gv.agedge(self.handle, uh, vh, key, _Action.find)
KeyError: 'agedge: no key'

Проблема имеет какое-то отношение к вызову функции grungeviz agege, похоже, не соответствует формату параметра key; когда я меняю (строка 480 из agraph.py):

...
    eh = gv.agedge(self.handle, uh, vh, key , _Action.create)
...

к

...
    eh = gv.agedge(self.handle, uh, vh, "a_string" , _Action.create)
...

он больше не терпит неудачу (но теряет метки клавиш).

Есть ли очевидный способ исправить этот (так что значения параметра key сохраняются) ?. Ничего, что я пытаюсь, похоже, работает.

Каковы наиболее разумные последующие шаги отладки?


Из здесь, кажется, что функция c agege (которую я не вижу в бинарнике .pyd) имеет следующий формат:

*agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)

где ключ char *name является ключом.

Я не могу понять, почему он не примет dtpe str как в начальной ошибке.


Примечание:

networkx - 1.11, pygraphviz - 1.3.1  (установлен из http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygraphviz) Python 2.7 (32bit - не поддерживается через python (x, y)) в Windows 7 (64-разрядная версия), GraphViz - 2.38

Я также видел, что этот вопрос возникает в этих вопросах:


ОБНОВЛЕНИЕ 1

Я попытался настроить вход key на функцию agege на несколько вариантов массивов char (например, (ct.c_char_p * len(key))(key) (ct - модуль ctypes) на основе this). Это изменяет ошибку на:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\networkx\drawing\nx_agraph.py", line 262, in pygraphviz_layout
    A=to_agraph(G)
  File "C:\Python27\lib\site-packages\networkx\drawing\nx_agraph.py", line 155, in to_agraph
    A.add_edge(u,v,str(key),**str_edgedata)
  File "C:\Python27\lib\site-packages\pygraphviz\agraph.py", line 482, in add_edge
    eh = gv.agedge(self.handle, uh, vh, (ct.c_char_p * len(key))(key), _Action.create)
TypeError: in method 'agedge', argument 4 of type 'char *'

ОБНОВЛЕНИЕ 2

Я могу заставить его запустить (но не возвращать мультиграфию), если я это сделаю:

В agraph.py заменить строку

eh = gv.agedge(self.handle, uh, vh, key , _Action.create)

с

    try:
        # new
        if key==0:
            eh = gv.agedge(self.handle, uh, vh, str(0), _Action.create)
        else:
            eh = gv.agedge(self.handle, uh, vh, str(1), _Action.create)

Я не знаю, почему просто кастинг в строку str(key) не работает.

ОБНОВЛЕНИЕ 3 - ИЗМЕНИТЬ с помощью функции

Здесь найдена функция - https://github.com/ellson/graphviz/blob/master/lib/cgraph/edge.c

Agedge_t *agedge(Agraph_t * g, Agnode_t * t, Agnode_t * h, char *name,
int cflag)
{
    Agedge_t *e;
    IDTYPE id;
    int have_id;
    have_id = agmapnametoid(g, AGEDGE, name, &id, FALSE);
    if (have_id || ((name == NILstr) && (NOT(cflag) || agisstrict(g)))) {
        /* probe for pre-existing edge */
        Agtag_t key;
        key = Tag;
        if (have_id) {
            key.id = id;
            key.objtype = AGEDGE;
        } else {
            key.id = key.objtype = 0;
        }
        /* might already exist locally */
        e = agfindedge_by_key(g, t, h, key);
        if ((e == NILedge) && agisundirected(g))
            e = agfindedge_by_key(g, h, t, key);
        if (e)
            return e;
        if (cflag) {
            e = agfindedge_by_key(agroot(g), t, h, key);
            if ((e == NILedge) && agisundirected(g))
                e = agfindedge_by_key(agroot(g), h, t, key);
            if (e) {
                subedge(g,e);
                return e;
            }
        }
}

ОБНОВЛЕНИЕ 4:

Источник ошибки находится в этот файл pygraphviz, graphviz_wrap.c, строка 3921:

SWIGINTERN PyObject *_wrap_agedge(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
    PyObject *resultobj = 0;
    Agraph_t *arg1 = (Agraph_t *) 0 ;
    Agnode_t *arg2 = (Agnode_t *) 0 ;
    Agnode_t *arg3 = (Agnode_t *) 0 ;
    char *arg4 = (char *) 0 ;
    int arg5 ;
    void *argp1 = 0 ;
    int res1 = 0 ;
    void *argp2 = 0 ;
    int res2 = 0 ;
    void *argp3 = 0 ;
    int res3 = 0 ;
    int res4 ;
    char *buf4 = 0 ;
    int alloc4 = 0 ;
    int val5 ;
    int ecode5 = 0 ;
    PyObject * obj0 = 0 ;
    PyObject * obj1 = 0 ;
    PyObject * obj2 = 0 ;
    PyObject * obj3 = 0 ;
    PyObject * obj4 = 0 ;
    Agedge_t *result = 0 ;

    if (!PyArg_ParseTuple(args, char*)"OOOOO:agedge",&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; 
    res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Agraph_t, 0 | 0 );
    if (!SWIG_IsOK(res1)) {
        SWIG_exception_fail(SWIG_ArgError(res1), "in method '""agedge" "', argument " "1"" of type '" "Agraph_t *""'");
    }
    arg1 = (Agraph_t *)(argp1);
    res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_Agnode_t, 0 | 0 );
    if (!SWIG_IsOK(res2)) {
        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "agedge" "', argument " "2"" of type '" "Agnode_t *""'");
    }
    arg2 = (Agnode_t *)(argp2);
    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_Agnode_t, 0 | 0 );
    if (!SWIG_IsOK(res3)) {
        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "agedge" "', argument " "3"" of type '" "Agnode_t *""'");
    }
    arg3 = (Agnode_t *)(argp3);
    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
    if (!SWIG_IsOK(res4)) {
        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "agedge" "', argument " "4"" of type '" "char *""'");
    }
    arg4 = (char *)(buf4);
    ecode5 = SWIG_AsVal_int(obj4, &val5);
    if (!SWIG_IsOK(ecode5)) {
        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "agedge" "', argument " "5"" of type '" "int""'");
    }
    arg5 = (int)(val5);
    {
        result = (Agedge_t *)agedge(arg1,arg2,arg3,arg4,arg5);
        if (!result) {
            PyErr_SetString(PyExc_KeyError,"agedge: no key");
            return NULL;
        }
    }
    resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Agedge_t, 0 | 0 );
    if (alloc4 == SWIG_NEWOBJ) free((char*)buf4);
    return resultobj;
    fail:
        if (alloc4 == SWIG_NEWOBJ) free((char*)buf4);
        return NULL;
}

Или, в этот, graphviz.i, строка 68.

В любом случае, кажется, что строка ошибки "agege: no key" возвращается, если agedge сбой по какой-либо причине... Возможно, это что-то связано с SWIG.

4b9b3361

Ответ 1

Попробуйте изменить имя переменной из "ключа" на что-то еще, например "temp_key". Я имею в виду, что возможно, что вы (или любой ранее импортированный модуль) объявили переменную типа "ключ", отличную от строки...?

Очевидно, если он работает:

eh = gv.agedge(self.handle, uh, vh, key , _Action.create)

не работает, но работает:

eh = gv.agedge(self.handle, uh, vh, "key" , _Action.create)

не дает вам никаких проблем, это может быть только относительный тип переменной "ключ".. вы пробовали это:

eh = gv.agedge(self.handle, uh, vh, str(key) , _Action.create)

или eh = gv.agedge(self.handle, uh, vh, unicode(key) , _Action.create)

Интегрируйте str()/unicode() в свой исходный код:

import networkx as nx
G=nx.MultiGraph()
fromnodes=[0,0,1,1,1,1,1,2,3,4,5,5,5,7,8,9,10]
tonodes=[1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
dupedgeind=0
for x,y in zip(fromnodes,tonodes):
    if G.has_edge(x,y):
        dupedgeind=dupedgeind+1
        G.add_edge(x,y,key=str(dupedgeind))
        #G.add_edge(x,y,key=unicode(dupedgeind))
    else:
        dupedgeind=0
        G.add_edge(x,y,key=str(dupedgeind))
        #G.add_edge(x,y,key=unicode(dupedgeind))

обе версии (версия str и unicode) отлично работают в Linux.

С наилучшими пожеланиями

Ответ 2

Моя среда python2.7 32-разрядная версия для Windows 7 64-битная, и я делаю проект, который использует pygraphviz/graphviz для рисования FSM. Во время использования я также столкнулся с той же ошибкой

KeyError: 'agege: no key'

В этом проекте есть закрытая проблема, указывающая, что ошибка появляется только при переходе, где исходное состояние совпадает с состоянием адресата. Или в более простых терминах, когда состояние указывает на себя.

Я могу подтвердить, что я получаю ошибку, когда есть состояния, указывающие на себя, а если я создаю график, который не имеет таких переходов, он работает и корректно создает файл изображения (.png) в моем случае.

https://github.com/tyarkoni/transitions/issues/133

P.S. Я не думаю, что это требует полного ответа, потому что это не полное решение. Но, к сожалению, у меня недостаточно очков репутации для комментариев.