Algorithm to visualise data (multidimensional scaling?) in PHP project - php

I have small matrix of +-100 points/values, results of test and their distances (0-10, 10 is the closest) to each other: http://vis.arcs.cz.
I would like to visualize it in 2D to quickly find a groups of close values. So I need to process this matrix and get the coordinates of points in 2D.
The way is propably multidimensional scaling but I wasnt able to find an algorithm, library or extension nor use the math formulas into PHP code.
Im googling last two days and the closest results of it is
http://www.php.net/manual/en/lapack.leastsquaresbysvd.php - ?
(cant share more links as novice)
I'll be grateful for any solution applicable in php project (compiled MathLab code in C++...).

index.php:
<?php
require("data.php");
require("Mds.php");
$mds = new Mds();
$mds->prepareData($data);
//cislo udava pocet iteraci algoritmu,
//idealne by melo mit hodnotu pocetUzlu na druhou, prakticky muze byt o dost mensi, 5 az 10 krat pocet uzlu.
$mds->scale(100);
//mira splneni podminek - vraci cislo < mensi nez 1. Cim blizsi k 1, tim lepe vyhovuji vzdalenosti
//z vypocteneho rozlozeni zadanym vzdalenostem.
//v nemetrickych datech ovsem dochazi rychle k poklesu az do zapornych hodnot, protoze ve 2D neexistuje
//pro nektere body zadne spravne misto.
echo $mds->getRSquared();
?>
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://canvasjs.com/assets/script/canvasjs.min.js"></script>
<script type="text/javascript">
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer",
{
title:{
text: "MDS",
fontFamily: "arial black",
fontColor: "black"
},
axisX: {
title:"",
titleFontFamily: "arial"
},
axisY:{
title: "",
titleFontFamily: "arial",
titleFontSize: 12
},
data: [
{
type: "scatter",
toolTipContent: "<span style='"'color: {color};'"'><strong>{name}</strong></span> x: {y}, y: {y}",
dataPoints:
<?php
echo $mds->printCoords('{x: %X, y: %Y, name: "%LABEL"}');
?>
}]
});
chart.render();
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 600px; width: 600px;">
</div>
mds.zip
</body>
</html>
data.php:
$data = array(
array ("Jablko", "Voda", 2),
array("Jablko", "Ohen", 7),
array("Jablko", "Cervena", 3),
array("Jablko", "Zelena", 2),
array("Voda", "Ohen", 8),
array("Voda", "Cervena", 8),
array("Voda", "Zelena", 2),
array("Ohen", "Cervena", 1),
array("Ohen", "Zelena", 5),
array("Cervena", "Zelena", 3)
);
Mds.php:
<?php
class Mds {
//node - pole tvaru [[x, y, label], ...]
public $nodes = array();
//tvaru [source][target]=distance
public $givenDistances = array();
public $currentDistances = array();
public function prepareData($data) {
$nodesMap = array();
$xxxx = 10000;
$xxx= 1000;
// $xxxx = 5000;
// $xxx = 600;
foreach($data as $link) {
$source = $link[0];
$target = $link[1];
if(!isset($nodesMap[$source])) {
$nodesMap[$source] = true;
$this->nodes[]=array((float) rand(1,$xxxx) / $xxx, (float) rand(1,$xxxx) / $xxx, $source);
}
if(!isset($nodesMap[$target])) {
$nodesMap[$target] = true;
$this->nodes[]= array((float) rand(1,$xxxx) / $xxx, (float) rand(1,$xxxx) / $xxx, $target);
}
}
//vytvori matici pro ulozeni vzdalenosti
foreach($this->nodes as $node) {
$this->givenDistances[$node[2]] = array();
$this->currentDistances[$node[2]] = array();
}
foreach($data as $link) {
$source = $link[0];
$target = $link[1];
$distance = $link[2];
$this->givenDistances[$source][$target] = $distance;
$this->givenDistances[$target][$source] = $distance;
}
}
protected function countCurrentDistances() {
$mean = 0;
$i = 0;
foreach($this->nodes as $nodeA) {
foreach($this->nodes as $nodeB) {
$dist = sqrt(($nodeB[0]-$nodeA[0])*($nodeB[0]-$nodeA[0]) + ($nodeB[1]-$nodeA[1])*($nodeB[1]-$nodeA[1]));
$this->currentDistances[$nodeA[2]][$nodeB[2]] = $dist;
if($nodeA[2]!==$nodeB[2]) {
$mean += $this->givenDistances[$nodeA[2]][$nodeB[2]];
}
}
}
// echo "<pre>";
// var_dump($this->currentDistances);
// echo "</pre>";
$check = array();
$nodesCount = count($this->nodes);
$this->mean = $mean/($nodesCount*$nodesCount);
}
public function getRSquared() {
$this->countCurrentDistances();
$sum = 0;
$SStot = 0;
$SSres = 0;
foreach($this->nodes as $nodeA) {
foreach($this->nodes as $nodeB) {
$aLab = $nodeA[2];
$bLab = $nodeB[2];
if($aLab===$bLab) {
continue;
}
$given = $this->givenDistances[$aLab][$bLab];
$computed = $this->currentDistances[$aLab][$bLab];
$SSres+=(($given-$computed)*($given-$computed));
$SStot+= ($given-$this->mean)*($given-$this->mean);
}
}
return 1 - ($SSres/$SStot);
}
protected function iterate($inverseCoefStrenth=1) {
for($i=0; $i<count($this->nodes); $i++) {
$nodeA = $this->nodes[$i];
$move = array(0,0);
$moves = 0;
for($j=0; $j<count($this->nodes); $j++) {
if($j===$i) {
continue;
}
$nodeB = $this->nodes[$j];
$dist = $this->givenDistances[$nodeA[2]][$nodeB[2]];
$AB = array($nodeB[0]-$nodeA[0], $nodeB[1]-$nodeA[1]);
$lAB = sqrt(($AB[0]*$AB[0])+($AB[1]*$AB[1]));
$coef = ($lAB - $dist)/$lAB;
$AA1 = array($AB[0]*$coef, $AB[1]*$coef);
$moves++;
$move[0]+=$AA1[0];
$move[1]+=$AA1[1];
}
if($moves>0) {
$resultingMoveX = $move[0]/($moves*$inverseCoefStrenth);
$resultingMoveY = $move[1]/($moves*$inverseCoefStrenth);
$this->nodes[$i][0]+=$resultingMoveX;
$this->nodes[$i][1]+=$resultingMoveY;
}
}
}
public function scale($iterations, $coefIncrease=0) {
$basicCoef=1;
for($i=0; $i<$iterations; $i++) {
$this->iterate($basicCoef);
//echo $this->getRSquared();
//echo " | ";
$basicCoef+=$coefIncrease;
}
}
public function coordsAsString() {
$coords = array();
foreach($this->nodes as $node) {
$coords[]="[{$node[0]}, {$node[1]}]";
}
$res = join(", ",$coords);
return "[$res]";
}
public function printCoords($pattern='[%X,%Y,"%LABEL"]') {
$coords = array();
foreach($this->nodes as $node) {
$x = $node[0];
$y = $node[1];
$label = $node[2];
$res = str_replace('%X', $x, $pattern);
$res = str_replace('%Y', $y, $res);
$res = str_replace('%LABEL', $label, $res);
$coords[]=$res;
}
$res = join(", ",$coords);
return "[$res]";
}
public function pointsCoords() {
$coords = array();
foreach($this->nodes as $node) {
$res['x'] = round($node[0]*100);
$res['y'] = round($node[1]*100);
$res['label'] = $node[2];
$coords[] = $res;
}
return $coords;
}
}

