1
/* PeTe - Petri Engine exTremE
2
* Copyright (C) 2011 Jonas Finnemann Jensen <jopsen@gmail.com>,
3
* Thomas Søndersø Nielsen <primogens@gmail.com>,
4
* Lars Kærlund Østergaard <larsko@gmail.com>,
6
* This program 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 3 of the License, or
9
* (at your option) any later version.
11
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
21
#include "PQL/Contexts.h"
22
#include "Structures/State.h"
29
namespace PetriEngine{
31
PetriNet::PetriNet(int places, int transitions, int variables)
32
: _places(places), _transitions(transitions), _variables(variables) {
33
//Store size for later
35
_nTransitions = transitions;
36
_nVariables = variables;
38
//Allocate space for ranges
39
_ranges = new VarVal[variables];
41
//Allocate space for conditions and assignments
42
size_t s = (sizeof(PQL::Condition*) + sizeof(PQL::AssignmentExpression*)) * transitions;
43
char* d = new char[s];
45
_conditions = (PQL::Condition**)d;
46
_assignments = (PQL::AssignmentExpression**)(d + sizeof(PQL::Condition*)*transitions);
48
//Allocate transition matrix
49
_tm = new MarkVal[places * transitions * 2];
50
for(int i = 0; i < places * transitions * 2; i++)
54
PetriNet::~PetriNet(){
61
//Conditions and assignments is allocated in the same block
63
delete[] (char*)_conditions;
68
bool PetriNet::fire(unsigned int t,
72
VarVal* result_a) const{
75
!_conditions[t]->evaluate(PQL::EvaluationContext(m, a)))
78
const MarkVal* tv = _tv(t);
79
//Check that we can take from the marking
80
for(size_t i = 0; i < _nPlaces; i++){
81
result_m[i] = m[i] - tv[i];
85
//Add stuff that the marking gives us
86
for(size_t i = 0; i < _nPlaces; i++)
87
result_m[i] += tv[i+_nPlaces];
91
_assignments[t]->evaluate(m, a, result_a, _ranges, _nVariables);
93
memcpy(result_a, a, sizeof(VarVal) * _nVariables);
98
bool PetriNet::fire(unsigned int t,
99
const Structures::State* s,
100
Structures::State* ns,
103
//Check the condition
105
!_conditions[t]->evaluate(PQL::EvaluationContext(s->marking(), s->valuation())))
108
// We can handle multiplicity if there's conditions or assignments on the transition
109
if((_conditions[t] && multiplicity != 1) || (_assignments[t] && multiplicity != 1))
112
const MarkVal* tv = _tv(t);
113
//Check that we can take from the marking
115
for(size_t i = 0; i < _nPlaces; i++){
116
ns->marking()[i] = s->marking()[i] - tv[i] * multiplicity;
117
sum += ns->marking()[i];
118
if(ns->marking()[i] < 0)
121
//Check that we're within k-bound
122
if(kbound != 0 && sum > kbound)
125
//Add stuff that the marking gives us
126
for(size_t i = 0; i < _nPlaces; i++)
127
ns->marking()[i] += tv[i+_nPlaces] * multiplicity;
131
_assignments[t]->evaluate(s->marking(), s->valuation(), ns->valuation(), _ranges, _nVariables);
133
memcpy(ns->valuation(), s->valuation(), sizeof(VarVal) * _nVariables);
138
void PetriNet::fireWithoutCheck(unsigned int t,
143
int multiplicity) const {
144
//Don't check conditions
146
// Do assignment first, so that we can allow m0 == m2 and a0 == a2
147
// e.g. reuse of memory...
148
//Assume that multiplicity is zero if there's an assignment
150
_assignments[t]->evaluate(m0, a0, a2, _ranges, _nVariables);
152
memcpy(a2, a0, sizeof(VarVal) * _nVariables);
154
const MarkVal* tv = _tv(t);
155
//Check that we can take from the marking
156
for(size_t i = 0; i < _nPlaces; i++)
157
m2[i] = m0[i] - tv[i] * multiplicity + tv[i+_nPlaces] * multiplicity;
160
bool PetriNet::fireWithMarkInf(unsigned int t,
164
VarVal* result_a) const{
165
//Check the condition
166
if(_conditions[t] && //TODO: Use evaluate that respects MarkInf
167
!_conditions[t]->evaluate(PQL::EvaluationContext(m, a)))
170
const MarkVal* tv = _tv(t);
171
//Check that we can take from the marking
172
for(size_t i = 0; i < _nPlaces; i++){
175
result_m[i] = m[i] - tv[i];
179
//Add stuff that the marking gives us
180
for(size_t i = 0; i < _nPlaces; i++){
183
result_m[i] += tv[i+_nPlaces];
187
if(_assignments[t]) //TODO: Use evaluate that respects MarkInf
188
_assignments[t]->evaluate(m, a, result_a, _ranges, _nVariables);
190
memcpy(result_a, a, sizeof(VarVal) * _nVariables);
195
int PetriNet::inArc(unsigned int place, unsigned int transition) const{
196
return _tv(transition)[place];
199
int PetriNet::outArc(unsigned int transition, unsigned int place) const{
200
return _tv(transition)[place + _nPlaces];