diff --git a/CPNCalc.jl b/CPNCalc.jl new file mode 100644 index 0000000000000000000000000000000000000000..c3e732924cd04dcb6084500ee781eecfcb408cdb --- /dev/null +++ b/CPNCalc.jl @@ -0,0 +1,164 @@ +module CPNCalc + +export runPN + +using ..context +using ..ContextualPNs + +function nonNeg(x) + sign.(sign.(x) .+ 1) +end + +function pos(x) + sign.(sign.(x) .- 1) .+ 1 +end + +function neg(x) + 1 .- nonNeg(x) +end + +function matrixify(v, N) + transpose(transpose(v) .* ones(N)) +end + +function runPN(W_i::AbstractArray, W_o::AbstractArray, W_inhibitor::AbstractArray, W_test::AbstractArray, t::AbstractArray, P::AbstractArray) + while true + T = matrixify(t, size(W_i)[2]) + f_normal = nonNeg(findmin(T .- W_o, dims=1)[1]) + f_inhibitor = neg(findmax(T .- W_inhibitor, dims=1)[1]) + f_test = nonNeg(findmin(T .- W_test, dims=1)[1]) + f = f_normal .* f_inhibitor .* f_test + c = neg(t .- W_o * transpose(f)) + + while sum(c) > 0 + m = findmax(P, dims=1)[1] + f = f .- pos(findmax(P .- matrixify(m, size(W_i)[2]) .+ matrixify(c, size(W_i)[2]), dims=2)[1]) + c = neg(t .- W_o * transpose(f)) + end + if sum((W_i .- W_o) * transpose(f)) == 0 + break + end + t = t .+ (W_i .- W_o) * transpose(f) + println("Token Vector: ", t) + end +end + +function runPN(pn::CompiledPetriNet, activeContexts::AbstractVector=[]) + if activeContexts == [] + a = zeros(size(pn.ContextMatrix)[2]) + elseif activeContexts isa AbstractVector{Int} + if size(activeContexts)[2] != size(pn.ContextMatrix)[2] + print("ERROR") + end + elseif activeContexts isa AbstractVector{String} + a = zeros(size(pn.ContextMatrix)[2]) + for context in activeContexts + a[pn.ContextMap[context]] = 1 + end + elseif activeContexts isa AbstractVector{<:Context} + a = zeros(size(pn.ContextMatrix)[2]) + for context in activeContexts + a[pn.ContextMap[context]] = 1 + end + end + + FL = Vector{Context}(undef, size(pn.ContextMatrix)[2]) + for context in keys(pn.ContextMap) + FL[pn.ContextMap[context]] = context + end + while true + T = matrixify(pn.tokenVector, size(pn.WeightMatrix_in)[2]) + f_normal = nonNeg(findmin(T .- pn.WeightMatrix_out, dims=1)[1]) + f_inhibitor = neg(findmax(pn.WeightMatrix_inhibitor .* (T .- pn.WeightMatrix_inhibitor), dims=1)[1]) + f_test = nonNeg(findmin(T .- pn.WeightMatrix_test, dims=1)[1]) + f_context = nonNeg(transpose(pn.ContextMatrix * a - pn.ContextMatrix * ones(size(pn.ContextMatrix)[2]))) + f = f_normal .* f_inhibitor .* f_test .* f_context + c = neg(pn.tokenVector .- pn.WeightMatrix_out * transpose(f)) + while sum(c) > 0 + m = findmax(pn.PrioritiesMatrix, dims=2)[1] + f = f .- pos(findmax(pn.PrioritiesMatrix .- matrixify(m, size(pn.WeightMatrix_in)[2]) .+ matrixify(c, size(pn.WeightMatrix_in)[2]), dims=1)[1]) + c = neg(pn.tokenVector .- pn.WeightMatrix_out * transpose(f)) + end + if sum(f) == 0 + println("Petri net is dead.") + break + end + u = sign.(pn.UpdateMatrix * transpose(f)) + a = pos(a + u) + for context in FL[Bool.(dropdims(a, dims=2))] + activateContext(context) + end + for context in FL[Bool.(dropdims((a .- 1).^2, dims=2))] + deactivateContext(context) + end + pn.tokenVector = vec(pn.tokenVector .+ (pn.WeightMatrix_in .- pn.WeightMatrix_out) * transpose(f)) + println("Token Vector: ", pn.tokenVector, " active Contexts: ", FL[Bool.(dropdims(a, dims=2))]) + end +end + +""" +function runPN(pn::CompiledPetriNet, activeContexts::AbstractVector=[]) + W_i = pn.WeightMatrix_in + W_o = pn.WeightMatrix_out + W_inhibitor = pn.WeightMatrix_inhibitor + W_test = pn.WeightMatrix_test + P = pn.PrioritiesMatrix + t = pn.tokenVector + F = pn.ContextMatrix + U = pn.UpdateMatrix + CM = pn.ContextMap + + if activeContexts == [] + a = zeros(size(F)[2]) + elseif activeContexts isa AbstractVector{Int} + if size(activeContexts)[2] != size(F)[2] + print("ERROR") + end + elseif activeContexts isa AbstractVector{String} + a = zeros(size(F)[2]) + for context in activeContexts + a[CM[context]] = 1 + end + elseif activeContexts isa AbstractVector{<:Context} + a = zeros(size(F)[2]) + for context in activeContexts + a[CM[context]] = 1 + end + end + + FL = Vector{Context}(undef, size(F)[2]) + for context in keys(CM) + FL[CM[context]] = context + end + while true + T = matrixify(t, size(W_i)[2]) + f_normal = nonNeg(findmin(T .- W_o, dims=1)[1]) + f_inhibitor = neg(findmax(W_inhibitor .* (T .- W_inhibitor), dims=1)[1]) + f_test = nonNeg(findmin(T .- W_test, dims=1)[1]) + f_context = nonNeg(transpose(F * a - F * ones(size(F)[2]))) + f = f_normal .* f_inhibitor .* f_test .* f_context + c = neg(t .- W_o * transpose(f)) + while sum(c) > 0 + m = findmax(P, dims=2)[1] + f = f .- pos(findmax(P .- matrixify(m, size(W_i)[2]) .+ matrixify(c, size(W_i)[2]), dims=1)[1]) + c = neg(t .- W_o * transpose(f)) + end + if sum(f) == 0 + println("Petri net is dead.") + break + end + u = sign.(U * transpose(f)) + a = pos(a + u) + for context in FL[Bool.(dropdims(a, dims=2))] + activateContext(context) + end + for context in FL[Bool.(dropdims((a .- 1).^2, dims=2))] + deactivateContext(context) + end + t = t .+ (W_i .- W_o) * transpose(f) + println("Token Vector: ", t, " active Contexts: ", FL[Bool.(dropdims(a, dims=2))]) + end +end +""" + +end \ No newline at end of file diff --git a/ContextualPNs.jl b/ContextualPNs.jl new file mode 100644 index 0000000000000000000000000000000000000000..1f79b073653ba4b2a994d778b2f3b151c77d85c9 --- /dev/null +++ b/ContextualPNs.jl @@ -0,0 +1,133 @@ +module ContextualPNs +using ..context + +export CompiledPetriNet, PetriNet, place, continuousTransition, discreteTransition, normalArc, inhibitorArc, testArc, compile, on, off, update, context + +abstract type PNObject end + +mutable struct place <: PNObject + const name::String + token::Real +end + +@enum UpdateValue on off + +mutable struct update + context::Context + updateValue::UpdateValue +end + +abstract type transition <: PNObject end +Base.@kwdef struct discreteTransition <: transition + name::String + contexts::Union{AbstractArray{<:Context}, AbstractArray{Any}} = [] + updates::AbstractArray{update} +end +struct continuousTransition <: transition + name::String +end + +# Fuzzy Transition? + +abstract type arc end + +Base.@kwdef mutable struct normalArc <: arc + const from::PNObject + const to::PNObject + weight::Real + priority::Int = 0 +end +mutable struct inhibitorArc <: arc + const from::place + const to::transition + weight::Real +end +mutable struct testArc <: arc + const from::place + const to::transition + weight::Real +end + +struct PetriNet + places::Vector{place} + transitions::Vector{<:transition} + arcs::Vector{<:arc} +end + +mutable struct CompiledPetriNet + WeightMatrix_in::Matrix + WeightMatrix_out::Matrix + WeightMatrix_inhibitor::Matrix + WeightMatrix_test::Matrix + tokenVector::Vector + PrioritiesMatrix::Matrix + ContextMatrix::Matrix + UpdateMatrix::Matrix + ContextMap::Dict +end + +function compile(pn::PetriNet) + # should test here if name is given two times + # should test here if arcs are connected correctly (not place to place etc.) + np = length(pn.places) # number of places + nt = length(pn.transitions) # number of transitions + nc = 0 # number of contexts + W_i = zeros(Float64, np, nt) # Input Arc weights matrix (to place) + W_o = zeros(Float64, np, nt) # Output Arc weights matrix(from place) + W_inhibitor = zeros(Float64, np, nt) .+ Inf # Inhibitor Arc weights matrix + W_test = zeros(Float64, np, nt) # Test Arc weights matrix + t = zeros(Float64, np) # Token vector + P = zeros(Float64, np, nt) # Priority matrix + pdict = Dict() # dictionary of places and corresponding index + tdict = Dict() # dictionary of transitions and corresponding index + fdict = Dict() # dictionary of contexts and corresponding index + + for (i, place) in enumerate(pn.places) + t[i] = place.token + pdict[place.name] = i + end + for (i, transition) in enumerate(pn.transitions) + tdict[transition.name] = i + for context in transition.contexts + if !(context in keys(fdict)) + nc += 1 + fdict[context] = nc + end + end + end + F = zeros(Float64, nt, nc) # Context matrix + U = zeros(Float64, nc, nt) # Update matrix + for transition in pn.transitions + for context in transition.contexts + F[tdict[transition.name], fdict[context]] = 1 + end + for update in transition.updates + if update.updateValue == on + U[fdict[update.context], tdict[transition.name]] = 1 + else + U[fdict[update.context], tdict[transition.name]] = -1 + end + end + end + for arc in pn.arcs + if arc.from isa place + if arc isa normalArc + W_o[pdict[arc.from.name], tdict[arc.to.name]] = arc.weight + if !(arc.priority in P[pdict[arc.from.name]]) + P[pdict[arc.from.name], tdict[arc.to.name]] = arc.priority + else + print("check priority of place ", arc.from.name) + end + elseif arc isa inhibitorArc + W_inhibitor[pdict[arc.from.name], tdict[arc.to.name]] = arc.weight + else + W_test[pdict[arc.from.name], tdict[arc.to.name]] = arc.weight + end + else + W_i[pdict[arc.to.name], tdict[arc.from.name]] = arc.weight + end + end + CompiledPetriNet(W_i, W_o, W_inhibitor, W_test, t, P, F, U, fdict) +end + +end \ No newline at end of file diff --git a/contextPNModelling.jl b/contextPNModelling.jl new file mode 100644 index 0000000000000000000000000000000000000000..708790aff214946f26c3435428846d691d28419b --- /dev/null +++ b/contextPNModelling.jl @@ -0,0 +1,35 @@ +include("./context.jl") +include("./ContextualPNs.jl") +include("./CPNCalc.jl") +using .ContextualPNs +using .CPNCalc +using .context + +p1 = place("p1", 7) +p2 = place("p2", 0) +p3 = place("p3", 1) +@newContext C1 +@newContext C2 +t1 = discreteTransition("t1", [C1], []) +t2 = discreteTransition("t2", [C1, C2], []) +t3 = discreteTransition("t3", [], [update(C1, off)]) +arcs = [normalArc(p1, t1, 2, 1), + normalArc(t1, p2, 1, 1), + normalArc(p2, t3, 2, 1), + normalArc(t1, p3, 1, 1), + normalArc(t2, p1, 1, 1), + inhibitorArc(p3, t2, 3)] + + +pn = PetriNet([p1, p2, p3], [t1, t2, t3], arcs) +compiled_pn = compile(pn) +println("inital token:", compiled_pn.tokenVector) +println("0 ", getActiveContexts()) +runPN(compiled_pn, getActiveContexts()) +println("1 ", getActiveContexts()) +activateContext(C1) +println("inital token after reset C1:", compiled_pn.tokenVector) +println("2 ", getActiveContexts()) +runPN(compiled_pn, getActiveContexts()) +println("3 ", getActiveContexts()) +runPN(compiled_pn, getActiveContexts()) \ No newline at end of file