From 77642f158a17991a8c017cc8bc7922b1e75aaf4b Mon Sep 17 00:00:00 2001
From: Christian Gutsche <christian.gutsche@mailbox.tu-dresden.de>
Date: Tue, 30 Jan 2024 15:22:09 +0100
Subject: [PATCH] Big Update! Added Context Rules for Context Petri nets fire
 conditions. Roles renamed to Mixin, for later update in which Relational
 Mixins aka Roles are going to be added.

---
 CPNCalc.jl            | 146 ++++++++++++--------------------
 ContextualPNs.jl      | 104 +++++++++++++----------
 context.jl            | 190 ++++++++++++++++++++++++++++++------------
 contextExample.jl     |  64 +++++++++-----
 contextPNModelling.jl |  42 ++++++----
 5 files changed, 314 insertions(+), 232 deletions(-)

diff --git a/CPNCalc.jl b/CPNCalc.jl
index c3e7329..71792a5 100644
--- a/CPNCalc.jl
+++ b/CPNCalc.jl
@@ -21,57 +21,31 @@ 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)
+function runPN(pn::CompiledPetriNet)
+    nContexts = size(pn.ContextMatrices[1])[2]
+    nTransitions = size(pn.WeightMatrix_in)[2]
+    a = zeros(nContexts)
+    for context in getActiveContexts()
+        a[pn.ContextMap[context]] = 1
     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])
+    ContextVector = Vector{Union{<:Context, <:context.AbstractContextRule}}(undef, nContexts)
     for context in keys(pn.ContextMap)
-        FL[pn.ContextMap[context]] = context
+        ContextVector[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_context = zeros(1, nTransitions)
+        for i in 1:nTransitions
+            h1 = pos(transpose(pn.ContextMatrices[i]))
+            h2 = -neg(transpose(pn.ContextMatrices[i]))
+            b1 = (findmin(findmax(h1 .- (h1 .* matrixify(a, size(pn.ContextMatrices[i])[1])), dims=1)[1], dims=2)[1])[1] == 0
+            b2 = (findmax(findmin(h2 .* matrixify(a, size(pn.ContextMatrices[i])[1]), dims=1)[1], dims=2)[1])[1] == 0
+            f_context[1, i] = 1 * b1 * b2
+        end
         f = f_normal .* f_inhibitor .* f_test .* f_context
         c = neg(pn.tokenVector .- pn.WeightMatrix_out * transpose(f))
         while sum(c) > 0
@@ -85,80 +59,64 @@ function runPN(pn::CompiledPetriNet, activeContexts::AbstractVector=[])
         end
         u = sign.(pn.UpdateMatrix * transpose(f))
         a = pos(a + u)
-        for context in FL[Bool.(dropdims(a, dims=2))]
+        for context in ContextVector[Bool.(dropdims(a, dims=2))]
             activateContext(context)
         end
-        for context in FL[Bool.(dropdims((a .- 1).^2, dims=2))]
+        for context in ContextVector[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))])
+        println("Token Vector: ", pn.tokenVector, "   active Contexts: ", getActiveContexts())
     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  
+function runPN(pn::CompiledPetriNet, N::Int, activeContexts::AbstractVector=[])
+    nContexts = size(pn.ContextMatrices[1])[2]
+    nTransitions = size(pn.WeightMatrix_in)[2]
+    a = zeros(nContexts)
+    for context in getActiveContexts()
+        a[pn.ContextMap[context]] = 1
+    end
 
-    FL = Vector{Context}(undef, size(F)[2])
-    for context in keys(CM)
-        FL[CM[context]] = context
+    ContextVector = Vector{Union{<:Context, <:context.AbstractContextRule}}(undef, nContexts)
+    for context in keys(pn.ContextMap)
+        ContextVector[pn.ContextMap[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])))
+    for i in 1:N
+        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 = zeros(1, nTransitions)
+        for i in 1:nTransitions
+            h1 = pos(transpose(pn.ContextMatrices[i]))
+            h2 = -neg(transpose(pn.ContextMatrices[i]))
+            b1 = (findmin(findmax(h1 .- (h1 .* matrixify(a, size(pn.ContextMatrices[i])[1])), dims=1)[1], dims=2)[1])[1] == 0
+            b2 = (findmax(findmin(h2 .* matrixify(a, size(pn.ContextMatrices[i])[1]), dims=1)[1], dims=2)[1])[1] == 0
+            f_context[1, i] = 1 * b1 * b2
+        end
         f = f_normal .* f_inhibitor .* f_test .* f_context