Related

Testing database speed with PHP

i am trying to test database speed with php script.
database connect time
database query time/execution time
database basic information like version, port etc
I am using : https://stackoverflow.com/a/39559173
I am trying :
<?php
/**
* Created by PhpStorm.
* User: NEO
* Date: 9/18/2016
* Time: 10:57 AM
*/
/**
* PHP Script to benchmark PHP and MySQL-Server
*
* inspired by / thanks to:
* - www.php-benchmark-script.com (Alessandro Torrisi)
* - www.webdesign-informatik.de
*
* #author odan
* #license MIT
*/
// -----------------------------------------------------------------------------
// Setup
// -----------------------------------------------------------------------------
set_time_limit(120); // 2 minutes
$options = array();
// Optional: mysql performance test
$options['db.host'] = '127.0.0.1';
$options['db.user'] = 'root';
$options['db.pw'] = '';
$options['db.name'] = 'bache3';
// -----------------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------------
// check performance
$benchmarkResult = test_benchmark($options);
// html output
echo "<!DOCTYPE html>\n<html><head>\n";
echo "<style>
table {
color: #333; /* Lighten up font color */
font-family: Helvetica, Arial, sans-serif; /* Nicer font */
width: 640px;
border-collapse:
collapse; border-spacing: 0;
}
td, th {
border: 1px solid #CCC; height: 30px;
} /* Make cells a bit taller */
th {
background: #F3F3F3; /* Light grey background */
font-weight: bold; /* Make sure they're bold */
}
td {
background: #FAFAFA; /* Lighter grey background */
}
</style>
</head>
<body>";
echo array_to_html($benchmarkResult);
echo "\n</body></html>";
exit;
// -----------------------------------------------------------------------------
// Benchmark functions
// -----------------------------------------------------------------------------
function test_benchmark($settings)
{
$timeStart = microtime(true);
$result = array();
$result['version'] = '1.1';
$result['sysinfo']['time'] = date("Y-m-d H:i:s");
$result['sysinfo']['php_version'] = PHP_VERSION;
$result['sysinfo']['platform'] = PHP_OS;
$result['sysinfo']['server_name'] = $_SERVER['SERVER_NAME'];
$result['sysinfo']['server_addr'] = $_SERVER['SERVER_ADDR'];
test_math($result);
test_string($result);
test_loops($result);
test_ifelse($result);
if (isset($settings['db.host'])) {
test_mysql($result, $settings);
}
$result['total'] = timer_diff($timeStart);
return $result;
}
function test_math(&$result, $count = 99999)
{
$timeStart = microtime(true);
$mathFunctions = array("abs", "acos", "asin", "atan", "bindec", "floor", "exp", "sin", "tan", "pi", "is_finite", "is_nan", "sqrt");
for ($i = 0; $i < $count; $i++) {
foreach ($mathFunctions as $function) {
call_user_func_array($function, array($i));
}
}
$result['benchmark']['math'] = timer_diff($timeStart);
}
function test_string(&$result, $count = 99999)
{
$timeStart = microtime(true);
$stringFunctions = array("addslashes", "chunk_split", "metaphone", "strip_tags", "md5", "sha1", "strtoupper", "strtolower", "strrev", "strlen", "soundex", "ord");
$string = 'the quick brown fox jumps over the lazy dog';
for ($i = 0; $i < $count; $i++) {
foreach ($stringFunctions as $function) {
call_user_func_array($function, array($string));
}
}
$result['benchmark']['string'] = timer_diff($timeStart);
}
function test_loops(&$result, $count = 999999)
{
$timeStart = microtime(true);
for ($i = 0; $i < $count; ++$i) {
}
$i = 0;
while ($i < $count) {
++$i;
}
$result['benchmark']['loops'] = timer_diff($timeStart);
}
function test_ifelse(&$result, $count = 999999)
{
$timeStart = microtime(true);
for ($i = 0; $i < $count; $i++) {
if ($i == -1) {
} elseif ($i == -2) {
} else if ($i == -3) {
}
}
$result['benchmark']['ifelse'] = timer_diff($timeStart);
}
function test_mysql(&$result, $settings)
{
$timeStart = microtime(true);
$link = mysqli_connect($settings['db.host'], $settings['db.user'], $settings['db.pw']);
$result['benchmark']['mysql']['connect'] = timer_diff($timeStart);
//$arr_return['sysinfo']['mysql_version'] = '';
mysqli_select_db($link, $settings['db.name']);
$result['benchmark']['mysql']['select_db'] = timer_diff($timeStart);
$dbResult = mysqli_query($link, 'SELECT VERSION() as version;');
$arr_row = mysqli_fetch_array($dbResult);
$result['sysinfo']['mysql_version'] = $arr_row['version'];
$result['benchmark']['mysql']['query_version'] = timer_diff($timeStart);
$query = "SELECT BENCHMARK(1000000,ENCODE('hello',RAND()));";
$dbResult = mysqli_query($link, $query);
$result['benchmark']['mysql']['query_benchmark'] = timer_diff($timeStart);
mysqli_close($link);
$result['benchmark']['mysql']['total'] = timer_diff($timeStart);
return $result;
}
function timer_diff($timeStart)
{
return number_format(microtime(true) - $timeStart, 3);
}
function array_to_html($array)
{
$result = '';
if (is_array($array)) {
$result .= '<table>';
foreach ($array as $k => $v) {
$result .= "\n<tr><td>";
$result .= '<strong>' . htmlentities($k) . "</strong></td><td>";
$result .= array_to_html($v);
$result .= "</td></tr>";
}
$result .= "\n</table>";
} else {
$result = htmlentities($array);
}
return $result;
}
The above script is working fine but it does not have a option to add custom port for testing and it do not show information like execution time etc

