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

#718 - Add Flowpipe type #719

Merged
merged 6 commits into from
Dec 15, 2019
Merged

#718 - Add Flowpipe type #719

merged 6 commits into from
Dec 15, 2019

Conversation

schillic
Copy link
Member

@schillic schillic commented Dec 12, 2019

Closes #718.
Closes #707.

  • add changes
  • test changes (mainly projection and plotting, particularly for the operators whose project methods got removed) in practice

These changes turned out to be more complicated than I thought because we do have several places where we manually extract information from the vectors of reach sets (which are now Flowpipes) and we have a certain plotting feature that required more work.

Notable changes:

  • new type Flowpipe
  • ReachSolution now stores a Vector of Flowpipes.
    • new helper function n_sets(::ReachSolution) that counts the number of sets
  • Continuous-post operators now return a Flowpipe object instead of a Vector{<:AbstractReachSet}.
  • I removed the additional project methods in some continuous-post operators (they were not callable anymore with the change of the interface).
  • tube⋂inv! does not receive the Vector of reach sets anymore but rather computes a new one; consequently I removed the ! in the name.
  • A bigger change was needed to account for plotting certain indices of a ReachSolution only. The code should still give in the previous result, but it is obviously more complicated now that the sets distribute over different flowpipes.

@schillic schillic changed the title WIP #718 - Add Flowpipe type #718 - Add Flowpipe type Dec 14, 2019
@schillic schillic requested a review from mforets December 14, 2019 15:25
@schillic
Copy link
Member Author

This is what I tested with. In master this crashes in various places. So this PR is already an improvement.

using Reachability, MathematicalSystems, HybridSystems, LinearAlgebra
using TaylorIntegration
using TaylorModels: @taylorize
using Reachability: solve
using LazySets: HalfSpace

A = [0.0509836  0.168159  0.95246   0.33644
     0.42377    0.67972   0.129232  0.126662
     0.518654   0.981313  0.489854  0.588326
     0.38318    0.616014  0.518412  0.778765];
X0 = BallInf(ones(4), 0.1);
B = [0.866688  0.771231
     0.065935  0.349839
     0.109643  0.904222
     0.292474  0.227857];
U = Interval(0.99, 1.01) × Interval(0.99, 1.01);

s1 = solve(IVP(LCS(A), X0), :T=>0.1);
s2 = solve(IVP(LCS(A), X0),
          Options(:T=>0.1, :project_reachset=>true),
          op=BFFPSV18(:vars=>[1,3], :partition=>[1:2, 3:4]));
s3 = solve(IVP(LCS(A), X0),
          Options(:T=>0.1, :project_reachset=>false),
          op=BFFPSV18(:vars=>[1,3], :partition=>[1:2, 3:4]));
s4 = project(s3);

s5 = solve(IVP(CLCCS(A, B, nothing, U), X0),
           Options(:T=>0.2, :project_reachset=>true), op=GLGM06());

@taylorize function vanderPol!(dx, x, params, t)
    local μ = 1.0
    dx[1] = x[2]
    dx[2] =* x[2]) * (1 - x[1]^2) - x[1]
    return dx
end;
𝑆 = BlackBoxContinuousSystem(vanderPol!, 2);
X0 = Hyperrectangle(low=[1.25, 2.35], high=[1.55, 2.45]);
𝑃 = InitialValueProblem(𝑆, X0);
s6 = solve(𝑃, Options(:T=>7.0, :mode=>"reach"),
           op=TMJets(:abs_tol=>1e-10, :orderT=>10, :orderQ=>2));
s7 = solve(𝑃, Options(:T=>7.0, :mode=>"reach", :project_reachset=>true),
           op=TMJets(:abs_tol=>1e-10, :orderT=>10, :orderQ=>2));

function bouncing_ball()
    # automaton structure
    automaton = LightAutomaton(1)

    # mode 1
    A = [0.0 1.0; 0.0 0.0]
    B = reshape([0.0, -1.0], (2, 1))
    U = Singleton([1.0])
    inv = HalfSpace([-1.0, 0.0], 0.0) # x >= 0
    m1 = ConstrainedLinearControlContinuousSystem(A, B, inv, ConstantInput(U))

    # modes
    modes = [m1]

    # transition from m1 to m1 (self-loop)
    add_transition!(automaton, 1, 1, 1)
    A = [1.0 0.0; 0.0 -0.75]
    guard = HPolyhedron([HalfSpace([0.0, 1.0], 0.0),   # v ≤ 0
                         HalfSpace([-1.0, 0.0], 0.0),  # x ≥ 0
                         HalfSpace([1.0, 0.0], 0.0)])  # x ≤ 0
    t1 = ConstrainedLinearMap(A, guard)

    # transition annotations
    resetmaps = [t1]

    # switching
    switchings = [AutonomousSwitching()]

    ℋ = HybridSystem(automaton, modes, resetmaps, switchings)

    # initial condition in mode 1
    X0 = Hyperrectangle(low=[10.0, 0.0], high=[10.2, 0.0])
    initial_condition = [(1, X0)]

    system = InitialValueProblem(ℋ, initial_condition)

    options = Options(:mode=>"reach", :T=>5.0,
                      :plot_vars=>[1, 2], :max_jumps=>1, :verbosity=>1)

    return (system, options)
end

