SlideShare a Scribd company logo
1 of 6
Download to read offline
/**
* @mainpage
* @anchor mainpage
* @brief
* @details
* @copyright Russell John Childs, PhD, 2016
* @author Russell John Childs, PhD
* @date 2016-03-06
*
* This file contains classes: BurglarProblem
* Problem statement: A burglar wishses to maximise the value of goods stolen
* from N houses, subject to the constraint that they can only visit houses
* that are not neighbours.
*
* Solution: Dyanmic programming with complexity O(n) through the fololowing
* recurrence relation:
*
* optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is
* the weighting for house i and optimum(i) is the optimum solution for the 1st
* i houses.
*
* Algorithm tested against exhaustive search using binary number 1 to 2^(N-1)
* where 1-bts are houses visited, 0-bits are houses skipped and neighbours are
* illegal: E.g. 10010, but not 100110
*
* Compiled and verified under Visual Studio 13
*
* Documentation: Doxygen comments for interfaces, normal for impl.
*
* Usage: After compiling, run. The binary will send:
* n
* (1) test results to stdout
*
* The file unit_test.hpp is required for the tests and must be requested from
* author.
*
* @file dynamic_programming_burglar_problem.cpp
* @see
* @ref mainpage
*/
#include <vector>
#include <utility>
#include <random>
#include <bitset>
#include<algorithm>
#include "unit_test.hpp"
//Unit test framework is written for Linux. This #define ports it to Visual Studio 2013
#define __PRETTY_FUNCTION__ __FUNCSIG__
/**
* addtogroup BurglarProblem
* @{
*/
namespace BurglarProblem
{
class Burglar
{
/**
* This class solves the following problem:
* A burglar wishses to maximise the value of goods stolen
* from N houses, subject to the constraint that they can only visit houses
* that are not neighbours.
*
* It uses Dynamic Programming to achieve O(n) complexity using the recurrence
* relation:
*
* optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is
* the weighting for house i and optimum(i) is the optimum solution for the 1st
* i houses.
*
*/
private:
/**
* Initialiser function that makes all weights positive, sets optimum(0) and
* optimum(1), house list for optimum(0) and house list for optimum(1)
*/
void init(void)
{
//Make all weights positive
unsigned i = 0;
for (auto weight : m_weights)
{
m_weights[i] = std::abs(m_weights[i]);
++i;
}
//Store current and previous max for recurrence relation
auto min_max = std::minmax(m_weights[0], m_weights[1]);
m_max_found[0] = min_max.first;
m_max_found[1] = min_max.second;
//Store current and previous best list of houses for recurrence relation
m_houses[0].clear();
m_houses[0].push_back(m_weights[0] > m_weights[1]);
m_houses[1].clear();
m_houses[1].push_back(m_weights[1] > m_weights[0]);
}
public:
/**
* @param weights {const std::vector<double>&} - new list of weights
*/
Burglar(const std::vector<double>& weights) :
m_weights(weights),
m_which_list(false)
{
init();
}
/**
* dtor
*/
~Burglar(void)
{
}
/**
* This function resets the list of weights used.
* @param weights {const std::vector<double>&} - new list of weights
*
* @return {Burglar& } - *this
*
* Usage my_burgalr_object(new_list).solve();
*/
Burglar& reset(const std::vector<double>& weights)
{
m_weights = weights;
init();
return *this;
}
/**
* This function finds the optimum set of houses to visit, using:
*
* optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is
* the weighting for house i and optimum(i) is the optimum solution for the 1st
* i houses.
*/
void solve(void)
{
auto size = m_weights.size();
//Loop over houses
for (unsigned i = 2; i < size; ++i)
{
//Get last house in current optimum list
unsigned last = m_houses[1].back();
//Check house has value
if (m_weights[i] > 0)
{
//If is not a neighbour of current house
if (i > (last + 1))
{
//Add house value to current value
m_max_found[1] += m_weights[i];
//set prev optimum to current
m_houses[0] = m_houses[1];
//Add house to current optimum
m_houses[1].push_back(i);
}
else
{
//house is a neighbour, find best way to add it:
//(Skip, replace current house, add to prev optimum)
enum Choose{ do_nothing = 0, replace = 1, add = 2 } choose
= do_nothing;
double tmp_max = m_max_found[1];
//Get value if we replace current house in optimum(i-1)
double tmp = m_max_found[1] + (m_weights[i] - m_weights[i - 1]);
if (tmp > tmp_max)
{
tmp_max = tmp;
choose = replace;
}
//Get value if we add house to previous optimum(i-2)
tmp = m_max_found[0] + m_weights[i];
if ((tmp > tmp_max) && (i != (m_houses[0].back()+1)))
{
tmp_max = tmp;
choose = add;
}
//Set new vals for optimum(i-1), optimum(i)
m_max_found[0] = m_max_found[1];
m_max_found[1] = tmp_max;
//Replace optimum(i) house with new house
if (choose == replace)
{
m_houses[0] = m_houses[1];
m_houses[1].back() = i;
}
//Add new house to optimum(i-1)
else if (choose == add)
{
std::vector<unsigned> tmp_list = m_houses[0];
m_houses[0] = m_houses[1];
m_houses[1] = tmp_list;
m_houses[1].push_back(i);
}
}
}
}
}
/**
* This function return optimum value of goods stolen and houses to visit
*
* @return {std::pair<double,std::reference_wrapper<std::vector<unsigned>>>}
* - {optimum value, list of houses}
*/
std::pair<double, std::reference_wrapper<std::vector<unsigned>>>
get_result(void)
{
//Return optimum value and corresponding house list
return std::pair<double, std::reference_wrapper<std::vector<unsigned>>>
(m_max_found[1], m_houses[1]);
}
//private:
std::vector<double> m_weights;
bool m_which_list;
double m_max_found[2];
std::vector<unsigned> m_houses[2];
};
}
/**
* @}
*/
/**
* addtogroup Tests
* @{
*/
namespace Tests
{
/**
* Wrapper class for std::vector converting {a, b, c, ...} to "a b c ..."
*/
struct PrintVector
{
PrintVector(const std::vector<unsigned>& vec) :
m_vec(vec)
{
}
std::string str()
{
std::stringstream ss;
for (auto elem : m_vec)
{
ss << elem << " ";
}
return ss.str();
}
std::vector<unsigned> m_vec;
};
/**
* This function compares algorithm against exhaustive search for best
* solution using: binary number 1 to 2^(N-1)
* where 1-bts are houses visited, 0-bits are houses skipped and neighbours are
* illegal: E.g. 10010, but not 100110
*/
void tests(void)
{
using namespace UnitTest;
using namespace BurglarProblem;
//Print test banner
Verify<> banner("Burglar solver");
typedef std::vector<unsigned> uv;
//Two houses with 1st being the optimal choice
Burglar test(std::vector<double>{3, 1});
test.solve();
std::string msg_arg("std::vector<double>{3, 1}");
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 3;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 0 }).str();
//Two houses with 2nd being the optimal choice
test.reset(std::vector<double>{2, 4}).solve();
msg_arg = "std::vector<double>{2, 4})";
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 4;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 1 }).str();
//Three houses with 1st and 3rd being the optimal choice
test.reset(std::vector<double>{4, 9, 6}).solve();
msg_arg = "std::vector<double>{4, 9, 6}";
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 10;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 0,2 }).str();
//Three houses with 2nd being the optimal choice
test.reset(std::vector<double>{5, 13, 7});
msg_arg = "std::vector<double>{5, 13, 7}";
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 13;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 1 }).str();
//Test proof of recurrence relation. Fourth house not optimal
test.reset(std::vector<double>{5, 10, 7, 1}).solve();
msg_arg = "std::vector<double>{5, 10, 7, 1}";
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 12;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 0, 2 }).str();
//Test proof of recurrence relation. Fourth house optimal
test.reset(std::vector<double>{5, 10, 7, 3}).solve();
msg_arg = "std::vector<double>{5, 10, 7, 3}";
VERIFY(std::string("Input weights=") + msg_arg,
test.get_result().first) == 13;
VERIFY(std::string("Input weights=") +
msg_arg, PrintVector(test.get_result().second.get()).str()) ==
PrintVector(uv{ 1, 3 }).str();
unsigned run = 0;
auto exhaustive = [&]()
{
//Test by exhaustive enumeration. Enumeration subject to constraints
//took me a while to deduce. Idea is to use a binary number from
//1 to 2^N, where "1" means visit house and "0" means skip. Discard
//any binary number that violates the constraints (visits 2 neighbours)
//I am not 100% confident this is right and welcome a code review.
//(1) 20 houses with random weights (if you change this, ensure n<64)
const unsigned n = 20;
std::vector<double> random_weights;
std::random_device dev;
//std::mt19937 generator(dev());
std::mt19937 generator(run);
std::uniform_int_distribution<> distribution(1, 1000000);
for (int i = 0; i < n; ++i)
{
random_weights.push_back(distribution(generator));
}
//(2) Generate a binary number from 1 to 2^n
//and treat as house1=visit/skip, house2=visit/skip ...
double exhaustive_search_max = 0;
std::vector<unsigned> exahustive_search_house_list;
for (long long unsigned bin = 0; bin < ((1 << n) - 1); ++bin)
{
//Reverse to represent house1=0/1, house2=0/1, ...
//Happily bitset does this anyway.
std::bitset<n> houses(bin);
//Loop over bits until we find two neighbours
unsigned prev_pos = 0;
bool is_neighbour = false;
unsigned j = 0;
while ((is_neighbour == false) && j < n)
{
is_neighbour = (j != 0) && (houses[prev_pos] && houses[j]);
prev_pos = j;
++j;
}
//if we haven't found any neighbours, we have a legal permutation
if (is_neighbour == false)
{
//Get global maximum and houses corresponding to global max
double tmp = 0;
unsigned house_number = 0;
for (auto weight : random_weights)
{
tmp += (weight * houses[house_number]);
++house_number;
}
//If new global max found
if (tmp > exhaustive_search_max)
{
//Update global max
exhaustive_search_max = tmp;
//update house list
exahustive_search_house_list.clear();
for (unsigned index = 0; index < n; ++index)
{
if (houses[index])
{
exahustive_search_house_list.push_back(index);
}
}
}
}
}
//(3) Validate algorithm agaisnt exhaustive search
test.reset(random_weights).solve();
msg_arg = "Exhaustive search with randomw weights: ";
VERIFY(msg_arg, test.get_result().first) == exhaustive_search_max;
VERIFY(msg_arg, PrintVector(uv(test.get_result().second.get())).str()) ==
PrintVector(exahustive_search_house_list).str();
};
//Run 20 exhasutive checks
for (unsigned i = 0; i < 20; ++i)
{
run = i;
std::cout << std::endl << "Run=" << run << std::endl;
exhaustive();
}
}
}
/**
* @}
*/
int main(void)
{
using namespace Tests;
using namespace UnitTest;
//This struct pauses at the end of tests to print out results
struct BreakPointAfterMainExits
{
BreakPointAfterMainExits(void)
{
static BreakPointAfterMainExits tmp;
}
~BreakPointAfterMainExits(void)
{
unsigned set_bp_here_for_test_results = 0;
}
} dummy;
//Run tests
tests();
Verify<Results> results;
}