Printing prime numbers from an user's input php

I'm trying ta make a program that will ask the user for a number and then show all the prime numbers between 0 to this number in an array.
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
function isPrime($n)
{
if ($n <= 1)
return false;
for ($i = 2; $i < $n; $i++)
if ($n % $i == 0)
return false;
return true;
}
function printPrime($n)
{
for ($i = 2; $i <= $n; $i++)
{
if (isPrime($i))
echo $i . " ";
}
}
$n = 7;
printPrime($n);
/*end of your code here */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This code work, but with a $n fixed.
I don't know how to use an input who ask the user a number
It's a code who verify itself and show us when it's ok
The code that i have to complete is this one (we only have this at first):
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
/* YOUR CODE HERE */
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}
}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
This is your script:
<?php
class SmallerPrimes{
public function __construct($file){
$this->input_filename = $file;
}
public function Main(){
$smaller_than = (int)$this->readString()[0];
$result = array();
function isPrime($n) {
if ($n <= 1) return false;
for ($i = 2; $i < $n; $i++) if ($n % $i == 0) return false;
return true;
}
function printPrime($n) {
for ($i = 2; $i < $n; $i++) if (isPrime($i)) $result[] = $i;
return $result;
}
$result = printPrime($smaller_than);
return $result;
}
public function readString(){
$file = fopen($this->input_filename, "r");
$line = array();
while (!feof($file)){
array_push($line, str_replace(PHP_EOL, "", fgets($file)));
}
return $line;
}}
$o = new SmallerPrimes($argv[1]);
echo implode(" ", $o->Main()) . PHP_EOL;
function getSmallerPrimes($smaller_than) {
if ($smaller_than <= 2) {
return [];
}
$result = [2];
$sqrt = sqrt($smaller_than);
for ($n = 3; $n < $smaller_than; $n += 2) {
$isPrime = true;
foreach($result as $prime) {
if ($n % $prime == 0) {
$isPrime = false;
break;
}
if ($prime > $sqrt) {
break;
}
}
if ($isPrime) {
$result[] = $n;
}
}
return $result;
}
$input = 23;
echo implode(' ', getSmallerPrimes($input));
Result: 2 3 5 7 11 13 17 19

