Calculating similarity -> python code to php code - Whats wrong? - php

I am trying to convert the following python code to a PHP code. Can you please explain me what is wrong in my PHP code, because I do not get the same results. If you need example data please let me know.
# Returns a distance-based similarity score for person1 and person2
def sim_distance(prefs,person1,person2):
# Get the list of shared_items
si={}
for item in prefs[person1]:
if item in prefs[person2]: si[item]=1
# if they have no ratings in common, return 0
if len(si)==0: return 0
# Add up the squares of all the differences
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in prefs[person1] if item in prefs[person2]])
return 1/(1+sum_of_squares)
My PHP code:
$sum = 0.0;
foreach($arr[$person1] as $item => $val)
{
if(array_key_exists($item, $arr[$person2]))
{
$p = sqrt(pow($arr[$person1][$item] - $arr[$person2][$item], 2));
$sum = $sum + $p;
}
}
$sum = 1 / (1 + $sum);
echo $sum;
Thanks for helping!

The main difference is that you've added sqrt to the PHP code. The PHP also doesn't handle the special case of no prefs in common, which gives 0 in the python version and 1 in the PHP version.
I tested both versions and those are the only differences I found.

this is close as i could make a direct translation... (untested)
function sim_distance($prefs, $person1, $person2) {
$si = array();
foreach($prefs[$person1] as $item) {
if($item in $prefs[$person2]) $si[$item]=1;
}
if(count($si)==0) return 0;
$squares = array();
foreach($prefs[$person1] as $item) {
if(array_key_exists($item,$prefs[$person2])) {
$squares[] = pow($prefs[$person1][$item]-$prefs[$person2][$item],2);
}
}
$sum_of_squares = array_sum($squares);
return 1/(1+$sum_of_squares);
}
I don't really know what you're trying to do, or if I've interpreted the indentation correctly...but maybe this'll help. I'm assuming your data structures have the same layout as in the python script.
oh...and i'm interpreting the python as this:
def sim_distance(prefs,person1,person2):
# Get the list of shared_items
si={}
for item in prefs[person1]:
if item in prefs[person2]: si[item]=1
# if they have no ratings in common, return 0
if len(si)==0: return 0
# Add up the squares of all the differences
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2) for item in prefs[person1] if item in prefs[person2]])
return 1/(1+sum_of_squares)

Related

Php Recursive Function Infinite loop Error

