1
////////////////////////////////////////////////////////////////////////////////
3
// This file is part of Toolkit for Conceptual Modeling (TCM).
4
// (c) copyright 1995, Vrije Universiteit Amsterdam.
5
// Author: Frank Dehne (frank@cs.vu.nl).
7
// TCM is free software; you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation; either version 2 of the License, or
10
// (at your option) any later version.
12
// TCM is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with TCM; if not, write to the Free Software
19
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21
////////////////////////////////////////////////////////////////////////////////
26
#include "outputfile.h"
29
nodes = new List<Node *>;
30
edges = new List<Edge *>;
31
nodeTypes = new int[static_cast<int>(MAX_TYPES)];
32
edgeTypes = new int[static_cast<int>(MAX_TYPES)];
37
connections [i][j][k]= False;
51
void Graph::AddNode(Node *node) {
52
if (!HasNode(node)) nodes->add(node);}
54
void Graph::AddEdge(Edge *edge) {
55
if (!HasEdge(edge)) edges->add(edge);}
57
bool Graph::CheckConnection(int subjecttype1, int subjecttype2, int edgetype) {
59
[Code::GetIndex(subjecttype1, nodeTypes)]
60
[Code::GetIndex(subjecttype2, nodeTypes)]
61
[Code::GetIndex(edgetype, edgeTypes)];
64
bool Graph::IsConnected(Subject *s1, Subject *s2) {
65
return IsConnected(s1, s2, -1);
68
bool Graph::IsConnected(Subject *s1, Subject *s2, int t) {
69
for (edges->first(); !edges->done(); edges->next()) {
70
Edge *edge = edges->cur();
73
if (edge->GetClassType()==t || t==-1) {
74
if (edge->IsDirected()) {
75
if (edge->GetSubject1()==s1 &&
76
edge->GetSubject2()==s2)
80
if (edge->PartOf(s1)&&edge->PartOf(s2))
87
bool Graph::IsConnected(Subject *s1, Subject *s2, const string *s) {
88
return IsConnected(s1, s2, s, -1);
91
bool Graph::IsConnected(Subject *s1, Subject *s2,
92
const string *s, int t) {
93
for (edges->first(); !edges->done(); edges->next()) {
94
Edge *edge = edges->cur();
97
if (*edge->GetName()==*s &&
98
(edge->GetClassType()==t || t==-1)) {
99
if (edge->IsDirected()) {
100
if (edge->GetSubject1()==s1 &&
101
edge->GetSubject2()==s2)
105
if (edge->PartOf(s1) && edge->PartOf(s2))
112
int Graph::GetConnected(List<Subject *> *l, Subject *s) {
114
for (edges->first(); !edges->done(); edges->next()) {
115
Edge *edge = edges->cur();
118
Subject *n1 = edge->GetSubject1();
119
Subject *n2 = edge->GetSubject2();
120
if (edge->IsDirected()) {
121
if (n1==s && l->find(n2) == -1)
125
if (n1==s && l->find(n2) == -1)
127
else if (n2==s && l->find(n1) == -1)
134
int Graph::CompleteSubjects(List<Subject *> *l) {
136
for (l->last(); !l->done(); l->prev()) {
137
Subject *s = l->cur();
139
CompleteSubject(l, s);
144
int Graph::CompleteSubject(List<Subject *> *l, Subject *s) {
146
List<Edge *> newEdges;
147
for (edges->first(); !edges->done(); edges->next()) {
148
Edge *edge = edges->cur();
152
if (l->find(edge) == -1) {
157
// complete newly added edges.
158
for (newEdges.first(); !newEdges.done(); newEdges.next())
159
CompleteSubject(l, newEdges.cur());
163
int Graph::CompleteSubject(List<Subject *> *l, Subject *s1, Subject *s2) {
165
for (edges->first(); !edges->done(); edges->next()) {
166
Edge *edge = edges->cur();
169
if (edge->PartOf(s1) && edge->PartOf(s2))
170
if (l->find(edge) == -1)
176
int Graph::CompleteEdges(List<Subject *> *l) {
178
List<Subject *> newEdges;
179
for (l->last(); !l->done(); l->prev()) {
181
Subject *s = l->cur();
184
subj = ((Edge *)s)->GetSubject1();
185
if (l->find(subj) == -1) {
191
subj = ((Edge *)s)->GetSubject2();
192
if (l->find(subj) == -1) {
201
if (newEdges.count() > 0) {
202
CompleteEdges(&newEdges);
203
for (newEdges.first(); !newEdges.done(); newEdges.next())
204
if (l->find(newEdges.cur()) == -1)
205
l->add(newEdges.cur());
210
int Graph::GetNodes(List<Subject *> *l) {
212
for (nodes->first(); !nodes->done(); nodes->next()) {
213
if (check(nodes->cur() && !nodes->cur()->IsEdge()))
214
l->add(nodes->cur());
219
int Graph::GetNodes(List<Subject *> *l, int t) {
221
for (nodes->first(); !nodes->done(); nodes->next()) {
222
Subject *s = nodes->cur();
223
if (check(s && !s->IsEdge())) {
224
if (s->GetClassType() == t)
231
int Graph::GetNodes(List<Subject *> *l, const string *n) {
233
for (nodes->first(); !nodes->done(); nodes->next()) {
234
Subject *s = nodes->cur();
235
if (check(s && !s->IsEdge())) {
236
if (*s->GetName() == *n)
243
int Graph::GetNodes(List<Subject *> *l, const string *n, int t) {
245
for (nodes->first(); !nodes->done(); nodes->next()) {
246
Subject *s = nodes->cur();
247
if (check(s && !s->IsEdge())) {
248
if (s->GetClassType() == t && *s->GetName() == *n)
256
int Graph::GetEdges(List<Subject *> *l) {
258
for (edges->first(); !edges->done(); edges->next()) {
259
Edge *e = edges->cur();
266
int Graph::GetEdges(List<Subject *> *l, int t) {
268
for (edges->first(); !edges->done(); edges->next()) {
269
Edge *e = edges->cur();
271
if (e->GetClassType() == t)
278
int Graph::GetEdges(List<Subject *> *l, const string *n) {
280
for (edges->first(); !edges->done(); edges->next()) {
281
Edge *e = edges->cur();
283
if (*e->GetName() == *n)
290
int Graph::GetEdges(List<Subject *> *l, const string *n, int t) {
292
for (edges->first(); !edges->done(); edges->next()) {
293
Edge *e = edges->cur();
295
if (e->GetClassType() == t && *e->GetName() == *n)
303
int Graph::GetEdgesFrom(List<Subject *> *l, Subject *s) {
305
for (edges->first(); !edges->done(); edges->next()) {
306
Edge *e = edges->cur();
308
if (e->IsDirected() && e->GetSubject1() == s)
310
else if (!e->IsDirected() && (e->PartOf(s)))
317
int Graph::GetEdgesFrom(List<Subject *> *l, Subject *s, int t) {
319
for (edges->first(); !edges->done(); edges->next()) {
320
Edge *e = edges->cur();
322
if (e->GetClassType() == t) {
323
if (e->IsDirected() && e->GetSubject1() == s)
325
else if (!e->IsDirected() && (e->PartOf(s)))
333
int Graph::GetEdgesFrom(List<Subject *> *l, Subject *s, const string *n) {
335
for (edges->first(); !edges->done(); edges->next()) {
336
Edge *e = edges->cur();
338
if (*e->GetName() == *n) {
339
if (e->IsDirected() && e->GetSubject1() == s)
341
else if (!e->IsDirected() && (e->PartOf(s)))
349
int Graph::GetEdgesFrom(List<Subject *> *l, Subject *s, const string *n, int t) {
351
for (edges->first(); !edges->done(); edges->next()) {
352
Edge *e = edges->cur();
354
if (e->GetClassType() == t && *e->GetName() == *n) {
355
if (e->IsDirected() && e->GetSubject1() == s)
357
else if (!e->IsDirected() && (e->PartOf(s)))
365
int Graph::GetEdgesTo(List<Subject *> *l, Subject *s) {
367
for (edges->first(); !edges->done(); edges->next()) {
368
Edge *e = edges->cur();
370
if (e->IsDirected() && e->GetSubject2() == s)
372
else if (!e->IsDirected() && (e->PartOf(s)))
379
int Graph::GetEdgesTo(List<Subject *> *l, Subject *s, int t) {
381
for (edges->first(); !edges->done(); edges->next()) {
382
Edge *e = edges->cur();
384
if (e->GetClassType() == t) {
385
if (e->IsDirected() && e->GetSubject2() == s)
387
else if (!e->IsDirected() && (e->PartOf(s)))
395
int Graph::GetEdgesTo(List<Subject *> *l, Subject *s, const string *n) {
397
for (edges->first(); !edges->done(); edges->next()) {
398
Edge *e = edges->cur();
400
if (*e->GetName() == *n) {
401
if (e->IsDirected() && e->GetSubject2() == s)
403
else if (!e->IsDirected() && (e->PartOf(s)))
411
int Graph::GetEdgesTo(List<Subject *> *l, Subject *s, const string *n, int t) {
413
for (edges->first(); !edges->done(); edges->next()) {
414
Edge *e = edges->cur();
416
if (e->GetClassType() == t && *e->GetName() == *n) {
417
if (e->IsDirected() && e->GetSubject2() == s)
419
else if (!e->IsDirected() && (e->PartOf(s)))
427
int Graph::GetEdges(List<Subject *> *l, Subject *s1, Subject *s2) {
429
for (edges->first(); !edges->done(); edges->next()) {
430
Edge *e = edges->cur();
432
if (e->GetSubject1() == s1 && e->GetSubject2() == s2)
434
else if (!e->IsDirected() && s1 != s2 &&
435
e->GetSubject1() == s2 &&
436
e->GetSubject2() == s1)
443
int Graph::GetEdges(List<Subject *> *l, Subject *s1, Subject *s2, int t) {
445
for (edges->first(); !edges->done(); edges->next()) {
446
Edge *e = edges->cur();
448
if (e->GetClassType()==t) {
449
if (e->GetSubject1() == s1 &&
450
e->GetSubject2() == s2)
452
else if (!e->IsDirected() && s1 != s2 &&
453
e->GetSubject1() == s2 &&
454
e->GetSubject2() == s1)
462
int Graph::GetEdges(List<Subject *> *l, Subject *s1, Subject *s2, const string *n) {
464
for (edges->first(); !edges->done(); edges->next()) {
465
Edge *e = edges->cur();
467
if (*e->GetName()==*n) {
468
if (e->GetSubject1() == s1 &&
469
e->GetSubject2() == s2)
471
else if (!e->IsDirected() && s1 != s2 &&
472
e->GetSubject1() == s2 &&
473
e->GetSubject2() == s1)
481
int Graph::GetEdges(List<Subject *> *l, Subject *s1, Subject *s2, const string *n, int t) {
483
for (edges->first(); !edges->done(); edges->next()) {
484
Edge *e = edges->cur();
486
if (*e->GetName()==*n && e->GetClassType() == t) {
487
if (e->GetSubject1() == s1 &&
488
e->GetSubject2() == s2)
490
else if (!e->IsDirected() && s1 != s2 &&
491
e->GetSubject1() == s2 &&
492
e->GetSubject2() == s1)
500
int Graph::CountNodes() {
501
return nodes->count();
504
int Graph::CountNodes(int t) {
506
return GetNodes(&s, t);
509
int Graph::CountNodes(const string *n) {
511
return GetNodes(&s, n);
514
int Graph::CountNodes(const string *n, int t) {
516
return GetNodes(&s, n, t);
519
int Graph::CountEdges() {
520
return edges->count();
523
int Graph::CountEdges(int t) {
525
return GetEdges(&e, t);
528
int Graph::CountEdges(const string *n) {
530
return GetEdges(&e, n);
533
int Graph::CountEdges(const string *n, int t) {
535
return GetEdges(&e, n, t);
538
int Graph::CountEdgesFrom(Subject *s) {
540
return GetEdgesFrom(&e, s);
543
int Graph::CountEdgesFrom(Subject *s, const string *n) {
545
return GetEdgesFrom(&e, s, n);
548
int Graph::CountEdgesFrom(Subject *s, int t) {
550
return GetEdgesFrom(&e, s, t);
553
int Graph::CountEdgesFrom(Subject *s, const string *n, int t) {
555
return GetEdgesFrom(&e, s, n, t);
558
int Graph::CountEdgesTo(Subject *s) {
560
return GetEdgesTo(&e, s);
563
int Graph::CountEdgesTo(Subject *s, const string *n) {
565
return GetEdgesTo(&e, s, n);
568
int Graph::CountEdgesTo(Subject *s, int t) {
570
return GetEdgesTo(&e, s, t);
573
int Graph::CountEdgesTo(Subject *s, const string *n, int t) {
575
return GetEdgesTo(&e, s, n, t);
578
int Graph::CountEdges(Subject *s1, Subject *s2) {
580
return GetEdges(&e, s1, s2);
583
int Graph::CountEdges(Subject *s1, Subject *s2, const string *n) {
585
return GetEdges(&e, s1, s2, n);
588
int Graph::CountEdges(Subject *s1, Subject *s2, int t) {
590
return GetEdges(&e, s1, s2, t);
593
int Graph::CountEdges(Subject *s1, Subject *s2, const string *n, int t) {
595
return GetEdges(&e, s1, s2, n, t);
598
// PathExists members are implemented by David Jansen
599
// <dnjansen@cs.utwente.nl> on 28 September 2000.
600
bool Graph::PathExists(Subject *s1, Subject *s2) {
601
return PathExists(s1, s2, 0, True);
604
bool Graph::PathExists(Subject *s1, Subject *s2, int t) {
605
return PathExists(s1, s2, t, True);
608
bool Graph::UndirectedPathExists(Subject *s1, Subject *s2) {
609
return PathExists(s1, s2, 0, False);
612
bool Graph::PathExists(Subject *s1, Subject *s2,
613
int edgetype, bool Directed) {
614
// The procedure looks for a path from s1 to s2, composed of
615
// edges of the given type (edgetype, Directed).
616
// It doesn't account for composed edges.
617
List<Subject *> edgelist;
619
GetEdges(&edgelist, edgetype);
623
List<Subject *> visitsubj;
628
for ( edgelist.first() ; ! edgelist.done() ; ) {
629
Edge *edge = dynamic_cast<Edge *>(edgelist.cur());
633
Subject *n1 = edge->GetSubject1();
634
Subject *n2 = edge->GetSubject2();
636
if ( ! visitsubj.contains(n1) ) {
637
if ( Directed && edge->IsDirected()
638
|| ! visitsubj.contains(n2) ) {
649
if ( ! subj1 || ! visitsubj.contains(n2) ) {
653
edgelist.removecur();
661
old and slow implementation.
662
bool Graph::PathExists(Subject *s1, Subject *s2,
663
int edgetype, bool Directed) {
664
for (edges->first(); !edges->done(); edges->next()) {
665
Edge *edge = edges->cur();
666
if (edgetype > 0 && edge->GetClassType()!=edgetype)
670
Subject *n1 = edge->GetSubject1();
671
Subject *n2 = edge->GetSubject2();
673
// directed: only n1 -> n2.
674
if (n1 == s1 && edge->IsDirected()) {
677
// undirected: both n1 -> n2 and n1 <- n2 allowed.
678
else if ((!edge->IsDirected() || !Directed) &&
679
(n1 == s1 || n2 == s1)) {
692
else if (path->find(edge) == -1) {
694
if (PathExists(n2, s2, path, edgetype, Directed))
697
if (!edges->setcur(edge))
698
error("%s %d: internal graph error\n",
708
void Graph::WriteSubjects(OutputFile *f) {
709
(*f) << "# GRAPH NODES\n\n";
710
for (nodes->first(); !nodes->done(); nodes->next()) {
711
if (check(nodes->cur()))
712
nodes->cur()->Write(f);
714
(*f) << "# GRAPH EDGES\n\n";
715
for (edges->first(); !edges->done(); edges->next()) {
716
if (check(edges->cur()))
717
edges->cur()->Write(f);
721
int Graph::CountIndex(const string *index, List<Subject *> *l) {
723
for (l->first(); !l->done(); l->next()) {
724
if (!l->cur()->IsEdge()) {
725
Node *node = (Node *)l->cur();
726
if (*node->GetIndex() == *index) {
734
void Graph::GetIndex(string *s) {
735
*s = *GetIndexPrefix();
738
if (GetCounter() > 0)
742
void Graph::GetNextIndex(string *index) {
744
// make index one higher, until a unique index is found.
745
if (GetCounter() > 0) {
750
SetCounter(GetCounter()+1);
752
} while (CountIndex(index, &l) != 0);
756
int Graph::CountIndexes(const string *index) {
759
return CountIndex(index, &l);