-        c = neg(t .- W_o * transpose(f))
+        c = neg(pn.tokenVector .- pn.WeightMatrix_out * 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))
+            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.(U * transpose(f))
+        u = sign.(pn.UpdateMatrix * transpose(f))
         a = pos(a + u)
-        for context in FL[Bool.(dropdims(a, dims=2))]
+        for context in ContextVector[Bool.(dropdims(a, dims=2))]
             activateContext(context)
         end
-        for context in FL[Bool.(dropdims((a .- 1).^2, dims=2))]
+        for context in ContextVector[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))])
+        pn.tokenVector = vec(pn.tokenVector .+ (pn.WeightMatrix_in .- pn.WeightMatrix_out) * transpose(f))
+        println("Token Vector: ", pn.tokenVector, "   active Contexts: ", getActiveContexts())
     end
 end
-"""
 
-end
\ No newline at end of file
+end
diff --git a/ContextualPNs.jl b/ContextualPNs.jl
index 1f79b07..a494736 100644
--- a/ContextualPNs.jl
+++ b/ContextualPNs.jl
@@ -1,57 +1,51 @@
 module ContextualPNs
 using ..context
 
-export CompiledPetriNet, PetriNet, place, continuousTransition, discreteTransition, normalArc, inhibitorArc, testArc, compile, on, off, update, context
+export CompiledPetriNet, PetriNet, Place, Transition, NormalArc, InhibitorArc, TestArc, compile, on, off, Update
 
 abstract type PNObject end
 
-mutable struct place <: PNObject 
+mutable struct Place <: PNObject 
     const name::String
     token::Real
 end 
 
 @enum UpdateValue on off
 
-mutable struct update
+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 
+struct Transition <: PNObject 
     name::String
+    contexts::Union{<:Context, Any, <:context.AbstractContextRule}
+    updates::AbstractArray{Update}
 end
 
-# Fuzzy Transition?
+abstract type Arc end
 
-abstract type arc end
-
-Base.@kwdef mutable struct normalArc <: arc
+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
+mutable struct InhibitorArc <: Arc
+    const from::Place
+    const to::Transition
     weight::Real
 end
-mutable struct testArc <: arc
-    const from::place
-    const to::transition
+mutable struct TestArc <: Arc
+    const from::Place
+    const to::Transition
     weight::Real
 end
 
-struct PetriNet
-    places::Vector{place}
-    transitions::Vector{<:transition}
-    arcs::Vector{<:arc}
+Base.@kwdef mutable struct PetriNet
+    places::Vector{Union{Any, Place}} = []
+    transitions::Vector{Union{Any, Transition}} = []
+    arcs::Vector{Union{Any, <:Arc}} = []
 end
 
 mutable struct CompiledPetriNet
@@ -61,17 +55,43 @@ mutable struct CompiledPetriNet
     WeightMatrix_test::Matrix
     tokenVector::Vector
     PrioritiesMatrix::Matrix
-    ContextMatrix::Matrix
+    ContextMatrices::Vector
     UpdateMatrix::Matrix
     ContextMap::Dict
 end
 
+function genContextRuleMatrix(cr::T, cdict::Dict, nc::Int) where {T <: Union{Context, Any, context.AbstractContextRule}}
+    matrix = zeros(1, nc)
+    if typeof(cr) <: context.AbstractContextRule
+        if cr isa AndContextRule
+            a = genContextRuleMatrix(cr.c1, cdict, nc)
+            b = genContextRuleMatrix(cr.c2, cdict, nc)
+            matrix = nothing
+            c = 0
+            for i in 1:size(a)[1]
+                for j in 1:size(b)[1]
+                    findmin((a[i, :] .- b[j, :]) .* b[j, :])[1] < -1 ? c = zeros(1, size(a)[2]) : c = a[i, :] .+ b[j, :]
+                    c = reshape(c, 1, length(c))
+                    matrix == nothing ? matrix = [c;] : matrix = [matrix; c]
+                end            
+            end       
+        elseif cr isa OrContextRule
+            matrix = [genContextRuleMatrix(cr.c1, cdict, nc); genContextRuleMatrix(cr.c2, cdict, nc)]
+        else
+            matrix = -genContextRuleMatrix(cr.c, cdict, nc)
+        end
+    elseif typeof(cr) <: Context
+        matrix[cdict[cr]] = 1
+    end
+    matrix
+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
+    nc = length(getContexts())                          # 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
@@ -80,7 +100,7 @@ function compile(pn::PetriNet)
     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
+    cdict = Dict()                                      # dictionary of contexts and corresponding index
 
     for (i, place) in enumerate(pn.places)
         t[i] = place.token
@@ -88,37 +108,35 @@ function compile(pn::PetriNet)
     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
+    for (i, context) in enumerate(getContexts())
+        cdict[context] = i
+    end
+
+
+    C = nothing                                         # 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
+        c = sign.(genContextRuleMatrix(transition.contexts, cdict, nc))
+        C == nothing ? C = [c] : C = [C; [c]]
         for update in transition.updates
             if update.updateValue == on
-                U[fdict[update.context], tdict[transition.name]] = 1
+                U[cdict[update.context], tdict[transition.name]] = 1
             else
-                U[fdict[update.context], tdict[transition.name]] = -1
+                U[cdict[update.context], tdict[transition.name]] = -1
             end
         end 
     end
     for arc in pn.arcs
-        if arc.from isa place
-            if arc isa normalArc
+        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
+            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
@@ -127,7 +145,7 @@ function compile(pn::PetriNet)
             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)
+    CompiledPetriNet(W_i, W_o, W_inhibitor, W_test, t, P, C, U, cdict)
 end
 
 end
\ No newline at end of file
diff --git a/context.jl b/context.jl
index 9c9d5ac..f3a70ef 100644
--- a/context.jl
+++ b/context.jl
@@ -1,18 +1,19 @@
 module context
 
-export addContext, addRole, getContexts, getRoles, getRole, @newContext, @newRole, @context, assignRole, disassignRole, Context, Role
+export addContext, getActiveContexts, isActive, activateContext, deactivateContext, addMixin, getContexts, getMixins, getMixin, @newContext, @newMixin, @context, assignMixin, disassignMixin, Context, Mixin, AndContextRule, OrContextRule, NotContextRule
 
 using Parameters
 
-abstract type Role end
+abstract type Mixin end
 
 abstract type Context end
 
 @with_kw mutable struct ContextManagement
 	contexts::Vector{Context} = []
-	roles::Dict{Context, Dict{Any, Vector{DataType}}} = Dict()
-	roleTypeDB::Dict{Any, Dict{Context, DataType}} = Dict()
-	roleDB::Dict{Any, Dict{Context, Any}} = Dict()
+	activeContexts::Vector{Context} = []
+	mixins::Dict{Context, Dict{Any, Vector{DataType}}} = Dict()
+	mixinTypeDB::Dict{Any, Dict{Context, DataType}} = Dict()
+	mixinDB::Dict{Any, Dict{Context, Any}} = Dict()
 end
 
 global contextManager = ContextManagement()
@@ -23,40 +24,55 @@ end
 
 function addContext(context::T) where {T <: Context}
 	push!(contextManager.contexts, eval(context))
+	push!(contextManager.activeContexts, eval(context))
 end
 
-function addRole(context, contextualType, roleNameSymbol)
-	if (eval(context)) in keys(contextManager.roles)
-		if (eval(contextualType)) in keys(contextManager.roles[eval(context)])
-			push!(contextManager.roles[eval(context)][eval(contextualType)], eval(roleNameSymbol))
+function getActiveContexts()
+	contextManager.activeContexts
+end
+
+function activateContext(context::T) where {T <: Context}
+	if !(context in contextManager.activeContexts) push!(contextManager.activeContexts, eval(context)) end
+end
+
+function deactivateContext(context::T) where {T <: Context}
+	deleteat!(contextManager.activeContexts, findall(x->x==context, contextManager.activeContexts))
+end
+
+function isActive(context::T) where {T <: Context}
+	context in contextManager.activeContexts
+end
+
+function addMixin(context, contextualType, mixinNameSymbol)
+	if (context) in keys(contextManager.mixins)
+		if (contextualType) in keys(contextManager.mixins[context])
+			push!(contextManager.mixins[context][contextualType], mixinNameSymbol)
 		else
-			contextManager.roles[eval(context)][eval(contextualType)] = [eval(roleNameSymbol)]
+			contextManager.mixins[context][contextualType] = [mixinNameSymbol]
 		end
 	else
-		contextManager.roles[eval(context)] = Dict((eval(contextualType))=>[eval(roleNameSymbol)])
+		contextManager.mixins[context] = Dict((contextualType)=>[mixinNameSymbol])
 	end
 end
 
-function getRoles()
-	contextManager.roles
+function getMixins()
+	contextManager.mixins
 end
 
-function getRoles(type)
-	contextManager.roleDB[type]
+function getMixins(type)
+	contextManager.mixinDB[type]
 end
 
-function getRole(type, context::T) where {T <: Context}
-	(contextManager.roleDB[type])[context]
+function getMixin(type, context::T) where {T <: Context}
+	(contextManager.mixinDB[type])[context]
 end
 
 macro newContext(contextName)
 	if typeof(contextName) == String || typeof(contextName) == Symbol
-		if typeof(contextName) == Symbol
-			contextName = repr(contextName)[2:end]
+		if typeof(contextName) == String
+			contextName = Meta.parse(contextName)
 		end
-		contextNameString = contextName*"ContextType"
-		contextTypeNameSymbol = Meta.parse(contextNameString)
-		contextName = Meta.parse(contextName)
+		contextTypeNameSymbol = Symbol(contextName, :ContextType)
 
 		structDefExpr = :(struct $(contextTypeNameSymbol) <: Context end;)
 		SingletonDefExpr = :($(contextName) = $contextTypeNameSymbol())
@@ -67,57 +83,49 @@ macro newContext(contextName)
 	end
 end
 
-macro newRole(roleName, attributes, context, contextualType)
-	if endswith(repr(attributes), "))") || endswith(repr(attributes), "])")
-		attrString = "(" * replace(replace(repr(attributes)[4:end-2], ","=>";"), " => "=>"::") * ")"
-	else
-		attrString = "(" * replace(replace(repr(attributes)[3:end-1], ","=>";"), " => "=>"::") * ")"
-	end
-	
-	roleNameSymbol = Symbol(roleName)
-	attrString = attrString
 
-	attrExpr = @eval(Meta.parse($attrString))
+macro newMixin(mixin, attributes, context)
+	contextualType = Symbol(strip((split(repr(mixin), "<:")[2])[1:end-1]))
+	mixin = Symbol(strip((split(repr(mixin), " <: ")[1])[3:end]))
+	Base.remove_linenums!(attributes)
 
-	newStructExpr = :(struct $roleNameSymbol <: Role
-		$attrExpr
+	newStructExpr = :(struct $mixin <: Mixin
+		$attributes
 	end)
 
-	
-	return esc(:($newStructExpr; addRole($context, $contextualType, $roleNameSymbol)))
-	
+	return esc(:($newStructExpr; addMixin($context, $contextualType, $mixin)))
 end
 
-function assignRole(pair::Pair, context::T) where {T<:Context}
+function assignMixin(pair::Pair, context::T) where {T<:Context}
 	type = pair[1]
-	role = pair[2]
-	if type in keys(contextManager.roleDB)
-		if context in keys(contextManager.roleDB[type])
-			@warn(repr(type)*" already has Role in context "*repr(context)*". Previous Role will be overwritten!")
+	mixin = pair[2]
+	if type in keys(contextManager.mixinDB)
+		if context in keys(contextManager.mixinDB[type])
+			@warn(repr(type)*" already has Mixin in context "*repr(context)*". Previous Mixin will be overwritten!")
 		end
-		contextManager.roleDB[type][context] = role
+		contextManager.mixinDB[type][context] = mixin
 	else
-		contextManager.roleDB[type] = Dict(context => role)
+		contextManager.mixinDB[type] = Dict(context => mixin)
 	end
-	if type in keys(contextManager.roleTypeDB)
-		contextManager.roleTypeDB[type][context] = typeof(role)
+	if type in keys(contextManager.mixinTypeDB)
+		contextManager.mixinTypeDB[type][context] = typeof(mixin)
 	else
-		contextManager.roleTypeDB[type] = Dict(context => typeof(role))
+		contextManager.mixinTypeDB[type] = Dict(context => typeof(mixin))
 	end
 end
 
-function disassignRole(pair::Pair, context::T) where {T<:Context}
+function disassignMixin(pair::Pair, context::T) where {T<:Context}
 	type = pair[1]
-	role = pair[2]
-	if type in keys(contextManager.roleDB)
-		delete!(contextManager.roleDB[type], context)
+	mixin = pair[2]
+	if type in keys(contextManager.mixinDB)
+		delete!(contextManager.mixinDB[type], context)
 	else
-		error("Role is not assigned to type "*repr(type))
+		error("Mixin is not assigned to type "*repr(type))
 	end
-	if type in keys(contextManager.roleTypeDB)
-		delete!(contextManager.roleTypeDB[type], context)
+	if type in keys(contextManager.mixinTypeDB)
+		delete!(contextManager.mixinTypeDB[type], context)
 	else
-		error("Role is not assigned to type "*repr(type))
+		error("Mixin is not assigned to type "*repr(type))
 	end
 end
 
@@ -144,10 +152,82 @@ macro context(cname, expr)
 			end
 			callExpr = Meta.parse(callString)
 			return esc(eval(callExpr))
+		elseif expr.head == :macrocall
+			callString = repr(expr)
+			contextString = repr(cname)
+			callString = callString[3:end-1] * " " * contextString[2:end] 
+			callExpr = Meta.parse(callString)
+			return esc(callExpr)
 		else
 			error("Second argument of @context must be a function or function definition")
 		end
 	end
 end
 
+
+abstract type AbstractContextRule end
+
+struct AndContextRule <: AbstractContextRule
+	c1::Union{<:Context, <:AbstractContextRule}
+	c2::Union{<:Context, <:AbstractContextRule}
+end
+
+struct OrContextRule <: AbstractContextRule
+	c1::Union{<:Context, <:AbstractContextRule}
+	c2::Union{<:Context, <:AbstractContextRule}
+end
+
+struct NotContextRule <: AbstractContextRule
+	c::Union{<:Context, <:AbstractContextRule}
+end
+
+function isActive(contextRule::T) where {T <: AbstractContextRule}
+	if contextRule isa AndContextRule
+		isActive(contextRule.c1) & isActive(contextRule.c2)
+	elseif contextRule isa OrContextRule
+		isActive(contextRule.c1) | isActive(contextRule.c2)
+	else
+		!isActive(contextRule.c)
+	end
+end
+
+function getContextsOfRule(contextRule::T) where {T <: AbstractContextRule}
+	contexts = []
+	if ((contextRule isa AndContextRule) | (contextRule isa OrContextRule))
+		if typeof(contextRule.c1) <: AbstractContextRule
+			append!(contexts, getContextsOfRule(contextRule.c1))
+		else
+			append!(contexts, [contextRule.c1])
+		end
+		if typeof(contextRule.c2) <: AbstractContextRule
+			append!(contexts, getContextsOfRule(contextRule.c2))
+		else
+			append!(contexts, [contextRule.c2])
+		end
+	else
+		if typeof(contextRule.c) <: AbstractContextRule
+			append!(contexts, getContextsOfRule(contextRule.c))
+		else
+			append!(contexts, [contextRule.c])
+		end
+	end
+	union(contexts)
+end
+
+function isActive(context::Nothing)
+	true
+end
+
+function Base.:&(c1::CT1, c2::CT2) where {CT1, CT2 <: Union{Context, AbstractContextRule}}
+    AndContextRule(c1, c2)
+end
+
+function Base.:|(c1::CT1, c2::CT2) where {CT1, CT2 <: Union{Context, AbstractContextRule}}
+    OrContextRule(c1, c2)
+end
+
+function Base.:!(c::CT) where {CT <: Union{Context, AbstractContextRule}}
+    NotContextRule(c)
+end
+
 end
\ No newline at end of file
diff --git a/contextExample.jl b/contextExample.jl
index 9f22697..f8bb290 100644
--- a/contextExample.jl
+++ b/contextExample.jl
@@ -14,56 +14,74 @@ end
 println("Contexts: ", getContexts())
 println("First element is Business: ", getContexts()[1] == Business)
 
-@newRole(Husband, [partner=>Person, dayOfMariage=>String], Family, Person)
-@newRole(Wife, [partner=>Person, dayOfMariage=>String], Family, Person)
-@newRole(Student, [UniversityName=>String, MatrNr=>Int], University, Person)
-@newRole Professor [UniversityName::String, Chair::String] University Person
-@newRole AcademicStaff UniversityName=>String, Chair=>String, id=>Int University Person
-@newRole Employee (CompanyName=>String, partner=>Person) Business Person
-@newRole Employer (CompanyName=>String) Business Person
-@newRole Chairperson OrganizationName=>String Volunteering Person
+@context University @newMixin Professor <: Person begin
+	UniversityName::String
+	Chair::String
+end
+
+@context Family @newMixin Husband <: Person begin
+	partner::Person
+	dayOfMariage::String
+end
+
+@context Family @newMixin Wife <: Person begin
+	partner::Person
+	dayOfMariage::String
+end
+
+@context Business @newMixin Employee <: Person begin
+	CompanyName::String
+	partner::Person
+end
+
+@context Business @newMixin Employer <: Person begin
+	CompanyName::String
+end
+
+@context Family @newMixin Teenager <: Person begin
+end
+
 
 println(" ")
 println("Husband attributes:", fieldnames(Husband))
 println("Wife attributes:", fieldnames(Wife))
 println("Employee attributes:", fieldnames(Employee))
-println("Chairperson attributes:", fieldnames(Chairperson))
 
 println(" ")
-println(getRoles())
+println(getMixins())
 println(" ")
 
 John = Person("John", 34)
 Jane = Person("Jane", 42)
 Jake = Person("Jake", 24)
 
-assignRole(John=>Employee("Test Inc.", Jake), Business)
+assignMixin(John=>Employee("Test Inc.", Jake), Business)
 
 function marry(p1::Person, p2::Person, dayOfMariage::String)
-	assignRole(p1=>Husband(p2, dayOfMariage), Family)
-	@context Family assignRole(p2=>Wife(p1, dayOfMariage))
+	assignMixin(p1=>Husband(p2, dayOfMariage), Family)
+	@context Family assignMixin(p2=>Wife(p1, dayOfMariage))
 end
 
 marry(John, Jane, "10.10.2020")
 
 println(" ")
-println("Roles of John: ", getRoles(John))
+println("Mixins of John: ", getMixins(John))
 println(" ")
 
-@context University assignRole(Jane => Professor("TU Dresden", "Chair of Context Oriented Programming"))
+@context University assignMixin(Jane => Professor("TU Dresden", "Chair of Context Oriented Programming"))
 
-println(getRoles())
+println(getMixins())
 
 println(" ")
-println("Roles of Jane: ", getRoles(Jane))
+println("Mixins of Jane: ", getMixins(Jane))
 println(" ")
 
 @context Family function getPartner(person::Person)
-	(@context context getRole(person)).partner
+	(@context context getMixin(person)).partner
 end
 
 @context Business function getPartner(person::Person)
-	getRole(person, context).partner
+	getMixin(person, context).partner
 end
 
 println("John's Family Partner: ", @context Family getPartner(John))
@@ -71,15 +89,15 @@ println("John's Business Partner: ", @context Business getPartner(John))
 println("Janes's Family Partner: ", getPartner(Jane, Family))
 
 function divorce(p1::Person, p2::Person)
-	disassignRole(p1=>Husband, Family)
-	disassignRole(p2=>Wife, Family)
+	disassignMixin(p1=>Husband, Family)
+	disassignMixin(p2=>Wife, Family)
 end
 
 divorce(John, Jane)
 
 println(" ")
-println("Roles of John: ", getRoles(John))
+println("Mixins of John: ", getMixins(John))
 println(" ")
 
-assignRole(John=>Employer("Test Inc."), Business)
+assignMixin(John=>Employer("Test Inc."), Business)
 marry(Jane, Jake, "01.01.2023")
diff --git a/contextPNModelling.jl b/contextPNModelling.jl
index 708790a..f1fe586 100644
--- a/contextPNModelling.jl
+++ b/contextPNModelling.jl
@@ -5,31 +5,39 @@ using .ContextualPNs
 using .CPNCalc
 using .context
 
-p1 = place("p1", 7)
-p2 = place("p2", 0)
-p3 = place("p3", 1)
+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)]
-
+@newContext C3
+t1 = Transition("t1", C1, [])
+t2 = Transition("t2", C1 & C2, [])
+t3 = Transition("t3", nothing, [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()
 println("inital token:", compiled_pn.tokenVector)
+println()
 println("0 ", getActiveContexts())
-runPN(compiled_pn, getActiveContexts())
+
+runPN(compiled_pn)
+
 println("1 ", getActiveContexts())
 activateContext(C1)
-println("inital token after reset C1:", compiled_pn.tokenVector)
+println()
+println("inital token after reactivation of C1:", compiled_pn.tokenVector)
 println("2 ", getActiveContexts())
-runPN(compiled_pn, getActiveContexts())
+
+runPN(compiled_pn)
+println()
 println("3 ", getActiveContexts())
-runPN(compiled_pn, getActiveContexts())
\ No newline at end of file
+runPN(compiled_pn)
\ No newline at end of file
-- 
GitLab