Commit 715d6a6a authored by Chanelle Lee's avatar Chanelle Lee
Browse files

Combined all c++ functions into one file

parent 1312599f
......@@ -7,8 +7,7 @@ set(SOURCE_DIR "src/noComparisonSimulation")
#Tell CMake that headers are also in SOURCE_DIR
include_directories(${SOURCE_DIR})
set(SOURCES "${SOURCE_DIR}/agentFunctions.cpp")
set(SOURCES "${SOURCE_DIR}/evidenceFunctions.cpp")
set(SOURCES "${SOURCE_DIR}/helperFunctions.cpp")
# Generate python module
#find_package(pybind11 REQUIRED)
......
......@@ -3,7 +3,7 @@ from operator import attrgetter
from collections import Counter
# C module written by CLL
from noComparisonSimulation import agentFunctions as af
from noComparisonSimulation import helperFunctions as hf
class Agent(object):
......@@ -63,7 +63,7 @@ class Agent(object):
"""
Updates belief value based on the new piece of evidence received
"""
self._belief = af.update_on_evidence(evidenceID,
self._belief = hf.update_on_evidence(evidenceID,
self._distrust,
self._belief)
......@@ -79,7 +79,7 @@ class Agent(object):
neighbour : instance of the agent class
other agent for comparison
"""
return af.check_neighbour_consistent(self._belief,
return hf.check_neighbour_consistent(self._belief,
neighbour.getBelief())
def aggregate(self, neighbourhood):
......@@ -94,12 +94,12 @@ class Agent(object):
"""
beliefs = [n.getBelief() for n in neighbourhood]
poolSize = len(neighbourhood)
if af.check_neighbourhood_consistent(self._numOptions,
if hf.check_neighbourhood_consistent(self._numOptions,
poolSize,
beliefs):
# Change here for different operator
try:
retBelief = af.aggregate_MProdOp(self._numOptions,
retBelief = hf.aggregate_MProdOp(self._numOptions,
poolSize,
beliefs)
return retBelief
......@@ -108,7 +108,3 @@ class Agent(object):
else:
# All neighbours inconsistent so no aggregation
return None
#include <pybind11/pybind11.h>
#include "agentFunctions.hpp"
#include "evidenceFunctions.hpp"
#include "helperFunctions.hpp"
PYBIND11_MODULE(helperFunctions, m){
m.doc() = "Functions for improving agent and evidence performance";
m.def("pick_option", &pick_option, "Picks an option from a weighted distribution");
m.def("update_on_evidence", &update_on_evidence,
"Updates agent's belief based on negative evidence");
m.def("aggregate_MProdOp", &aggregate_MProdOp,
......@@ -13,5 +13,4 @@ PYBIND11_MODULE(helperFunctions, m){
"Check for consistent beliefs between neighbours");
m.def("check_neighbourhood_consistent", &check_neighbourhood_consistent,
"Checks neighbourhood only contains consistent beliefs");
m.def("pick_option", &pick_option, "Picks an option from a weighted distribution");
}
......@@ -2,7 +2,7 @@ from numpy.random import choice
from operator import attrgetter
# C module written by CLL
from noComparisonSimulation import evidenceFunctions as ef
from noComparisonSimulation import helperFunctions as hf
class Evidence(object):
......@@ -38,5 +38,5 @@ class Evidence(object):
def retWeightedRandomOption(self):
"""Returns an option at random from a weighted distribution"""
evidenceID = ef.pick_option(self.numOptions, self.optionWeights)
evidenceID = hf.pick_option(self.numOptions, self.optionWeights)
return evidenceID
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <vector>
#include <math.h>
#include "evidenceFunctions.hpp"
int pick_option(int num_options, py::array_t<double> weights){
if (weights.ndim() != 1)
{
throw std::invalid_argument("Expected 1-D array for weights");
}
py::buffer_info weights_buf = weights.request();
double *weights_ptr = (double *) weights_buf.ptr;
int totalWeight = 0; // this stores sum of weights of all elements before current
int selected = 0; // currently selected element
for (int i = 0; i < num_options; ++i)
{
// Have to turn weights into a integer and do this by raising by 10^5
// this should be a suitable level of accuracy.
int weight = 100000 * weights_ptr[i]; // weight of current element
if ((totalWeight + weight) != 0)
{
int r = rand() % (totalWeight + weight); // random value
if (r >= totalWeight)
{ // probability of this is weight/(totalWeight+weight)
selected = i; // it is the probability of discarding last selected element and selecting current one instead
}
totalWeight += weight; // increase weight sum
}
}
return selected;
}
#ifndef EV_FUNCS
#define EV_FUNCS
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <vector>
namespace py = pybind11;
/*! Pick an option from a possible n using a weighted random distribution
\param num_options : an integer signifying the number of options to be chosen from
\param weights : a pybind11 numpy array with the weights for the options
*/
int pick_option(int num_option, py::array_t<double> weights);
#endif
......@@ -5,7 +5,43 @@
#include <vector>
#include <math.h>
#include "agentFunctions.hpp"
#include "helperFunctions.hpp"
// Helper functions for the Evidence Class
int pick_option(int num_options, py::array_t<double> weights){
if (weights.ndim() != 1)
{
throw std::invalid_argument("Expected 1-D array for weights");
}
py::buffer_info weights_buf = weights.request();
double *weights_ptr = (double *) weights_buf.ptr;
int totalWeight = 0; // this stores sum of weights of all elements before current
int selected = 0; // currently selected element
for (int i = 0; i < num_options; ++i)
{
// Have to turn weights into a integer and do this by raising by 10^5
// this should be a suitable level of accuracy.
int weight = 100000 * weights_ptr[i]; // weight of current element
if ((totalWeight + weight) != 0)
{
int r = rand() % (totalWeight + weight); // random value
if (r >= totalWeight)
{ // probability of this is weight/(totalWeight+weight)
selected = i; // it is the probability of discarding last selected element and selecting current one instead
}
totalWeight += weight; // increase weight sum
}
}
return selected;
}
// Helper functions for the Agent Class
py::array_t<double> update_on_evidence(int evidence_id, double distrust,
py::array_t<double> belief)
......@@ -54,8 +90,6 @@ py::array_t<double> update_on_evidence(int evidence_id, double distrust,
}
return result;
}
}
py::array_t<double> aggregate_MProdOp(int num_options, int pool_size,
......@@ -183,3 +217,17 @@ int check_neighbourhood_consistent(int num_options, int pool_size,
}
return 1;
}
double ret_prob_of_confusion(double options_diff, double lambda)
{
double denom = 1 - exp(-lambda);
if (denom != 0)
{
return 0.5 * ((exp((-lambda) * options_diff) - exp(-lambda)) / denom);
}
else
{
return 0.5;
}
}
......@@ -8,6 +8,12 @@
namespace py = pybind11;
/*! Pick an option from a possible n using a weighted random distribution
\param num_options : an integer signifying the number of options to be chosen from
\param weights : a pybind11 numpy array with the weights for the options
*/
int pick_option(int num_option, py::array_t<double> weights);
/*! Updates a given belief negative bayesian updating
\param evidence_id : integer denoting option to update /p belief on
\param distrust : a double representing weighting for the bayesian updating
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment