Contributing to panchi
Thank you for your interest in contributing to panchi! This guide will help you understand our development philosophy and contribution process.
Table of Contents
- Philosophy and Values
- Getting Started
- Development Setup
- Code Standards
- Testing Requirements
- Documentation Standards
- Contribution Workflow
- What We're Looking For
- Code Review Process
- Community Guidelines
Philosophy and Values
panchi is built on the following core principles. Every contribution should align with them:
1. Clarity Over Optimization
Code should be understandable by someone learning linear algebra. A clear implementation beats a clever one.
Good:
def dot(vector_1: Vector, vector_2: Vector) -> float:
if vector_1.dims != vector_2.dims:
raise ValueError("Vector dimensions must match for dot product.")
n = vector_1.dims
return sum(vector_1[i] * vector_2[i] for i in range(n))
Avoid:
def dot(v1, v2):
return sum(map(lambda x: x[0] * x[1], zip(v1, v2)))
The second version is more concise but less transparent about what's happening.
2. Educational Value First
Implementations should focus on teaching linear algebra, instead of simplifying or obscuring calculations.
3. Mathematical Correctness
Implementations must match standard mathematical definitions and textbook algorithms.
4. Informative Errors
Error messages should explain what went wrong and why, helping users learn.
5. Minimal External Dependencies
The core library (i.e. vector and matrix implementations and operations/algorithms) esclusively uses Python's standard library to remain transparent and accessible.
Additional features such as visualizations should strive to minimize dependencies, especially those that rely on packages that are not solely setup with pip (e.g. Manim, which relies on C libraries, though this case is provided as an optional package for prettier visualizations, and greatly improves learning).
6. Break Any of These Principles for Education
Although these are guides, if they are blocking the advancement of this library's purpose: break them. It's that simple!
Getting Started
Prerequisites
- Python 3.10+
- Git
- pytest (for testing)
- Basic understanding of linear algebra
- Familiarity with type hints
First Contribution Ideas
- Fix typos in documentation
- Add test cases for edge conditions
- Improve error messages
- Write examples in the docs
- Implement small utility functions
Development Setup
1. Fork and Clone
# Fork the repository on GitHub, then:
git clone https://github.com/Gustavo-Galvao-e-Silva/panchi.git
cd panchi
2. Create Virtual Environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
3. Install in Development Mode
pip install -e ".[dev]"
4. Verify Installation
python -c "from panchi.primitives import Vector; print(Vector([1, 2, 3]))"
pytest tests/ -v
5. Create Feature Branch
git checkout -b feature/your-feature-name
Code Standards
File Organization
panchi/
├── primitives/ # Core classes (Vector, Matrix) and factory functions
├── algorithms/ # Reductions, decompositions, and other complex algorithms
└── visualizations/ # Plotting utilities
Naming Conventions
- Classes:
PascalCase(e.g.,Vector,Matrix) - Functions:
snake_case(e.g.,dot,cross,rotation_matrix_2d) - Constants:
UPPER_SNAKE_CASE(if needed) - Private/helper methods:
_leading_underscore(e.g.,_apply_transformation)
Type Hints
Always include type hints and guards. They're documentation and help catch errors.
def zero_vector(dims: int) -> Vector:
if not isinstance(dims, int):
raise TypeError(f"Dimension must be an integer. Got {type(dims).__name__}.")
if dims <= 0:
raise ValueError(f"Dimension must be positive. Got {dims}.")
return Vector([0 for _ in range(dims)])
Minimalist Comments (Except Docstrings)
Some comments in more complex implementations are genuinely welcome, but if you find yourself needing many comments to explain what the code does, that's usually a sign to refactor rather than annotate.
Good:
def ref(matrix: Matrix) -> Reduction:
result = matrix.copy()
operations = []
pivots = []
i = 0
for j in range(min(matrix.cols, matrix.rows)):
result, swap_operations = _swap_pivot(i, j, result)
operations += swap_operations
if result[i][j] == 0:
continue
result, addition_operations = _add_below_pivot(i, j, result)
operations += addition_operations
pivots.append((i, j))
i += 1
return Reduction(matrix, result, operations, pivots, "REF")
Avoid:
def reduce(m: Matrix):
r = m.copy()
ops = []
pvts = []
i = 0
for j in range(min(m.cols, m.rows)):
# Find a non-zero row below i in column j and swap it into position
r, s = _sp(i, j, r)
ops += s
# No pivot in this column, move on
if r[i][j] == 0:
continue
# Zero out all rows below the pivot row
r, a = _ab(i, j, r)
ops += a
pvts.append((i, j))
i += 1
# Return the result along with the recorded operations and pivot positions
return Reduction(m, r, ops, pvts, "REF")
No Debug/Print Statements
Never commit code with print() statements for debugging. Use proper logging if necessary, or remove them entirely.
Explicit Over Implicit
Be clear about what operations are happening.
Good:
row_count = self.rows
col_count = self.cols
result = []
for i in range(row_count):
new_row = []
for j in range(col_count):
new_row.append(self[i][j] + other[i][j])
result.append(new_row)
Avoid:
return Matrix([[self[i][j] + other[i][j] for j in range(self.cols)] for i in range(self.rows)])
Testing Requirements
Test Every Public Function
All public functions and methods must have tests covering: - Normal operation - Edge cases - Error conditions - Type validation
Test File Organization
tests/
├── test_decompositions.py # Decompositions function tests
├── test_matrix.py # Matrix class tests
├── test_matrix_algorithms.py # Matrix algorithm tests
├── test_matrix_operations.py # Matrix operation tests
├── test_operations.py # Operations function tests
└── test_vector.py # Vector class tests
Test Naming Convention
class TestVectorAddition:
def test_add_same_dimension(self):
# Test normal case
def test_add_different_dimensions(self):
# Test error condition
def test_add_zero_vector(self):
# Test edge case
Writing Good Tests
def test_matrix_multiplication_2x2(self):
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])
result = m1 @ m2 # @ is matrix multiplication; * is scalar multiplication
expected = Matrix([[19, 22], [43, 50]])
assert result == expected
assert result.shape == (2, 2)
Test Error Messages
def test_add_different_dimensions(self):
v1 = Vector([1, 2])
v2 = Vector([1, 2, 3])
with pytest.raises(TypeError) as excinfo:
result = v1 + v2
assert "dimension" in str(excinfo.value).lower()
Run Tests Before Submitting
# Run all tests
pytest tests/
# Run specific test file
pytest tests/test_vector.py
# Run with verbose output
pytest tests/ -v
# Run with coverage report
pytest tests/ --cov=panchi
Documentation Standards
Docstring Format
Use NumPy/Google style docstrings for all public functions and classes.
def rotation_matrix_2d(angle: int | float, radians: bool = True) -> Matrix:
"""
Create a 2D rotation matrix.
Constructs a matrix that rotates points in 2D space by the specified
angle. The rotation is counterclockwise when using standard coordinate
orientation.
Parameters
----------
angle : int | float
Rotation angle. Interpreted as radians if radians=True,
degrees if radians=False.
radians : bool, optional
If True (default), angle is in radians. If False, angle is in degrees.
Returns
-------
Matrix
A 2×2 rotation matrix.
Examples
--------
>>> from math import pi
>>> rot90 = rotation_matrix_2d(pi / 2)
>>> point = Vector([1, 0])
>>> rotated = rot90 * point
>>> print(rotated)
[0, 1]
See Also
--------
rotation_matrix_3d : 3D rotation about an arbitrary axis
"""
angle_radians = angle if radians else (angle * pi / 180)
cos_angle = cos(angle_radians)
sin_angle = sin(angle_radians)
return Matrix([[cos_angle, -sin_angle], [sin_angle, cos_angle]])
Docstring Sections
Include these sections as appropriate: - Short summary (one line) - Extended description (optional, for complex functions) - Parameters (all parameters with types and descriptions) - Returns (return type and description) - Raises (exceptions that can be raised) - Examples (working code examples) - See Also (related functions) - Notes (implementation details, algorithms used)
Parameter Descriptions
Be specific about constraints:
Parameters
----------
dims : int
Number of components in the vector. Must be positive.
index : int
Position of the 1 component (0-indexed). Must be in range [0, dims).
Examples in Docstrings
- Use actual code that can be copied and run
- Show expected output
- Cover common use cases
- Include edge cases when helpful
Contribution Workflow
1. Create an Issue (Optional but Recommended)
Before starting work, create an issue describing: - What you want to add/fix - Why it's valuable - How you plan to implement it
This helps avoid duplicate work and ensures alignment with project goals.
2. Write Your Code
Follow all code standards and write tests as you go.
3. Update Documentation
- Add/update docstrings
- Update API documentation if needed
- Add examples if relevant
4. Run Tests
pytest tests/ -v
All tests must pass before submitting.
5. Commit Your Changes
Write clear, descriptive commit messages:
# Good commit messages
git commit -m "Add determinant calculation for square matrices"
git commit -m "Fix dimension check in matrix multiplication"
git commit -m "Improve error message for incompatible vector addition"
# Avoid vague messages
git commit -m "Update code"
git commit -m "Fix bug"
git commit -m "Changes"
6. Push and Create Pull Request
git push origin feature/your-feature-name
OR
git push origin bug-fix/bug-name
OR
git push origin documentation/change-name
Then create a pull request on GitHub with: - Clear title summarizing the change - Description of what changed and why - Reference to related issues - Examples of the new functionality
7. Respond to Review Feedback
Reviewers may request changes. This is normal and helps maintain quality.
What We're Looking For
High Priority Contributions
1. QR Decomposition
Implement using Gram-Schmidt process.
Requirements: - Returns Q (orthogonal) and R (upper triangular) - Clear step-by-step implementation - Verification tests
2. Visualization Tools
Create functions to visualize vectors and transformations.
Requirements: - Simple, clear visualizations - Works with existing Vector/Matrix classes - Matplotlib or Manim (optional dependency) - Examples in documentation
Also Welcome
- Bug fixes with test cases
- Documentation improvements
- Additional utility functions (with justification)
- Performance improvements that maintain clarity
- Educational examples
- Better error messages
Not Currently Seeking
- Alternative implementations of existing features
- Features requiring external dependencies in core library
- Highly optimized but opaque implementations
- Features without clear educational value
Code Review Process
What Reviewers Check
- Correctness: Does it work? Are there bugs?
- Clarity: Is the code easy to understand?
- Tests: Are there comprehensive tests?
- Documentation: Are docstrings complete and accurate?
- Style: Does it follow project conventions?
- Educational value: Does it help users learn?
Approval Requirements
Pull requests need: - ✅ All tests passing - ✅ At least one maintainer approval - ✅ No unresolved conversations - ✅ Updated documentation
Community Guidelines
Be Respectful
- Treat all contributors with respect
- Assume good intentions
- Provide constructive feedback
- Welcome newcomers
- Be kind to all in spite of such a cruel world :)
Be Collaborative
- Share knowledge
- Help others learn
- Credit contributions
- Build on each other's work
Be Patient
- Code review takes time
- Discussions may be lengthy
- Learning happens at different paces
Ask Questions
- No question is too basic
- Clarify requirements before implementing
- Discuss design decisions
- Seek feedback early
Getting Help
- Questions about implementation: Open a GitHub issue
- Clarifying requirements: Comment on relevant issue/PR
- General discussion: Use GitHub Discussions
- Private concerns: Email maintainers (coming soon)
Recognition
All contributors are recognized in: - CONTRIBUTORS.md file - Release notes - Project README (for significant contributions)
License
By contributing to panchi, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to panchi! Your work helps make linear algebra more accessible and understandable for everyone!