More Related Content

What's hot

Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax Basics
Richard Paul
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++
vidyamittal
 

What's hot (20)

Image Recognition with Neural Network
Image Recognition with Neural NetworkImage Recognition with Neural Network
Image Recognition with Neural Network
 
Javascript & Ajax Basics
Javascript & Ajax BasicsJavascript & Ajax Basics
Javascript & Ajax Basics
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
C++ ARRAY WITH EXAMPLES
C++ ARRAY WITH EXAMPLESC++ ARRAY WITH EXAMPLES
C++ ARRAY WITH EXAMPLES
 
Unit 3
Unit 3 Unit 3
Unit 3
 
C++ TUTORIAL 8
C++ TUTORIAL 8C++ TUTORIAL 8
C++ TUTORIAL 8
 
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
 
c programming
c programmingc programming
c programming
 
C++ prgms 3rd unit
C++ prgms 3rd unitC++ prgms 3rd unit
C++ prgms 3rd unit
 
Modern C++ Concurrency API
Modern C++ Concurrency APIModern C++ Concurrency API
Modern C++ Concurrency API
 
Monolith to Reactive Microservices
Monolith to Reactive MicroservicesMonolith to Reactive Microservices
Monolith to Reactive Microservices
 
Advance features of C++
Advance features of C++Advance features of C++
Advance features of C++
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 4 of 5 by...
 
