From 13b125ea24b3b48f277c9179f18f7ddaea8de900 Mon Sep 17 00:00:00 2001 From: Greg Heileman Date: Fri, 1 Oct 2021 16:21:44 -0700 Subject: [PATCH 1/9] algorithms for edge crossings in a graph cut --- src/DataTypes/Course.jl | 3 ++- src/DataTypes/DegreePlan.jl | 2 +- src/GraphAlgs.jl | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/DataTypes/Course.jl b/src/DataTypes/Course.jl index 8cce7fdc..5a347384 100644 --- a/src/DataTypes/Course.jl +++ b/src/DataTypes/Course.jl @@ -87,7 +87,8 @@ mutable struct Course <: AbstractCourse this.metrics = Dict{String, Any}() this.metadata = Dict{String, Any}() this.learning_outcomes = learning_outcomes - this.vertex_id = Dict{Int, Int}() # curriculum id -> vertex id + this.vertex_id = Dict{Int, Int}() # curriculum id -> vertex id, note: course may be in multiple curricula + this.passrate = passrate return this diff --git a/src/DataTypes/DegreePlan.jl b/src/DataTypes/DegreePlan.jl index 4c93f939..24b4a682 100644 --- a/src/DataTypes/DegreePlan.jl +++ b/src/DataTypes/DegreePlan.jl @@ -9,7 +9,7 @@ instantiate a `Term` use: where c1, c2, ... are `Course` data objects """ mutable struct Term - courses::Array{AbstractCourse} # The courses associated with a term in a degree plan + courses::Array{AbstractCourse} # The courses associated with a term in a degree plan num_courses::Int # The number of courses in the Term credit_hours::Real # The number of credit hours associated with the term metrics::Dict{String, Any} # Term-related metrics diff --git a/src/GraphAlgs.jl b/src/GraphAlgs.jl index ced610ec..9d64011d 100644 --- a/src/GraphAlgs.jl +++ b/src/GraphAlgs.jl @@ -342,4 +342,40 @@ function longest_paths(g::AbstractGraph{T}) where T length(path) == max ? push!(lps, path) : nothing end return lps +end + +# determine the number of edges crossing a graph cut, where s is the set of vertices on one side of the cut, +# and the other side are the remanining vertices in g. +""" + edge_crossing(g, s) + +Given a graph ``g=(V,E)``,and a set of vertices ``s \subseteq V``, determine the number of edges +crossing the cut determined by the partition ``(s,V-s)``. + + # Arguments +Required: +- `g::AbstractGraph` : acylic graph. +- `s::Array{Int}` : array of vertex indicies. + +```julia-repl +julia> cut_size = edge_crossing(g, s) +``` +""" +function edge_crossings(g::AbstractGraph{T}, s::Array{Int,1}) where T + total = 0 + d = convert(Array{Int,1}, vertices(g)) # collect the graph vertex ids in a integer array + filter!(x->x ∉ s, d) # remove the vertex ids in s from d + for v in s + total += edge_crossings(g, v, d) + end + return total +end + +# find number of crossing from a single vertex to all vertices in some vertex set d +function edge_crossings(g::AbstractGraph{T}, s::Int, d::Array{Int,1}) where T + total = 0 + for v in d + has_edge(g, s, v) ? total += 1 : nothing + end + return total end \ No newline at end of file From a38bbb3c0c0d15a90f12e4090c6bd01bb9e5b8be Mon Sep 17 00:00:00 2001 From: Greg Heileman Date: Fri, 1 Oct 2021 16:36:38 -0700 Subject: [PATCH 2/9] add knowledge_crossing algorithm --- src/CurricularAnalytics.jl | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/CurricularAnalytics.jl b/src/CurricularAnalytics.jl index 0f2875fa..3b769c28 100644 --- a/src/CurricularAnalytics.jl +++ b/src/CurricularAnalytics.jl @@ -32,7 +32,7 @@ export AA, AAS, AS, AbstractCourse, AbstractRequirement, BA, BS, Course, CourseC gad, grade, homology, is_duplicate, isvalid_curriculum, isvalid_degree_plan, longest_path, longest_paths, merge_curricula, pass_table, passrate_table, pre, print_plan, quarter, reach, reach_subgraph, reachable_from, reachable_from_subgraph, reachable_to, reachable_to_subgraph, read_csv, requisite_distance, requisite_type, semester, set_passrates, set_passrate_for_course, set_passrates_from_csv, similarity, simple_students, simulate, simulation_report, - strict_co, topological_sort, total_credits, transfer_equiv, tree_edge, write_csv + strict_co, topological_sort, total_credits, transfer_equiv, tree_edge, write_csv, knowledge_transfer # Check if a curriculum graph has requisite cycles. """ @@ -818,4 +818,34 @@ function dead_ends(curric::Curriculum, prefixes::Array{String,1}) return (prefixes, dead_end_courses) end +""" + knowledge_transfer(dp) + +Determine the number of requisites crossing the "cut" in a degree plan that occurs between each term. + +# Arguments +- `dp::DegreePlan` : the degree to analyze. + +Returns an array of crossing values between the courses in the first term and the remainder of the degree plan, +between the courses in the first two terms in the degree plan, and the remainder of the degree plan, etc. +The number of values returned will be one less than the number of terms in the degree plan. + +```julia-repl +julia> knowledge_transfer(dp) +``` +""" +function knowledge_transfer(dp::DegreePlan) + ec_terms = [] + s = Array{Int64,1}() + for term in dp.terms + sum = 0 + for c in term.courses + push!(s, c.vertex_id[dp.curriculum.id]) + end + sum += edge_crossings(dp.curriculum.graph, s) + push!(ec_terms, sum) + end + return deleteat!(ec_terms, lastindex(ec_terms)) # the last value will always be zero, so remove it +end + end # module From f117072ffda283d470d34290e06c86027a9a29a2 Mon Sep 17 00:00:00 2001 From: Greg Heileman Date: Tue, 5 Oct 2021 17:42:50 -0700 Subject: [PATCH 3/9] fixed bug in isvalid_curriculum() --- src/CurricularAnalytics.jl | 80 ++++++++++++++++++++++--------- test/CurricularAnalytics.jl | 24 ++++++++++ test/big_unsatisfiable_curric.csv | 58 ++++++++++++++++++++++ 3 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 test/big_unsatisfiable_curric.csv diff --git a/src/CurricularAnalytics.jl b/src/CurricularAnalytics.jl index 3b769c28..37f7c740 100644 --- a/src/CurricularAnalytics.jl +++ b/src/CurricularAnalytics.jl @@ -39,11 +39,10 @@ export AA, AAS, AS, AbstractCourse, AbstractRequirement, BA, BS, Course, CourseC isvalid_curriculum(c::Curriculum, errors::IOBuffer) Tests whether or not the curriculum graph ``G_c`` associated with curriculum `c` is valid, i.e., -whether or not it contains a requisite cycle. Returns a boolean value, with `true` indicating the -curriculum is valid, and `false` indicating it is not. +whether or not it contains a requisite cycle, or requisites that cannot be satisfied. Returns +a boolean value, with `true` indicating the curriculum is valid, and `false` indicating it is not. -If ``G_c`` is not valid, the requisite cycle(s) are written to the `errors` buffer. To view these -cycles, use: +If ``G_c`` is not valid, the `errors` buffer. To view these errors, use: ```julia-repl julia> errors = IOBuffer() @@ -51,15 +50,40 @@ julia> isvalid_curriculum(c, errors) julia> println(String(take!(errors))) ``` -A curriculum graph is not valid if it contains a directed cycle; in this case it is not possible to complete -the curriculum. +A curriculum graph is not valid if it contains a directed cycle or unsatisfiable requisites; in this +case it is not possible to complete the curriculum. For the case of unsatisfiable requistes, consider +two courses ``c_1`` and ``c_2``, with ``c_1`` a prerequisite for ``c_2``. If a third course ``c_3`` +is a strict corequisite for ``c_2``, as well as a requisite for ``c_1`` (or a requisite for any course +on a path leading to ``c_2``), then the set of requisites cannot be satisfied. """ function isvalid_curriculum(c::Curriculum, error_msg::IOBuffer=IOBuffer()) - g = c.graph + g = deepcopy(c.graph) validity = true - # first check for cycles + # First check for simple cycles cycles = simplecycles(g) - if size(cycles,1) != 0 + # Next check for cycles that could be created by strict co-requisites. + # For every strict-corequisite in the curriculum, add another strict-corequisite between the same two vertices, but in + # the opposite direction. If this creates any cycles of length greater than 2 in the modified graph (i.e., involving + # more than the two courses in the strict-corequisite relationship), then the curriculum is unsatisfiable. + for course in c.courses + for (k,r) in course.requisites + if r == strict_co + v_d = course_from_id(c,course.id).vertex_id[c.id] # destination vertex + v_s = course_from_id(c,k).vertex_id[c.id] # source vertex + add_edge!(g, v_d, v_s) + end + end + end + new_cycles = simplecycles(g) + idx = [] + for (i,cyc) in enumerate(new_cycles) # remove length-2 cycles + if length(cyc) == 2 + push!(idx, i) + end + end + deleteat!(new_cycles, idx) + cycles = union(new_cycles, cycles) # remove redundant cycles + if length(cycles) != 0 validity = false c.institution != "" ? write(error_msg, "\n$(c.institution): ") : "\n" write(error_msg, " curriculum \'$(c.name)\' has requisite cycles:\n") @@ -77,19 +101,6 @@ function isvalid_curriculum(c::Curriculum, error_msg::IOBuffer=IOBuffer()) return validity end -## refactoring this out of the function above, to reduce warning outputs -- use extraneous_requisites() in its place -#else # no cycles, can now check for extraneous requisites -# extran_errors = IOBuffer() -# if extraneous_requisites(c, extran_errors) -# validity = false -# c.institution != "" ? write(error_msg, "\n$(c.institution): ") : "\n" -# write(error_msg, " curriculum \'$(c.name)\' has extraneous requisites:\n") -# write(error_msg, String(take!(extran_errors))) -# end -# end -# return validity -#end - """ extraneous_requisites(c::Curriculum; print=false) @@ -849,3 +860,28 @@ function knowledge_transfer(dp::DegreePlan) end end # module + + +for cs in c.courses + for (k,r) in cs.requisites + v_k = course_from_id(c,k).vertex_id[c.id] + if r == strict_co + v_set = reachable_to(g, v_k) # no predecessor to k can have r as a requisite (makes curriculum unsatisfiable) + # Todo: remove r from reachable set + println("checking edges ...\n") + for v in v_set + if CurricularAnalytics.has_edge(g, v, v_k) # found a possibly unsatisfiable requisite + println("found a edge that needs checking\n") + if v in keys(cs.requisites) # check for one exception: if v is also a co-requsite for cs, no problem + # map(course_from_id, fill(curric,length(cs.requisites)), keys(cs.requisites)) + if cs.requisites[v] == pre # it's not, is a prerequisite + validity = false + println(" setting validity false\n") + write(error_msg, "$(course_from_id(c,r).name) cannot be a strict co-requisite for $(cs.name) as well as a requisite for some predecessor of $(cs.name)\n") + end + end + end + end + end + end +end \ No newline at end of file diff --git a/test/CurricularAnalytics.jl b/test/CurricularAnalytics.jl index 818f5bf4..48857f4a 100644 --- a/test/CurricularAnalytics.jl +++ b/test/CurricularAnalytics.jl @@ -21,6 +21,30 @@ errors = IOBuffer() @test isvalid_curriculum(curric, errors) == false #@test String(take!(errors)) == "\nCurriculum Cycle contains the following requisite cycles:\n(A)\n" +# create unsatisfiable requisites +# +# (pre) +# A---* B +# * \ |* (strict_co) +# \ | +# \| +# C + +a = Course("A", 3) +b = Course("B", 3) +c = Course("C", 3) + +add_requisite!(a,b,pre) +add_requisite!(c,b,strict_co) +add_requisite!(c,a,pre) # can be any requisite + +curric = Curriculum("Unsatisfiable", [a, b, c], sortby_ID=false) +errors = IOBuffer() +@test isvalid_curriculum(curric, errors) == false + +curric = read_csv("big_unsatisfiable_curric.csv") +@test isvalid_curriculum(curric, errors) == false + # Curric1: 4-vertex test curriculum - invalid (contains a extraneous prerequisite) # # A --------* C diff --git a/test/big_unsatisfiable_curric.csv b/test/big_unsatisfiable_curric.csv new file mode 100644 index 00000000..a6d3166b --- /dev/null +++ b/test/big_unsatisfiable_curric.csv @@ -0,0 +1,58 @@ +Curriculum,Chemical Engineering,,,,,,,,, +Institution,Big Bad U,,,,,,,,, +Degree Type,BS,,,,,,,,, +System Type,semester,,,,,,,,, +CIP,,,,,,,,,, +Courses,,,,,,,,,, +Course ID,Course Name,Prefix,Number,Prerequisites,Corequisites,Strict-Corequisites,Credit Hours,Institution,Canonical Name,Term +1,Calculus I,MAT,220,,,,5,Pima CC,Calculus I,1 +2,Gen Chemistry I,CHM,151IN,,,3,4,Pima CC,General Chemsitry I,1 +3,Gen Chemistry I Recitation,CHM,151RC,,,,1,Pima CC,,1 +4,English Composition I,WRT,101,,,,3,Pima CC,English Composition I,1 +5,Problem-Solving and Engineering Design,ENG,102IN,,1,,3,Pima CC,Intro to Engineering,1 +6,AGEC-S Course,,,,,,3,Pima CC,,1 +7,Calculus II,MAT,231,1,,,4,Pima CC,Calculus II,2 +8,Gen Chemistry II,CHM,152IN,2,,9,4,Pima CC,General Chemsitry II,2 +9,Gen Chemistry II Recitation,CHM,152RC,,,,1,Pima CC,,2 +10,Intro Mechanics,PHY,210IN,1,,11,4,Pima CC,,2 +11,Intro Mechanics Recitation,PHY,210RC,,,,1,Pima CC,,2 +12, English Composition II,WRT,102,4,,,3,Pima CC, English Composition,2 +13,Intro to MATLAB I,ENG,105IN,,1,,1,Pima CC,,2 +14,AGEC-S Course,,,,,,3,Pima CC,,3 +15,AGEC-S Course,,,,,,3,Pima CC,,3 +16,Calculus III,MAT,241,7,,,4,Pima CC,Calculus III,3 +17,General Organic Chemistry I,,235IN,8,,18,4,Pima CC,Organic Chemistry I,3 +18,General Organic Chemistry I Recitation,CHM ,235RC,,,,1,Pima CC,,3 +19,AGEC-S Course,,,,,,3,Pima CC,,3 +20,AGEC-S Course,,,,,,3,Pima CC,,4 +21,AGEC-S Course,,,,,,3,Pima CC,,4 +22,Differential Equations,MAT,262,7,,,3,Pima CC,Differential Equations,4 +23,Intro Electricity & Magnetism,PHY,216IN,7;10,,24,4,Pima CC,,4 +24,Intro Electricity & Magnetism,PHY,216RC,,,,1,Pima CC,,4 +25,General Organic Chemistry II,CHM,236IN,17,,26,4,Pima CC,Organic Chemistry II,4 +26,General Organic Chemistry II Recitation,CHM ,236RC,,,,1,Pima CC,,4 +27,Intro to MATLAB II,ENG,205IN,13,,,1,Pima CC,,4 +28,Elements of Chem and Envirn Eng I,CHEE,201,1;5;8;13,27,,3,University of Arizona,,5 +29,Elements of Chem and Envirn Eng I Lab,,201L,1,13,,1,University of Arizona,,5 +30,Physical Chem,CHEM,480A,7;2;23,,,3,University of Arizona,,5 +31,Engineering Elective,,,,,,3,University of Arizona,,5 +32,Engineering Elective,,,,,,3,University of Arizona,,5 +33,Technical Elective,,,,,,3,University of Arizona,,6 +34,Elements of Chem Eng II,CHEE,202,28;29,19,,4,University of Arizona,,6 +35,Chem Eng Heat Xfer & Fluid Flow,CHEE,203,28;10,,,3,University of Arizona,,6 +36,Engineering Elective,,,,,,3,University of Arizona,,6 +37,Technical Elective,,,,,,3,University of Arizona,,6 +38,Chem Eng Mass Xfer,CHEE,303,35,,,3,University of Arizona,,7 +39,Chem Eng Modeling,CHEE,402,22;34,,,3,University of Arizona,,7 +40,Chem Eng Lab I,CHEE,301A,22;34;35,42;43,,1,University of Arizona,,8 +41,Trends in Nanomedicine Eng,CHEE,489,,,,3,University of Arizona,,7 +42,Chem Eng Transport Phenom,CHEE,305,38;39,,,3,University of Arizona,,8 +43,Chem & Phys Equilibrium,CHEE,326,28;30,,,3,University of Arizona,,8 +44,Chem Eng Lab II,CHEE,301B,38;40,,42;43,1,University of Arizona,,9 +45,Chem Reaction Eng,CHEE,420,43,,,3,University of Arizona,,9 +46,Chem Eng Design Principles,CHEE,442,38;43,,45,3,University of Arizona,,9 +47,Chem and Enviorn Eng Lab I,CHEE,401A,44,45,,1,University of Arizona,,10 +48,Physical Chem,CHEM,480B,30,,,3,University of Arizona,,8 +49,Process Control and Simulation,CHEE,413,39,,,3,University of Arizona,,8 +50,Process Dynamics and Control Lab,CHEE,401B,40;44,49,,1,University of Arizona,,10 +51,Chem Eng Plant Design,CHEE,443,46,,,3,University of Arizona,,10 \ No newline at end of file From 01955c8050fc93726eb6208df4cdd24937df174d Mon Sep 17 00:00:00 2001 From: Greg Heileman Date: Wed, 6 Oct 2021 12:12:30 -0700 Subject: [PATCH 4/9] Code clean up in CurricularAnalytics.jl --- src/CurricularAnalytics.jl | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/CurricularAnalytics.jl b/src/CurricularAnalytics.jl index 37f7c740..31402afe 100644 --- a/src/CurricularAnalytics.jl +++ b/src/CurricularAnalytics.jl @@ -860,28 +860,3 @@ function knowledge_transfer(dp::DegreePlan) end end # module - - -for cs in c.courses - for (k,r) in cs.requisites - v_k = course_from_id(c,k).vertex_id[c.id] - if r == strict_co - v_set = reachable_to(g, v_k) # no predecessor to k can have r as a requisite (makes curriculum unsatisfiable) - # Todo: remove r from reachable set - println("checking edges ...\n") - for v in v_set - if CurricularAnalytics.has_edge(g, v, v_k) # found a possibly unsatisfiable requisite - println("found a edge that needs checking\n") - if v in keys(cs.requisites) # check for one exception: if v is also a co-requsite for cs, no problem - # map(course_from_id, fill(curric,length(cs.requisites)), keys(cs.requisites)) - if cs.requisites[v] == pre # it's not, is a prerequisite - validity = false - println(" setting validity false\n") - write(error_msg, "$(course_from_id(c,r).name) cannot be a strict co-requisite for $(cs.name) as well as a requisite for some predecessor of $(cs.name)\n") - end - end - end - end - end - end -end \ No newline at end of file From a336b79237c9b09655233e21f09bbfc52357f468 Mon Sep 17 00:00:00 2001 From: Hayden Free Date: Thu, 28 Oct 2021 19:56:43 -0400 Subject: [PATCH 5/9] csv_stream --- src/CurricularAnalytics.jl | 4 +-- src/DataHandler.jl | 51 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/CurricularAnalytics.jl b/src/CurricularAnalytics.jl index 31402afe..7714d789 100644 --- a/src/CurricularAnalytics.jl +++ b/src/CurricularAnalytics.jl @@ -31,8 +31,8 @@ export AA, AAS, AS, AbstractCourse, AbstractRequirement, BA, BS, Course, CourseC courses_from_vertices, create_degree_plan, cross_edge, dead_ends, delay_factor, delete_requisite!, dfs, extraneous_requisites, find_term, forward_edge, gad, grade, homology, is_duplicate, isvalid_curriculum, isvalid_degree_plan, longest_path, longest_paths, merge_curricula, pass_table, passrate_table, pre, print_plan, quarter, reach, reach_subgraph, reachable_from, reachable_from_subgraph, reachable_to, reachable_to_subgraph, read_csv, requisite_distance, - requisite_type, semester, set_passrates, set_passrate_for_course, set_passrates_from_csv, similarity, simple_students, simulate, simulation_report, - strict_co, topological_sort, total_credits, transfer_equiv, tree_edge, write_csv, knowledge_transfer + requisite_type, semester, set_passrates, set_passrate_for_course, set_passrates_from_csv, similarity, simple_students, simulate, simulation_report, + strict_co, topological_sort, total_credits, transfer_equiv, tree_edge, write_csv, knowledge_transfer, csv_stream # Check if a curriculum graph has requisite cycles. """ diff --git a/src/DataHandler.jl b/src/DataHandler.jl index 31259123..bd54f540 100644 --- a/src/DataHandler.jl +++ b/src/DataHandler.jl @@ -383,4 +383,55 @@ function write_csv(original_plan::DegreePlan, file_path::AbstractString) write_learning_outcomes(curric, csv_file, all_course_lo) end return true +end + +# TODO: Implement this functionality / option into the above methods via optional args +# Write CSV to stream to return via API +function csv_stream(curric::Curriculum) + dict_curric_degree_type = Dict(AA=>"AA", AS=>"AS", AAS=>"AAS", BA=>"BA", BS=>"BS") + dict_curric_system = Dict(semester=>"semester", quarter=>"quarter") + csv_file = IOBuffer() + # open(io, "w") do csv_file + # Write Curriculum Name + curric_name = "Curriculum," * string(curric.name) * ",,,,,,,,," + write(csv_file, curric_name) + + # Write Institution Name + curric_ins = "\nInstitution," * string(curric.institution) * ",,,,,,,,," + write(csv_file, curric_ins) + + # Write Degree Type + curric_dtype="\nDegree Type," * string(dict_curric_degree_type[curric.degree_type]) * ",,,,,,,,," + write(csv_file, curric_dtype) + + # Write System Type (Semester or Quarter) + curric_stype="\nSystem Type," * string(dict_curric_system[curric.system_type]) * ",,,,,,,,," + write(csv_file, curric_stype) + + # Write CIP Code + curric_CIP="\nCIP," * string(curric.CIP) * ",,,,,,,,," + write(csv_file, curric_CIP) + + # Define the course header, 10 columns of data for each course + course_header="\nCourse ID,Course Name,Prefix,Number,Prerequisites,Corequisites,Strict-Corequisites,Credit Hours,Institution,Canonical Name" + # Write Course Section and Course Header + write(csv_file, "\nCourses,,,,,,,,,,") + write(csv_file, course_header) + + # Define dict to store all course learning outcomes + all_course_lo = Dict{Int,Array{LearningOutcome,1}}() + # Iterate through each course in the curriculum + for course in curric.courses + # Write the current course to the CSV + write(csv_file, course_line(course,"")) + # Check if the course has learning outcomes, if it does store them + if length(course.learning_outcomes) > 0 + all_course_lo[course.id] = course.learning_outcomes + end + end + + # Write course and curriculum learning outcomes, if any + write_learning_outcomes(curric, csv_file, all_course_lo) + # end + return csv_file end \ No newline at end of file From bc47fea99520be782529052bcc4b52bf98f92c9a Mon Sep 17 00:00:00 2001 From: Hayden Free Date: Thu, 28 Oct 2021 20:02:19 -0400 Subject: [PATCH 6/9] fix docs typo --- src/GraphAlgs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GraphAlgs.jl b/src/GraphAlgs.jl index 9d64011d..d20c6111 100644 --- a/src/GraphAlgs.jl +++ b/src/GraphAlgs.jl @@ -349,7 +349,7 @@ end """ edge_crossing(g, s) -Given a graph ``g=(V,E)``,and a set of vertices ``s \subseteq V``, determine the number of edges +Given a graph ``g=(V,E)``,and a set of vertices ``s \\subseteq V``, determine the number of edges crossing the cut determined by the partition ``(s,V-s)``. # Arguments From 97ce2c2289b957896b5777e8d89852c4fbf3f976 Mon Sep 17 00:00:00 2001 From: Hayden Free Date: Thu, 28 Oct 2021 20:22:46 -0400 Subject: [PATCH 7/9] transition to Graphs.jl --- Manifest.toml | 150 +++++++++++++++--------- Project.toml | 4 +- docs/src/graph_algs.md | 2 +- examples/Introduction/Example_ECE_UA.jl | 2 +- src/CurricularAnalytics.jl | 2 +- src/DataTypes/Curriculum.jl | 8 +- src/Simulation/Simulation.jl | 2 +- test/DataTypes.jl | 2 +- test/GraphAlgs.jl | 2 +- 9 files changed, 104 insertions(+), 70 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 17001f01..f1d9fa29 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -1,16 +1,16 @@ # This file is machine-generated - editing it directly is not advised +[[ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + [[ArnoldiMethod]] deps = ["LinearAlgebra", "Random", "StaticArrays"] -git-tree-sha1 = "f87e559f87a45bece9c9ed97458d3afe98b1ebb9" +git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae" uuid = "ec485272-7323-5ecc-a04f-4719b315124d" -version = "0.1.0" +version = "0.2.0" [[Artifacts]] -deps = ["Pkg"] -git-tree-sha1 = "c30985d8821e0cd73870b17b0ed0ce6dc44cb744" uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -version = "1.3.0" [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -35,14 +35,14 @@ version = "0.7.0" [[Compat]] deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] -git-tree-sha1 = "919c7f3151e79ff196add81d7f4e45d91bbf420b" +git-tree-sha1 = "31d0151f5716b655421d9d75b7fa74cc4e744df2" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "3.25.0" +version = "3.39.0" [[DataAPI]] -git-tree-sha1 = "dfb3b7e89e395be1e25c2ad6d7690dc29cc53b1d" +git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" -version = "1.6.0" +version = "1.9.0" [[DataFrames]] deps = ["CategoricalArrays", "Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "Missings", "PooledArrays", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] @@ -74,10 +74,10 @@ deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[DocStringExtensions]] -deps = ["LibGit2", "Markdown", "Pkg", "Test"] -git-tree-sha1 = "9d4f64f79012636741cf01133158a54b24924c32" +deps = ["LibGit2"] +git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b" uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -version = "0.8.4" +version = "0.8.6" [[Documenter]] deps = ["Base64", "Dates", "DocStringExtensions", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"] @@ -85,10 +85,20 @@ git-tree-sha1 = "395fa1554c69735802bba37d9e7d9586fd44326c" uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" version = "0.24.11" +[[Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + [[Future]] deps = ["Random"] uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" +[[Graphs]] +deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] +git-tree-sha1 = "92243c07e786ea3458532e199eb3feee0e7e08eb" +uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" +version = "1.4.1" + [[Inflate]] git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c" uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" @@ -99,10 +109,9 @@ deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" [[InvertedIndices]] -deps = ["Test"] -git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc" +git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f" uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" -version = "1.0.0" +version = "1.1.0" [[IteratorInterfaceExtensions]] git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" @@ -115,30 +124,31 @@ git-tree-sha1 = "9f2f2f24e60305feb6ae293a617ddf06f429efc3" uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" version = "0.4.3" -[[JLLWrappers]] -git-tree-sha1 = "a431f5f2ca3f4feef3bd7a5e94b8b8d4f2f647a0" -uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.2.0" - [[JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] -git-tree-sha1 = "81690084b6198a2e1da36fcfda16eeca9f9f24e4" +git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37" uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" -version = "0.21.1" +version = "0.21.2" + +[[LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" [[LibGit2]] -deps = ["Printf"] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +[[LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + [[Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" -[[LightGraphs]] -deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] -git-tree-sha1 = "432428df5f360964040ed60418dd5601ecd240b6" -uuid = "093fc24a-ae57-5d10-9952-331d41423f4d" -version = "1.3.5" - [[LinearAlgebra]] deps = ["Libdl"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -148,19 +158,23 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" [[MacroTools]] deps = ["Markdown", "Random"] -git-tree-sha1 = "6a8a2a625ab0dea913aba95c11370589e0239ff0" +git-tree-sha1 = "3d3e902b31198a27340d0bf00d6ac452866021cf" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.6" +version = "0.5.9" [[Markdown]] deps = ["Base64"] uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +[[MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" + [[MetaGraphs]] -deps = ["JLD2", "LightGraphs", "Random"] -git-tree-sha1 = "9cc756ced4fc5ecfff62605462c1001eec1cf324" +deps = ["Graphs", "JLD2", "Random"] +git-tree-sha1 = "5658bebcf7e58e7ff09aa004ff6e806478c5e93a" uuid = "626554b9-1ddb-594c-aa3c-2596fe9399a5" -version = "0.6.7" +version = "0.7.0" [[Missings]] deps = ["DataAPI"] @@ -171,19 +185,25 @@ version = "0.4.5" [[Mmap]] uuid = "a63ad114-7e13-5084-954f-fe012c677804" +[[MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + +[[NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" + [[OrderedCollections]] -git-tree-sha1 = "4fa2ba51070ec13fcc7517db714445b4ab986bdf" +git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.4.0" +version = "1.4.1" [[Parsers]] deps = ["Dates"] -git-tree-sha1 = "c8abc88faa3f7a3950832ac5d6e690881590d6dc" +git-tree-sha1 = "bfd7d8c7fd87f04543810d9cbd3995972236ba1b" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "1.1.0" +version = "1.1.2" [[Pkg]] -deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" [[PooledArrays]] @@ -197,7 +217,7 @@ deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" [[REPL]] -deps = ["InteractiveUtils", "Markdown", "Sockets"] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[Random]] @@ -221,9 +241,9 @@ uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" [[SentinelArrays]] deps = ["Dates", "Random"] -git-tree-sha1 = "6ccde405cf0759eba835eb613130723cb8f10ff9" +git-tree-sha1 = "f45b34656397a1f6e729901dc9ef679610bd12b5" uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.2.16" +version = "1.3.8" [[Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -234,9 +254,9 @@ uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" [[SimpleTraits]] deps = ["InteractiveUtils", "MacroTools"] -git-tree-sha1 = "daf7aec3fe3acb2131388f93a4c409b8c7f62226" +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" -version = "0.9.3" +version = "0.9.4" [[Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" @@ -253,9 +273,9 @@ uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" [[StaticArrays]] deps = ["LinearAlgebra", "Random", "Statistics"] -git-tree-sha1 = "2f01a51c23eed210ff4a1be102c4cc8236b66e5b" +git-tree-sha1 = "3c76dde64d03699e074ac02eb2e8ba8254d428da" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.1.0" +version = "1.2.13" [[Statistics]] deps = ["LinearAlgebra", "SparseArrays"] @@ -263,31 +283,39 @@ uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" [[StructTypes]] deps = ["Dates", "UUIDs"] -git-tree-sha1 = "89b390141d2fb2ef3ac2dc32e336f7a5c4810751" +git-tree-sha1 = "d24a825a95a6d98c385001212dc9020d609f2d4f" uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" -version = "1.5.0" +version = "1.8.1" + +[[TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" [[TableTraits]] deps = ["IteratorInterfaceExtensions"] -git-tree-sha1 = "b1ad568ba658d8cbb3b892ed5380a6f3e781a81e" +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" -version = "1.0.0" +version = "1.0.1" [[Tables]] deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"] -git-tree-sha1 = "a9ff3dfec713c6677af435d6a6d65f9744feef67" +git-tree-sha1 = "fed34d0e71b91734bf0a7e10eb1bb05296ddbcd0" uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.4.1" +version = "1.6.0" + +[[Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" [[Test]] -deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[TranscodingStreams]] deps = ["Random", "Test"] -git-tree-sha1 = "7c53c35547de1c5b9d46a4797cf6d8253807108c" +git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c" uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.9.5" +version = "0.9.6" [[UUIDs]] deps = ["Random", "SHA"] @@ -297,7 +325,13 @@ uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [[Zlib_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "320228915c8debb12cb434c59057290f0834dbf6" +deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.11+18" + +[[nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" diff --git a/Project.toml b/Project.toml index ad73b924..248a22d3 100644 --- a/Project.toml +++ b/Project.toml @@ -9,7 +9,7 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -LightGraphs = "093fc24a-ae57-5d10-9952-331d41423f4d" +Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" MetaGraphs = "626554b9-1ddb-594c-aa3c-2596fe9399a5" @@ -21,5 +21,5 @@ CSV = "0.7" DataFrames = "0.21.0" DataStructures = "0.17.0" Documenter = "0.24.0" -LightGraphs = "1.3.0" +Graphs = "1.4.0" julia = "1.3, 1.4, 1.5" diff --git a/docs/src/graph_algs.md b/docs/src/graph_algs.md index 84a521dc..b272e6e6 100644 --- a/docs/src/graph_algs.md +++ b/docs/src/graph_algs.md @@ -1,6 +1,6 @@ # Graph Algorithms -This toolbox makes use of a number of the graph algorithms provided in the [LightGraphs](https://juliagraphs.github.io/LightGraphs.jl/latest/index.html) package. In addition, we have implemented a number of graph algorithms that you may find useful when developing analytics around curriculum graphs. The functions implementing these algorithms are described next. +This toolbox makes use of a number of the graph algorithms provided in the [Graphs.jl](https://juliagraphs.org/Graphs.jl/dev/) package. In addition, we have implemented a number of graph algorithms that you may find useful when developing analytics around curriculum graphs. The functions implementing these algorithms are described next. ```@docs dfs diff --git a/examples/Introduction/Example_ECE_UA.jl b/examples/Introduction/Example_ECE_UA.jl index dfc718ea..71b4b76e 100644 --- a/examples/Introduction/Example_ECE_UA.jl +++ b/examples/Introduction/Example_ECE_UA.jl @@ -2,7 +2,7 @@ using CurricularAnalytics using MetaGraphs -using LightGraphs +using Graphs # # create learning outcomes l = Array{LearningOutcome}(undef, 368) diff --git a/src/CurricularAnalytics.jl b/src/CurricularAnalytics.jl index 7714d789..99cd4f49 100644 --- a/src/CurricularAnalytics.jl +++ b/src/CurricularAnalytics.jl @@ -9,7 +9,7 @@ directed edge from vertex ``v_i`` to ``v_j`` is in ``E`` if course ``c_i`` is a module CurricularAnalytics # Dependencies -using LightGraphs +using Graphs using DataStructures using Printf using Markdown diff --git a/src/DataTypes/Curriculum.jl b/src/DataTypes/Curriculum.jl index 701ee78e..168cd718 100644 --- a/src/DataTypes/Curriculum.jl +++ b/src/DataTypes/Curriculum.jl @@ -185,7 +185,7 @@ function create_graph!(curriculum::Curriculum) for (i, c) in enumerate(curriculum.courses) if add_vertex!(curriculum.graph) c.vertex_id[curriculum.id] = i # The vertex id of a course w/in the curriculum - # Lightgraphs orders graph vertices sequentially + # Graphs.jl orders graph vertices sequentially # TODO: make sure course is not alerady in the curriculum else error("vertex could not be created") @@ -218,7 +218,7 @@ function create_course_learning_outcome_graph!(curriculum::Curriculum) for (i, c) in enumerate(curriculum.courses) if add_vertex!(curriculum.course_learning_outcome_graph) c.vertex_id[curriculum.id] = i # The vertex id of a course w/in the curriculum - # Lightgraphs orders graph vertices sequentially + # Graphs.jl orders graph vertices sequentially # TODO: make sure course is not alerady in the curriculum else error("vertex could not be created") @@ -229,7 +229,7 @@ function create_course_learning_outcome_graph!(curriculum::Curriculum) for (j, lo) in enumerate(curriculum.learning_outcomes) if add_vertex!(curriculum.course_learning_outcome_graph) lo.vertex_id[curriculum.id] = len_courses + j # The vertex id of a learning outcome w/in the curriculum - # Lightgraphs orders graph vertices sequentially + # Graphs.jl orders graph vertices sequentially # TODO: make sure course is not alerady in the curriculum else error("vertex could not be created") @@ -290,7 +290,7 @@ function create_learning_outcome_graph!(curriculum::Curriculum) for (i, lo) in enumerate(curriculum.learning_outcomes) if add_vertex!(curriculum.learning_outcome_graph) lo.vertex_id[curriculum.id] = i # The vertex id of a course w/in the curriculum - # Lightgraphs orders graph vertices sequentially + # Graphs.jl orders graph vertices sequentially # TODO: make sure course is not alerady in the curriculum else error("vertex could not be created") diff --git a/src/Simulation/Simulation.jl b/src/Simulation/Simulation.jl index 8828661e..79577b83 100644 --- a/src/Simulation/Simulation.jl +++ b/src/Simulation/Simulation.jl @@ -1,7 +1,7 @@ # File: Simulation.jl using DataFrames -using LightGraphs +using Graphs include("PassRate.jl") include("Enrollment.jl") diff --git a/test/DataTypes.jl b/test/DataTypes.jl index b64a3c6e..3ff62a86 100644 --- a/test/DataTypes.jl +++ b/test/DataTypes.jl @@ -1,7 +1,7 @@ # DataTypes tests using Dates -using LightGraphs +using Graphs @testset "DataTypes Tests" begin diff --git a/test/GraphAlgs.jl b/test/GraphAlgs.jl index eaefe5ed..25995df0 100644 --- a/test/GraphAlgs.jl +++ b/test/GraphAlgs.jl @@ -1,6 +1,6 @@ # Graph Algs tests -using LightGraphs +using Graphs @testset "GraphAlgs Tests" begin From afc01dcdd2a9de455ec3acce100167cd910df09f Mon Sep 17 00:00:00 2001 From: Hayden Free Date: Thu, 28 Oct 2021 20:23:58 -0400 Subject: [PATCH 8/9] Version 1.1.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 248a22d3..8ae40cbd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "CurricularAnalytics" uuid = "593ffa3d-269e-5d81-88bc-c3b6809c35a6" authors = ["Greg Heileman ", "Hayden Free ", "Orhan Abar ", "Will Thompson "] -version = "1.1.1" +version = "1.1.2" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" From 77f3865635f09d1925190ef53e07561f78e76d9d Mon Sep 17 00:00:00 2001 From: Hayden Free Date: Thu, 28 Oct 2021 20:26:57 -0400 Subject: [PATCH 9/9] Version 1.2.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 8ae40cbd..2844485a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "CurricularAnalytics" uuid = "593ffa3d-269e-5d81-88bc-c3b6809c35a6" authors = ["Greg Heileman ", "Hayden Free ", "Orhan Abar ", "Will Thompson "] -version = "1.1.2" +version = "1.2.0" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"