Skip to content

Lumen refactoring #49

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

Merged
merged 49 commits into from
Jun 7, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e4d257d
fix if 1 lmf [TodoReview this]
Perro2110 Jan 13, 2025
67af772
Add test, add iscomplete
giopaglia Jan 20, 2025
ebe5d9d
Merge branch 'gio/refractoring' of https://github.com/aclai-lab/SoleM…
Perro2110 Jan 23, 2025
a287352
refactoring name
Perro2110 Feb 19, 2025
b2312c1
minor fix
Perro2110 Mar 11, 2025
4bc2854
update image_family
Perro2110 Mar 29, 2025
afd1161
decisiontree and xgboost ext working
PasoStudio73 Mar 29, 2025
183de68
minor fix in Project.toml for compatibility
Perro2110 Apr 1, 2025
8ee5cf3
Fix
giopaglia Apr 2, 2025
8ef0051
Merge branch 'lumen-refactoring' of https://github.com/aclai-lab/Sole…
giopaglia Apr 2, 2025
d870851
debug xgboost, not yet ready
PasoStudio73 Apr 2, 2025
5de4302
Refining XGBoost
PasoStudio73 Apr 9, 2025
2ad6442
xgboost float predict issue
PasoStudio73 Apr 11, 2025
dd23501
xgboost predict found areas requireing fixes
PasoStudio73 Apr 14, 2025
93fba4d
XGBoost test passed
PasoStudio73 Apr 14, 2025
ae4e5a1
working on tests
PasoStudio73 Apr 14, 2025
52deed0
codecov working
PasoStudio73 Apr 14, 2025
7c4f025
removed MLJXGBoostInterface in tests
PasoStudio73 Apr 14, 2025
6593222
still fixing codecov
PasoStudio73 Apr 14, 2025
2828e50
again
PasoStudio73 Apr 14, 2025
7c3fbde
guess what?
PasoStudio73 Apr 14, 2025
a9acf2e
update ci.yml breaking!
PasoStudio73 Apr 14, 2025
828c446
again
PasoStudio73 Apr 14, 2025
a7ced5b
last try
PasoStudio73 Apr 14, 2025
fba387a
reverted ci.yml
PasoStudio73 Apr 15, 2025
1e0971f
atom getter
PasoStudio73 Apr 15, 2025
53161b1
adaboost test
PasoStudio73 Apr 15, 2025
d7a5d15
xgboost classifier ready, tested and working
PasoStudio73 Apr 16, 2025
c948f27
xgboost apply!
PasoStudio73 Apr 16, 2025
ef11380
extractrules --> modalextractrules
Perro2110 Apr 18, 2025
36d7ef9
Merge branch 'lumen-refactoring' of https://github.com/aclai-lab/Sole…
Perro2110 Apr 18, 2025
d26e198
minor add in TODO
Perro2110 Apr 18, 2025
9638489
fix tests & deps
PasoStudio73 Apr 18, 2025
b2a4869
posthoc
PasoStudio73 Apr 23, 2025
16476a9
Merge branch 'devTest' into lumen-refactoring
Perro2110 Apr 26, 2025
1b5a6c6
test fixed
PasoStudio73 Apr 27, 2025
dbe8e83
fix extras deps
PasoStudio73 Apr 27, 2025
6c34e4d
cleaned unused packages, tests still working
PasoStudio73 Apr 27, 2025
bcefa20
updated SoleData dep
PasoStudio73 Apr 27, 2025
ba4d143
updated solelogics dep
PasoStudio73 Apr 27, 2025
72efb54
added a @show for checking
PasoStudio73 May 2, 2025
bd889ac
removed guard
PasoStudio73 May 2, 2025
83ffb33
test working
PasoStudio73 Jun 7, 2025
54ae95f
updated github ci
PasoStudio73 Jun 7, 2025
4275b3d
added distributed package
PasoStudio73 Jun 7, 2025
42c052e
added MLJXGBoostInterface package
PasoStudio73 Jun 7, 2025
1218cb1
fix XGB
PasoStudio73 Jun 7, 2025
37daad6
added MMI
PasoStudio73 Jun 7, 2025
d3f8dfe
Merge branch 'main' into lumen-refactoring
PasoStudio73 Jun 7, 2025
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
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
freebsd_instance:
image_family: freebsd-14-0
image_family: freebsd-14-2
task:
name: FreeBSD
artifacts_cache:
Expand Down
28 changes: 24 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
name = "SoleModels"
uuid = "4249d9c7-3290-4ddd-961c-e1d3ec2467f8"
license = "MIT"
authors = ["Michele GHIOTTI", "Giovanni PAGLIARINI", "Edoardo PONSANESI", "Eduard I. STAN"]
authors = [
"Michele GHIOTTI",
"Giovanni PAGLIARINI",
"Edoardo PONSANESI",
"Eduard I. STAN",
]
version = "0.10.0"