system, options = bouncing_ball();
sols = [];
for opC in [BFFPSV18(=>0.1), GLGM06(=>0.1)]
    sol = solve(system, options, opC, LazyDiscretePost(:check_invariant_intersection => true));
    sol_proj = project(sol);
    push!(sols, sol_proj);
end

using Plots
plot(s2)
plot(s4)
plot(s5)
plot(s5, indices=[1,3,5,7,9,20])
plot(s6)
plot(s7)
plot(sols[1])
plot(sols[2])

@mforets
Copy link
Member

mforets commented Dec 14, 2019

This is what I tested with. In master this crashes in various places. So this PR is already an improvement.

Sounds good!

Does this PR also solve some or all of #707 ?

Also, as the PR introduces breaking changes i would like to tag a new minor version of this package before merging this PR, for future reference.

@schillic
Copy link
Member Author

Does this PR also solve some or all of #707 ?

It resolves the crashes.

using Reachability, MathematicalSystems
A = rand(4, 4);
S = LinearContinuousSystem(A);
X0 = rand(Hyperrectangle, dim=4);
M = rand(1, 4);
P = InitialValueProblem(S, X0);
opts = Options(:T=>1.0, :project_reachset=>true, :projection_matrix=>M);
opts_algo = Options(=>0.1, :vars=>[1, 2]);
solve(P, opts, op=BFFPSV18(opts_algo));

#707 uses inputs that are not supported (M = rand(2, 4)), but I would say that then an error is expected.

@mforets
Copy link
Member

mforets commented Dec 14, 2019

Good. So we can as well close #707 with this PR, what do you think?

@mforets
Copy link
Member

mforets commented Dec 14, 2019

This is what I tested with. In master this crashes in various places. So this PR is already an improvement.

Can you link to a notebook with the plots?

@mforets
Copy link
Member

mforets commented Dec 14, 2019

I'm curious because bouncing ball was not working well last time i checked. In this notebook i tried Reachability#master with the bouncing ball example and the overapproximation error was very bad. If you scroll down to Out [85] there is a picture that shows GLGM06 using zonotopes and with a smaller overapproximation error of the intersection.

@schillic schillic mentioned this pull request Dec 15, 2019
@schillic
Copy link
Member Author

Can you link to a notebook with the plots?

using Reachability, MathematicalSystems, HybridSystems, LinearAlgebra, Plots

function bouncing_ball()
    # automaton structure
    automaton = LightAutomaton(1)

    # mode 1
    A = [0.0 1.0; 0.0 0.0]
    B = reshape([0.0, -1.0], (2, 1))
    U = Singleton([1.0])
    inv = HalfSpace([-1.0, 0.0], 0.0) # x >= 0
    m1 = ConstrainedLinearControlContinuousSystem(A, B, inv, ConstantInput(U))

    # modes
    modes = [m1]

    # transition from m1 to m1 (self-loop)
    add_transition!(automaton, 1, 1, 1)
    A = [1.0 0.0; 0.0 -0.75]
    guard = HPolyhedron([HalfSpace([0.0, 1.0], 0.0),   # v ≤ 0
                         HalfSpace([-1.0, 0.0], 0.0),  # x ≥ 0
                         HalfSpace([1.0, 0.0], 0.0)])  # x ≤ 0
    t1 = ConstrainedLinearMap(A, guard)

    # transition annotations
    resetmaps = [t1]

    # switching
    switchings = [AutonomousSwitching()]

    ℋ = HybridSystem(automaton, modes, resetmaps, switchings)

    # initial condition in mode 1
    X0 = Hyperrectangle(low=[10.0, 0.0], high=[10.2, 0.0])
    initial_condition = [(1, X0)]

    system = InitialValueProblem(ℋ, initial_condition)

    options = Options(:mode=>"reach", :T=>20.0,
                      :plot_vars=>[1, 2], :max_jumps=>3, :verbosity=>1)

    return (system, options)
end

system, options = bouncing_ball();
sols = [];
for opC in [BFFPSV18(=>0.01), GLGM06(=>0.01)]
    sol = solve(system, options, opC, LazyDiscretePost(:check_invariant_intersection => true));
    sol_proj = project(sol);
    push!(sols, sol_proj);
end

plot(sols[1])
plot(sols[2])

BFFPSV18

GLGM06

@mforets
Copy link
Member

mforets commented Dec 15, 2019

The plots look good. I can't tell if the second plot has zonotopes, is it the case?

@schillic
Copy link
Member Author

I can't tell if the second plot has zonotopes, is it the case?

The algorithm is GLGM06, so I think those are zonotopes.

@schillic schillic merged commit 573612f into master Dec 15, 2019
@schillic schillic deleted the schillic/718 branch December 15, 2019 11:09
@mforets
Copy link
Member

mforets commented Dec 15, 2019

Ok, i was asking because that didn't work on master, see #716.

@mforets
Copy link
Member

mforets commented Dec 15, 2019

If the PR solves that problem that issue can be closed as well.

@schillic
Copy link
Member Author

Ok, i was asking because that didn't work on master, see #716.

I see. No, this PR did not address that issue.

julia> flowpipe_GLGM06 = sols[2].flowpipes[1];

julia> typeof(flowpipe_GLGM06.reachsets[2])
ReachSet{Hyperrectangle{Float64,Array{Float64,1},Array{Float64,1}}}

@mforets
Copy link
Member

mforets commented Dec 15, 2019

Ok, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Flowpipe type Errors with projection
2 participants