I am having a php recursive function to calculate nearest sale price. but i don't know why its run infinite time and throw error of maximum execution.
Its look like below:
function getamazonsaleper($portal)
{
$cp = floatval($this->input->post('cp')); //user provided inputs
$sp = floatval($this->input->post('sp')); //user provided input
$gst = floatval($this->input->post('gst')); //user provided input
$rfsp = floatval($this->input->post('rfsp')); //user provided input
$mcp = (int)($this->input->post('mcp')); //user provided input
$weight = floatval($this->input->post('weight')); //user provided input
$output = $this->getsalepercent($cp,$sp,$gst,$rfsp,$mcp,$weight,$portal);
return $output;
}
function getsalepercent($cp,$sp,$gst,$rfsp,$mcp,$weight,$portal) //recursive funtion
{
$spcost = ((($sp/100)*$cp));
$gstamount= (($spcost/(100+$gst))*$gst);
$rfspamount= ($spcost*($rfsp/100));
$mcpamount= ($cp*($mcp/100));
$fixedfee=$this->getfixedfee($portal,$spcost);
$weightfee=$this->getweightprice($portal,$weight);
$totalcost=$fixedfee+$weightfee+$rfspamount;
$gstinput=($totalcost*(18/100));
$remittances = $spcost-$totalcost-$gstinput;
$actualprofit= $remittances-$cp-$gstamount+$gstinput;
$actualprofitpercent = ($actualprofit/$cp)*100;
if( $actualprofitpercent >= $mcp)
{
return $sp;
}elseif($actualprofitpercent < $mcp)
{
$newsp = (int)($sp+10) ;
$this->getsalepercent($cp,$newsp,$gst,$rfsp,$mcp,$weight,$portal);
}
}
Can anybody tell me how can resolve this issue? Thanks in advance.
Edited :
Perameters
$cp=100;
$sp=200;
$mcp=20;
$weight=0.5;
$gst=28;
$rfsp=6.5;
First a couple of side notes:
- the way you use $gstinput it cancels itself out when you calculate $actualprofit (it's -$gstinput in $remittances which gets added to +$gstinput).
- $mcpamount seems to go completely unused in the code... I thought for a second you might vahe simply confused vars when doing the comparison, but of course for $cp = 100 it makes no difference.
Even so when I made a few calculations using the example values you gave for $sp = 200 (and growing by 10), I got:
Value of $actualprofit, which for $cp = 100 is also the value of $actualprofitpercent...
for $sp = 200:
43.25 - $fixedfee - $weightfee
for $sp = 210:
50.4125 - $fixedfee - $weightfee
for $sp = 220:
57.575 - $fixedfee - $weightfee
so for each $sp = $sp + 10 recursion the value of $actualprofitpercent (without taking into account $fixedfee and $weightfee) seems to grow by 7.1625.
The value of $weightfee should stay the same, but the value of $fixedfee depends on the value of $sp... Could it be that at each recursion getfixedfee() returns a value which grows faster than 7.1625?

Issue with PHP recursive function

I need to traverse the following type of structures:
P
/ | \
E1 E2 E3 .....
/ \ / \ |
V1 V2 V1 V2 V3 .....
| | | | / \
T1 T2 T3 T4 T5 T6 .....
In order to form an associative array with the following elements:
V1(key) = [T1(E1), T3(E2), ...]
V2(key) = [T2(E1), T4(E2), ...]
V3(key) = [T5(E3), T6(E3), ...]
.....
Now here comes the tricky part: the structure is actually simplified. I don't know beforehand how many E-level nodes I'll actually need to deal with (3 in the drawing), or how many V-level nodes each of them has (but at least 1 will be there), and furthermore, each V-level node may also have multiple T-nodes.
I tried using a recursion function to do this (in PHP). I'll simplify the code because it has weird methods regarding some objects that don't really matter to the discussion. My current attempt results in:
V1(key) = [T1(E1)]
V2(key) = [T2(E1)]
That I think means that the traversal is only occurring going down the first E-level "branch".
This is my code:
$result = [];
$traverser = function($node) use (&$traverser, &$result) {
$children = $node->getChildrenArray();
foreach($children as $key=>$child){
if ($child->nodeType() == 'v_node') {
$v_node_key = $child->name;
$t_nodes = $child->getChildrenArray();
if ( !array_key_exists($v_node_key, $results) ){
$results[$v_node_key] = [];
}
foreach($t_nodes as $keyt=>$t_node) {
$info_array = $t_node->toArray();
array_push($results[$v_node_key], $info_array);
}
} else if ($child->nodeType() == 'e_node') {
// keep digging
return $traverser($child);
}
}
};
$traverser($p_node);
I think the problem is that once I call the $traverser function within the foreach it won't come back and resume from the previous state.
Can anyone advise on how I should be tackling this to get the result I placed above?
Well, this is a bit awkward and I'm still not entirely sure if this is the right motive, but I solved this by removing the return in my code.
I thought that the return would allow me to exit the nested function call, but rather I think it jumped out of the first function call (the $traverser($p_node); line).
Even so, by changing the return $traverser($child); line to $traverser($child); it did what it had to do.
Hope this helps anyone!
I not show about what error you got but i suggest you to change you function to be this
function traverser($results, $node) {
$children = $node->getChildrenArray();
foreach($children as $key=>$child){
if ($child->nodeType() == 'v_node') {
$v_node_key = $child->name;
$t_nodes = $child->getChildrenArray();
if ( !array_key_exists($v_node_key, $results) ){
$results[$v_node_key] = [];
}
foreach($t_nodes as $keyt=>$t_node) {
$info_array = $t_node->toArray();
array_push($results[$v_node_key], $info_array);
}
} else if ($child->nodeType() == 'e_node') {
// keep digging
return traverser($child);
}
}
return $results;
}
Hope this help
Well, since you know that you'll have P->E->V->T-nodes, you could simply go for multiple foreach-loops, like this
foreach($p_node->getChildren() as $e_node) {
$e_node_key = $e_node->name;
foreach($e_node->getChildren() as $v_node) {
$v_node_key = $v_node->name;
foreach($v_node->getChildren() as $t_node) {
$t_node_key = $t_node->name;
// do whatever it needs to array_push to results
}
}
}

PHP Memory exceeded while writing to array in a loop

I need to update a value in an array inside a loop. Normally this works fine, but something about this loop is causing the memory to max out.
while ($watering_window['total_run_time'] > $water_window_total)
{
foreach ($master_schedule as &$_ms)
{
$current_soak_time = $_ms['between_starts'] - $_ms['total_run_time'];
if ($current_soak_time > 0)
{
$new_soak_time = ceil($current_soak_time * 0.9);
$_ms['between_starts'] = $_ms['total_run_time'] + $new_soak_time;
$watering_window['total_run_time'] -= $current_soak_time - $new_soak_time;
}
}
}
Something about writing to $_ms['between_starts'] (an existing key) is causing the memory problem. If I change it to write a NEW key (like $_ms['between_starts_new'], no memory problem. I also tried writing a constant value to it (instead of something mathy) and it still timed out.
You'll need to increase the memory_limit.
Add the following at the top of your php script:
<?php
ini_set('memory_limit','256M');
...
Adjust the value according to your needs.
Try unsetting the key that is causing the problem before you set it.
foreach ($master_schedule as &$_ms)
{
$current_soak_time = $_ms['between_starts'] - $_ms['total_run_time'];
if ($current_soak_time > 0)
{
$new_soak_time = ceil($current_soak_time * 0.9);
unset($master_schedule['between_starts']);
$_ms['between_starts'] = $_ms['total_run_time'] + $new_soak_time;
$watering_window['total_run_time'] -= $current_soak_time - $new_soak_time;
}
}

Using R, how to reference variable variables (or variables variable) a la PHP [revisited]

In a previous Using R, how to reference variable variables (or variables variable) a la PHP[post]
I asked a question about something in R analagous to PHP $$ function:
Using R stats, I want to access a variable variable scenario similar to PHP double-dollar-sign technique: http://php.net/manual/en/language.variables.variable.php
Specifically, I am looking for a function in R that is equivalent to $$ in PHP.
The get( response works for strings (characters).
lapply is a way to loop over lists
Or I can loop over and get the values ...
for(name in names(vars))
{
val = vars[[name]];
I still haven't had the $$ function in R answered, although the lapply solved what I needed in the moment.
`$$` <- function
that allows any variable type to be evaluated. That is still the question.
UPDATES
> mlist = list('four'="score", 'seven'="years");
> str = 'mlist$four'
> mlist
$four
[1] "score"
$seven
[1] "years"
> str
[1] "mlist$four"
> get(str)
Error in get(str) : object 'mlist$four' not found
> mlist$four
[1] "score"
Or how about attributes for an object such as mobj#index
UPDATES #2
So let's put specific context on the need. I was hacking the texreg package to build a custom latex output of 24 models of regression for a research paper. I am using plm fixed effects, and the default output of texreg uses dcolumns to center, which I don't like (I prefer r#{}l, so I wanted to write my own template. The purpose for me, to code this, is for me to write extensible code that I can use again and again. I can rebuild my 24 tables across 4 pages in seconds, so if the data change, or if I want to tweak the function, I immediately have a nice answer. The power of abstraction.
As I hacked this, I wanted to get more than the number of observations, but also the number of groups, which can be any user defined index. In my case it is "country" (wait for it, hence, the need for variable variables).
If I do a lookup of the structure, what I want is right there: model$model#index$country which would be nice to simply call as $$('model$model#index$country'); where I can easily build the string using paste. Nope, this is my workaround.
getIndexCount = function(model,key="country")
{
myA = attr(summary(model)$model,"index");
for(i in 1:length(colnames(myA)))
{
if(colnames(myA)[i] == key) {idx = i; break;}
}
if(!is.na(idx))
{
length(unique(myA[,idx]));
} else {
FALSE;
}
}
UPDATES #3
Using R, on the command line, I can type in a string and it gets evaluated. Why can't that internal function be directly accessed, and the element captured that then gets printed to the screen?
There is no equivalent function in R. get() works for all types, not just strings.
Here is what I came up with, after chatting with the R-bug group, and getting some ideas from them. KUDOS!
`$$` <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
`$$`(nstr);
}
}
Below are some example use cases, where I can directly access what the str(obj) is providing... Extending the utility of the '$' operator by also allowing '#' for attributes.
model = list("four" = "score", "seven"="years");
str = 'model$four';
result = `$$`(str);
print(result);
matrix = matrix(rnorm(1000), ncol=25);
str='matrix[1:5,8:10]';
result = `$$`(str);
print(result);
## Annette Dobson (1990) "An Introduction to Generalized Linear Models".
## Page 9: Plant Weight Data.
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14);
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69);
group <- gl(2, 10, 20, labels = c("Ctl","Trt"));
weight <- c(ctl, trt);
lm.D9 <- lm(weight ~ group);
lm.D90 <- lm(weight ~ group - 1); # omitting intercept
myA = anova(lm.D9); myA; str(myA);
str = 'myA#heading';
result = `$$`(str);
print(result);
myS = summary(lm.D90); myS; str(myS);
str = 'myS$terms#factors';
result = `$$`(str);
print(result);
str = 'myS$terms#factors#dimnames';
result = `$$`(str);
print(result);
str = 'myS$terms#dataClasses#names';
result = `$$`(str);
print(result);
After realizing the back-tick can be a bit tedious, I chose to update the function, calling it access
access <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
access(nstr);
}
}