[deps]
Expand Down Expand Up @@ -61,9 +66,9 @@ ProgressMeter = "1"
Random = "1"
Reexport = "1"
Revise = "3"
SoleBase = "0.13"
SoleBase = "0.11 - 0.13"
SoleData = "0.15, 0.16"
SoleLogics = "0.11 - 0.12"
SoleLogics = "0.11 - 0.13"
StatsBase = "0.30 - 0.34"
Suppressor = "0.2"
Tables = "1"
Expand All @@ -89,4 +94,19 @@ SoleData = "123f1ae1-6307-4526-ab5b-aab3a92a2b8c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "DataFrames", "Random", "MLJ", "MLJXGBoostInterface", "MultiData", "Markdown", "InteractiveUtils", "BenchmarkTools", "MLJBase", "XGBoost", "DecisionTree", "MLJDecisionTreeInterface", "SoleData"]
test = [
"Test",
"DataFrames",
"Random",
"MLJ",
"MLJXGBoostInterface",
"MultiData",
"Markdown",
"InteractiveUtils",
"BenchmarkTools",
"MLJBase",
"XGBoost",
"DecisionTree",
"MLJDecisionTreeInterface",
"SoleData",
]
2 changes: 1 addition & 1 deletion src/SoleModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export subtreeheight
include("symbolic-utils.jl")

export PlainRuleExtractor
export extractrules, listrules, joinrules
export modalextractrules, listrules, joinrules
Copy link
Member

Choose a reason for hiding this comment

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

I want to stress the fact that I'm not bothered by the function being called "modalextractrules". But we need to be able to call it "extractrules". So again my suggestion is on of the following:

  • rename the function into "extractrules", and then put a "const modalextractrules = extractrules; export modalextractrules" in a deprecate.jl file
  • keep the name "modalextractrules", but also put a "const extractrules = modalextractrules; export xtractrules" in a deprecate.jl file

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I fully agree, I chose the first option: rename the function into "extractrules", and then put a "const modalextractrules = extractrules; export modalextractrules" in a deprecate.jl file


include("rule-extraction.jl")