array_multisort how to mount with foreach

I need to mount an array_multisort with the values from one array.
I tryied to mount a string concated and call on the array_multidimensional like here:
function ordenar_matriz_ultima_posicion_por_distancia($matriz_up,$m_vehiculo_distancias){
$total_vehiculos=count($matriz_up[id_vehiculo]);
//resetear las keys de vehiculos para coger bien los kms y asignarlos
$a_vehiculo_distancia = array_values($m_vehiculo_distancias);
$ordenar = array();
foreach ($a_vehiculo_distancia as $key) {
$ordenar[] = $key;
}
sort($m_vehiculo_distancias);
$string= "";
$ultim_key = end(array_keys($matriz_up));
foreach ($matriz_up as $key => $valor) {
if ($key != $ultim_key) $string.= $matriz_up[$key].',';
else $string.= $matriz_up[$key];
$aaa = '$matriz_up[$key]';
}
echo $string;
echo "<br>";
array_multisort($ordenar, SORT_ASC, $string);
for($i=0;$i<$total_vehiculos;$i++){
$matriz_up['cercanos'][$i] = $m_vehiculo_distancias[$i];
echo $matriz_up['id_vehiculo'][$i]."<br>";
echo $matriz_up['fecha_gps'][$i]."<br>";
echo $matriz_up['id_tipo_posicion'][$i]."<br>";
echo $matriz_up['cercanos'][$i]."<br>";
echo $matriz_up['vaina'][$i]."<br>";
echo "------------<br>";
}
return $matriz_up;
}
$matriz_up['id_vehiculo'][0] = 9;
$matriz_up['fecha_gps'][0] = '2014';
$matriz_up['id_tipo_posicion'][0] = 11111;
$matriz_up['cercanos'][0] = 0;
$matriz_up['vaina'][0] = 12345;
$matriz_up['id_vehiculo'][1] = 3;
$matriz_up['fecha_gps'][1] = '2015';
$matriz_up['id_tipo_posicion'][1] = 22222;
$matriz_up['cercanos'][1] = 0;
$matriz_up['vaina'][1] = 5555;
$matriz_up['id_vehiculo'][2] = 1;
$matriz_up['fecha_gps'][2] = '2016';
$matriz_up['id_tipo_posicion'][2] = 33333;
$matriz_up['cercanos'][2] = 0;
$matriz_up['vaina'][2] = 988;
$matriz_up['id_vehiculo'][3] = 4;
$matriz_up['fecha_gps'][3] = '2017';
$matriz_up['id_tipo_posicion'][3] = 44444;
$matriz_up['cercanos'][3] = 0;
$matriz_up['vaina'][3] = 777;
$m_vehiculo_distancias[9] = 345;
$m_vehiculo_distancias[3] = 712;
$m_vehiculo_distancias[1] = 10;
$m_vehiculo_distancias[4] = 35;
ordenar_matriz_ultima_posicion_por_distancia($matriz_up,$m_vehiculo_distancias);
With this array_multisort works, but i need to take all the key without put manually..
array_multisort($ordenar, SORT_ASC, $matriz_up['id_vehiculo'], $matriz_up['fecha_gps'], $matriz_up['id_tipo_posicion'], $matriz_up['vaina'] );
Try this code:
<?php
$matriz_up = $m_vehiculo_distancias = array();
$matriz_up['id_vehiculo'][0] = 9;
$matriz_up['fecha_gps'][0] = '2014';
$matriz_up['id_tipo_posicion'][0] = 11111;
$matriz_up['cercanos'][0] = 0;
$matriz_up['vaina'][0] = 12345;
$matriz_up['id_vehiculo'][1] = 3;
$matriz_up['fecha_gps'][1] = '2015';
$matriz_up['id_tipo_posicion'][1] = 22222;
$matriz_up['cercanos'][1] = 0;
$matriz_up['vaina'][1] = 5555;
$matriz_up['id_vehiculo'][2] = 1;
$matriz_up['fecha_gps'][2] = '2016';
$matriz_up['id_tipo_posicion'][2] = 33333;
$matriz_up['cercanos'][2] = 0;
$matriz_up['vaina'][2] = 988;
$matriz_up['id_vehiculo'][3] = 4;
$matriz_up['fecha_gps'][3] = '2017';
$matriz_up['id_tipo_posicion'][3] = 44444;
$matriz_up['cercanos'][3] = 0;
$matriz_up['vaina'][3] = 777;
$m_vehiculo_distancias[9] = 345;
$m_vehiculo_distancias[3] = 712;
$m_vehiculo_distancias[1] = 10;
$m_vehiculo_distancias[4] = 35;
function sortArray($arrayToSortParam, $orderArray)
{
$result = array();
$arrayToSort = $arrayToSortParam;
$keys = array_keys($arrayToSort);
asort($orderArray, true);
$newSort = $cercanos = array();
foreach($orderArray as $key => $value)
{
$newSort[] = array_keys($arrayToSort['id_vehiculo'], $key)[0];
$cercanos[] = $orderArray[$key];
}
foreach($keys as $keyName)
{
uksort($arrayToSort[$keyName], function($key1, $key2) use ($newSort) {
return (array_search($key1, $newSort) > array_search($key2, $newSort));
});
}
$arrayToSort['cercanos'] = $cercanos;
//reset indexes
foreach($keys as $keyName)
{
$arrayToSort[$keyName] = array_values($arrayToSort[$keyName]);
}
return $arrayToSort;
}
echo '<pre>';
//print_r($matriz_up);
//print_r($m_vehiculo_distancias);
print_r(sortArray($matriz_up, $m_vehiculo_distancias)); //this is result
Working fiddle: CLICK!

