Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

induced subnet #119

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/AlgebraicPetri.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module AlgebraicPetri
export SchPetriNet, PetriNet, OpenPetriNetOb, AbstractPetriNet,
ns, nt, ni, no, os, ot, is, it,
add_species!, add_transition!, add_transitions!,
add_input!, add_inputs!, add_output!, add_outputs!, inputs, outputs,
add_input!, add_inputs!, add_output!, add_outputs!, inputs, outputs, induced_subnet,
TransitionMatrices, vectorfield, vectorfield_expr, flatten_labels,
SchLabelledPetriNet, LabelledPetriNet, AbstractLabelledPetriNet, sname, tname, snames, tnames,
SchReactionNet, ReactionNet, AbstractReactionNet, concentration, concentrations, rate, rates,
Expand Down Expand Up @@ -272,6 +272,21 @@ inputs(p::AbstractPetriNet, t) = subpart(p, incident(p, t, :it), :is)
"""
outputs(p::AbstractPetriNet, t) = subpart(p, incident(p, t, :ot), :os)

""" induced_subnet(p::T, t)

Return the induced subnet consisting of the transition(s) in `t`, all input
places and input arcs, and all output places and output arcs. The returned
object will be of the same type as `p`.
"""
function induced_subnet(p::T, t) where {T <: AbstractPetriNet}
induced_subnet(p, [t])
end

function induced_subnet(p::T, t::AbstractVector{Int}) where {T <: AbstractPetriNet}
subnet = Subobject(p, T=t)
return dom(hom(~(¬subnet)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we return the Subobject and have the caller call dom if they want just the domain?

We could add overloads for Subobject -> PetriNet so that they can call PetriNet(induced_subnet(g)) if they don't want the morphism?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jpfairbanks those all sound like good ideas, but I don't know how we'd want to implement the overload for PetriNet to pull the domain subobject out. PetriNet is a specific type made by calling the @acset_type macro, it's plausible a user would want to get the domain petri net out of a subobject where the petri nets in question are of a different type, like a labelled petri net. How should the overload work in that case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would T(p::Subobject{T}) where T<:AbstractPetriNet = dom(p) work?

end

valueat(x::Number, u, t) = x
valueat(f::Function, u, t) =
try
Expand Down
53 changes: 53 additions & 0 deletions test/algebraicpetri/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,57 @@ for p in [sir_proplpetri, sir_proplrxn]
@test Open(p, [:S], [:I], [:R]) == Open(p)
end

# test subnet for each type of net
for net in [sir_petri, sir_rxn]
si_net = induced_subnet(net, 1)

@test ns(si_net) == 2
@test nt(si_net) == 1
@test is(si_net) == [1,2]
@test os(si_net) == [2,2]

r_net = induced_subnet(net, 2)

@test ns(r_net) == 2
@test nt(r_net) == 1
@test is(r_net) == [1]
@test os(r_net) == [2]
end

for net in [sir_lpetri, sir_lrxn]
si_net = induced_subnet(sir_lpetri, 1)

@test ns(si_net) == 2
@test nt(si_net) == 1
@test is(si_net) == [1,2]
@test os(si_net) == [2,2]
@test only(si_net[:tname]) == :inf
@test si_net[:sname] == [:S,:I]

r_net = induced_subnet(sir_lpetri, 2)

@test ns(r_net) == 2
@test nt(r_net) == 1
@test is(r_net) == [1]
@test os(r_net) == [2]
@test only(r_net[:tname]) == :rec
@test r_net[:sname] == [:I,:R]
end

sir_net = induced_subnet(sir_petri, [1,2])
sir_net == sir_petri

test_petri = PetriNet(
6,
1 => (3,4),
1 => 2,
5 => 6
)

test_net = induced_subnet(test_petri, [1,2])
@test ns(test_net) == 4
@test nt(test_net) == 2
@test ni(test_net) == 2
@test no(test_net) == 3

end
Loading