SlideShare una empresa de Scribd logo
1 de 6
Descargar para leer sin conexión
/**
* @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;
}

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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 a 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 a 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
 

Más de 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
 

Más de 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
 

Último

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
+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
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 

Último (20)

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%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
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
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
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
+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...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 

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; }