apply apriori php to CI

I downloaded apriori algorithm on php from www.vtwo.org but i want to apply it to my CI framework, but the input value won't be called. so it couldn't display the result. is it something wrong on my CI code changes? please help
this is my apriori controller (apriori.php)
class Apriori {
private $delimiter = ',';
private $minSup = 2;
private $minConf = 50;
private $rules = array();
private $table = array();
private $allthings = array();
private $allsups = array();
private $keys = array();
private $freqItmsts = array();
private $phase = 1;
//maxPhase>=2
private $maxPhase = 20;
private $fiTime = 0;
private $arTime = 0;
public function setDelimiter($char)
{
$this->delimiter = $char;
}
public function setMinSup($int)
{
$this->minSup = $int;
}
public function setMinConf($int)
{
$this->minConf = $int;
}
public function setMaxScan($int)
{
$this->maxPhase = $int;
}
public function getDelimiter()
{
return $this->delimiter;
}
public function getMinSup()
{
return $this->minSup;
}
public function getMinConf()
{
return $this->minConf;
}
public function getMaxScan()
{
return $this->maxPhase;
}
/**
1. جدول آیتمها را می سازد
2. کلید دسترسی به هر آیتم را تولید می کند
3. تمامی آیتمها و تکرار آنها را محاسبه می کند - سطح 1
توجه: حداقل تکرار محاسبه میشود
**/
private function makeTable($db)
{
$table = array();
$array = array();
$counter = 1;
if(!is_array($db))
{
$db = file($db);
}
$num = count($db);
for($i=0; $i<$num; $i++)
{
$tmp = explode($this->delimiter, $db[$i]);
$num1 = count($tmp);
$x = array();
for($j=0; $j<$num1; $j++)
{
$x = trim($tmp[$j]);
if($x==='')
{
continue;
}
if(!isset($this->keys['v->k'][$x]))
{
$this->keys['v->k'][$x] = $counter;
$this->keys['k->v'][$counter] = $x;
$counter++;
}
if(!isset($array[$this->keys['v->k'][$x]]))
{
$array[$this->keys['v->k'][$x]] = 1;
$this->allsups[$this->keys['v->k'][$x]] = 1;
}
else
{
$array[$this->keys['v->k'][$x]]++;
$this->allsups[$this->keys['v->k'][$x]]++;
}
$table[$i][$this->keys['v->k'][$x]] = 1;
}
}
$tmp = array();
foreach($array as $item => $sup)
{
if($sup>=$this->minSup)
{
$tmp[] = array($item);
}
}
$this->allthings[$this->phase] = $tmp;
$this->table = $table;
}
/**
1. مقدار سوپریموم را با توجه به ورودی شناسه آیتمها شمارش می کند
**/
private function scan($arr, $implodeArr = '')
{
$cr = 0;
if($implodeArr)
{
if(isset($this->allsups[$implodeArr]))
{
return $this->allsups[$implodeArr];
}
}
else
{
sort($arr);
$implodeArr = implode($this->delimiter, $arr);
if(isset($this->allsups[$implodeArr]))
{
return $this->allsups[$implodeArr];
}
}
$num = count($this->table);
$num1 = count($arr);
for($i=0; $i<$num; $i++)
{
$bool = true;
for($j=0; $j<$num1; $j++)
{
if(!isset($this->table[$i][$arr[$j]]))
{
$bool = false;
break;
}
}
if($bool)
{
$cr++;
}
}
$this->allsups[$implodeArr] = $cr;
return $cr;
}
/**
1. ترکیب دو آرایه و حذف مقادیر اضافی
**/
private function combine($arr1, $arr2)
{
$result = array();
$num = count($arr1);
$num1 = count($arr2);
for($i=0; $i<$num; $i++)
{
if(!isset($result['k'][$arr1[$i]]))
{
$result['v'][] = $arr1[$i];
$result['k'][$arr1[$i]] = 1;
}
}
for($i=0; $i<$num1; $i++)
{
if(!isset($result['k'][$arr2[$i]]))
{
$result['v'][] = $arr2[$i];
$result['k'][$arr2[$i]] = 1;
}
}
return $result['v'];
}
/**
1. نام آیتم را با توجه به شناسه آیتم یا آیتمها بر می گرداند
{1,2,3,4} => {A,B,C,D}
**/
private function realName($arr)
{
$result = '';
$num = count($arr);
for($j=0; $j<$num; $j++)
{
if($j)
{
$result .= $this->delimiter;
}
$result .= $this->keys['k->v'][$arr[$j]];
}
return $result;
}
//1-2=>2-3 : false
//1-2=>5-6 : true
private function checkRule($a, $b)
{
$a_num = count($a);
$b_num = count($b);
for($i=0; $i<$a_num; $i++)
{
for($j=0; $j<$b_num; $j++)
{
if($a[$i]==$b[$j])
{
return false;
}
}
}
return true;
}
private function confidence($sup_a, $sup_ab)
{
return round(($sup_ab / $sup_a) * 100, 2);
}
private function subsets($items)
{
$result = array();
$num = count($items);
$members = pow(2, $num);
for($i=0; $i<$members; $i++)
{
$b = sprintf("%0".$num."b", $i);
$tmp = array();
for($j=0; $j<$num; $j++)
{
if($b[$j]=='1')
{
$tmp[] = $items[$j];
}
}
if($tmp)
{
sort($tmp);
$result[] = $tmp;
}
}
return $result;
}
/**
1. آیتم ستهای تکراری را بر می گرداند
**/
private function freqItemsets($db)
{
$this->fiTime = $this->startTimer();
$this->makeTable($db);
while(1)
{
if($this->phase>=$this->maxPhase)
{
break;
}
$num = count($this->allthings[$this->phase]);
$cr = 0;
for($i=0; $i<$num; $i++)
{
for($j=$i; $j<$num; $j++)
{
if($i==$j)
{
continue;
}
$item = $this->combine($this->allthings[$this->phase][$i], $this->allthings[$this->phase][$j]);
sort($item);
$implodeArr = implode($this->delimiter, $item);
if(!isset($this->freqItmsts[$implodeArr]))
{
$sup = $this->scan($item, $implodeArr);
if($sup>=$this->minSup)
{
$this->allthings[$this->phase+1][] = $item;
$this->freqItmsts[$implodeArr] = 1;
$cr++;
}
}
}
}
if($cr<=1)
{
break;
}
$this->phase++;
}
//زیر مجموعه های مربوط به مجموعه های بزرگتر را حذف می کند
foreach($this->freqItmsts as $k => $v)
{
$arr = explode($this->delimiter, $k);
$num = count($arr);
if($num>=3)
{
$subsets = $this->subsets($arr);
$num1 = count($subsets);
for($i=0; $i<$num1; $i++)
{
if(count($subsets[$i])<$num)
{
unset($this->freqItmsts[implode($this->delimiter, $subsets[$i])]);
}
else
{
break;
}
}
}
}
$this->fiTime = $this->stopTimer($this->fiTime);
}
/**
1. قوانین نهایی را با توجه به مقدار حداقل کانفیندس محاسبه می کند
**/
public function process($db)
{
$checked = $result = array();
$this->freqItemsets($db);
$this->arTime = $this->startTimer();
foreach($this->freqItmsts as $k => $v)
{
$arr = explode($this->delimiter, $k);
$subsets = $this->subsets($arr);
$num = count($subsets);
for($i=0; $i<$num; $i++)
{
for($j=0; $j<$num; $j++)
{
if($this->checkRule($subsets[$i], $subsets[$j]))
{
$n1 = $this->realName($subsets[$i]);
$n2 = $this->realName($subsets[$j]);
$scan = $this->scan($this->combine($subsets[$i], $subsets[$j]));
$c1 = $this->confidence($this->scan($subsets[$i]), $scan);
$c2 = $this->confidence($this->scan($subsets[$j]), $scan);
if($c1>=$this->minConf)
{
$result[$n1][$n2] = $c1;
}
if($c2>=$this->minConf)
{
$result[$n2][$n1] = $c2;
}
$checked[$n1.$this->delimiter.$n2] = 1;
$checked[$n2.$this->delimiter.$n1] = 1;
}
}
}
}
$this->arTime = $this->stopTimer($this->arTime);
return $this->rules = $result;
}
public function printFreqItemsets()
{
echo 'Time: '.$this->fiTime.' second(s)<br />===============================================================================<br />';
foreach($this->freqItmsts as $k => $v)
{
$tmp = '';
$tmp1 = '';
$k = explode($this->delimiter, $k);
$num = count($k);
for($i=0; $i<$num; $i++)
{
if($i)
{
$tmp .= $this->delimiter.$this->realName($k[$i]);
$tmp1 .= $this->delimiter.$k[$i];
}
else
{
$tmp = $this->realName($k[$i]);
$tmp1 = $k[$i];
}
}
echo '{'.$tmp.'} = '.$this->allsups[$tmp1].'<br />';
}
}
public function saveFreqItemsets($filename)
{
$content = '';
foreach($this->freqItmsts as $k => $v)
{
$tmp = '';
$tmp1 = '';
$k = explode($this->delimiter, $k);
$num = count($k);
for($i=0; $i<$num; $i++)
{
if($i)
{
$tmp .= $this->delimiter.$this->realName($k[$i]);
$tmp1 .= $this->delimiter.$k[$i];
}
else
{
$tmp = $this->realName($k[$i]);
$tmp1 = $k[$i];
}
}
$content .= '{'.$tmp.'} = '.$this->allsups[$tmp1]."\n";
}
file_put_contents($filename, $content);
}
public function getFreqItemsets()
{
$result = array();
foreach($this->freqItmsts as $k => $v)
{
$tmp = array();
$tmp['sup'] = $this->allsups[$k];
$k = explode($this->delimiter, $k);
$num = count($k);
for($i=0; $i<$num; $i++)
{
$tmp[] = $this->realName($k[$i]);
}
$result[] = $tmp;
}
return $result;
}
public function printAssociationRules()
{
echo 'Time: '.$this->arTime.' second(s)<br />===============================================================================<br />';
foreach($this->rules as $a => $arr)
{
foreach($arr as $b => $conf)
{
echo "$a => $b = $conf%<br />";
}
}
}
public function saveAssociationRules($filename)
{
$content = '';
foreach($this->rules as $a => $arr)
{
foreach($arr as $b => $conf)
{
$content .= "$a => $b = $conf%\n";
}
}
file_put_contents($filename, $content);
}
public function getAssociationRules()
{
return $this->rules;
}
private function startTimer()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
private function stopTimer($start, $round=2)
{
$endtime = $this->startTimer()-$start;
$round = pow(10, $round);
return round($endtime*$round)/$round;
}} ?>
my welcome controller (welcome.php)
class Welcome extends CI_Controller {
function __construct() {
parent::__construct();
include 'class.apriori.php';
}
// input page
public function index() {
$this->load->view('welcome_message');
}
// minSup, minConf, maxScan value as input
public function ambilinput() {
$minSup = $this->input->post('minSup', true);
$minConf = $this->input->post('minConf', true);
$maxScan = $this->input->post('maxScan', true);
redirect("welcome/apriori/$minSup/$minConf/$maxScan");
}
//APRIORI on system
public function apriori($minSup, $minConf, $maxScan) {
$Apriori = new Apriori();
$Apriori->setMaxScan($maxScan);
$Apriori->setMinSup($minSup);
$Apriori->setMinConf($minConf);
$Apriori->setDelimiter(',');
$dataset = array();
$dataset[] = array('A', 'B', 'C', 'D');
$dataset[] = array('A', 'D', 'C');
$dataset[] = array('B', 'C');
$dataset[] = array('A', 'E', 'C');
$Apriori->process($dataset);
echo '<h1>Frequent Itemsets</h1>';
$Apriori->printFreqItemsets();
echo '<h3>Frequent Itemsets Array</h3>';
print_r($Apriori->getFreqItemsets());
//Association Rules
echo '<h1>Association Rules</h1>';
$Apriori->printAssociationRules();
echo '<h3>Association Rules Array</h3>';
print_r($Apriori->getAssociationRules());
}
}
my view file to input minsup, minconf, and maxScan value
(welcome_message.php)
<head>
<meta charset="utf-8">
<title>Input 1</title>
</head>
<body>
<div>
<form action="<?php echo base_url(); ?>index.php/welcome/ambilinput" method="post">
<input type="number" name="minSup" placeholder="Minimal Support dalam %"/></br></br>
<input type="number" name="minConf" placeholder="Minimal Coff dalam %"/></br></br>
<input type="number" name="maxScan" placeholder="Jumlah Transaksi"/></br></br>
<button type="submit" name="submit">Hitung Apriori</button>
</form>
</div>
</body>

