Skip to content

Commit

Permalink
Merge pull request #71 from ModischFabrications/feature/multi-stocks
Browse files Browse the repository at this point in the history
Multiple stocks for solver
  • Loading branch information
ModischFabrications authored Apr 15, 2024
2 parents 90b39ef + 345f0f7 commit dc6c9bb
Show file tree
Hide file tree
Showing 25 changed files with 1,074 additions and 527 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,18 @@ jobs:
- name: Lint with flake8 🔍
run: |
# stop the build if there are Python syntax errors or undefined names
pipenv run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
pipenv run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
pipenv run flake8 tests/ app/ --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings
pipenv run flake8 tests/ app/ --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics
- name: Test with mypy 🔍
run: |
# stop the build if there are typing errors
pipenv run python -m mypy app/ tests/
- name: Test with pytest 🔍
run: |
# stop the build if there are failed tests
pipenv run python -m pytest --durations=10
build-and-push-docker:
Expand Down
20 changes: 14 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ default_language_version:

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
rev: v4.5.0
hooks:
# https://blog.mphomphego.co.za/blog/2019/10/03/Why-you-need-to-stop-using-Git-Hooks.html
- id: check-ast
Expand Down Expand Up @@ -49,8 +49,16 @@ repos:
- id: requirements-txt-fixer
name: requirements-txt-fixer
description: Sorts entries in requirements.txt
- id: check-json
name: check-json
description: Attempts to load all json files to verify syntax.

#bandit, vulture?
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
hooks:
- id: mypy
name: mypy
description: Check typing

- repo: local
hooks:
Expand All @@ -63,9 +71,9 @@ repos:
language: system
# git version check only needed if version could have changed
files: main.py
types: [python]
types: [ python ]
# TODO: use post-commit
stages: [push]
stages: [ push ]

- id: tests
name: run tests
Expand All @@ -74,5 +82,5 @@ repos:
pass_filenames: false
entry: pipenv run python -m pytest -sv
language: system
types: [python]
stages: [push]
types: [ python ]
stages: [ push ]
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ flake8 = "==7.0.0"
httpx = "==0.26.0"
black = "==24.3.0"
pytest-cov = "==5.0.0"
mypy = "==1.9.0"

[packages]
fastapi = "==0.109.1"
uvicorn = "==0.26.0"
pydantic-settings = "==2.2.1"
more-itertools = "10.2.0"

[requires]
python_version = "3.11"
78 changes: 68 additions & 10 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ This Solver is using integers exclusively, as there is no need for arbitrary pre
Feel free to shift your numbers a few decimals if you need fractions.
It has no concept of units, so you can use whatever you want.

*Nerd talk*: This is the 2D "Cutting Stock Problem", which is NP-hard. It can be reduced to the Bin-Packing-Problem (
BPP).
*Nerd talk*: This is the 2D "Cutting Stock Problem", which is NP-hard.
No algorithm exists to calculate a perfect solution in polynomial time, therefore brute force (perfect
solution) is used for small jobs (usually <12 entries) and FFD (fast solution) für larger ones.
Don't be surprised if you get different results, many combinations have equal trimmings and are therefore seen as
Expand Down Expand Up @@ -73,17 +72,23 @@ You might need to replace `#!/bin/sh` with `#!/usr/bin/env sh` in the resulting
All obvious errors should be checked and or fixed by pre-commit, execute `pre-commit run --all-files --hook-stage push`
to run manually.

use `git push --no-verify` if you really need to skip these tests, but you better have a good explanation.

Change version number in main.py:version for newer releases, git tags will be created automatically.

### Testing

Remember to test your changes using `pytest`. This will happen automatically both in pre-commit and in CI/CD, but manual
tests will reduce iteration times.

Make sure your changes keep app.* imports or pytest will crash and burn due to missing import settings.

Code coverage and runtimes can be checked
using `pipenv run python -m pytest --durations=5 --cov=app/ --cov-report term-missing`.
Make sure that all critical parts of the code are covered, at v1.0.1 it is at 94%.

Proper type usage can be checked using `pipenv run python -m mypy app`.

### Development Docker Images

1. Build and start this image using `docker-compose up`
Expand Down Expand Up @@ -127,14 +132,17 @@ This project uses:

* [FastAPI](https://github.com/tiangolo/fastapi): easy API (this includes much more!)
* [Uvicorn](https://github.com/encode/uvicorn): async web server
* [more-itertools](https://github.com/more-itertools/more-itertools): higher performance permutations

Also used for development is:

* [pipenv](https://github.com/pypa/pipenv): library management
* [httpie](https://github.com/jakubroztocil/httpie): simpler `curl` for docker healthchecks
* [pytest](https://pytest.org): A lot nicer unit tests
* [flake8](https://flake8.pycqa.org/): Linting
* [mypy](https://mypy-lang.org/): Static type checking
* [requests](https://requests.readthedocs.io/): simple HTTP requests
* [httpx](https://www.python-httpx.org/): requirement of TestClient
* [black](https://github.com/psf/black): uncompromising code formatter; currently unused

## External links
Expand Down
10 changes: 4 additions & 6 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
from contextlib import asynccontextmanager

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from fastapi.middleware.cors import CORSMiddleware
from starlette.requests import Request
from starlette.responses import HTMLResponse, PlainTextResponse

from app.settings import version, solverSettings
# don't mark /app as a sources root or pycharm will delete the "app." prefix
# that's needed for pytest to work correctly
from app.solver.data.Job import Job
from app.solver.data.Result import Result
from app.solver.solver import solve
Expand Down Expand Up @@ -55,10 +53,10 @@ async def catch_exceptions_middleware(request: Request, call_next):
)


# response model ensures correct documentation
@app.post("/solve", response_model=Result)
# response model ensures correct documentation, exclude skips optional
@app.post("/solve", response_model=Result, response_model_exclude_defaults=True)
def post_solve(job: Job):
# pydantic guarantees type safety, no need to check manually
# pydantic guarantees type safety, no need to check inputs
solved: Result = solve(job)

return solved
Expand Down
7 changes: 3 additions & 4 deletions app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
from pydantic_settings import BaseSettings

# constant; used for git tags
version = "v1.0.2"
version = "v1.1.0"


class SolverSettings(BaseSettings):
# Desktop with Ryzen 2700X:
# (4, 3, 2)=1260 => 0.1s, (4, 3, 3)=4200 => 0.8s, (5, 3, 3)=9240 => 8s
bruteforce_max_combinations: PositiveInt = 5000
# print n_combinations from tests to find the limit
bruteforce_max_combinations: PositiveInt = 9000
# that is already unusable x100, but the solver takes it easily
solver_n_max: PositiveInt = 2000

Expand Down
Loading

0 comments on commit dc6c9bb

Please sign in to comment.