All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
knapsack_fptas_common.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_FPTAS_COMMON_HPP
16 #define PAAL_KNAPSACK_FPTAS_COMMON_HPP
17 
20 
21 namespace paal {
22 namespace detail {
23 
27 template <typename Objects, typename Functor>
28 boost::optional<double> get_multiplier(Objects &&objects, double epsilon,
29  double lowerBound, Functor,
31  double n = boost::distance(objects);
32  auto ret = n / (epsilon * lowerBound);
33  static const double SMALLEST_MULTIPLIER = 1.;
34  if (ret > SMALLEST_MULTIPLIER) return boost::none;
35  return ret;
36 }
37 
38 // TODO this multiplier does not guarantee fptas
43 template <typename Objects, typename Functor>
44 boost::optional<double> get_multiplier(Objects &&objects, double epsilon,
45  double lowerBound, Functor f,
47  double minF = *min_element_functor(objects, f);
48  double n = int(double(lowerBound) * (1. + epsilon) / minF +
49  1.); // maximal number of elements in the found solution
50  auto ret = n / (epsilon * lowerBound);
51  static const double SMALLEST_MULTIPLIER = 1.;
52  if (ret > SMALLEST_MULTIPLIER) return boost::none;
53  return ret;
54 }
55 
56 template <typename KnapsackData, typename IsZeroOne, typename RetrieveSolution,
57  typename ReturnType = typename KnapsackData::return_type>
58 ReturnType knapsack_general_on_value_fptas(double epsilon,
59  KnapsackData knap_data,
60  IsZeroOne is_0_1_Tag,
61  RetrieveSolution retrieve_solution) {
62  using ObjectRef = typename KnapsackData::object_ref;
63  using Value = typename KnapsackData::value;
64  using Size = typename KnapsackData::size;
65 
66  auto &&objects = knap_data.get_objects();
67 
68  if (boost::empty(objects)) {
69  return ReturnType{};
70  }
71 
72  double maxValue =
73  detail::get_value_bound(knap_data, is_0_1_Tag, lower_tag{});
74  auto multiplier = get_multiplier(objects, epsilon, maxValue,
75  knap_data.get_value(), is_0_1_Tag);
76 
77  if (!multiplier) {
78  return knapsack_check_integrality(std::move(knap_data), is_0_1_Tag,
79  retrieve_solution);
80  }
81 
82  auto newValue = utils::make_scale_functor<double, Value>(
83  knap_data.get_value(), *multiplier);
84  auto ret = knapsack_check_integrality(
85  detail::make_knapsack_data(objects, knap_data.get_capacity(),
86  knap_data.get_size(), newValue,
87  knap_data.get_output_iter()),
88  is_0_1_Tag, retrieve_solution);
89  return std::make_pair(Value(double(ret.first) / *multiplier), ret.second);
90 }
91 
92 template <typename KnapsackData, typename IsZeroOne, typename RetrieveSolution,
93  typename ReturnType = typename KnapsackData::return_type>
94 ReturnType knapsack_general_on_size_fptas(double epsilon,
95  KnapsackData knap_data,
96  IsZeroOne is_0_1_Tag,
97  RetrieveSolution retrieve_solution) {
98  using ObjectRef = typename KnapsackData::object_ref;
99  using Size = typename KnapsackData::size;
100 
101  auto &&objects = knap_data.get_objects();
102 
103  if (boost::empty(objects)) {
104  return ReturnType{};
105  }
106 
107  auto multiplier = get_multiplier(objects, epsilon, knap_data.get_capacity(),
108  knap_data.get_size(), is_0_1_Tag);
109 
110  if (!multiplier) {
111  return knapsack_check_integrality(std::move(knap_data), is_0_1_Tag,
112  retrieve_solution);
113  }
114 
115  auto newSize = utils::make_scale_functor<double, Size>(knap_data.get_size(),
116  *multiplier);
117  auto ret = knapsack_check_integrality(
118  detail::make_knapsack_data(
119  objects, Size(knap_data.get_capacity() * *multiplier), newSize,
120  knap_data.get_value(), knap_data.get_output_iter()),
121  is_0_1_Tag, retrieve_solution);
122  return ReturnType(ret.first, double(ret.second) / *multiplier);
123 }
124 
125 template <typename KnapsackData, typename IsZeroOne>
126 typename KnapsackData::return_type
127 knapsack_general_on_value_fptas_retrieve(double epsilon, KnapsackData knap_data,
128  IsZeroOne is_0_1_Tag) {
129  using ObjectRef = typename KnapsackData::object_ref;
130  using Value = typename KnapsackData::value;
131 
132  Value realValue{};
133  auto addValue = [&](ObjectRef obj) {
134  realValue += knap_data.get_value(obj);
135  knap_data.out(obj);
136  }
137  ;
138 
139  auto newOut = boost::make_function_output_iterator(addValue);
140 
141  auto reducedReturn = knapsack_general_on_value_fptas(
142  epsilon, detail::make_knapsack_data(
143  knap_data.get_objects(), knap_data.get_capacity(),
144  knap_data.get_size(), knap_data.get_value(), newOut),
145  is_0_1_Tag, retrieve_solution_tag{});
146  return std::make_pair(realValue, reducedReturn.second);
147 }
148 
149 template <typename KnapsackData, typename IsZeroOne,
150  typename ReturnType = typename KnapsackData::return_type>
151 ReturnType knapsack_general_on_size_fptas_retrieve(double epsilon,
152  KnapsackData knap_data,
153  IsZeroOne is_0_1_Tag) {
154  using ObjectRef = typename KnapsackData::object_ref;
155  using Size = typename KnapsackData::size;
156 
157  Size realSize{};
158  auto add_size = [&](ObjectRef obj) {
159  realSize += knap_data.get_size(obj);
160  knap_data.out(obj);
161  }
162  ;
163 
164  auto newOut = boost::make_function_output_iterator(add_size);
165 
166  auto reducedReturn = knapsack_general_on_size_fptas(
167  epsilon, detail::make_knapsack_data(
168  knap_data.get_objects(), knap_data.get_capacity(),
169  knap_data.get_size(), knap_data.get_value(), newOut),
170  is_0_1_Tag, retrieve_solution_tag{});
171  return ReturnType(reducedReturn.first, realSize);
172 }
173 
174 } // detail
175 } // paal
176 
177 #endif // PAAL_KNAPSACK_FPTAS_COMMON_HPP
auto min_element_functor(Range &&range, Functor f)
combination of boost::min_element and boost::adaptors::transformed
boost::optional< double > get_multiplier(Objects &&objects, double epsilon, double lowerBound, Functor, detail::zero_one_tag)
computes multiplier for FPTAS, version for 0/1