source: orange/source/orangeom/networkoptimization.cpp @ 3611:68e6e38b778b

Revision 3611:68e6e38b778b, 16.0 KB checked in by janezd <janez.demsar@…>, 6 years ago (diff)
  • fixed a few more casts from TStringValue to PSomeValue
Line 
1/*
2    This file is part of Orange.
3
4    Orange is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    Orange is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with Orange; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18    Author: Miha Stajdohar, 1996--2002
19*/
20
21
22#include "ppp/networkoptimization.ppp"
23
24TNetworkOptimization::TNetworkOptimization()
25{
26    import_array();
27   
28    nVertices = 0;
29    nLinks = 0;
30
31    k = 1;
32    k2 = 1;
33    width = 1000;
34    height = 1000;
35    temperature = sqrt((double)(width*width + height*height)) / 10;
36}
37
38#ifdef _MSC_VER
39#if _MSC_VER < 1300
40template<class T>
41inline T &min(const T&x, const T&y)
42{ return x<y ? x : y; }
43#endif
44#endif
45
46TNetworkOptimization::~TNetworkOptimization()
47{
48    int i;
49    for (i = 0; i < nLinks; i++)
50    {
51        free(links[i]);
52    }
53
54    free(links);
55    free_Carrayptrs(pos);
56}
57
58double TNetworkOptimization::attractiveForce(double x)
59{
60    return x * x / k;
61
62}
63
64double TNetworkOptimization::repulsiveForce(double x)
65{
66    if (x == 0)
67        return k2 / 1;
68
69    return   k2 / x; 
70}
71
72double TNetworkOptimization::cool(double t)
73{
74    return t * 0.96;
75}
76
77void TNetworkOptimization::dumpCoordinates()
78{
79    int rows = nVertices;
80    int columns = 2;
81
82    for (int i = 0; i < rows; i++)
83    {
84        for (int j = 0; j < columns; j++)
85        {
86            cout << pos[i][j] << "  ";
87        }
88
89        cout << endl;
90    }
91}
92
93
94void TNetworkOptimization::random()
95{
96    srand(time(NULL));
97    int i;
98    for (i = 0; i < nVertices; i++)
99    {
100        pos[i][0] = rand() % width;
101        pos[i][1] = rand() % height;
102    }
103}
104
105void TNetworkOptimization::fruchtermanReingold(int steps)
106{
107    /*
108    cout << "nVertices: " << nVertices << endl << endl;
109    dumpCoordinates(pos, nVertices, 2);
110    /**/
111    int i = 0;
112    int count = 0;
113    double kk = 1;
114    double **disp = (double**)malloc(nVertices * sizeof (double));
115
116    for (i = 0; i < nVertices; i++)
117    {
118        disp[i] = (double *)calloc(2, sizeof(double));
119
120        if (disp[i] == NULL)
121        {
122            cerr << "Couldn't allocate memory\n";
123            exit(1);
124        }
125    }
126
127    int area = width * height;
128    k2 = area / nVertices;
129    k = sqrt(k2);
130    kk = 2 * k;
131
132    // iterations
133    for (i = 0; i < steps; i++)
134    {
135        // reset disp
136        int j = 0;
137        for (j = 0; j < nVertices; j++)
138        {
139            disp[j][0] = 0;
140            disp[j][1] = 0;
141        }
142
143        // calculate repulsive force
144        int v = 0;
145        for (v = 0; v < nVertices - 1; v++)
146        {
147            for (int u = v + 1; u < nVertices; u++)
148            {
149                double difX = pos[v][0] - pos[u][0];
150                double difY = pos[v][1] - pos[u][1];
151
152                double dif = sqrt(difX * difX + difY * difY);
153
154                if (dif == 0)
155                    dif = 1;
156
157                if (dif < kk)
158                {
159                    disp[v][0] = disp[v][0] + ((difX / dif) * repulsiveForce(dif));
160                    disp[v][1] = disp[v][1] + ((difY / dif) * repulsiveForce(dif));
161
162                    disp[u][0] = disp[u][0] - ((difX / dif) * repulsiveForce(dif));
163                    disp[u][1] = disp[u][1] - ((difY / dif) * repulsiveForce(dif));
164                }
165            }
166        }
167
168        // calculate attractive forces
169        for (j = 0; j < nLinks; j++)
170        {
171            int v = links[j][0];
172            int u = links[j][1];
173
174            //cout << "v: " << v << " u: " << u << endl;
175
176            // cout << "     v: " << v << " u: " << u << " w: " << edge->weights << endl;
177           
178            double difX = pos[v][0] - pos[u][0];
179            double difY = pos[v][1] - pos[u][1];
180
181            double dif = sqrt(difX * difX + difY * difY);
182
183            if (dif == 0)
184                dif = 1;
185
186            disp[v][0] = disp[v][0] - ((difX / dif) * attractiveForce(dif));
187            disp[v][1] = disp[v][1] - ((difY / dif) * attractiveForce(dif));
188
189            disp[u][0] = disp[u][0] + ((difX / dif) * attractiveForce(dif));
190            disp[u][1] = disp[u][1] + ((difY / dif) * attractiveForce(dif));
191        }
192
193        // limit the maximum displacement to the temperature t
194        // and then prevent from being displaced outside frame
195        for (v = 0; v < nVertices; v++)
196        {
197            double dif = sqrt(disp[v][0] * disp[v][0] + disp[v][1] * disp[v][1]);
198
199            if (dif == 0)
200                dif = 1;
201
202            pos[v][0] = pos[v][0] + ((disp[v][0] / dif) * min(fabs(disp[v][0]), temperature));
203            pos[v][1] = pos[v][1] + ((disp[v][1] / dif) * min(fabs(disp[v][1]), temperature));
204
205            //pos[v][0] = min((double)width,  max((double)0, pos[v][0]));
206            //pos[v][1] = min((double)height, max((double)0, pos[v][1]));
207        }
208
209        temperature = cool(temperature);
210    }
211
212    // free space
213    for (i = 0; i < nVertices; i++)
214    {
215        free(disp[i]);
216    }
217
218    free(disp);
219    //dumpCoordinates();
220}
221
222#include "externs.px"
223#include "orange_api.hpp"
224
225PyObject *NetworkOptimization_new(PyTypeObject *type, PyObject *args, PyObject *keyw) BASED_ON (Orange, "(Graph) -> None") 
226{
227    PyObject *pygraph;
228   
229    if (PyArg_ParseTuple(args, "O:GraphOptimization", &pygraph))
230    {
231        TGraphAsList *graph = &dynamic_cast<TGraphAsList &>(PyOrange_AsOrange(pygraph).getReference());
232
233        if (graph->nVertices < 2)
234          PYERROR(PyExc_AttributeError, "graph has less than two nodes", NULL);
235
236        //return WrapNewOrange(new TGraphOptimization(graph->nVertices, pos, nLinks, links), type);
237        return WrapNewOrange(new TNetworkOptimization(), type);
238    }
239    else
240    {
241        return WrapNewOrange(new TNetworkOptimization(), type);
242    }
243}
244/* ==== Free a double *vector (vec of pointers) ========================== */ 
245void TNetworkOptimization::free_Carrayptrs(double **v)  {
246    free((char*) v);
247}
248
249/* ==== Allocate a double *vector (vec of pointers) ======================
250    Memory is Allocated!  See void free_Carray(double ** )                  */
251double **TNetworkOptimization::ptrvector(long n)  {
252    double **v;
253    v=(double **)malloc((size_t) (n*sizeof(double)));
254    if (!v)   {
255        printf("In **ptrvector. Allocation of memory for double array failed.");
256        exit(0);  }
257    return v;
258}
259
260/* ==== Create Carray from PyArray ======================
261    Assumes PyArray is contiguous in memory.
262    Memory is allocated!                                    */
263double **TNetworkOptimization::pymatrix_to_Carrayptrs(PyArrayObject *arrayin)  {
264    double **c, *a;
265    int i,n,m;
266   
267    n = arrayin->dimensions[0];
268    m = arrayin->dimensions[1];
269    c = ptrvector(n);
270    a = (double *) arrayin->data;  /* pointer to arrayin data as double */
271   
272    for (i = 0; i < n; i++)
273    {
274        c[i] = a + i * m;
275    }
276
277    return c;
278}
279
280void TNetworkOptimization::setGraph(TGraphAsList *graph)
281{
282    cout << "1" << endl; 
283    int v, l;
284    for (l = 0; l < nLinks; l++)
285    {
286        free(links[l]);
287    }
288    cout << "2" << endl; 
289    free(links);
290    cout << "3" << endl; 
291    free_Carrayptrs(pos);
292    cout << "4" << endl; 
293    nVertices = graph->nVertices;
294    int dims[2];
295    dims[0] = nVertices;
296    dims[1] = 2;
297    cout << "5" << endl; 
298    coors = (PyArrayObject *) PyArray_FromDims(2, dims, NPY_DOUBLE);
299    pos = pymatrix_to_Carrayptrs(coors);
300    random();
301
302    //dumpCoordinates();
303
304    links = NULL;
305    nLinks = 0;
306    cout << "6" << endl; 
307    for (v = 0; v < graph->nVertices; v++)
308    {
309        TGraphAsList::TEdge *edge = graph->edges[v];
310
311        if (edge != NULL)
312        {
313            int u = edge->vertex;
314            links = (int**)realloc(links, (nLinks + 1) * sizeof(int));
315
316            if (links == NULL)
317            {
318                cerr << "Couldn't allocate memory\n";
319                exit(1);
320            }
321
322            links[nLinks] = (int *)malloc(2 * sizeof(int));
323
324            if (links[nLinks] == NULL)
325            {
326                cerr << "Couldn't allocate memory\n";
327                exit(1);
328            }
329
330            links[nLinks][0] = v;
331            links[nLinks][1] = u;
332            nLinks++;
333
334            TGraphAsList::TEdge *next = edge->next;
335            while (next != NULL)
336            {
337                int u = next->vertex;
338
339                links = (int**)realloc(links, (nLinks + 1) * sizeof (int));
340
341                if (links == NULL)
342                {
343                    cerr << "Couldn't allocate memory\n";
344                    exit(1);
345                }
346
347                links[nLinks] = (int *)malloc(2 * sizeof(int));
348               
349                if (links[nLinks] == NULL)
350                {
351                    cerr << "Couldn't allocate memory\n";
352                    exit(1);
353                }
354
355                links[nLinks][0] = v;
356                links[nLinks][1] = u;
357                nLinks++;
358
359                next = next->next;
360            }
361        }
362    }
363}
364
365int getWords(string const& s, vector<string> &container)
366{
367    int n = 0;
368    bool quotation = false;
369    string::const_iterator it = s.begin(), end = s.end(), first;
370    for (first = it; it != end; ++it)
371    {
372        // Examine each character and if it matches the delimiter
373        if (((!quotation) && ((' ' == *it) || ('\t' == *it) || ('\r' == *it) || ('\f' == *it) || ('\v' == *it))) || ('\n' == *it))
374        {
375            if (first != it)
376            {
377                // extract the current field from the string and
378                // append the current field to the given container
379                container.push_back(string(first, it));
380                ++n;
381               
382                // skip the delimiter
383                first = it + 1;
384            }
385            else
386            {
387                ++first;
388            }
389        }
390        else if (('\"' == *it) || ('\'' == *it))
391        {
392            if (quotation)
393            {
394                quotation = false;
395
396                // extract the current field from the string and
397                // append the current field to the given container
398                container.push_back(string(first, it));
399                ++n;
400               
401                // skip the delimiter
402                first = it + 1;
403            }
404            else
405            {
406                quotation = true;
407
408                // skip the quotation
409                first = it + 1;
410            }
411        }
412    }
413    if (first != it)
414    {
415        // extract the last field from the string and
416        // append the last field to the given container
417        container.push_back(string(first, it));
418        ++n;
419    }
420    return n;
421}
422
423PyObject *NetworkOptimization_setGraph(PyObject *self, PyObject *args) PYARGS(METH_VARARGS, "(Graph) -> None")
424{
425    PyObject *pygraph;
426
427    if (!PyArg_ParseTuple(args, "O:NetworkOptimization.setGraph", &pygraph))
428        return NULL;
429
430    TGraphAsList *graph = &dynamic_cast<TGraphAsList &>(PyOrange_AsOrange(pygraph).getReference());
431
432    CAST_TO(TNetworkOptimization, graphOpt);
433    cout << "networkoptimization.cpp/setGraph: setting graph..." << endl;
434    graphOpt->setGraph(graph);
435    cout << "done." << endl;
436    RETURN_NONE;
437}
438
439PyObject *NetworkOptimization_fruchtermanReingold(PyObject *self, PyObject *args) PYARGS(METH_VARARGS, "(steps, temperature) -> temperature")
440{
441    int steps;
442    double temperature = 0;
443
444    if (!PyArg_ParseTuple(args, "id:NetworkOptimization.fruchtermanReingold", &steps, &temperature))
445        return NULL;
446
447    CAST_TO(TNetworkOptimization, graph);
448
449    graph->temperature = temperature;
450    graph->fruchtermanReingold(steps);
451   
452    return Py_BuildValue("d", graph->temperature);
453}
454
455PyObject *NetworkOptimization_get_coors(PyObject *self, PyObject *args) /*P Y A RGS(METH_VARARGS, "() -> Coors")*/
456{
457    CAST_TO(TNetworkOptimization, graph);   
458    Py_INCREF(graph->coors);
459    return (PyObject *)graph->coors;
460}
461
462PyObject *NetworkOptimization_random(PyObject *self, PyObject *args) PYARGS(METH_VARARGS, "() -> None")
463{
464    CAST_TO(TNetworkOptimization, graph);
465
466    graph->random();
467   
468    RETURN_NONE;
469}
470
471void temp(TGraph &graph)
472{
473    graph = TGraphAsList(5, 0, false);
474}
475
476WRAPPER(ExampleTable)
477
478PyObject *readNetwork(PyObject *, PyObject *args) PYARGS(METH_VARARGS, "(fn) -> Graph")
479{
480    TGraph *graph;
481    TDomain *domain = new TDomain();
482    TExampleTable *table;
483
484    //cout << "readNetwork" << endl;
485    char *fn;
486
487    if (!PyArg_ParseTuple(args, "s", &fn))
488        return NULL;
489
490    //cout << "File: " << fn << endl;
491
492    string line;
493    ifstream file(fn);
494    string graphName = "";
495    int nVertices = 0;
496
497    if (file.is_open())
498    {
499        // read head
500        while (!file.eof())
501        {
502            getline (file, line);
503            vector<string> words;
504            int n = getWords(line, words);
505            //cout << line << "  -  " << n << endl;
506            if (n > 0)
507            {
508                if (stricmp(words[0].c_str(), "*network") == 0)
509                {
510                    //cout << "Network" << endl;
511                    if (n > 1)
512                    {
513                        graphName = words[1];
514                        //cout << "Graph name: " << graphName << endl;
515                    }
516                    else
517                        return NULL;
518                }
519                else if (stricmp(words[0].c_str(), "*vertices") == 0)
520                {
521                    //cout << "Vertices" << endl;
522                    if (n > 1)
523                    {
524                        istringstream strVertices(words[1]);
525                        strVertices >> nVertices;
526                        if (nVertices == 0)
527                            return NULL;
528
529                        //cout << "nVertices: " << nVertices << endl;
530                    }
531                    else
532                        return NULL;
533
534                    break;
535                }
536            }
537        }
538        graph = new TGraphAsList(nVertices, 0, false);
539        domain->addVariable(new TIntVariable("index"));
540        domain->addVariable(new TStringVariable("label"));
541        domain->addVariable(new TFloatVariable("x"));
542        domain->addVariable(new TFloatVariable("y"));
543        domain->addVariable(new TFloatVariable("z"));
544        domain->addVariable(new TStringVariable("ic"));
545        domain->addVariable(new TStringVariable("bc"));
546        domain->addVariable(new TStringVariable("bw"));
547        table = new TExampleTable(domain);
548
549        // read vertex descriptions
550        while (!file.eof())
551        {
552            getline (file, line);
553            vector<string> words;
554            int n = getWords(line, words);
555            //cout << line << "  -  " << n << endl;
556            if (n > 0)
557            {
558                TExample *example = new TExample(domain);
559
560                if ((stricmp(words[0].c_str(), "*arcs") == 0) || (stricmp(words[0].c_str(), "*edges") == 0))
561                    break;
562
563                int index = -1;
564                istringstream strIndex(words[0]);
565                strIndex >> index;
566                if ((index <= 0) || (index > nVertices))
567                    return NULL;
568
569                //cout << "index: " << index << " n: " << n << endl;
570                (*example)[0] = TValue(index);
571
572                if (n > 1)
573                {
574                    string label = words[1];
575                    //cout << "label: " << label << endl;
576                    (*example)[1] = TValue(new TStringValue(label), STRINGVAR);
577
578                    int i = 2;
579                    char *xyz = "  xyz";
580                    // read coordinates
581                    while ((i <= 4) && (i < n))
582                    {
583                        float coor = -1;   
584                        istringstream strCoor(words[i]);
585                        strCoor >> coor;
586                       
587                        if ((coor < 0) || (coor > 1))
588                            break;
589                       
590                        //cout << xyz[i] << ": " << coor * 1000 << endl;
591                        (*example)[i] = TValue(coor);
592                        i++;
593                    }
594                    // read attributes
595                    while (i < n)
596                    {
597                        if (stricmp(words[i].c_str(), "ic") == 0)
598                        {
599                            if (i + 1 < n) i++; else return NULL;
600
601                            //cout << "ic: " << words[i] << endl;
602                            (*example)[5] = TValue(new TStringValue(words[i]), STRINGVAR);
603                        }
604                        else if (stricmp(words[i].c_str(), "bc") == 0)
605                        {
606                            if (i + 1 < n) i++; else return NULL;
607
608                            //cout << "bc: " << words[i] << endl;
609                            (*example)[6] = TValue(new TStringValue(words[i]), STRINGVAR);
610                        }
611                        else if (stricmp(words[i].c_str(), "bw") == 0)
612                        {
613                            if (i + 1 < n) i++; else return NULL;
614
615                            //cout << "bw: " << words[i] << endl;
616                            (*example)[7] = TValue(new TStringValue(words[i]), STRINGVAR);
617                        }
618                        i++;
619                    }
620                    table->push_back(example);
621                }
622            }
623        }
624        // read arcs
625        vector<string> words;
626        int n = getWords(line, words);
627        if (n > 0)
628        {
629            if (stricmp(words[0].c_str(), "*arcs") == 0)
630            {
631                while (!file.eof())
632                {
633                    getline (file, line);
634                    vector<string> words;
635                    int n = getWords(line, words);
636                    //cout << line << "  -  " << n << endl;
637                    if (n > 0)
638                    {
639                        if (stricmp(words[0].c_str(), "*edges") == 0)
640                            break;
641
642                        if (n > 1)
643                        {
644                            int i1 = -1;
645                            int i2 = -1;
646                            istringstream strI1(words[0]);
647                            istringstream strI2(words[1]);
648
649                            strI1 >> i1;
650                            strI2 >> i2;
651
652                            if ((i1 <= 0) || (i1 > nVertices) || (i2 <= 0) || (i2 > nVertices)) 
653                                return NULL;
654
655                            if (i1 == i2)
656                                continue;
657                           
658                            //cout << "i1: " << i1 << " i2: " << i2 << endl;
659                            *graph->getOrCreateEdge(i1 - 1, i2 - 1) = 1;
660                        }
661                    }
662                }
663            }
664        }
665        // read edges
666        n = getWords(line, words);
667        if (n > 0)
668        {
669            if (stricmp(words[0].c_str(), "*edges") == 0)
670            {
671                while (!file.eof())
672                {
673                    getline (file, line);
674                    vector<string> words;
675                    int n = getWords(line, words);
676                    //cout << line << "  -  " << n << endl;
677                    if (n > 1)
678                    {
679                        int i1 = -1;
680                        int i2 = -1;
681                        istringstream strI1(words[0]);
682                        istringstream strI2(words[1]);
683
684                        strI1 >> i1;
685                        strI2 >> i2;
686
687                        if ((i1 <= 0) || (i1 > nVertices) || (i2 <= 0) || (i2 > nVertices)) 
688                            return NULL;
689
690                        if (i1 == i2)
691                            continue;
692
693                        *graph->getOrCreateEdge(i1 - 1, i2 - 1) = 1;
694                        *graph->getOrCreateEdge(i2 - 1, i1 - 1) = 1;
695                    }
696                }
697            }
698        }
699
700        file.close();
701    }
702    else 
703        cout << "Unable to open file."; 
704   
705    PExampleTable wtable = table;
706    PGraph wgraph = graph;
707    //graph->setProperty("items", wtable);
708
709    return Py_BuildValue("OO", WrapOrange(wgraph), WrapOrange(wtable));
710}
711
712#include "networkoptimization.px"
Note: See TracBrowser for help on using the repository browser.