c programming
c programmingc programming
c programming
 
cpp_sample
cpp_samplecpp_sample
cpp_sample
 
C++ L08-Classes Part1
C++ L08-Classes Part1C++ L08-Classes Part1
C++ L08-Classes Part1
 
C++ L09-Classes Part2
C++ L09-Classes Part2C++ L09-Classes Part2
C++ L09-Classes Part2
 
Asssignment2
Asssignment2 Asssignment2
Asssignment2
 
Property-based testing
Property-based testingProperty-based testing
Property-based testing
 
The Ring programming language version 1.4 book - Part 29 of 30
The Ring programming language version 1.4 book - Part 29 of 30The Ring programming language version 1.4 book - Part 29 of 30
The Ring programming language version 1.4 book - Part 29 of 30
 

Similar to Dynamic programming burglar_problem

Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docxAssg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
festockton
 
SaveI need help with this maze gui that I wrote in java, I am tryi.pdf
SaveI need help with this maze gui that I wrote in java, I am tryi.pdfSaveI need help with this maze gui that I wrote in java, I am tryi.pdf
SaveI need help with this maze gui that I wrote in java, I am tryi.pdf
arihantstoneart
 
Help please!!(Include your modified DList.java source code file in.pdf
Help please!!(Include your modified DList.java source code file in.pdfHelp please!!(Include your modified DList.java source code file in.pdf
Help please!!(Include your modified DList.java source code file in.pdf
jyothimuppasani1
 
need help with code I wrote. This code is a maze gui, and i need hel.pdf
need help with code I wrote. This code is a maze gui, and i need hel.pdfneed help with code I wrote. This code is a maze gui, and i need hel.pdf
need help with code I wrote. This code is a maze gui, and i need hel.pdf
arcotstarsports
 
Java concepts and questions
Java concepts and questionsJava concepts and questions
Java concepts and questions
Farag Zakaria
 

Similar to Dynamic programming burglar_problem (18)

C++ Language
C++ LanguageC++ Language
C++ Language
 
Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docxAssg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
Assg 12 Binary Search Trees COSC 2336assg-12.cppAssg 12 Binary .docx
 
SaveI need help with this maze gui that I wrote in java, I am tryi.pdf
SaveI need help with this maze gui that I wrote in java, I am tryi.pdfSaveI need help with this maze gui that I wrote in java, I am tryi.pdf
SaveI need help with this maze gui that I wrote in java, I am tryi.pdf
 
Recursion examples
Recursion examplesRecursion examples
Recursion examples
 
C Recursion, Pointers, Dynamic memory management
C Recursion, Pointers, Dynamic memory managementC Recursion, Pointers, Dynamic memory management
C Recursion, Pointers, Dynamic memory management
 
Help please!!(Include your modified DList.java source code file in.pdf
Help please!!(Include your modified DList.java source code file in.pdfHelp please!!(Include your modified DList.java source code file in.pdf
Help please!!(Include your modified DList.java source code file in.pdf
 
Ch01 basic concepts_nosoluiton
Ch01 basic concepts_nosoluitonCh01 basic concepts_nosoluiton
Ch01 basic concepts_nosoluiton
 
CPP Language Basics - Reference
CPP Language Basics - ReferenceCPP Language Basics - Reference
CPP Language Basics - Reference
 
C++ TUTORIAL 4
C++ TUTORIAL 4C++ TUTORIAL 4
C++ TUTORIAL 4
 
M269 Data Structures And Computability.docx
M269 Data Structures And Computability.docxM269 Data Structures And Computability.docx
M269 Data Structures And Computability.docx
 
Leet Code May Coding Challenge - DataStructure and Algorithm Problems
Leet Code May Coding Challenge - DataStructure and Algorithm ProblemsLeet Code May Coding Challenge - DataStructure and Algorithm Problems
Leet Code May Coding Challenge - DataStructure and Algorithm Problems
 
Lecture01a correctness
Lecture01a correctnessLecture01a correctness
Lecture01a correctness
 
Chapter ii(oop)
Chapter ii(oop)Chapter ii(oop)
Chapter ii(oop)
 
need help with code I wrote. This code is a maze gui, and i need hel.pdf
need help with code I wrote. This code is a maze gui, and i need hel.pdfneed help with code I wrote. This code is a maze gui, and i need hel.pdf
need help with code I wrote. This code is a maze gui, and i need hel.pdf
 
Advance data structure & algorithm
Advance data structure & algorithmAdvance data structure & algorithm
Advance data structure & algorithm
 
Java concepts and questions
Java concepts and questionsJava concepts and questions
Java concepts and questions
 
Chapter2
Chapter2Chapter2
Chapter2
 
Lecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of TwenteLecture on Rubinius for Compiler Construction at University of Twente
Lecture on Rubinius for Compiler Construction at University of Twente
 

More from Russell Childs

Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016
Russell Childs
 
Full_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_ChildsFull_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_Childs
Russell Childs
 

More from Russell Childs (20)

spinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdfspinor_quantum_simulator_user_guide_.pdf
spinor_quantum_simulator_user_guide_.pdf
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching o_n
String searching o_nString searching o_n
String searching o_n
 
String searching
String searchingString searching
String searching
 
Permute
PermutePermute
Permute
 
Permute
PermutePermute
Permute
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theorem
 
Feature extraction using adiabatic theorem
Feature extraction using adiabatic theoremFeature extraction using adiabatic theorem
Feature extraction using adiabatic theorem
 
Wavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pagesWavelets_and_multiresolution_in_two_pages
Wavelets_and_multiresolution_in_two_pages
 
Relativity 2
Relativity 2Relativity 2
Relativity 2
 
Recursion to iteration automation.
Recursion to iteration automation.Recursion to iteration automation.
Recursion to iteration automation.
 
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
Dirac demo (quantum mechanics with C++). Please note: There is a problem with...
 
Shared_memory_hash_table
Shared_memory_hash_tableShared_memory_hash_table
Shared_memory_hash_table
 
Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016Full resume dr_russell_john_childs_2016
Full resume dr_russell_john_childs_2016
 
Simple shared mutex UML
Simple shared mutex UMLSimple shared mutex UML
Simple shared mutex UML
 
Design pattern to avoid downcasting
Design pattern to avoid downcastingDesign pattern to avoid downcasting
Design pattern to avoid downcasting
 
Interview uml design
Interview uml designInterview uml design
Interview uml design
 
Interview C++11 code
Interview C++11 codeInterview C++11 code
Interview C++11 code
 
Full_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_ChildsFull_resume_Dr_Russell_John_Childs
Full_resume_Dr_Russell_John_Childs
 

Recently uploaded

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Recently uploaded (20)

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 

Dynamic programming burglar_problem

  • 1. /** * @mainpage * @anchor mainpage * @brief * @details * @copyright Russell John Childs, PhD, 2016 * @author Russell John Childs, PhD * @date 2016-03-06 * * This file contains classes: BurglarProblem * Problem statement: A burglar wishses to maximise the value of goods stolen * from N houses, subject to the constraint that they can only visit houses * that are not neighbours. * * Solution: Dyanmic programming with complexity O(n) through the fololowing * recurrence relation: * * optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is * the weighting for house i and optimum(i) is the optimum solution for the 1st * i houses. * * Algorithm tested against exhaustive search using binary number 1 to 2^(N-1) * where 1-bts are houses visited, 0-bits are houses skipped and neighbours are * illegal: E.g. 10010, but not 100110 * * Compiled and verified under Visual Studio 13 * * Documentation: Doxygen comments for interfaces, normal for impl. * * Usage: After compiling, run. The binary will send: * n * (1) test results to stdout * * The file unit_test.hpp is required for the tests and must be requested from * author. * * @file dynamic_programming_burglar_problem.cpp * @see * @ref mainpage */ #include <vector> #include <utility> #include <random> #include <bitset> #include<algorithm> #include "unit_test.hpp" //Unit test framework is written for Linux. This #define ports it to Visual Studio 2013 #define __PRETTY_FUNCTION__ __FUNCSIG__ /** * addtogroup BurglarProblem * @{ */ namespace BurglarProblem { class Burglar { /** * This class solves the following problem: * A burglar wishses to maximise the value of goods stolen * from N houses, subject to the constraint that they can only visit houses * that are not neighbours. * * It uses Dynamic Programming to achieve O(n) complexity using the recurrence * relation: * * optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is * the weighting for house i and optimum(i) is the optimum solution for the 1st * i houses. * */ private:
  • 2. /** * Initialiser function that makes all weights positive, sets optimum(0) and * optimum(1), house list for optimum(0) and house list for optimum(1) */ void init(void) { //Make all weights positive unsigned i = 0; for (auto weight : m_weights) { m_weights[i] = std::abs(m_weights[i]); ++i; } //Store current and previous max for recurrence relation auto min_max = std::minmax(m_weights[0], m_weights[1]); m_max_found[0] = min_max.first; m_max_found[1] = min_max.second; //Store current and previous best list of houses for recurrence relation m_houses[0].clear(); m_houses[0].push_back(m_weights[0] > m_weights[1]); m_houses[1].clear(); m_houses[1].push_back(m_weights[1] > m_weights[0]); } public: /** * @param weights {const std::vector<double>&} - new list of weights */ Burglar(const std::vector<double>& weights) : m_weights(weights), m_which_list(false) { init(); } /** * dtor */ ~Burglar(void) { } /** * This function resets the list of weights used. * @param weights {const std::vector<double>&} - new list of weights * * @return {Burglar& } - *this * * Usage my_burgalr_object(new_list).solve(); */ Burglar& reset(const std::vector<double>& weights) { m_weights = weights; init(); return *this; } /** * This function finds the optimum set of houses to visit, using: * * optimum(i) = max(optimum(i-1)-w(i-1)+w(i), optimum(i-2)+w(i)), where w(i) is * the weighting for house i and optimum(i) is the optimum solution for the 1st * i houses. */ void solve(void) { auto size = m_weights.size(); //Loop over houses for (unsigned i = 2; i < size; ++i) { //Get last house in current optimum list unsigned last = m_houses[1].back();
  • 3. //Check house has value if (m_weights[i] > 0) { //If is not a neighbour of current house if (i > (last + 1)) { //Add house value to current value m_max_found[1] += m_weights[i]; //set prev optimum to current m_houses[0] = m_houses[1]; //Add house to current optimum m_houses[1].push_back(i); } else { //house is a neighbour, find best way to add it: //(Skip, replace current house, add to prev optimum) enum Choose{ do_nothing = 0, replace = 1, add = 2 } choose = do_nothing; double tmp_max = m_max_found[1]; //Get value if we replace current house in optimum(i-1) double tmp = m_max_found[1] + (m_weights[i] - m_weights[i - 1]); if (tmp > tmp_max) { tmp_max = tmp; choose = replace; } //Get value if we add house to previous optimum(i-2) tmp = m_max_found[0] + m_weights[i]; if ((tmp > tmp_max) && (i != (m_houses[0].back()+1))) { tmp_max = tmp; choose = add; } //Set new vals for optimum(i-1), optimum(i) m_max_found[0] = m_max_found[1]; m_max_found[1] = tmp_max; //Replace optimum(i) house with new house if (choose == replace) { m_houses[0] = m_houses[1]; m_houses[1].back() = i; } //Add new house to optimum(i-1) else if (choose == add) { std::vector<unsigned> tmp_list = m_houses[0]; m_houses[0] = m_houses[1]; m_houses[1] = tmp_list; m_houses[1].push_back(i); } } } } } /** * This function return optimum value of goods stolen and houses to visit * * @return {std::pair<double,std::reference_wrapper<std::vector<unsigned>>>} * - {optimum value, list of houses} */ std::pair<double, std::reference_wrapper<std::vector<unsigned>>> get_result(void) { //Return optimum value and corresponding house list return std::pair<double, std::reference_wrapper<std::vector<unsigned>>> (m_max_found[1], m_houses[1]); }
  • 4. //private: std::vector<double> m_weights; bool m_which_list; double m_max_found[2]; std::vector<unsigned> m_houses[2]; }; } /** * @} */ /** * addtogroup Tests * @{ */ namespace Tests { /** * Wrapper class for std::vector converting {a, b, c, ...} to "a b c ..." */ struct PrintVector { PrintVector(const std::vector<unsigned>& vec) : m_vec(vec) { } std::string str() { std::stringstream ss; for (auto elem : m_vec) { ss << elem << " "; } return ss.str(); } std::vector<unsigned> m_vec; }; /** * This function compares algorithm against exhaustive search for best * solution using: binary number 1 to 2^(N-1) * where 1-bts are houses visited, 0-bits are houses skipped and neighbours are * illegal: E.g. 10010, but not 100110 */ void tests(void) { using namespace UnitTest; using namespace BurglarProblem; //Print test banner Verify<> banner("Burglar solver"); typedef std::vector<unsigned> uv; //Two houses with 1st being the optimal choice Burglar test(std::vector<double>{3, 1}); test.solve(); std::string msg_arg("std::vector<double>{3, 1}"); VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 3; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 0 }).str(); //Two houses with 2nd being the optimal choice test.reset(std::vector<double>{2, 4}).solve(); msg_arg = "std::vector<double>{2, 4})"; VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 4; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 1 }).str(); //Three houses with 1st and 3rd being the optimal choice
  • 5. test.reset(std::vector<double>{4, 9, 6}).solve(); msg_arg = "std::vector<double>{4, 9, 6}"; VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 10; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 0,2 }).str(); //Three houses with 2nd being the optimal choice test.reset(std::vector<double>{5, 13, 7}); msg_arg = "std::vector<double>{5, 13, 7}"; VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 13; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 1 }).str(); //Test proof of recurrence relation. Fourth house not optimal test.reset(std::vector<double>{5, 10, 7, 1}).solve(); msg_arg = "std::vector<double>{5, 10, 7, 1}"; VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 12; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 0, 2 }).str(); //Test proof of recurrence relation. Fourth house optimal test.reset(std::vector<double>{5, 10, 7, 3}).solve(); msg_arg = "std::vector<double>{5, 10, 7, 3}"; VERIFY(std::string("Input weights=") + msg_arg, test.get_result().first) == 13; VERIFY(std::string("Input weights=") + msg_arg, PrintVector(test.get_result().second.get()).str()) == PrintVector(uv{ 1, 3 }).str(); unsigned run = 0; auto exhaustive = [&]() { //Test by exhaustive enumeration. Enumeration subject to constraints //took me a while to deduce. Idea is to use a binary number from //1 to 2^N, where "1" means visit house and "0" means skip. Discard //any binary number that violates the constraints (visits 2 neighbours) //I am not 100% confident this is right and welcome a code review. //(1) 20 houses with random weights (if you change this, ensure n<64) const unsigned n = 20; std::vector<double> random_weights; std::random_device dev; //std::mt19937 generator(dev()); std::mt19937 generator(run); std::uniform_int_distribution<> distribution(1, 1000000); for (int i = 0; i < n; ++i) { random_weights.push_back(distribution(generator)); } //(2) Generate a binary number from 1 to 2^n //and treat as house1=visit/skip, house2=visit/skip ... double exhaustive_search_max = 0; std::vector<unsigned> exahustive_search_house_list; for (long long unsigned bin = 0; bin < ((1 << n) - 1); ++bin) { //Reverse to represent house1=0/1, house2=0/1, ... //Happily bitset does this anyway. std::bitset<n> houses(bin); //Loop over bits until we find two neighbours unsigned prev_pos = 0; bool is_neighbour = false; unsigned j = 0; while ((is_neighbour == false) && j < n) { is_neighbour = (j != 0) && (houses[prev_pos] && houses[j]); prev_pos = j; ++j; } //if we haven't found any neighbours, we have a legal permutation if (is_neighbour == false)
  • 6. { //Get global maximum and houses corresponding to global max double tmp = 0; unsigned house_number = 0; for (auto weight : random_weights) { tmp += (weight * houses[house_number]); ++house_number; } //If new global max found if (tmp > exhaustive_search_max) { //Update global max exhaustive_search_max = tmp; //update house list exahustive_search_house_list.clear(); for (unsigned index = 0; index < n; ++index) { if (houses[index]) { exahustive_search_house_list.push_back(index); } } } } } //(3) Validate algorithm agaisnt exhaustive search test.reset(random_weights).solve(); msg_arg = "Exhaustive search with randomw weights: "; VERIFY(msg_arg, test.get_result().first) == exhaustive_search_max; VERIFY(msg_arg, PrintVector(uv(test.get_result().second.get())).str()) == PrintVector(exahustive_search_house_list).str(); }; //Run 20 exhasutive checks for (unsigned i = 0; i < 20; ++i) { run = i; std::cout << std::endl << "Run=" << run << std::endl; exhaustive(); } } } /** * @} */ int main(void) { using namespace Tests; using namespace UnitTest; //This struct pauses at the end of tests to print out results struct BreakPointAfterMainExits { BreakPointAfterMainExits(void) { static BreakPointAfterMainExits tmp; } ~BreakPointAfterMainExits(void) { unsigned set_bp_here_for_test_results = 0; } } dummy; //Run tests tests(); Verify<Results> results; }