Why isn't my sorting algorithm working?

I'm developing a system for a client that creates a csv of packing labels which is sent to a printer. The client has six different items. Customers order products in bulk from my client. Two items (product A and product B) share the same packing line. In order to make packing more efficient my client wants to alternate between packing product A and packing product B first.
For example, if John, Sally, and James all ordered both products, the system needs to write John's orders to the csv starting with product A, Sally's orders starting with product B, and James' orders starting with product A again.
I've pasted my non-working code below, but this is really screwing with my head and I'm having a really tough time with it.
foreach($orders as $order) {
$name = null;
$phone = null;
$account = DAO_ContactPerson::get($order->account_id);
$delivery = false;
if($account->is_agency) {
$name = $order->getAttribute('name');
$phone = $order->getAttribute('phone');
} else {
$name = sprintf("%s %s",
$account->getPrimaryAddress()->first_name,
$account->getPrimaryAddress()->last_name
);
$phone = $account->phone;
}
$name = trim($name);
$phone = trim($phone);
$items = $order->getItems();
if($order->getAttribute('delivery')) {
$type = 'deliveries';
$destination = 'Delivery';
$address = sprintf("%s %s %s",
$order->getAttribute('delivery_address.line1'),
$order->getAttribute('delivery_address.line2'),
$order->getAttribute('delivery_address.postal')
);
} else {
$type = 'pickups';
$agency = DAO_ContactPerson::getAgency($order->getAttribute('pickup'));
$destination = $agency->name;
// Override account id so orders are grouped by agency
$order->account_id = $agency->id;
$address = null;
}
// var_dump($order->id);
// Init account array
if(!isset($rows[$type][$order->account_id]))
$rows[$type][$order->account_id] = array('combined' => array(), 'separate' => array());
foreach($items as $item) {
$packing = 'separated';
if($item->product_id == 3 || $item->product_id == 4)
$packing = 'combined';
if(!isset($rows[$type][$order->account_id][$packing][$item->product_id]))
$rows[$type][$order->account_id][$packing][$item->product_id] = array();
$i = 0;
while($i < $item->quantity) {
$rows[$type][$order->account_id][$packing][$item->product_id][] = array(
'number' => $order->id,
'destination' => $destination,
'size' => $item->product_id,
'name' => $name,
'address' => $address,
'phone' => $phone
);
$i++;
}
}
// if($order->id == 176) {
// var_dump($rows[$type][$order->account_id][$packing]);
// }
}
$this->weight = 1;
$pickups = count($rows['pickups']);
for($i = 0; $i < $pickups; $i++) {
$account =& $rows['pickups'][$i];
$account['output'] = array();
if(isset($account['combined'])) {
$combined_products =& $account['combined'];
if(!empty($combined_products)) {
foreach($combined_products as $prod_id => $combined) {
usort($combined_products[$prod_id], array($this, "_compareBoxes"));
}
// Flip weights once we finish with this account
$last_box = end($combined_products);
$last_box = array_pop($last_box);
reset($combined_products);
if($this->weight == 1) {
$this->weight = -1;
if($last_box['size'] == 3) {
asort($combined_products);
}
} else {
if($last_box['size'] == 4) {
arsort($combined_products);
}
$this->weight = 1;
}
foreach($combined_products as $combined) {
$account['output'][] = $combined;
}
foreach($account['separated'] as $separate) {
$account['output'][] = $separate;
}
}
} else {
if(isset($account['separated']))
$account['output'] = $account['separated'];
}
}
$deliveries = count($rows['deliveries']);
for($i = 0; $i < $deliveries; $i++) {
$account =& $rows['deliveries'][$i];
$account['output'] = array();
if(isset($account['combined'])) {
$combined_products =& $account['combined'];
if(!empty($combined_products)) {
foreach($combined_products as $prod_id => $combined) {
usort($combined_products[$prod_id], array($this, "_compareBoxes"));
}
// Flip weights once we finish with this account
$last_box = end($combined_products);
$last_box = array_pop($last_box);
reset($combined_products);
if($this->weight == 1) {
$this->weight = -1;
if($last_box['size'] == 3) {
asort($combined_products);
}
} else {
if($last_box['size'] == 4) {
arsort($combined_products);
}
$this->weight = 1;
}
foreach($combined_products as $combined) {
$account['output'][] = $combined;
}
foreach($account['separated'] as $separate) {
$account['output'][] = $separate;
}
}
} else {
if(isset($account['separated']))
$account['output'] = $account['separated'];
}
}
$rows['output'] = $rows['pickups'];
array_push($rows['output'], $rows['deliveries']);
$output = '';
foreach($rows['output'] as $account_id => $boxes) {
if(!empty($boxes['output'])) {
foreach($boxes['output'] as $labels) {
if(!empty($labels)) {
foreach($labels as $label) {
$output .= implode(',', $label) . "<br>";
}
}
}
}
}
The _compareBoxes method looks like this:
private function _compareBoxes($a, $b) {
if($a['size'] == $b['size']) {
return 0;
}
if($this->weight == 1) {
// Medium first, then Large
return ($a['size'] < $b['size']) ? -1 : 1;
}
if($this->weight == -1) {
// Large first, then Medium
return ($a['size'] > $b['size']) ? -1 : 1;
}
}

Categories