creating office shelf

This commit is contained in:
Thomas Weinhold 2023-01-25 23:44:48 +01:00
commit 06d1d3474a
34 changed files with 551 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

176
OfficeShelf/zuschnitt.py Normal file
View file

@ -0,0 +1,176 @@
import time
class LengthError(ValueError):
pass
class Cut(object):
def __init__(self, l):
self.Length = l
class CutableRod(object):
def __init__(self):
self.Length = 6000
self.CutThickness = 0
self.Remainder = self.Length
self.Cuts = []
def addCut(self, cut):
if not self.canAddCut(cut):
raise LengthError("Cut.Length=%i, Remainder=%i" % (cut.Length, self.Remainder))
self.Cuts.append(cut)
self.Remainder -= cut.Length
self.Remainder -= self.CutThickness
def copy(self):
new_rod = CutableRod()
new_rod.Length = self.Length
new_rod.CutThickness = self.CutThickness
new_rod.Remainder = self.Remainder
for c in self.Cuts:
new_rod.Cuts.append(c)
return new_rod
def canAddCut(self, cut):
return self.Remainder >= cut.Length
def variety(self):
""" Amount of different cut lengths
"""
lengths = []
for cut in self.Cuts:
if cut.Length not in lengths:
lengths.append(cut.Length)
return len(lengths)
class CutSolution(object):
def __init__(self):
self.Rods = []
def isBetterThan(self, other):
if self.rods() != other.rods():
return self.rods() < other.rods()
elif self.remainder() != other.remainder():
return self.remainder() < other.remainder()
elif self.variety() != other.variety():
return self.variety() < other.variety()
else:
return False
def copy(self):
new_solution = CutSolution()
for r in self.Rods:
new_solution.Rods.append(r.copy())
return new_solution
def variety(self):
variety = 0
for r in self.Rods:
v = r.variety()
if v > 1:
variety += v
return variety
def rods(self):
return len(self.Rods)
def remainder(self):
remainder = 0
for r in self.Rods:
remainder += r.Remainder
return remainder
def print(self, short=False):
if not short:
print("\nSolution")
for idx_r in range(len(self.Rods)):
r = self.Rods[idx_r]
print("Rod ", idx_r, ": ", end="", sep="")
for idx_c in range(len(r.Cuts)):
c = r.Cuts[idx_c]
print(c.Length, " ", end="", sep="")
print("(-", r.Remainder, ")", sep="")
print("Rods=", self.rods(), ", Remainder=", self.remainder(), ", Variety=", self.variety(), sep="")
class CutRequest(object):
def __init__(self):
self.Cuts = []
self.CreatedSolutions = []
def add(self, amount, length):
for i in range(amount):
c = Cut(length)
self.Cuts.append(c)
def _iterate(self, current_solution, remaining_cuts):
if len(remaining_cuts) == 0:
return current_solution
best_solution = None
tested_lengths = []
for idx_try in range(len(remaining_cuts)):
cut = remaining_cuts[idx_try]
# avoid testing same length again
if cut.Length in tested_lengths:
continue
tested_lengths.append(cut.Length)
# create temporary solution for trial
trysol = CutSolution() if current_solution is None else current_solution.copy()
# add cut to temporary solution
if len(trysol.Rods) == 0 or not trysol.Rods[-1].canAddCut(cut):
trysol.Rods.append(CutableRod())
trysol.Rods[-1].addCut(cut)
# create list of remaining other cuts
remaining_cuts_without_try = []
for idx_other in range(len(remaining_cuts)):
if idx_other != idx_try:
cut_other = remaining_cuts[idx_other]
remaining_cuts_without_try.append(cut_other)
# solve for tried remaining cuts
trysol = self._iterate(trysol, remaining_cuts_without_try)
# keep best solution
if best_solution is None or trysol.isBetterThan(best_solution):
best_solution = trysol
if current_solution is None:
print("Better Solution: ", end="")
best_solution.print(True)
return best_solution
def arrangeCuts(self):
time_start = time.time()
solution = self._iterate(None, self.Cuts)
solution.print()
time_stop = time.time()
print("duration: %0.1f" % (time_stop - time_start))
if __name__ == "__main__":
cr = CutRequest()
cr.add(8, 660);
cr.add(16, 620);
cr.add(1, 905);
cr.add(2, 442);
cr.add(2, 848);
cr.add(4, 414);
cr.arrangeCuts()

View file

@ -0,0 +1,74 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
CMakeLists.txt.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

