Repository navigation
Expand file tree
/
Copy pathPetriStructureReducer.cpp
More file actions
executable file
·3507 lines (2920 loc) · 131 KB
/
Copy pathPetriStructureReducer.cpp
File metadata and controls
executable file
·3507 lines (2920 loc) · 131 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include <chrono>
#include <omp.h>
#include "PetriStructureReducer.h"
#include "Petri_Net.h"
#include <algorithm> // 为std::find
#include <atomic>
#include <numeric> // 为std::gcd
#include <functional>
#include <limits> // 为numeric_limits
#include "DebugConfig.h"
// PetriStructureReducer.cpp
bool PetriStructureReducer::importFromFile(const string& filename) {
ifstream fin(filename);
if (!fin) {
cerr << "无法打开文件: " << filename << endl;
return false;
}
// 清空现有数据
places.clear();
transitions.clear();
units.clear();
significantPlaces.clear(); // 清空重要库所集合
// 读取库所、变迁和重要库所的总数
int totalPlaces, totalTransitions, totalSignificant;
fin >> totalPlaces >> totalTransitions >> totalSignificant;
// 读取重要库所列表
for (int i = 0; i < totalSignificant; i++) {
string placeId;
fin >> placeId;
significantPlaces.insert(placeId);
}
// 读取库所信息
for (int i = 0; i < totalPlaces; i++) {
string id, unitId;
unsigned int tokens;
fin >> id >> tokens >> unitId;
PetriPlace place;
place.id = id;
place.tokens = tokens;
place.unitId = unitId;
places[id] = place;
// 同时更新或创建unit
if (units.find(unitId) == units.end()) {
units[unitId] = PetriUnit{unitId, {}};
}
units[unitId].places.insert(id);
}
// 读取变迁信息
for (int i = 0; i < totalTransitions; i++) {
string id;
int inCount, outCount;
fin >> id >> inCount >> outCount;
PetriTransition trans;
trans.id = id;
// 读取输入库所
for (int j = 0; j < inCount; j++) {
string placeId;
weight_t weight;
fin >> placeId >> weight;
trans.inPlaces[placeId] = weight;
places[placeId].outTransitions[id] = weight;
}
// 读取输出库所
for (int j = 0; j < outCount; j++) {
string placeId;
weight_t weight;
fin >> placeId >> weight;
trans.outPlaces[placeId] = weight;
places[placeId].inTransitions[id] = weight;
}
transitions[id] = trans;
}
fin.close();
return true;
}
void PetriStructureReducer::exportToFile(const string& filename) const {
// 打开输出文件
ofstream fout(filename);
if (!fout) {
cerr << "无法创建文件: " << filename << endl;
return;
}
// ===== 1. 写入网络基本信息 =====
// 格式: [库所数量] [变迁数量] [重要库所数量]
fout << places.size() << " "
<< transitions.size() << " "
<< significantPlaces.size() << endl;
// ===== 2. 写入重要库所列表 =====
// 格式: 每行一个库所ID
for (const string& placeId : significantPlaces) {
fout << placeId << endl;
}
// ===== 3. 写入所有库所信息 =====
// 格式: [库所ID] [标识数] [单元ID]
for (const auto& [id, place] : places) {
fout << place.id << " "
<< place.tokens << " "
<< place.unitId << endl;
}
// ===== 4. 写入所有变迁信息 =====
for (const auto& [id, trans] : transitions) {
// 变迁头部信息: [变迁ID] [输入库所数量] [输出库所数量]
fout << trans.id << " "
<< trans.inPlaces.size() << " "
<< trans.outPlaces.size() << endl;
// 写入输入库所及其权重
// 格式: [库所ID] [权重]
for (const auto& [placeId, weight] : trans.inPlaces) {
fout << placeId << " " << weight << endl;
}
// 写入输出库所及其权重
// 格式: [库所ID] [权重]
for (const auto& [placeId, weight] : trans.outPlaces) {
fout << placeId << " " << weight << endl;
}
}
fout.close();
}
void PetriStructureReducer::importFromPetri(const Petri& petri, const set<index_t>& vis, bool cardinality) {
// 导入库所
for(index_t i = 0; i < petri.placecount; i++) {
PetriPlace place;
const Place& originalPlace = petri.place[i];
place.id = originalPlace.id;
place.tokens = originalPlace.initialMarking;
if(petri.NUPN) {
place.unitId = petri.unittable[petri.nupnExtra[i].myunit].uid;
} else {
place.unitId = "";
}
place.atomicLinks = originalPlace.atomicLinks;
// 导入弧
for(const auto& arc : originalPlace.producer) {
place.inTransitions[petri.transition[arc.idx].id] = arc.weight;
}
for(const auto& arc : originalPlace.consumer) {
place.outTransitions[petri.transition[arc.idx].id] = arc.weight;
}
places[place.id] = place;
if(petri.NUPN) {
units[place.unitId].places.insert(place.id);
}
}
// 导入变迁
for(index_t i = 0; i < petri.transitioncount; i++) {
PetriTransition trans;
const Transition& originalTrans = petri.transition[i];
trans.id = originalTrans.id;
for(const auto& arc : originalTrans.producer) {
trans.inPlaces[petri.place[arc.idx].id] = arc.weight;
}
for(const auto& arc : originalTrans.consumer) {
trans.outPlaces[petri.place[arc.idx].id] = arc.weight;
}
transitions[trans.id] = trans;
}
// 设置重要元素(库所或变迁)
// cout<<"vis: "<<endl;
// for (auto i :vis){
// cout<<i <<" ";
// }cout<<endl;
if(cardinality) {
// 对于Cardinality: 重要元素是查询中引用的库所
for(auto idx : vis) {
significantPlaces.insert(petri.place[idx].id);
}
} else {
// 对于Fireability: 重要元素是查询中引用的变迁
// 首先收集变迁的ID
for(auto idx : vis) {
significantTransitions.insert(petri.transition[idx].id);
}
// 对于Fireability约简,我们需要识别出变迁的输入库所
// 因为变迁能否激活取决于其所有输入库所是否有足够的标记
for(const auto& transId : significantTransitions) {
const auto& trans = transitions[transId];
// 将变迁的所有输入库所标记为重要库所
for(const auto& [placeId, _] : trans.inPlaces) {
significantPlaces.insert(placeId);
}
}
}
for(auto i:significantPlaces){
DEBUG_INFO("significantPlaces: "<<i);
}
// for(auto i)
// cout<<endl;
}
void PetriStructureReducer::exportToPetri(Petri& petri) {
// 清理原有数据
delete[] petri.place;
delete[] petri.transition;
delete[] petri.unittable;
delete[] petri.nupnExtra;
// map<string,index_t> mapPlace;
// map<string,index_t> mapTransition;
bool& LONGBITPLACE = petri.LONGBITPLACE;
petri.mapPlace.clear();
petri.mapTransition.clear();
// 设置新的大小
petri.placecount = places.size();
petri.transitioncount = transitions.size();
petri.unitcount = units.size();
// 创建映射表
unordered_map<string, index_t> placeIndex;
unordered_map<string, index_t> transitionIndex;
unordered_map<string, index_t> unitIndex;
// 分配内存
petri.place = new Place[petri.placecount];
petri.transition = new Transition[petri.transitioncount];
if(petri.NUPN) {
petri.nupnExtra = new NUPN_extra[petri.placecount];
petri.unittable = new Unit[petri.unitcount];
// 导出unit
index_t unitIdx = 0;
for(const auto& unit : units) {
petri.unittable[unitIdx].uid = unit.first;
petri.unittable[unitIdx].size = unit.second.places.size();
unitIndex[unit.first] = unitIdx++;
}
} else {
petri.nupnExtra = nullptr;
petri.unittable = nullptr;
}
// 导出place
index_t placeIdx = 0;
for(const auto& p : places) {
const PetriPlace& place = p.second;
placeIndex[place.id] = placeIdx;
petri.mapPlace[place.id] = placeIdx;
petri.place[placeIdx].id = place.id;
petri.place[placeIdx].initialMarking = place.tokens;
petri.place[placeIdx].atomicLinks = place.atomicLinks;
// 临时存储,等所有索引建立后再填充
if(petri.NUPN) {
petri.nupnExtra[placeIdx].myunit = unitIndex[place.unitId];
} else {
// petri.nupnExtra[placeIdx].myunit = -1;
}
placeIdx++;
}
// 导出transition
index_t transIdx = 0;
for(const auto& t : transitions) {
const PetriTransition& trans = t.second;
transitionIndex[trans.id] = transIdx;
petri.mapTransition[trans.id] = transIdx;
petri.transition[transIdx].id = trans.id;
petri.transition[transIdx].significant = true;
transIdx++;
}
// 填充弧信息
for(const auto& p : places) {
const PetriPlace& place = p.second;
index_t pIdx = placeIndex[place.id];
// 处理入弧
for(const auto& arc : place.inTransitions) {
SArc sarc;
sarc.weight = arc.second;
sarc.idx = transitionIndex[arc.first];
petri.place[pIdx].producer.push_back(sarc);
}
// 处理出弧
for(const auto& arc : place.outTransitions) {
SArc sarc;
sarc.weight = arc.second;
sarc.idx = transitionIndex[arc.first];
petri.place[pIdx].consumer.push_back(sarc);
}
}
// 填充变迁的弧信息
for(const auto& t : transitions) {
const PetriTransition& trans = t.second;
index_t tIdx = transitionIndex[trans.id];
// 处理入弧
for(const auto& arc : trans.inPlaces) {
SArc sarc;
sarc.weight = arc.second;
sarc.idx = placeIndex[arc.first];
petri.transition[tIdx].producer.push_back(sarc);
}
// 处理出弧
for(const auto& arc : trans.outPlaces) {
SArc sarc;
sarc.weight = arc.second;
sarc.idx = placeIndex[arc.first];
petri.transition[tIdx].consumer.push_back(sarc);
}
}
// 计算unit相关的编码信息
if(petri.NUPN) {
index_t temp_len = 0;
index_t startpos = 0;
for(index_t i = 0; i < petri.unitcount; i++) {
petri.unittable[i].startpos = startpos;
petri.unittable[i].mark_sp = temp_len;
petri.unittable[i].mark_length = ceil(log2(petri.unittable[i].size + 1));
temp_len = temp_len + petri.unittable[i].mark_length;
}
// 计算place的编码信息
for(const auto& p : places) {
index_t pIdx = placeIndex[p.first];
const PetriUnit& unit = units[p.second.unitId];
auto it = unit.places.find(p.first);
index_t offset = distance(unit.places.begin(), it);
NUPN_extra& pe = petri.nupnExtra[pIdx];
const Unit& uu = petri.unittable[pe.myunit];
pe.myoffset = offset;
pe.intnum = uu.mark_sp / 32;
pe.intoffset = uu.mark_sp % 32;
pe.read_mask = (((mask_t)1 << uu.mark_length) - 1) << pe.intoffset;
pe.zero_mask = ~(pe.read_mask);
pe.write_mask = ((mask_t)pe.myoffset + 1) << pe.intoffset;
}
}
}
void PetriStructureReducer::printNetworkStatistics(const string& prefix) const {
DEBUG_INFO(prefix << "网络统计信息:");
DEBUG_INFO(prefix << "- 库所数量: " << places.size());
DEBUG_INFO(prefix << "- 变迁数量: " << transitions.size());
DEBUG_INFO(prefix << "- 单元数量: " << units.size());
DEBUG_INFO(prefix << "- 重要库所数量: " << significantPlaces.size());
// 计算弧的总数
size_t totalArcs = 0;
for(const auto& [_, trans] : transitions) {
totalArcs += trans.inPlaces.size() + trans.outPlaces.size();
}
DEBUG_INFO(prefix << "- 弧数量: " << totalArcs);
}
string PetriStructureReducer::getTransitionSignature(const PetriTransition& trans) const {
// Step 1: Collect and sort input arcs (place ID and weight)
// Use vector of pairs and sort by place ID string
vector<pair<string, int>> sortedInArcs(trans.inPlaces.begin(), trans.inPlaces.end());
sort(sortedInArcs.begin(), sortedInArcs.end(), [](const auto& a, const auto& b){
return a.first < b.first; // Sort pairs based on the place ID (string comparison)
});
// Step 2: Collect and sort output arcs (place ID and weight)
vector<pair<string, int>> sortedOutArcs(trans.outPlaces.begin(), trans.outPlaces.end());
sort(sortedOutArcs.begin(), sortedOutArcs.end(), [](const auto& a, const auto& b){
return a.first < b.first; // Sort pairs based on the place ID (string comparison)
});
// Step 3: Build the signature string
// Format: "in:pID1:w1,pID2:w2|out:pID3:w3,pID4:w4"
string signature = "in:";
for (const auto& p_w : sortedInArcs) {
signature += p_w.first + ":" + to_string(p_w.second) + ",";
}
// Remove the trailing comma if there were input places
if (!sortedInArcs.empty()) {
signature.pop_back();
}
signature += "|out:";
for (const auto& p_w : sortedOutArcs) {
signature += p_w.first + ":" + to_string(p_w.second) + ",";
}
// Remove the trailing comma if there were output places
if (!sortedOutArcs.empty()) {
signature.pop_back();
}
return signature;
}
// -----------------------------------------------------------------------------
// Rule Lpre: Remove strictly identical duplicate transitions.
// This rule groups transitions by their arc signatures and removes all but one
// transition from each group of duplicates, unless any transition in the group
// is marked as significant. This should be applied before other reduction rules
// like Rule L to handle duplicates cleanly.
// -----------------------------------------------------------------------------
int PetriStructureReducer::removeDuplicateTransitionsRuleLpre() {
int count = 0; // Counter for removed transitions
// Map to group transition IDs by their unique signature
// Key: signature string, Value: vector of transition IDs with that signature
unordered_map<string, vector<string>> signatureToTransitionIds;
// List of transition IDs that are marked for removal
vector<string> toRemove;
// Step 1: Group transitions by their signature
// Iterate through all transitions in the net
for (const auto& [transId, trans] : transitions) {
// Get the unique signature for the current transition
string signature = getTransitionSignature(trans);
// Add the transition's ID to the vector associated with this signature
signatureToTransitionIds[signature].push_back(transId);
}
// Step 2: Identify duplicate groups and mark transitions for removal
// Iterate through the map of signatures to transition lists
for (const auto& [signature, transIds] : signatureToTransitionIds) {
// If a signature maps to more than one transition ID, these are duplicates
if (transIds.size() > 1) {
bool hasSignificant = false;
// Check if *any* transition within this group of duplicates is marked as significant
for (const string& transId : transIds) {
if (significantTransitions.count(transId)) {
hasSignificant = true;
break; // Found a significant transition, we should keep all duplicates in this group
}
}
// If the group does NOT contain any significant transition, mark duplicates for removal
if (!hasSignificant) {
// We keep the first transition in the list (arbitrary choice as the representative)
// Mark all subsequent transitions in the list for removal
for (size_t i = 1; i < transIds.size(); ++i) {
// Add the ID to the toRemove list
toRemove.push_back(transIds[i]);
}
}
// If hasSignificant is true, the entire group of duplicates is kept. Do nothing here.
}
}
// Step 3: Perform the actual removal of marked transitions
// Iterate through the list of transitions to remove
for (const string& transId : toRemove) {
// Safety check: Double-check that the transition is not significant before removing.
// Based on the logic in Step 2 (hasSignificant), this check should theoretically
// always pass for transitions in the 'toRemove' list, but it adds robustness.
if (significantTransitions.find(transId) == significantTransitions.end()) {
// Call the function to remove the transition from the net structure
eraseTransition(transId); // Assumes eraseTransition correctly updates transitions map, arcs, and place connections
count++; // Increment the counter for successfully removed transitions
}
}
// Return the total number of duplicate transitions removed
return count;
}
void PetriStructureReducer::reduce(string &applyrules, int time_limit_reduce, bool contains_next, bool all_ltl) {
// 在约简开始前打印统计信息
DEBUG_INFO("约简前:");
printNetworkStatistics(" ");
int total = 0;
double allTime = 0;
// 执行各种约简操作
int count;
auto start = chrono::high_resolution_clock::now();
// 根据LTL属性的特性确定约简策略
bool changed = true;
bool RQ = false;
//限时
auto periodicEnd = chrono::high_resolution_clock::now();
auto periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
int duplicatesRemoved = removeDuplicateTransitionsRuleLpre();
DEBUG_INFO("Removed " << duplicatesRemoved << " duplicate transitions.");
// cout << "Removed " << duplicatesRemoved << " duplicate transitions." << endl;
do {
restart:
// 如果LTL公式不包含NEXT操作符,可以应用更多规则
if (!contains_next) {
// 应用规则I AutoFlight-PT-06b-LTLFireability-08
if(applyrules.find("i") != string::npos) {
// count = removeIrrelevantElements();
changed = (count > 0);
// cout << "irrelevant_elements countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
}
// 应用规则J(GCD约简)- 这个规则对所有类型的公式都适用
if(applyrules.find("j") != string::npos) {
// count = reducePlaceWeightsByGCD();
changed |= (count > 0);
// DEBUG_INFO("reducePlaceWeightsByGCD countsum:" << count);
// cout << "reduce_weights_by_gcd countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
do {
do {
// 首先应用不移动标记的规则
changed = false;
// 规则E和规则N都不会改变网络的行为
// E对于识别和移除死变迁是不完全的
if(applyrules.find("e") != string::npos) {
count = applyRuleE();
changed |= (count > 0);
DEBUG_INFO("rule_e countsum:" << count);
// cout << "rule_e countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则N 疑似有bug, CSRepetitions-PT-02-LTLCardinality 验证
if(applyrules.find("n") != string::npos) {
// count = removeNonDisablingArcs();
changed |= (count > 0);
// cout << "non_disabling_arcs countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 应用规则C
if(applyrules.find("c") != string::npos) {
count = applyRuleFusionParallelPlaces();
changed |= (count > 0);
DEBUG_INFO("rule_c countsum:" << count);
// cout << "rule_c countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 基于公式特性应用规则
if (!contains_next) {
// 规则F(冗余库所)可能会影响循环结构
if(applyrules.find("f") != string::npos) {
count = removeRedundantPlacesRuleF();
changed |= (count > 0);
DEBUG_INFO("redundant_places_rule_f countsum:" << count);
// cout << "redundant_places_rule_f countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则G(冗余变迁) AutonomousCar-PT-02b-LTLFireability-09
if(applyrules.find("g") != string::npos) {
// count = removeRedundantTransitionsRuleG();
changed |= (count > 0);
// cout << "redundant_transitions_rule_g countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则D(变迁融合)
if(applyrules.find("d") != string::npos) {
count = applyRuleD();
changed |= (count > 0);
DEBUG_INFO("rule_d countsum:" << count);
// cout << "rule_d countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
}
} while (changed);
// 应用可能移动标记的规则
if (!contains_next) {
// 规则B(串行变迁合并)疑似有bug,BridgeAndVehicles-PT-V04P05N02-LTLCardinality 验证
if(applyrules.find("b") != string::npos) {
// count = applyRuleB();
changed |= (count > 0);
// cout << "rule_b countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则A(变迁扩展)
if(applyrules.find("a") != string::npos) {
count = applyRuleA();
changed |= (count > 0);
DEBUG_INFO("rule_a countsum:" << count);
// cout << "rule_a countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
}
} while (changed);
// 应用规则L(结构等价变迁合并)DES-PT-00a-LTLCardinality-03 验证 AutonomousCar-PT-02b-LTLFireability-09
if(applyrules.find("l") != string::npos) {
// count = removeRedundantTransitionsRuleL();
changed |= (count > 0);
// cout << "redundant_transitions_rule_l countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 对于不包含NEXT的LTL公式,可以应用更多高级规则
if (!contains_next && !changed) {
// 规则H(处理自循环)
if(applyrules.find("h") != string::npos) {
// bool ruleHApplied = applyRuleH();
// changed |= ruleHApplied;
// if (ruleHApplied) {
// cout << "rule_h applied" << endl;
// }
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则S(复杂结构替换)
if(applyrules.find("s") != string::npos) {
// count = applyRuleS();
changed |= (count > 0);
// cout << "rule_s countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
// 规则R(后置聚合)- 作为最后的手段
if(applyrules.find("r") != string::npos) {
// count = applyRuleR();
changed |= (count > 0);
DEBUG_INFO("rule_r countsum:" << count);
// cout << "rule_r countsum:" << count << endl;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
}
// 规则Q可能会让之前应用不了的规则变得可以应用
if(applyrules.find("q") != string::npos) {
if (!changed && !RQ && !contains_next) {
RQ = (applyRuleQ() > 0);
if (RQ) {
DEBUG_INFO("rule_q applied, restarting...");
// cout << "rule_q applied, restarting..." << endl;
goto restart;
}
}
RQ = false;
periodicEnd = chrono::high_resolution_clock::now();
periodicDuration = chrono::duration_cast<chrono::milliseconds>(periodicEnd - start);
if (periodicDuration.count() > time_limit_reduce * 1000) {
// cout << "时间限制到达,停止约简" << endl;
return;
}
}
total += count;
} while (changed);
auto end = chrono::high_resolution_clock::now();
allTime = chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1000000.0;
// 在约简结束后打印统计信息
DEBUG_INFO("约简后:");
printNetworkStatistics(" ");
// 计算减少的百分比
// cout << "\n约简效果:" << endl;
// cout << "- 总约简次数: " << total << endl;
// cout << "- 总约简时间: " << allTime << " ms" << endl;
}
struct ReductionUnit {
string transId; // 要删除的变迁
string inputPlaceId; // 输入库所
weight_t inputPlaceTokens; // 输入库所的标识数
unordered_map<string, weight_t> inTransToWeight; // 输入变迁及其权重
unordered_map<string, weight_t> outPlaceToWeight; // 输出库所及其权重
};
// 检查是否可以应用规则 A
bool PetriStructureReducer::canApplyRuleA(const string& transId, string& prePlace) {
// 检查变迁是否存在
if (transitions.find(transId) == transitions.end()) return false;
const PetriTransition& trans = transitions.at(transId);
// A1: 检查是否只有一个输入库所
if (trans.inPlaces.size() != 1) return false;
// 获取唯一的输入库所
prePlace = trans.inPlaces.begin()->first;
// 检查输入库所是否存在
if (places.find(prePlace) == places.end()) return false;
const PetriPlace& pre = places.at(prePlace);
// A5: 检查 pre 是否不是重要库所 (提前检查以避免不必要的后续检查)
if (significantPlaces.find(prePlace) != significantPlaces.end()) return false;
// A2: 检查输入库所是否只连接到这个变迁
if (pre.outTransitions.size() != 1 || pre.outTransitions.begin()->first != transId) return false;
// 获取弧 pre -> trans 的权重
weight_t w = trans.inPlaces.at(prePlace);
// A3: 检查输入弧权重条件 (所有到 pre 的生产者变迁的权重是否是 w 的倍数)
for (const auto& inTrans : pre.inTransitions) {
if (inTrans.second % w != 0) return false;
}
// A3 (cont.): 检查 pre 的初始标记是否可以被 w 整除
if (pre.tokens % w != 0) return false;
// A4: 检查 pre 是否不在 trans 的输出库所中 (非自循环)
if (trans.outPlaces.find(prePlace) != trans.outPlaces.end()) return false;
// A6: 检查 trans 的输出库所是否都不是重要库所
for (const auto& outPlace : trans.outPlaces) {
if (significantPlaces.find(outPlace.first) != significantPlaces.end()) return false;
}
return true;
}
// 应用规则 A 进行约简
int PetriStructureReducer::applyRuleA() {
int count = 0;
vector<string> toRemove;
// 预先收集所有变迁ID
vector<string> allTransIds;
allTransIds.reserve(transitions.size());
for (const auto& pair : transitions) {
allTransIds.push_back(pair.first);
}
// 查找可约简的变迁
for (const string& transId : allTransIds) {
string prePlace;
if (canApplyRuleA(transId, prePlace)) {
// 执行约简
// if (prePlace != "start") continue;
const PetriTransition& trans = transitions[transId];
PetriPlace& pre = places[prePlace];
weight_t w = trans.inPlaces.at(prePlace);
// UA1: 更新所有输出库所的初始标识
for (const auto& outPlace : trans.outPlaces) {
places[outPlace.first].tokens += (pre.tokens / w) * outPlace.second;
}
// UA2: 为每个输入变迁建立到输出库所的新连接
for (const auto& inTrans : pre.inTransitions) {
PetriTransition& inTransition = transitions[inTrans.first];
weight_t sourceWeight = inTrans.second;
// 对于每个输出库所
for (const auto& outPlace : trans.outPlaces) {
weight_t newWeight = (sourceWeight / w) * outPlace.second;
// 更新或创建连接
if (inTransition.outPlaces.find(outPlace.first) != inTransition.outPlaces.end()) {
inTransition.outPlaces[outPlace.first] += newWeight;
} else {
inTransition.outPlaces[outPlace.first] = newWeight;
}
// 更新输出库所的输入变迁
if (places[outPlace.first].inTransitions.find(inTrans.first) != places[outPlace.first].inTransitions.end()) {
places[outPlace.first].inTransitions[inTrans.first] += newWeight; // 累加,不要覆盖
} else {
places[outPlace.first].inTransitions[inTrans.first] = newWeight;
}
// places[outPlace.first].inTransitions[inTrans.first] = inTransition.outPlaces[outPlace.first];
}
// 删除输入变迁到 pre 的连接
inTransition.outPlaces.erase(prePlace);
}
// 删除所有输出库所到变迁的连接
for (const auto& outPlace : trans.outPlaces) {
places[outPlace.first].inTransitions.erase(transId);
}
// 删除 pre 和变迁
erasePlace(prePlace);
toRemove.push_back(transId);
count++;
break;
}
}
// 删除所有标记的变迁
for (const string& transId : toRemove) {
eraseTransition(transId);
}
return count;
}
// 检查是否可以应用规则 B
bool PetriStructureReducer::canApplyRuleB(const string& placeId, string& inTransId, string& outTransId) {
const PetriPlace& place = places[placeId];
// B2: 检查是否只有一个消费者变迁和至少一个生产者变迁
if (place.outTransitions.size() != 1 || place.inTransitions.empty()) {
return false;
}
// 获取唯一的消费者变迁
inTransId = place.outTransitions.begin()->first;
// 检查消费者变迁是否是重要变迁
if (significantTransitions.find(inTransId) != significantTransitions.end()) {
return false;
}
// 检查每个生产者变迁
for (const auto& inTrans : place.inTransitions) {
outTransId = inTrans.first;
// B1: 检查生产者不是消费者
if (outTransId == inTransId) {
continue;
}
// 检查生产者变迁是否是重要变迁
if (significantTransitions.find(outTransId) != significantTransitions.end()) {
continue;
}
const PetriTransition& in = transitions[inTransId];
const PetriTransition& out = transitions[outTransId];
// 检查至少一个变迁是单一的
if (out.outPlaces.size() != 1 && in.inPlaces.size() != 1) {
continue;
}
// 如果库所有初始标记且输入变迁不是单一的,则跳过
if (place.tokens > 0 && in.inPlaces.size() != 1) {
continue;
}
// B3: 检查输出权重是输入权重的倍数且非零
weight_t inWeight = place.outTransitions.at(inTransId);
weight_t outWeight = inTrans.second;
if (outWeight < inWeight || (outWeight % inWeight) != 0) {
continue;
}
// B5: 检查库所是否不是重要库所
if (significantPlaces.find(placeId) != significantPlaces.end()) {
continue;
}
// B6: 检查消费变迁的后置集中的库所是否不是重要库所
bool postOk = true;
for (const auto& outPlace : in.outPlaces) {
if (significantPlaces.find(outPlace.first) != significantPlaces.end()) {
postOk = false;
break;
}
}
if (!postOk) continue;
// B7: 检查消费变迁的前置集中的库所是否不是重要库所
bool preOk = true;
for (const auto& inPlace : in.inPlaces) {
if (significantPlaces.find(inPlace.first) != significantPlaces.end()) {
preOk = false;
break;
}
}
if (!preOk) continue;
// B2.a: 检查除了p之外没有其他库所给到消费变迁tIn
const auto& arcs = in.inPlaces.size() < out.outPlaces.size() ? in.inPlaces : out.outPlaces;
for (const auto& arc : arcs) {
if (arc.first != placeId && arc.second > 0) {
return false;
}
}
return true;
}
return false;
}
// 应用规则 B 进行约简
int PetriStructureReducer::applyRuleB() {