`InexactError` in my Plots.jl related script

Hello again, thanks for your help, I’ve made what you told me to, but now I have this:

ERROR: LoadError: InexactError: Int64(998.8002)
Stacktrace:
 [1] Int64
   @ ./float.jl:900 [inlined]
 [2] convert
   @ ./number.jl:7 [inlined]
 [3] push!
   @ ./array.jl:1060 [inlined]
 [4] propagation_virus(taux_transmission::Float64, personnes_infectees_initiales::Int64, population_totale::Int64, duree_simulation::Int64)
   @ Main ~/Documents/sujet veille technologique/Julia/propagation.jl:20
 [5] top-level scope
   @ ~/Documents/sujet veille technologique/Julia/propagation.jl:41
 [6] include(fname::String)
   @ Base.MainInclude ./client.jl:478
 [7] top-level scope
   @ REPL[1]:1

So here is the code :

using Plots

function propagation_virus(taux_transmission::Float64, personnes_infectees_initiales, population_totale, duree_simulation)
    # Initialisation des tableaux pour le suivi des données
    temps = 1:duree_simulation
    susceptibles = [population_totale - personnes_infectees_initiales]
    infectes = [personnes_infectees_initiales]
    recuperes = [round(4/3)]

    plots = []  # Stockage des tracés pour créer le GIF

    for jour in 2:duree_simulation
        # Calcul du nombre de nouvelles infections
        nouvelles_infections = (susceptibles[jour - 1] * taux_transmission * infectes[jour - 1] / population_totale)

        # Calcul du nombre de récupérés (hypothétiquement, après un certain temps)
        recuperes_jour = [infectes[jour - 1] - nouvelles_infections]

        # Mise à jour des tableaux
        push!(susceptibles, susceptibles[jour - 1] - nouvelles_infections)
        push!(infectes, infectes[jour - 1] + nouvelles_infections - recuperes_jour)
        push!(recuperes, recuperes[jour - 1] + recuperes_jour)

        # Création d'un graphique à chaque étape
        p = plot(temps[1:jour], susceptibles[1:jour], label="Susceptibles")
        plot!(temps[1:jour], infectes[1:jour], label="Infectés")
        plot!(temps[1:jour], recuperes[1:jour], label="Récupérés", xlabel="Jours", ylabel="Nombre de personnes", legend=true)
        push!(plots, p)
    end

    return plots
end

# Paramètres de la simulation
taux_transmission = 0.2  # Taux de transmission (0.2 signifie qu'une personne infecte 20% de la population)
personnes_infectees_initiales = 1
population_totale = 1000
duree_simulation = 100

# Exécution de la simulation
plots = propagation_virus(taux_transmission, personnes_infectees_initiales, population_totale, duree_simulation)

# Création du GIF
anim = @animate for p in plots
    p
end

gif(anim, "propagation_virus.gif", fps = 5)

Hi there!

I think your first problem is that you create an array (vector) of Int64s:

susceptibles = [population_totale - personnes_infectees_initiales]
1-element Vector{Int64}:
 999

but your first calculation is

susceptibles[jour - 1] - nouvelles_infections = 998.8002

and you can’t do this

push!(susceptibles, susceptibles[jour - 1] - nouvelles_infections)

because you can’t push a float into an array of Int64s.

I think the other problems have to do with mixing up scalar and array values. Try

recuperes_jour = infectes[jour - 1] - nouvelles_infections

rather than

recuperes_jour = [infectes[jour - 1] - nouvelles_infections]

perhaps.

Given that this is the third time I’ve said this in response to your post I promise it’s also the last:

You seem to be doing a simulation based on agents in a model, and therefore thinking in terms of integers (e.g. 100 infected individuals, 36 recovered individuals etc.)

In calculating these numbers however you inevitably end up with non-integer numbers: e.g. 25% of all infected recover each period, so the 100 in the first period become 75 in the second, but then 56.25 in the third. If you want to keep your models in terms of “whole agents” you therefore need to round your non-integer numbers.

The error you keep asking about has always been the same: Int(3.5) in Julia doesn’t work as Int is not rounding numbers; it will only create integers if the number you are passing in is exactly representable as an integer (e.g. Int(3.0) will work). Wherever you divide integers, or multiply by non-integer numbers (e.g. proportions) you will have to round your results by doing round(Int, result) to ensure you keep working with integers.

4 Likes

I was incorrect when I suggested removing the Int would fix the problem because Julia infers the type of the elements anyway. These array constructors both return the same type, so you cannot push! Floats into either. (Only an empty array constructor defaults to Any.)

julia> Int[1]
1-element Vector{Int64}:
 1

julia> [1]
1-element Vector{Int64}:
 1

You would either need to round your results to be integers before pushing, or make the array type such that it can store both Float and Int.

julia> v = Real[1]
1-element Vector{Real}:
 1

julia> push!(v, 1.1)
2-element Vector{Real}:
 1
 1.1

(This error is totally unrelated to Plots.jl. You need to break your problem down into smaller pieces and get those working first before trying to rerun the entire script. Try setting jour=2 and then step through the script in the REPL one line at a time to better understand the problem. You have been told what these errors mean and how to fix them. Now you need to work through your script slowly and implement those fixes as necessary.)

1 Like

yes I understand, but my program still doesn’t work, and I don’t know julia enough to fix that probleme

Just round the value you compute in line 20 (where the stacktrace points you to). So replace this line

with

nouvelles_infections = round(Int, susceptibles[jour - 1] * taux_transmission * infectes[jour - 1] / population_totale)

and it should work. Whether this is conceptually what you want, you need to figure out yourself.

A better fix is probably to ensure your Arrays are Float64-Arrays. So replace:

susceptibles = [population_totale - personnes_infectees_initiales]
infectes = [personnes_infectees_initiales]
recuperes = [round(4/3)]

with

susceptibles = Float64[population_totale - personnes_infectees_initiales]
infectes = Float64[personnes_infectees_initiales]
recuperes = Float64[round(4/3)]

And then you will get the next error from this line:

push!(infectes, infectes[jour - 1] + nouvelles_infections - recuperes_jour)

because you constructed recuperes_jour as an array

# square brackets "[" and "]" construct an Array!
recuperes_jour = [infectes[jour - 1] - nouvelles_infections]

So you will need remove the brackets from this line.

thank, but now I have this

LoadError: MethodError: no method matching -(::Float64, ::Vector{Float64})
For element-wise subtraction, use broadcasting with dot syntax: scalar .- array

Closest candidates are:
  -(::Union{Float16, Float32, Float64})
   @ Base float.jl:406
  -(::T, ::T) where T<:Union{Float16, Float32, Float64}
   @ Base float.jl:409
  -(::Union{Float16, Float32, Float64}, ::BigFloat)
   @ Base mpfr.jl:474

I already explained this in my answer four days ago:

You need to be careful about the distinction between a number (e.g. 4) and a one-element vector holding a single number ([4]). They are not the same thing and the difference matters.

Not to unfairly prejudge you, but it seems to me you might have very limited experience with coding and Julia specifically. Instead of posting a full model here and then letting people on the forum debug it line-by-line, I think you might find it more productive to spend a bit of time learning the basics; Think Julia: How to Think Like a Computer Scientist is a good starting point for getting started both on programming and Julia, if you’re more of a video person I know many people like https://www.youtube.com/c/juliafortalentedamateurs/about

3 Likes

I am rather certain that my other answer solves this:

1 Like