Beispiel #1
0
def test_equal():
    result1 = Result(solver_type=SolverType.FFD,
                     time_us=100,
                     lengths=[(100, 100, 100), (200, 200, 200)])
    result2 = Result(solver_type=SolverType.FFD,
                     time_us=200,
                     lengths=[(100, 100, 100), (200, 200, 200)])
    assert result1 == result2
Beispiel #2
0
def test_exactly():
    result1 = Result(solver_type=SolverType.FFD,
                     time_us=100,
                     lengths=[(100, 100, 100), (200, 200, 200)])
    result2 = Result(solver_type=SolverType.FFD,
                     time_us=200,
                     lengths=[(100, 100, 100), (200, 200, 200)])
    result3 = Result(solver_type=SolverType.FFD,
                     time_us=200,
                     lengths=[(100, 100, 100), (200, 200, 200)])
    assert not result1.exactly(result2)
    assert result2.exactly(result3)
Beispiel #3
0
def _solve_gapfill(job: Job) -> Result:
    # 1. Sort by magnitude (largest first)
    # 2. stack until limit is reached
    # 3. try smaller as long as possible
    # 4. create new bar

    # we are writing around in target sizes, prevent leaking changes to job
    mutable_sizes = copy.deepcopy(job.target_sizes)
    targets = sorted(mutable_sizes, reverse=True)

    stocks = []

    current_size = 0
    current_stock = []

    i_target = 0
    while len(targets) > 0:

        # nothing fit, next stock
        if i_target >= len(targets):
            # add local result
            stocks.append(current_stock)

            # reset
            current_stock = []
            current_size = 0
            i_target = 0

        current_target = targets[i_target]
        # target fits inside current stock, transfer to results
        if (current_size + current_target.length + job.cut_width) < job.max_length:
            current_stock.append(current_target.length)
            current_size += current_target.length + job.cut_width

            # remove empty entries
            if current_target.quantity <= 1:
                targets.remove(current_target)
            else:
                current_target.quantity -= 1
        # try smaller
        else:
            i_target += 1

    # apply last "forgotten" stock
    if current_stock:
        stocks.append(current_stock)

    # trimming could be calculated from len(stocks) * length - sum(stocks)
    return Result(solver_type=SolverType.gapfill, lengths=stocks)
Beispiel #4
0
def test_full_model():
    json_job = Path("./tests/data/in/testjob.json")
    assert json_job.exists()

    json_result = Path("./tests/data/out/testresult.json")

    with open(json_job, "r") as encoded_job:
        job = Job.parse_raw(encoded_job.read())

        solved = distribute(job)

        encoded_solved = solved.json()
        assert len(encoded_solved) > 20

    with open(json_result, "r") as encoded_result:
        result = Result.parse_raw(encoded_result.read())

        assert solved == result
Beispiel #5
0
def _solve_FFD(job: Job) -> Result:
    # iterate over list of stocks
    # put into first stock that it fits into

    # 1. Sort by magnitude (largest first)
    # 2. stack until limit is reached
    # 3. try smaller as long as possible
    # 4. create new bar

    mutable_sizes = copy.deepcopy(job.target_sizes)
    targets = sorted(mutable_sizes, reverse=True)

    assert len(targets) > 0

    stocks: List[List[int]] = [[]]
    stock_lengths: List[int] = [0]

    i_target = 0

    while i_target < len(targets):
        current_size = targets[i_target]

        for i, stock in enumerate(stocks):
            # step through existing stocks until current size fits
            if (job.max_length - stock_lengths[i]) > current_size.length:
                # add size
                stock.append(current_size.length)
                stock_lengths[i] += job.cut_width + current_size.length
                break
        else:  # nothing fit, opening next bin
            stocks.append([current_size.length])
            stock_lengths.append(0)

            assert len(stocks) == len(stock_lengths)

        # decrease/get next
        if current_size.quantity <= 1:
            i_target += 1
        else:
            current_size.quantity -= 1

    return Result(solver_type=SolverType.FFD, lengths=stocks)
Beispiel #6
0
def _solve_bruteforce(job: Job) -> Result:
    # failsafe
    if len(job) > 12:
        raise OverflowError("Input too large")

    # find every possible ordering (n! elements)
    all_orderings = permutations(job.get_sizes())
    # TODO: remove duplicates (due to "quantity")

    # "infinity"
    min_trimmings = len(job) * job.max_length
    min_stocks: List[List[int]] = []

    # possible improvement: Distribute combinations to multiprocessing worker threads
    for combination in all_orderings:
        stocks, trimmings = _split_combination(combination, job.max_length, job.cut_width)
        if trimmings < min_trimmings:
            min_stocks = stocks
            min_trimmings = trimmings

    return Result(solver_type=SolverType.bruteforce, lengths=min_stocks)
Beispiel #7
0
def test_constructor():
    result = Result(solver_type=SolverType.FFD,
                    time_us=100,
                    lengths=[(100, 100, 100), (200, 200, 200)])
    assert result
Beispiel #8
0
def test_invalid():
    invalid_result = Result(solver_type=SolverType.FFD,
                            time_us=-1,
                            lengths=[(100, 100, 100), (200, 200, 200)])
    assert not invalid_result.valid()
Beispiel #9
0
def test_valid():
    result = Result(solver_type=SolverType.FFD,
                    time_us=100,
                    lengths=[(100, 100, 100), (200, 200, 200)])
    assert result.valid()