Giter VIP home page Giter VIP logo

curricularanalytics.py's Introduction

CurricularAnalytics.py

CurricularAnalytics.py is a toolbox for studying and analyzing academic program curricula. The toolbox represents curricula as graphs, allowing various graph-theoretic measures to be applied in order to quantify the complexity of curricula. In addition to analyzing curricular complexity, the toolbox supports the ability to visualize curricula, to compare and contrast curricula, to create optimal degree plans for completing curricula that satisfy particular constraints, and to simulate the impact of various events on student progression through a curriculum.

CurricularAnalytics.py is a Python port of the original Julia package CurricularAnalytics.jl.

Documentation

Full documentation is available at GitHub Pages. Documentation for functions in this toolbox is also available via the Julia REPL help system. Additional tutorials can be found at the Curricular Analytics Notebooks site.

Installation

Installation is straightforward. First, ensure you have Python 3.8 or higher installed. Then, run the following command.

# Linux/macOS
python3 -m pip install -U curricularanalytics

# Windows
py -3 -m pip install -U curricularanalytics

Contributing and Reporting Bugs

We welcome contributions and bug reports! Please see CONTRIBUTING.md for guidance on development and bug reporting.

Development

To build a distribution for upload to PyPI, run the following command.

rm -r dist
python -m build
# To Test PyPI
python3 -m twine upload --repository testpypi dist/*
# To real PyPI
twine upload dist/*

Learn more about build and setuptools.

curricularanalytics.py's People

Contributors

haydenfree avatar heileman avatar johnny-flynn avatar juliatagbot avatar kevinwarne avatar orhanabar avatar sheeptester avatar wgthompson avatar will-hou avatar zymvincent avatar

Stargazers

 avatar  avatar

Watchers

 avatar

curricularanalytics.py's Issues

extraneous_requisites returns vertex IDs

image

Note that Julia returns course IDs

image

It makes sense for this function to return Course objects instead, but since it's in a Set and Courses aren't hashable, I guess course IDs are fine

Code quality

if letter_grade == "A➕"
return convert(Grade, 13)
elseif letter_grade == "A"
return convert(Grade, 12)
elseif letter_grade == "A➖"
return convert(Grade, 11)
elseif letter_grade == "B➕"
return convert(Grade, 10)
elseif letter_grade == "B"
return convert(Grade, 9)
elseif letter_grade == "B➖"
return convert(Grade, 8)
elseif letter_grade == "C➕"
return convert(Grade, 7)
elseif letter_grade == "C"
return convert(Grade, 6)
elseif letter_grade == "C➖"
return convert(Grade, 5)
elseif letter_grade == "D➕"
return convert(Grade, 4)
elseif letter_grade == "D"
return convert(Grade, 3)
elseif letter_grade == "D➖"
return convert(Grade, 2)
elseif letter_grade == "P"
return convert(Grade, 0)
elseif letter_grade == "F"
return convert(Grade, 0)
elseif letter_grade == "I"
return convert(Grade, 0)
elseif letter_grade == "WP"
return convert(Grade, 0)
elseif letter_grade == "W"
return convert(Grade, 0)
elseif letter_grade == "WF"
return convert(Grade, 0)

if int_grade == 13
return "A➕"
elseif int_grade == 12
return "A"
elseif int_grade == 11
return "A➖"
elseif int_grade == 10
return "B➕"
elseif int_grade == 9
return "B"
elseif int_grade == 8
return "B➖"
elseif int_grade == 7
return "C➕"
elseif int_grade == 6
return "C"
elseif int_grade == 5
return "C➖"
elseif int_grade == 4
return "D➕"
elseif int_grade == 3
return "D"
elseif int_grade == 2
return "D➖"
elseif int_grade == 0
return "F"

elseif str == "prefix"
course1.prefix == course2.prefix ? is_matched = true : is_matched = false
elseif str == "num"
course1.num == course2.num ? is_matched = true : is_matched = false
elseif str == "name"
course1.name == course2.name ? is_matched = true : is_matched = false
elseif str == "canonical name"
course1.canonical_name == course2.canonical_name ? is_matched = true : is_matched = false
elseif str == "credit hours"
course1.credit_hours == course2.credit_hours ? is_matched = true : is_matched = false

longest_path does not use the right graph

longest_path should find the shortest path in G, with all weights inverted

# The longest path from vertx s to any other vertex in a DAG G (not necessarily unique).
# Note: in a DAG G, longest paths in G = shortest paths in -G
"""
longest_path(g, s)
The longest path from vertx s to any other vertex in a acyclic graph `g`. The longest path
is not necessarily unique, i.e., there can be more than one longest path between two vertices.
# Arguments
Required:
- `g::AbstractGraph` : acylic graph.
- `s::Int` : index of the source vertex in `g`.
```julia-repl
julia> path = longest_paths(g, s)
```
"""
function longest_path(g::AbstractGraph{T}, s::Int) where T
if is_cyclic(g)
error("longest_path(): input graph has cycles")
end
lp = Array{Edge}[]
max = 0
# shortest path from s to all vertices in -G
for path in enumerate_paths(dijkstra_shortest_paths(g, s, -weights(g)))
if length(path) > max
lp = path
max = length(path)
end
end
return lp
end

# The longest path from vertx s to any other vertex in a DAG G (not necessarily unique).
# Note: in a DAG G, longest paths in G = shortest paths in -G
def longest_path(g: "nx.Graph[T]", s: T) -> List[T]:
"""
The longest path from vertex `s` to any other vertex in a acyclic graph `g`. The longest path
is not necessarily unique, i.e., there can be more than one longest path between two vertices.
For performance reasons, `longest_path` doesn't check that `g` is acyclic, unlike the Julia version.
Args:
g: Acylic graph.
s: Index of the source vertex in `g`.
"""
lp: List[T] = []
max = 0
# shortest path from s to all vertices in -G
for path in nx.shortest_path(g, s).values():
if len(path) > max:
lp = path
max = len(path)
return lp

all_paths optimizations

    def _centralities(self) -> List[int]:
        return [
            sum(
                len(path)
                for path in all_paths(self.graph)
                # conditions: path length is greater than 2, target course must be in the path, the target vertex
                # cannot be the first or last vertex in the path
                if (i in path and len(path) > 2 and path[0] != i and path[-1] != i)
            )
            for i in range(len(self.courses))
        ]

This recalculates all_paths(self.graph) for every vertex in the graph, even though it should be the same for each of them.

Metric Time
Blocking factor 1.5215 s
Delay factor 1.7919 s
Complexity 4.27298 s
Centrality 64.6228 s
Extraneous requisites 64.5413 s

I didn't measure longest paths in the same test, but in a separate test,

Metric % of time
Curriculum construction 2.2
Longest paths 2.9
Extraneous requisites 6.2
Total complexity 2.2
Basic metrics 86.3

`write_csv` fails to create curriculum csv file with metrics

The issue is with the course_line() function in csv_utilities.py:

course_line += f"{curriculum.course_complexity(course)},{curriculum.course_blocking_factor(course)},{curriculum.course_delay_factor(course)},{curriculum.course_centrality(course)}"

The function is calling .course_complexity(), etc. (which does not exist) instead of complexity() .

Additionally, I believe there needs to be a leading comma to correctly add in the new metrics columns.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.