All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
knapsack_unbounded.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
15 #ifndef PAAL_KNAPSACK_UNBOUNDED_HPP
16 #define PAAL_KNAPSACK_UNBOUNDED_HPP
17 
22 #include "paal/utils/functors.hpp"
26 #include "paal/utils/irange.hpp"
27 
28 #include <boost/range/adaptor/reversed.hpp>
29 #include <boost/optional.hpp>
30 
31 #include <vector>
32 
33 namespace paal {
34 
35 namespace detail {
41  template <typename T>
42  auto operator()(T begin, T end)->decltype(irange(begin, end)) {
43  return irange(begin, end);
44  }
45 };
46 
47 template <typename KnapsackData,
48  typename GetBestElement, typename ValuesComparator,
49  typename ReturnType = typename KnapsackData::return_type>
50 ReturnType knapsack_unbounded_dynamic(
51  KnapsackData knap_data,
52  GetBestElement getBest, ValuesComparator compareValues) {
53  using Value = typename KnapsackData::value;
54  using Size = typename KnapsackData::size;
55  using ObjectsIter = typename KnapsackData::object_iter;
56  using ObjIterWithValueOrNull =
57  boost::optional<std::pair<ObjectsIter, Value>>;
58  std::vector<ObjIterWithValueOrNull> objectOnSize(knap_data.get_capacity() + 1);
59 
60  auto compare = [ = ](const ObjIterWithValueOrNull & left,
61  const ObjIterWithValueOrNull & right) {
62  return compareValues(left->second, right->second);
63  };
64 
65  auto objectOnSizeBegin = objectOnSize.begin();
66  auto objectOnSizeEnd = objectOnSize.end();
67  fill_knapsack_dynamic_table(objectOnSizeBegin, objectOnSizeEnd, knap_data.get_objects(), knap_data.get_size(),
68  [&](ObjIterWithValueOrNull val, ObjectsIter obj)
69  ->ObjIterWithValueOrNull{
70  return std::make_pair(obj, val->second + knap_data.get_value(*obj));
71  },
72  compare, [](ObjIterWithValueOrNull & val) {
73  val = std::make_pair(ObjectsIter{}, Value{});
74  },
75  detail::knapsack_get_position_range());
76 
77  // getting position of the max value in the objectOnSize array
78  auto maxPos = getBest(objectOnSizeBegin, objectOnSizeEnd, compare);
79 
80  // setting solution
81  auto remainingSpaceInKnapsack = maxPos;
82  while (remainingSpaceInKnapsack != objectOnSizeBegin) {
83  assert(*remainingSpaceInKnapsack);
84  auto && obj = *((*remainingSpaceInKnapsack)->first);
85  knap_data.out(obj);
86  remainingSpaceInKnapsack -= knap_data.get_size(obj);
87  }
88 
89  // returning result
90  if (maxPos != objectOnSizeEnd) {
91  assert(*maxPos);
92  return ReturnType((*maxPos)->second, maxPos - objectOnSizeBegin);
93  } else {
94  return ReturnType(Value{}, Size{});
95  }
96 }
97 
107 template <typename KnapsackData,
108  typename ReturnType = typename KnapsackData::return_type,
109  typename Size = typename KnapsackData::size>
110 ReturnType knapsack(KnapsackData knap_data,
112  using ValueType = typename KnapsackData::value;
113  using ObjectsIter = typename KnapsackData::object_iter;
114  using TableElementType = boost::optional<std::pair<ObjectsIter, ValueType>>;
115 
116  auto && objects = knap_data.get_objects();
117 
118  if (boost::empty(objects)) {
119  return ReturnType{};
120  }
121  auto maxSize = get_value_bound(knap_data, unbounded_tag{}, upper_tag{});
122  auto ret = knapsack_unbounded_dynamic(
123  detail::make_knapsack_data(
124  knap_data.get_objects(), maxSize, knap_data.get_value(), knap_data.get_size(), knap_data.get_output_iter()),
126  TableElementType(std::make_pair(ObjectsIter{}, knap_data.get_capacity() + 1))),
127  utils::greater{});
128  return ReturnType(ret.second, ret.first);
129 }
130 
141 template <typename KnapsackData>
142 typename KnapsackData::return_type
143 knapsack(KnapsackData knap_data,
145  using Value = typename KnapsackData::value;
146  return knapsack_unbounded_dynamic(std::move(knap_data),
148  utils::less{});
149 }
150 
151 } // detail
152 
166 template <typename Objects, typename OutputIterator,
167  typename ObjectSizeFunctor,
168  typename ObjectValueFunctor = utils::return_one_functor>
169 typename detail::knapsack_base<Objects, ObjectSizeFunctor,
170  ObjectValueFunctor>::return_type
171 knapsack_unbounded(Objects && objects,
172  detail::FunctorOnRangePValue<ObjectSizeFunctor, Objects>
173  capacity, // capacity is of size type
174  OutputIterator out, ObjectSizeFunctor size,
175  ObjectValueFunctor value = ObjectValueFunctor()) {
176  return detail::knapsack_check_integrality(detail::make_knapsack_data(std::forward<Objects>(objects), capacity, size,
177  value, out), detail::unbounded_tag{},
179 }
180 
181 } // paal
182 
183 #endif // PAAL_KNAPSACK_UNBOUNDED_HPP
less functor
Definition: functors.hpp:497
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 knapsack dynamic algorithm for given element the table has to be traversed from the lowest to hig...
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
This file contains set of simple useful functors or functor adapters.
greater functor
Definition: functors.hpp:478
detail::knapsack_base< Objects, ObjectSizeFunctor, ObjectValueFunctor >::return_type knapsack_unbounded(Objects &&objects, detail::FunctorOnRangePValue< ObjectSizeFunctor, Objects > capacity, OutputIterator out, ObjectSizeFunctor size, ObjectValueFunctor value=ObjectValueFunctor())
Solution to the knapsack problem.