Expand Down
32 changes: 29 additions & 3 deletions src/evaluate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,20 @@ function evaluaterule(
checkmask, explanations = begin
if compute_explanations
# Note: This is kind of quick and dirty.
disjs = SoleLogics.disjuncts(SoleLogics.LeftmostDisjunctiveForm(antecedent(rule)))

#disjs = SoleLogics.disjuncts(SoleLogics.LeftmostDisjunctiveForm(antecedent(rule)))

ante = antecedent(rule)
if (ante isa SyntaxBranch)
# Radice disgiuntiva: trasformiamo in forma “disjunctive” e poi estraiamo i disgiunti
dnf = SoleLogics.LeftmostDisjunctiveForm(ante)
disjs = SoleLogics.disjuncts(dnf)
else
# Non è un OR in radice → un singolo disgiunto
disjs = [ante]
end


checkmatrix = hcat([check(disj, X; kwargs...) for disj in disjs]...)
# @show checkmatrix
checkmask = map(any, eachrow(checkmatrix))
Expand All @@ -337,11 +350,24 @@ function evaluaterule(
end
pos_checkmask = checkmask[classmask]
neg_checkmask = checkmask[(!).(classmask)]

#=
println("pos_checkmask: ",pos_checkmask)
println("neg_checkmask: ",neg_checkmask)

println("lgh pos_checkmask ",length(pos_checkmask))
println("lgh neg_checkmask ",length(neg_checkmask))
=#

# Controlli per array vuoti
sensitivity = length(pos_checkmask) > 0 ? sum(pos_checkmask)/length(pos_checkmask) : 0.0
specificity = length(neg_checkmask) > 0 ? 1-(sum(neg_checkmask)/length(neg_checkmask)) : 1.0

out = (;
classmask = classmask,
checkmask = checkmask,
sensitivity = sum(pos_checkmask)/length(pos_checkmask),
specificity = 1-(sum(neg_checkmask)/length(neg_checkmask)),
sensitivity = sensitivity,
specificity = specificity,
explanations = explanations,
)
return out
Expand Down
16 changes: 8 additions & 8 deletions src/rule-extraction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ An exact or heuristic logical method for extracting logical rule from symbolic m

Refer to [SolePostHoc](https://github.com/aclai-lab/SolePostHoc.jl) for rule extraction methods.

See also [`extractrules`](@ref), [`Rule`](@ref)], [`issymbolicmodel`](@ref).
See also [`modalextractrules`](@ref), [`Rule`](@ref)], [`issymbolicmodel`](@ref).
"""
abstract type RuleExtractor end

Expand All @@ -16,33 +16,33 @@ Return whether a rule extraction method is known to be exact (as opposed to heur
isexact(::RuleExtractor) = false

"""
extractrules(re::RuleExtractor, m, args...; kwargs...)
modalextractrules(re::RuleExtractor, m, args...; kwargs...)

Extract rules from symbolic model `m`, using a rule extraction method `re`.
"""
function extractrules(re::RuleExtractor, m, args...; kwargs...)
return error("Please, provide method extractrules(::$(typeof(m)), args...; kwargs...).")
function modalextractrules(re::RuleExtractor, m, args...; kwargs...)
return error("Please, provide method modalextractrules(::$(typeof(m)), args...; kwargs...).")
end

# Helpers
function (RE::Type{<:RuleExtractor})(args...; kwargs...)
return extractrules(RE(), args...; kwargs...)
return modalextractrules(RE(), args...; kwargs...)
end

# Helpers
function (re::RuleExtractor)(args...; kwargs...)
return extractrules(re, args...; kwargs...)
return modalextractrules(re, args...; kwargs...)
end

"""
Plain extraction method involves listing one rule per each possible symbolic path within the model.
With this method, [`extractrules`](@ref) redirects to [`listrules`](@ref).
With this method, [`modalextractrules`](@ref) redirects to [`listrules`](@ref).

See also [`listrules`](@ref), [`Rule`](@ref)], [`issymbolicmodel`](@ref).
"""
struct PlainRuleExtractor <: RuleExtractor end
isexact(::PlainRuleExtractor) = true
function extractrules(::PlainRuleExtractor, m, args...; kwargs...)
function modalextractrules(::PlainRuleExtractor, m, args...; kwargs...)
if haslistrules(m)
listrules(m, args...; kwargs...)
else
Expand Down
3 changes: 2 additions & 1 deletion src/utils/models/ensembles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ struct DecisionEnsemble{O,T<:AbstractModel,A<:Base.Callable,W<:Union{Nothing,Abs
O = Union{outcometype.(models)...}
DecisionEnsemble{O}(models, args...; kwargs...)
end

end


Expand All @@ -105,6 +104,8 @@ modelstype(m::DecisionEnsemble{O,T}) where {O,T} = T
models(m::DecisionEnsemble) = m.models
nmodels(m::DecisionEnsemble) = length(models(m))

iscomplete(m::DecisionEnsemble) = any(iscomplete.(models(m)))

aggregation(m::DecisionEnsemble) = m.aggregation
weights(m::DecisionEnsemble) = m.weights
# Returns the aggregation function, patched by weights if the model has them.
Expand Down
2 changes: 1 addition & 1 deletion src/utils/models/other.jl
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ iscomplete(m::DecisionSet) = m.iscomplete
isnonoverlapping(m::DecisionSet) = m.isnonoverlapping

function listrules(m::DecisionSet)
isnonoverlapping || error("Cannot listrules from non-overlapping decision set. Try `extractrules` with heuristics, instead.")
isnonoverlapping || error("Cannot listrules from non-overlapping decision set. Try `modalextractrules` with heuristics, instead.")
rules(m)
end

Expand Down
1 change: 0 additions & 1 deletion test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ using SoleModels: listrules, displaymodel, submodels

io = IOBuffer()

# parse_other_kind_of_formula = SoleLogics.parsebaseformula
parse_other_kind_of_formula = SoleLogics.parseformula

################################### LeafModel #############################################
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ end
println("Julia version: ", VERSION)

test_suites = [
("Models", ["base.jl", ]),
("Models", ["base.jl", "test_tree.jl"]),
("Miscellaneous", ["misc.jl", ]),
("Parse", ["parse.jl", ]),
("Rules", ["juliacon2024.jl", ]),
Expand Down
30 changes: 30 additions & 0 deletions test/test_tree.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
################################################
# p
# ┌───────┴─────────────┐
# │ r
# q ┌───┴───┐
# │ s "yes"
# ┌───┴───┐ ┌───┴───┐
# "yes" "no" "yes" "no"
##################################################

using SoleLogics
using SoleModels

formula_p = SoleLogics.parseformula("p")
formula_q = SoleLogics.parseformula("q")
formula_r = SoleLogics.parseformula("r")
formula_s = SoleLogics.parseformula("s")

branch_q = Branch(formula_q,("yes","no"),(;))
branch_s = Branch(formula_s,("yes","no"),(;))
branch_r = Branch(formula_r,(branch_s,"yes"),(;))

#dt_q = DecisionTree(branch_r,(;))


#Possibile path
path_all = [formula_p,formula_q,formula_s,formula_r,"yes"]
path_2 = [formula_p,formula_q,"yes"]
path_1 = [formula_p,"yes"]
path_0 = ["yes"]
Loading