1
/////////////////////////////////////////////////////////////////////////////////
2
// This file is part of Toolkit for Conceptual Modeling (TCM).
3
// (c) copyright 2001, Universiteit Twente.
4
// Author: Rik Eshuis (eshuis@cs.utwente.nl).
6
// TCM is free software; you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation; either version 2 of the License, or
9
// (at your option) any later version.
11
// TCM is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with TCM; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20
////////////////////////////////////////////////////////////////////////////////
21
#include "adsclockmanager.h"
24
#include "outputfile.h"
26
#include "adsvaluation.h"
27
#include "adstransition.h"
28
#include "adshypergraph.h"
29
#include "adspropertyvaluation.h"
32
ADSCks::ADSCks(ADSHyperGraph *a) : Graph() {
39
void ADSCks::AddNode(Node *n){
41
// vhl.add((ADSValuation *)n,((ADSValuation *)n)->ComputeKey());
44
void ADSCks::AddEdge(Edge *e){
46
// thl.add((ADSTransition *)e,((ADSTransition *)e)->ComputeKey());
50
void ADSCks::WriteSubjects(OutputFile *f) {
51
List <ADSValuation *> cksnodes;
52
GetNodes((List <Subject *> *)&cksnodes);
53
(*f) << "# GRAPH NODES\n\n";
54
for (cksnodes.first(); !cksnodes.done(); cksnodes.next()) {
55
if (check(cksnodes.cur()))
56
cksnodes.cur()->Write(f);
58
List <ADSTransition *> cksedges;
59
GetEdges((List <Subject *> *)&cksedges);
60
(*f) << "# GRAPH EDGES\n\n";
61
for (cksedges.first(); !cksedges.done(); cksedges.next()) {
62
if (check(cksedges.cur()))
63
cksedges.cur()->Write(f);
69
bool ADSCks::ExistsSimilarEdge( ADSTransition *e){
70
// if (thl.isin(e,e->ComputeKey())==NULL) return False;
73
List <ADSTransition *> cksedges;
74
GetEdges((List <Subject *> *)&cksedges);
75
for (cksedges.first(); !cksedges.done(); cksedges.next()){
76
if ((*cksedges.cur())==*e) {
85
ADSValuation *ADSCks::FindSimilarNode( ADSValuation *s){
86
// return vhl.isin(s,s->ComputeKey());
88
List <ADSValuation *> cksnodes;
89
GetNodes((List <Subject *> *)&cksnodes);
90
for (cksnodes.first(); !cksnodes.done(); cksnodes.next()){
91
if ((*cksnodes.cur())==*s) {
92
return cksnodes.cur();
101
// procedure to detect unbounded state nodes
102
// it is taken from the Karp-Miller algorithm
103
// if there exists another valuation s' such that s'->C' < s->C
104
// and there is a path from s to s' then
105
// some state node is unbounded
106
bool ADSCks::GrowsInfinite(ADSValuation *s, string &str){
107
Bag <Subject *> scfg;
109
List <ADSValuation *> cksnodes;
110
GetNodes((List <Subject *> *)&cksnodes);
111
for (cksnodes.first(); !cksnodes.done(); cksnodes.next()){
113
cksnodes.cur()->GetConfig(&cfg);
114
if ((scfg.contains(cfg)) && (!cfg.contains(scfg)) && (PathExists(cksnodes.cur(),s)) ){
117
for (l.first();!l.done();l.next()){
118
if (scfg.count(l.cur())>cfg.count(l.cur())) str=*(l.cur()->GetName());
120
return True; // scfg strictly contains cfg and cksnodes.cur() leads to s
128
string replace(string s){
135
// t.replace('(','_');
136
// t.replace(')','_');
148
void ADSCks::WriteSMVFile(OutputFile *ofile, bool sf){
149
(*ofile) << "MODULE main\n\nVAR\n";
150
List <Subject *> amnodes;
151
am->GetNodes((List <Subject *> *)&amnodes);
156
List <ADSValuation *> cksnodes;
157
GetNodes((List <Subject *> *)&cksnodes);
158
int nodescount=cksnodes.count();
160
(*ofile) << "\tc____counter : 0.." << nodescount-1 << " ; -- program counter \n"; // putting the program counter first gives more efficient BDD ordering
162
for (amnodes.first();!amnodes.done();amnodes.next()){
163
if ((amnodes.cur()->GetClassType()==Code::NOTE)||(amnodes.cur()->GetClassType()==Code::COMMENT)) continue; // skip these
164
string s=(*(amnodes.cur()->GetName()));
168
if (amnodes.cur()->GetClassType()==Code::ATD_INITIAL_STATE_NODE){
169
s="I___INITIAL";amnodes.cur()->SetName(&s);
171
if (amnodes.cur()->GetClassType()==Code::ATD_FINAL_STATE_NODE){
172
string t = (int)amnodes.cur()->GetId();
173
s="F___FINAL"+t; amnodes.cur()->SetName(&s);
175
(*ofile ) << "\t"<< replace(s) << " : 0.."<< am->GetBound(amnodes.cur()) <<";\n";
176
if (amnodes.cur()->GetClassType()==Code::ATD_ACTION_STATE_NODE){
177
(*ofile ) << "\tT_" << replace(s) << " : 0.."<< am->GetBound(amnodes.cur()) <<";\n";
182
for (pl.first();!pl.done();pl.next()){
183
string s=pl.cur()->GetName();
184
(*ofile ) << "\t" << replace(s) << " : boolean;\n";
186
(*ofile) << "\tstable:boolean;\n";
189
(*ofile) << "INIT\n";
190
(*ofile) << "\tc____counter = 0 & \n "; // because of assign number
191
for (amnodes.first();!amnodes.done();amnodes.next()){
192
if ((amnodes.cur()->GetClassType()==Code::NOTE)||(amnodes.cur()->GetClassType()==Code::COMMENT)) continue; // skip these
193
string s=(*(amnodes.cur()->GetName()));
194
(*ofile ) << "\t"<< replace(s) << " = " ;
195
(amnodes.cur()->GetClassType()==Code::ATD_INITIAL_STATE_NODE)? (*ofile) << "1" : (*ofile) << "0" ;
197
if (amnodes.cur()->GetClassType()==Code::ATD_ACTION_STATE_NODE){
198
(*ofile ) << "\tT_" << replace(s) << " = 0 & \n";
201
for (pl.first();!pl.done();pl.next()){
202
string s=pl.cur()->GetName();
203
(*ofile ) << "\t" << replace(s) << "= 0 & \n";
206
(*ofile) << "\tstable= 0 \n\n";
208
(*ofile) << "TRANS\n";
210
// print program counter
211
(*ofile) << "\tnext(c____counter) in\n\t\tcase\n";
212
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
213
(*ofile) << "\t\t\t c____counter = " << cksnodes.cur()->GetNumber() << " : {";
214
List <ADSTransition *> akl;
215
GetEdgesFrom((List <Subject *> *)&akl,cksnodes.cur());
218
(*ofile) << cksnodes.cur()->GetNumber() << "};\n"; // final state is self loop
222
(*ofile) << ((ADSValuation *)akl.cur()->GetSubject2())->GetNumber();
228
for (;!akl.done();akl.next()){
229
(*ofile) << "," << ((ADSValuation *)akl.cur()->GetSubject2())->GetNumber() ;
235
(*ofile) << "\t\tesac\n\t&\n";
237
// print configuration variables
238
for (amnodes.first();!amnodes.done();amnodes.next()){
239
if ((amnodes.cur()->GetClassType()==Code::NOTE)||(amnodes.cur()->GetClassType()==Code::COMMENT)) continue; // skip these
240
string s=(*(amnodes.cur()->GetName()));
241
(*ofile ) << "\tnext("<< replace(s) << ") in\n\t\tcase\n";
243
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
244
Bag <Subject *> currentcfg;
245
cksnodes.cur()->GetConfig(¤tcfg);
246
List <Subject *> currentcfgl;
247
currentcfg.GetSet(¤tcfgl);
248
if (currentcfgl.find(amnodes.cur())>-1){
249
(*ofile) << "\t\t\tnext(c____counter) = " << cksnodes.cur()->GetNumber() << ": " << currentcfg.count(amnodes.cur()) << ";\n";
252
(*ofile) << "\t\t\tnext(c____counter) = " << cksnodes.cur()->GetNumber() << ": 0 ;\n";
255
(*ofile) << "\t\tesac\n\t&\n";
257
if (amnodes.cur()->GetClassType()==Code::ATD_ACTION_STATE_NODE){
258
string str=(*(amnodes.cur()->GetName()));
259
(*ofile ) << "\tnext(T_"<< replace(str) << ") in\n\t\tcase\n";
260
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
261
Bag <ATDActionStateNode *> term;
262
cksnodes.cur()->GetTerminated(&term);
263
List <ATDActionStateNode *> terml;
265
if (terml.find((ATDActionStateNode *)amnodes.cur())>-1){
266
(*ofile) << "\t\t\tnext(c____counter) = " <<cksnodes.cur()->GetNumber() << ": "<< term.count((ATDActionStateNode *)amnodes.cur()) <<";\n";
269
(*ofile) << "\t\t\tnext(c____counter) = " <<cksnodes.cur()->GetNumber() << ": 0;\n";
272
(*ofile) << "\t\tesac\n\t&\n";
277
for (pl.first();!pl.done();pl.next()){
278
string s=pl.cur()->GetName();
279
(*ofile ) << "\tnext("<< replace(s) << ") in\n\t\tcase\n";
280
PropVal pvt(pl.cur(),true);
281
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
282
List <PropVal *> plcur;
283
cksnodes.cur()->GetPropList(&plcur);
285
for (plcur.first();!plcur.done();plcur.next()){
286
if (((*(plcur.cur()))==pvt)){
287
(*ofile) << "\t\t\tnext(c____counter) = "<< cksnodes.cur()->GetNumber() << ": 1; \n";
292
if (!Found){ // if not found, then false
293
(*ofile) << "\t\t\tnext(c____counter) = "<< cksnodes.cur()->GetNumber() << ": 0; \n";
296
(*ofile) << "\t\tesac\n\t\t&\n";
299
(*ofile) << "\tnext(stable) in\n\t\tcase\n";
300
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
301
(*ofile) << "\t\t\tnext(c____counter) = "<< cksnodes.cur()->GetNumber() << ": ";
302
if (cksnodes.cur()->isStable()){
309
(*ofile) << "\t\tesac\n";
312
List <ADSHyperEdge *> amedges;
313
am->GetHyperEdges((List<Subject *> *)&amedges);
314
for (amedges.first();!amedges.done();amedges.next()){
315
List <Subject *> *source=amedges.cur()->GetSubject1();
316
List <Subject *> *target=amedges.cur()->GetSubject2();
318
(*ofile) << "COMPASSION\n";
319
(*ofile) << "(stable &";
321
for (source->first();!source->done();source->next()){
322
string s = *(source->cur()->GetName());
327
(*ofile) << replace(s) << " > 0 ";
329
(*ofile) << ", stable & ";
331
for (target->first();!target->done();target->next()){
332
string s = *(target->cur()->GetName());
337
(*ofile) << replace(s) << " > 0 ";
351
void ADSCks::GetClocks(List <string> *l){
352
List <ADSHyperEdge *> amedges;
353
am->GetHyperEdges((List <Subject *> *)&amedges);
354
for (amedges.first();!amedges.done();amedges.next()){
355
if (amedges.cur()->hasClockConstraint()){
356
string s=amedges.cur()->GetClockConstraint()->GetClock()->GetName();
363
void ADSCks::AssignNumbers(){
364
List <ADSValuation *> cksnodes;
365
GetNodes((List <Subject *> *)&cksnodes);
367
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
368
cksnodes.cur()->SetNumber(i);
374
// the following procedure requires that AssignNumbers has been done before
375
ADSValuation *ADSCks::GetADSValuation(int i){
376
List <ADSValuation *> cksnodes;
377
GetNodes((List <Subject *> *)&cksnodes);
378
for (cksnodes.first();!cksnodes.done();cksnodes.next()){
379
if (i==cksnodes.cur()->GetNumber()) return cksnodes.cur();
384
// count and print different configurations
385
int ADSCks::countconfigs(){
386
List <ADSValuation *> configlist;
390
List <ADSValuation *> cksnodes;
391
GetNodes((List <Subject *> *)&cksnodes);
392
int ckscount=cksnodes.count();
393
for (int i=0;i<ckscount;i++){
394
if (!cksnodes[i]->isStable()) stablecount++;
395
else{ if (CountEdgesTo(cksnodes[i])>1) prec++;}
397
for (int j=i+1;j<ckscount;j++){
398
if (cksnodes[i]->hassameconfig(*cksnodes[j])){ found=True;break;}
402
configlist.add(cksnodes[i]);
405
std::cout << "\nThere are "<< stablecount << " unstable states\n";
406
std::cout << "\nThere are "<< prec << " states with more than one predecessor\n";
407
List <ADSTransition *> cksedges;
408
List <ADSValuation *> temp;
409
GetEdges((List <Subject *> *)&cksedges);
410
ckscount=cksedges.count();
411
for (int i=0;i<ckscount;i++){
412
if ((!((ADSValuation*)cksedges[i]->GetSubject1())->isStable()) &&
413
(!((ADSValuation*)cksedges[i]->GetSubject2())->isStable()))
414
if (temp.find((ADSValuation*)(cksedges[i]->GetSubject2()))<0)
415
temp.add((ADSValuation*)(cksedges[i]->GetSubject2()));
417
std::cout << "\nThere are "<< temp.count() << " superstep states\n";
418
std::cout << "\nThere are "<< cfgcounter << " different configruations!\n";