View file

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.5)
project(zuscnitt LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_FLAGS_DEBUG "-O3")
SET(CMAKE_C_FLAGS_DEBUG "-O3")
add_executable(zuscnitt main.cpp)
install(TARGETS zuscnitt
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

View file

@ -0,0 +1,287 @@
#include <cassert>
#include <ctime>
#include <iostream>
#include <memory>
#include <vector>
bool intvectcontains(const std::vector<int> &heystack, int needle) {
for (auto i: heystack) {
if (i == needle) return true;
}
return false;
}
class Cut {
public:
Cut(int l) {
this->Length = l;
}
int length() const {
return this->Length;
}
private:
Cut(Cut &); // deny copying
int Length = 0;
};
class CutableRod {
public:
CutableRod() {
this->Length = 6000;
this->CutThickness = 9;
this->Remainder = this->Length;
}
CutableRod(CutableRod &other) {
this->Length = other.Length;
this->CutThickness = other.CutThickness;
this->Remainder = other.Remainder;
for (auto c : other.Cuts) {
this->Cuts.push_back(c);
}
}
void addCut(std::shared_ptr<const Cut> cut) {
assert(this->canAddCut(cut));
this->Cuts.push_back(cut);
this->Remainder -= cut->length();
this->Remainder -= this->CutThickness;
}
bool canAddCut(std::shared_ptr<const Cut> cut) {
return this->Remainder >= cut->length();
}
std::vector<std::shared_ptr<const Cut>> cuts() {
return this->Cuts;
}
int remainder() {
return this->Remainder;
}
int variety(void) {
std::vector<int> lengths;
for (auto cut : this->Cuts) {
if (!intvectcontains(lengths, cut->length()))
lengths.push_back(cut->length());
}
return lengths.size();
}
private:
int Length = 0;
int CutThickness = 0;
int Remainder = 0;
std::vector<std::shared_ptr<const Cut>> Cuts;
};
class CutSolution {
public:
CutSolution() {
}
CutSolution(CutSolution &other) {
for (auto r_other: other.Rods) {
auto r_copy = std::make_shared<CutableRod>(*r_other);
this->Rods.push_back(r_copy);
}
}
void addCut(std::shared_ptr<const Cut> cut) {
// add rod if empty
if (this->Rods.empty()) {
auto new_rod = std::make_shared<CutableRod>();
this->Rods.push_back(new_rod);
}
// add rod if cannot add cut
if (!this->Rods.back()->canAddCut(cut)) {
auto new_rod = std::make_shared<CutableRod>();
this->Rods.push_back(new_rod);
}
// add cut to last rod
this->Rods.back()->addCut(cut);
}
bool isBetterThan(const CutSolution &other) {
// compare rod amount
int my_r = this->rods();
int other_r = other.rods();
if (my_r != other_r) {
return my_r < other_r;
// compare remainder amount
} else {
int my_r = this->remainder();
int other_r = other.remainder();
if (my_r != other_r) {
return my_r < other_r;
// compare variety amount
} else {
int my_v = this->variety();
int other_v = other.variety();
if (my_v != other_v) {
return my_v < other_v;
// both solutions are equal
} else {
return false;
}
}
}
}
void print(bool shortform=false) {
if (!shortform) {
std::cout << std::endl << "Solution" << std::endl;
for (auto it = this->Rods.begin(); it != this->Rods.end(); ++it) {
int pos = std::distance(this->Rods.begin(), it);
std::cout << "Rod " << pos << ": ";
for (auto c: (*it)->cuts()) {
std::cout << c->length() << " ";
}
std::cout << "(-" << (*it)->remainder() << ")" << std::endl;
}
}
std::cout << "Rods=" << this->rods();
std::cout << ", Remainder=" << this->remainder();
std::cout << ", Variety=" << this->variety();
std::cout << std::endl;
}
int remainder() const {
int ret = 0;
for (auto r: this->Rods) {
ret += r->remainder();
}
return ret;
}
int rods() const {
return (int) this->Rods.size();
}
int variety() const {
int ret = 0;
for (auto r: this->Rods) {
int v = r->variety();
if (v > 1) ret += v;
}
return ret;
}
private:
std::vector<std::shared_ptr<CutableRod>> Rods;
};
class CutRequest {
public:
CutRequest() {}
void add(int amount, int length) {
for (int i=0; i < amount; ++i) {
auto c = std::make_shared<Cut>(length);
this->Cuts.push_back(c);
}
}
void arrangeCuts() {
auto time_start = std::time(nullptr);
auto solution = CutSolution();
solution = this->arrangeCutIteration(solution, this->Cuts);
solution.print();
auto time_end = std::time(nullptr);
std::cout << "Duration: " << (time_end - time_start) << std::endl;
}
std::vector<std::shared_ptr<const Cut>> cuts() {
return this->Cuts;
}
private:
std::vector<std::shared_ptr<const Cut>> Cuts;
CutSolution arrangeCutIteration(CutSolution &current_solution,
std::vector<std::shared_ptr<const Cut>> remaining_cuts) {
if (remaining_cuts.empty()) return current_solution;
CutSolution best_solution;
bool ret_is_defined = false;
std::vector<int> tested_lengths;
for (int idx_try=0; idx_try < remaining_cuts.size(); ++idx_try) {
auto cut = remaining_cuts.at(idx_try);
// avaoid testing same length again
// if (std::find(tested_lengths.begin(), tested_lengths.end(), cut->length()) != tested_lengths.end()) continue;
if (intvectcontains(tested_lengths, cut->length())) continue;
tested_lengths.push_back(cut->length());
// create temporary solution for trial
CutSolution trysol(current_solution);
// add cut to temporary solution
trysol.addCut(cut);
// create list of remaining other cuts
std::vector<std::shared_ptr<const Cut>> remaining_cuts_without_try;
remaining_cuts_without_try.clear();
for (int idx_other=0; idx_other < remaining_cuts.size(); ++idx_other) {
if (idx_other == idx_try) continue;
auto cut_other = remaining_cuts.at(idx_other);
remaining_cuts_without_try.push_back(cut_other);
}
// solve for tried remaining cuts
trysol = this->arrangeCutIteration(trysol, remaining_cuts_without_try);
// keep best solution
if (!ret_is_defined || trysol.isBetterThan(best_solution)) {
best_solution = trysol;
if (current_solution.rods() == 0) {
std::cout << "Better Solution: ";
best_solution.print(true);
}
ret_is_defined = true;
}
}
return best_solution;
}
};
int main(void) {
CutRequest cr;
cr.add(8, 660);
cr.add(16, 620);
cr.add(1, 905);
cr.add(2, 442);
cr.add(2, 848);
cr.add(4, 414);
cr.arrangeCuts();
// // manual solve
// CutSolution cs;
// for (auto c: cr.cuts()) {
// cs.addCut(c);
// }
// cs.print();
return 0;
}