15 #ifndef PAAL_KNAPSACK_0_1_HPP
16 #define PAAL_KNAPSACK_0_1_HPP
26 #include <boost/range/adaptor/reversed.hpp>
27 #include <boost/function_output_iterator.hpp>
28 #include <boost/optional.hpp>
42 auto operator()(T begin, T end)
43 ->decltype(
irange(begin, end) | boost::adaptors::reversed) {
44 return irange(begin, end) | boost::adaptors::reversed;
57 template <
typename Objects,
typename ObjectSizeFunctor,
58 typename ObjectValueFunctor,
typename Comparator>
61 using SizeType =
typename base::SizeType;
62 using ValueType =
typename base::ValueType;
63 using ObjectType =
typename base::ObjectType;
64 using ObjectRef =
typename base::ObjectRef;
65 using ReturnType =
typename base::return_type;
66 using ValueOrNull = boost::optional<ValueType>;
67 static_assert(std::is_integral<SizeType>::value,
68 "Size type must be integral");
69 using ValueOrNullVector = std::vector<ValueOrNull>;
73 Knapsack_0_1(ObjectSizeFunctor size, ObjectValueFunctor value,
74 Comparator compare = Comparator())
75 : m_size(size), m_value(value), m_comparator(compare) {}
81 template <
typename GetBestElement>
82 ReturnType
solve(Objects objects, SizeType capacity,
83 GetBestElement getBest) {
84 m_object_on_size.resize(capacity + 1);
85 fill_table(m_object_on_size, objects, capacity);
86 auto maxValue = getBest(m_object_on_size.begin(),
87 m_object_on_size.end(), m_comparator);
89 if (maxValue != m_object_on_size.end()) {
90 return ReturnType(**maxValue, maxValue - m_object_on_size.begin());
92 return ReturnType(ValueType{}, SizeType{});
99 template <
typename OutputIterator>
100 void retrieve_solution(ValueType maxValue, SizeType size, Objects objects,
101 OutputIterator & out)
const {
102 m_object_on_size.resize(size + 1);
103 m_object_on_size_rec.resize(size + 1);
104 retrieve_solution_rec(maxValue, size, std::begin(objects),
105 std::end(objects), out);
109 template <
typename OutputIterator,
typename ObjectsIter>
110 void retrieve_solution_rec(ValueType maxValue, SizeType capacity,
111 ObjectsIter oBegin, ObjectsIter oEnd,
112 OutputIterator & out)
const {
113 if (maxValue == ValueType()) {
117 auto objNr = std::distance(oBegin, oEnd);
122 assert(m_value(*oBegin) == maxValue);
129 auto midle = oBegin + objNr / 2;
130 fill_table(m_object_on_size, boost::make_iterator_range(oBegin, midle),
132 fill_table(m_object_on_size_rec,
133 boost::make_iterator_range(midle, oEnd), capacity);
135 SizeType capacityLeftPartInOptimalSolution{};
136 for (
auto capacityLeftPart :
irange(capacity + 1)) {
137 auto left = m_object_on_size[capacityLeftPart];
138 auto right = m_object_on_size_rec[capacity - capacityLeftPart];
140 if (*left + *right == maxValue) {
141 capacityLeftPartInOptimalSolution = capacityLeftPart;
146 auto left = m_object_on_size[capacityLeftPartInOptimalSolution];
148 m_object_on_size_rec[capacity - capacityLeftPartInOptimalSolution];
149 assert(left && right && *left + *right == maxValue);
151 retrieve_solution_rec(*left, capacityLeftPartInOptimalSolution, oBegin,
153 retrieve_solution_rec(
154 *right, capacity - capacityLeftPartInOptimalSolution, midle, oEnd,
158 template <
typename ObjectsRange>
159 void fill_table(ValueOrNullVector &values, ObjectsRange &&objects,
160 SizeType capacity)
const {
162 values.begin(), values.begin() + capacity + 1,
163 std::forward<ObjectsRange>(objects), m_size,
165 typename boost::range_iterator<ObjectsRange>::type obj) {
166 return *val + m_value(*obj);
168 [&](ValueOrNull left, ValueOrNull right) {
169 return m_comparator(*left, *right);
171 [](ValueOrNull & val) {
174 Knapsack_0_1_get_position_range{});
177 ObjectSizeFunctor m_size;
178 ObjectValueFunctor m_value;
179 Comparator m_comparator;
180 mutable ValueOrNullVector m_object_on_size;
181 mutable ValueOrNullVector m_object_on_size_rec;
184 template <
typename Objects,
typename ObjectSizeFunctor,
185 typename ObjectValueFunctor,
typename Comparator>
186 Knapsack_0_1<Objects, ObjectSizeFunctor, ObjectValueFunctor, Comparator>
187 make_knapsack_0_1(ObjectSizeFunctor size, ObjectValueFunctor value,
189 return Knapsack_0_1<Objects, ObjectSizeFunctor, ObjectValueFunctor,
190 Comparator>(size, value, comp);
193 template <
typename Knapsack,
typename IndexType,
typename ValueType,
194 typename Objects,
typename OutputIterator>
195 void retrieve_solution(
const Knapsack &knapsack, ValueType maxValue,
196 IndexType size, Objects &&objects, OutputIterator & out,
197 retrieve_solution_tag) {
198 knapsack.retrieve_solution(maxValue, size, objects, out);
201 template <
typename Knapsack,
typename IndexType,
typename ValueType,
202 typename Objects,
typename OutputIterator>
203 void retrieve_solution(
const Knapsack &knapsack, ValueType maxValue,
204 IndexType size, Objects &&objects, OutputIterator & out,
205 no_retrieve_solution_tag) {}
211 template <
typename KnapsackData,
typename retrieve_solution_tag>
214 using Value =
typename KnapsackData::value;
216 auto knapsack = make_knapsack_0_1<typename KnapsackData::objects>(
217 knap_data.get_size(), knap_data.get_value(),
utils::less{});
219 knapsack.solve(knap_data.get_objects(), knap_data.get_capacity(),
221 retrieve_solution(knapsack, value_size.first, value_size.second,
222 knap_data.get_objects(), knap_data.get_output_iter(),
223 retrieve_solutionTag);
231 template <
typename KnapsackData,
typename retrieve_solution_tag>
234 using Value =
typename KnapsackData::value;
235 using Size =
typename KnapsackData::size;
237 auto knapsack = make_knapsack_0_1<typename KnapsackData::objects>(
240 auto value_size = knapsack.solve(
241 knap_data.get_objects(), maxValue,
244 boost::optional<Size>(knap_data.get_capacity() + 1)));
245 retrieve_solution(knapsack, value_size.first, value_size.second,
246 knap_data.get_objects(), knap_data.get_output_iter(),
247 retrieve_solutionTag);
248 return std::make_pair(value_size.second, value_size.first);
266 template <
typename Objects,
typename OutputIterator,
typename ObjectSizeFunctor,
269 detail::FunctorOnRangePValue<ObjectSizeFunctor, Objects>
271 OutputIterator out, ObjectSizeFunctor size,
272 ObjectValueFunctor value = ObjectValueFunctor{}) {
274 return detail::knapsack_check_integrality(
275 detail::make_knapsack_data(std::forward<Objects>(objects), capacity,
277 detail::zero_one_tag{});
293 template <
typename Objects,
typename ObjectSizeFunctor,
296 detail::FunctorOnRangePValue<ObjectSizeFunctor, Objects>
298 ObjectSizeFunctor size,
299 ObjectValueFunctor value = ObjectValueFunctor{}) {
301 return detail::knapsack_check_integrality(
302 detail::make_knapsack_data(
303 std::forward<Objects>(objects), capacity, size, value, out),
304 detail::zero_one_tag{}, detail::no_retrieve_solution_tag{});
309 #endif // PAAL_KNAPSACK_0_1_HPP
detail::FunctorOnRangePValue< ObjectSizeFunctor, Objects > fill_knapsack_dynamic_table(ValueIterator valuesBegin, ValueIterator valuesEnd, Objects &&objects, ObjectSizeFunctor size, Combine combine, Compare compare, Init init, GetPositionRange get_range)
Computes dynamic algorithm table (valuesBegin, valuesEnd) The values collection has element type Valu...
For 0/1 knapsack dynamic algorithm for given element the table has to be traversed from the highest t...
auto knapsack_0_1_no_output(Objects &&objects, detail::FunctorOnRangePValue< ObjectSizeFunctor, Objects > capacity, ObjectSizeFunctor size, ObjectValueFunctor value=ObjectValueFunctor{})
Solution to Knapsack 0/1 problem, without retrieving the objects in the solution. ...
auto irange(T begin, T end)
irange
ReturnType solve(Objects objects, SizeType capacity, GetBestElement getBest)
Function solves dynamic programming problem.
This file contains set of simple useful functors or functor adapters.
auto knapsack_0_1(Objects &&objects, detail::FunctorOnRangePValue< ObjectSizeFunctor, Objects > capacity, OutputIterator out, ObjectSizeFunctor size, ObjectValueFunctor value=ObjectValueFunctor{})
Solution to Knapsack 0/1 problem.
This class helps solving 0/1 knapsack problem. Function solve returns the optimal value Function Retr...