Making the leap from PhP to Python

I am a fairly comfortable PHP programmer, and have very little Python experience. I am trying to help a buddy with his project, the code is easy enough to write in Php, I have most of it ported over, but need a bit of help completing the translation if possible.
The target is to:
Generate a list of basic objects with uid's
Randomly select a few Items to create a second list keyed to the uid containing new
properties.
Test for intersections between the two lists to alter response accordingly.
The following is a working example of what I am trying to code in Python
<?php
srand(3234);
class Object{ // Basic item description
public $x =null;
public $y =null;
public $name =null;
public $uid =null;
}
class Trace{ // Used to update status or move position
# public $x =null;
# public $y =null;
# public $floor =null;
public $display =null; // Currently all we care about is controlling display
}
##########################################################
$objects = array();
$dirtyItems = array();
#CREATION OF ITEMS########################################
for($i = 0; $i < 10; $i++){
$objects[] = new Object();
$objects[$i]->uid = rand();
$objects[$i]->x = rand(1,30);
$objects[$i]->y = rand(1,30);
$objects[$i]->name = "Item$i";
}
##########################################################
#RANDOM ITEM REMOVAL######################################
foreach( $objects as $item )
if( rand(1,10) <= 2 ){ // Simulate full code with 20% chance to remove an item.
$derp = new Trace();
$derp->display = false;
$dirtyItems[$item->uid] = $derp; //# <- THIS IS WHERE I NEED THE PYTHON HELP
}
##########################################################
display();
function display(){
global $objects, $dirtyItems;
foreach( $objects as $key => $value ){ // Iterate object list
if( #is_null($dirtyItems[$value->uid]) ) // Print description
echo "<br />$value->name is at ($value->x, $value->y) ";
else // or Skip if on second list.
echo "<br />Player took item $value->uid";
}
}
?>
So, really I have most of it sorted I am just having trouble with Python's version of an Associative array, to have a list whose keys match the Unique number of Items in the main list.
The output from the above code should look similar to:
Player took item 27955
Player took item 20718
Player took item 10277
Item3 is at (8, 4)
Item4 is at (11, 13)
Item5 is at (3, 15)
Item6 is at (20, 5)
Item7 is at (24, 25)
Item8 is at (12, 13)
Player took item 30326
My Python skills are still course, but this is roughly the same code block as above.
I've been looking at and trying to use list functions .insert( ) or .setitem( ) but it is not quite working as expected.
This is my current Python code, not yet fully functional
import random
import math
# Begin New Globals
dirtyItems = {} # This is where we store the object info
class SimpleClass: # This is what we store the object info as
pass
# End New Globals
# Existing deffinitions
objects = []
class Object:
def __init__(self,x,y,name,uid):
self.x = x # X and Y positioning
self.y = y #
self.name = name #What will display on a 'look' command.
self.uid = uid
def do_items():
global dirtyItems, objects
for count in xrange(10):
X=random.randrange(1,20)
Y=random.randrange(1,20)
UID = int(math.floor(random.random()*10000))
item = Object(X,Y,'Item'+str(count),UID)
try: #This is the new part, we defined the item, now we see if the player has moved it
if dirtyItems[UID]:
print 'Player took ', UID
except KeyError:
objects.append(item) # Back to existing code after this
pass # Any error generated attempting to access means that the item is untouched by the player.
# place_items( )
random.seed(1234)
do_items()
for key in objects:
print "%s at %s %s." % (key.name, key.x, key.y)
if random.randint(1, 10) <= 1:
print key.name, 'should be missing below'
x = SimpleClass()
x.display = False
dirtyItems[key.uid]=x
print ' '
objects = []
random.seed(1234)
do_items()
for key in objects:
print "%s at %s %s." % (key.name, key.x, key.y)
print 'Done.'
So, sorry for the long post, but I wanted to be through and provide both sets of full code. The PhP works perfectly, and the Python is close. If anyone can point me in the correct direction it would be a huge help.
dirtyItems.insert(key.uid,x) is what i tried to use to make a list work as an Assoc array
Edit: minor correction.
You're declaring dirtyItems as an array instead of a dictionary. In python they're distinct types.
Do dirtyItems = {} instead.
Make a dictionary instead of an array:
import random
import math
dirtyItems = {}
Then you can use like:
dirtyItems[key.uid] = x

Categories