commit 61ee303d035c12d65272cbb2bdb6daff8cb85877 Author: ijab Date: Wed Jan 23 20:18:12 2013 -0500 Initial commit. diff --git a/demo/css/screen.css b/demo/css/screen.css new file mode 100644 index 0000000..d4dd897 --- /dev/null +++ b/demo/css/screen.css @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------- + + Blueprint CSS Framework 0.7.1 + http://blueprintcss.googlecode.com + + * Copyright (c) 2007-2008. See LICENSE for more info. + * See README for instructions on how to use Blueprint. + * For credits and origins, see AUTHORS. + * This is a compressed file. See the sources in the 'src' directory. + +----------------------------------------------------------------------- */ + +/* reset.css */ +html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;} +body {line-height:1.5;} +table {border-collapse:separate;border-spacing:0;} +caption, th, td {text-align:left;font-weight:normal;} +table, td, th {vertical-align:middle;} +blockquote:before, blockquote:after, q:before, q:after {content:"";} +blockquote, q {quotes:"" "";} +a img {border:none;} + +/* typography.css */ +body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;} +h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;} +h1 {font-size:3em;line-height:1;margin-bottom:0.5em;} +h2 {font-size:2em;margin-bottom:0.75em;} +h3 {font-size:1.5em;line-height:1;margin-bottom:1em;} +h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;height:1.25em;} +h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;} +h6 {font-size:1em;font-weight:bold;} +h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;} +p {margin:0 0 1.5em;} +p img {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;} +p img.right {float:right;margin:1.5em 0 1.5em 1.5em;} +a:focus, a:hover {color:#000;} +a {color:#009;text-decoration:underline;} +blockquote {margin:1.5em;color:#666;font-style:italic;} +strong {font-weight:bold;} +em, dfn {font-style:italic;} +dfn {font-weight:bold;} +sup, sub {line-height:0;} +abbr, acronym {border-bottom:1px dotted #666;} +address {margin:0 0 1.5em;font-style:italic;} +del {color:#666;} +pre, code {margin:1.5em 0;white-space:pre;} +pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;} +li ul, li ol {margin:0 1.5em;} +ul, ol {margin:0 1.5em 1.5em 1.5em;} +ul {list-style-type:disc;} +ol {list-style-type:decimal;} +dl {margin:0 0 1.5em 0;} +dl dt {font-weight:bold;} +dd {margin-left:1.5em;} +table {margin-bottom:1.4em;width:100%;} +th {font-weight:bold;background:#C3D9FF;} +th, td {padding:4px 10px 4px 5px;} +tr.even td {background:#E5ECF9;} +tfoot {font-style:italic;} +caption {background:#eee;} +.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;} +.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;} +.hide {display:none;} +.quiet {color:#666;} +.loud {color:#000;} +.highlight {background:#ff0;} +.added {background:#060;color:#fff;} +.removed {background:#900;color:#fff;} +.first {margin-left:0;padding-left:0;} +.last {margin-right:0;padding-right:0;} +.top {margin-top:0;padding-top:0;} +.bottom {margin-bottom:0;padding-bottom:0;} + +/* grid.css */ +.container {width:950px;margin:0 auto;} +.showgrid {background:url(src/grid.png);} +body {margin:1.5em 0;} +div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;} +div.last {margin-right:0;} +.span-1 {width:30px;} +.span-2 {width:70px;} +.span-3 {width:110px;} +.span-4 {width:150px;} +.span-5 {width:190px;} +.span-6 {width:230px;} +.span-7 {width:270px;} +.span-8 {width:310px;} +.span-9 {width:350px;} +.span-10 {width:390px;} +.span-11 {width:430px;} +.span-12 {width:470px;} +.span-13 {width:510px;} +.span-14 {width:550px;} +.span-15 {width:590px;} +.span-16 {width:630px;} +.span-17 {width:670px;} +.span-18 {width:710px;} +.span-19 {width:750px;} +.span-20 {width:790px;} +.span-21 {width:830px;} +.span-22 {width:870px;} +.span-23 {width:910px;} +.span-24, div.span-24 {width:950px;margin:0;} +.append-1 {padding-right:40px;} +.append-2 {padding-right:80px;} +.append-3 {padding-right:120px;} +.append-4 {padding-right:160px;} +.append-5 {padding-right:200px;} +.append-6 {padding-right:240px;} +.append-7 {padding-right:280px;} +.append-8 {padding-right:320px;} +.append-9 {padding-right:360px;} +.append-10 {padding-right:400px;} +.append-11 {padding-right:440px;} +.append-12 {padding-right:480px;} +.append-13 {padding-right:520px;} +.append-14 {padding-right:560px;} +.append-15 {padding-right:600px;} +.append-16 {padding-right:640px;} +.append-17 {padding-right:680px;} +.append-18 {padding-right:720px;} +.append-19 {padding-right:760px;} +.append-20 {padding-right:800px;} +.append-21 {padding-right:840px;} +.append-22 {padding-right:880px;} +.append-23 {padding-right:920px;} +.prepend-1 {padding-left:40px;} +.prepend-2 {padding-left:80px;} +.prepend-3 {padding-left:120px;} +.prepend-4 {padding-left:160px;} +.prepend-5 {padding-left:200px;} +.prepend-6 {padding-left:240px;} +.prepend-7 {padding-left:280px;} +.prepend-8 {padding-left:320px;} +.prepend-9 {padding-left:360px;} +.prepend-10 {padding-left:400px;} +.prepend-11 {padding-left:440px;} +.prepend-12 {padding-left:480px;} +.prepend-13 {padding-left:520px;} +.prepend-14 {padding-left:560px;} +.prepend-15 {padding-left:600px;} +.prepend-16 {padding-left:640px;} +.prepend-17 {padding-left:680px;} +.prepend-18 {padding-left:720px;} +.prepend-19 {padding-left:760px;} +.prepend-20 {padding-left:800px;} +.prepend-21 {padding-left:840px;} +.prepend-22 {padding-left:880px;} +.prepend-23 {padding-left:920px;} +div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;} +div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;} +.pull-1 {margin-left:-40px;} +.pull-2 {margin-left:-80px;} +.pull-3 {margin-left:-120px;} +.pull-4 {margin-left:-160px;} +.pull-5 {margin-left:-200px;} +.pull-6 {margin-left:-240px;} +.pull-7 {margin-left:-280px;} +.pull-8 {margin-left:-320px;} +.pull-9 {margin-left:-360px;} +.pull-10 {margin-left:-400px;} +.pull-11 {margin-left:-440px;} +.pull-12 {margin-left:-480px;} +.pull-13 {margin-left:-520px;} +.pull-14 {margin-left:-560px;} +.pull-15 {margin-left:-600px;} +.pull-16 {margin-left:-640px;} +.pull-17 {margin-left:-680px;} +.pull-18 {margin-left:-720px;} +.pull-19 {margin-left:-760px;} +.pull-20 {margin-left:-800px;} +.pull-21 {margin-left:-840px;} +.pull-22 {margin-left:-880px;} +.pull-23 {margin-left:-920px;} +.pull-24 {margin-left:-960px;} +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;} +.push-1 {margin:0 -40px 1.5em 40px;} +.push-2 {margin:0 -80px 1.5em 80px;} +.push-3 {margin:0 -120px 1.5em 120px;} +.push-4 {margin:0 -160px 1.5em 160px;} +.push-5 {margin:0 -200px 1.5em 200px;} +.push-6 {margin:0 -240px 1.5em 240px;} +.push-7 {margin:0 -280px 1.5em 280px;} +.push-8 {margin:0 -320px 1.5em 320px;} +.push-9 {margin:0 -360px 1.5em 360px;} +.push-10 {margin:0 -400px 1.5em 400px;} +.push-11 {margin:0 -440px 1.5em 440px;} +.push-12 {margin:0 -480px 1.5em 480px;} +.push-13 {margin:0 -520px 1.5em 520px;} +.push-14 {margin:0 -560px 1.5em 560px;} +.push-15 {margin:0 -600px 1.5em 600px;} +.push-16 {margin:0 -640px 1.5em 640px;} +.push-17 {margin:0 -680px 1.5em 680px;} +.push-18 {margin:0 -720px 1.5em 720px;} +.push-19 {margin:0 -760px 1.5em 760px;} +.push-20 {margin:0 -800px 1.5em 800px;} +.push-21 {margin:0 -840px 1.5em 840px;} +.push-22 {margin:0 -880px 1.5em 880px;} +.push-23 {margin:0 -920px 1.5em 920px;} +.push-24 {margin:0 -960px 1.5em 960px;} +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;} +.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;} +hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;} +hr.space {background:#fff;color:#fff;} +.clearfix:after, .container:after {content:".";display:block;height:0;clear:both;visibility:hidden;} +.clearfix, .container {display:inline-block;} +* html .clearfix, * html .container {height:1%;} +.clearfix, .container {display:block;} +.clear {clear:both;} + +/* forms.css */ +label {font-weight:bold;} +fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;} +legend {font-weight:bold;font-size:1.2em;} +input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;} +input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;} +input.text, input.title {width:300px;padding:5px;} +input.title {font-size:1.5em;} +textarea {width:390px;height:250px;padding:5px;} +.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;} +.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;} +.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;} +.success {background:#E6EFC2;color:#264409;border-color:#C6D880;} +.error a {color:#8a1f11;} +.notice a {color:#514721;} +.success a {color:#264409;} \ No newline at end of file diff --git a/demo/fuzzy-logic-calc-pam.php b/demo/fuzzy-logic-calc-pam.php new file mode 100644 index 0000000..3cd5b35 --- /dev/null +++ b/demo/fuzzy-logic-calc-pam.php @@ -0,0 +1,54 @@ +cal_fuzzy($inputs_v); + +?> + + + +Calculate PAM Impendance + + + + + +
+

Calculate PAM Impendance

+
+
+
+
+ + \ No newline at end of file diff --git a/demo/fuzzy-logic-calc-risk.php b/demo/fuzzy-logic-calc-risk.php new file mode 100644 index 0000000..ee91608 --- /dev/null +++ b/demo/fuzzy-logic-calc-risk.php @@ -0,0 +1,201 @@ +clearMembers(); +$x->SetInputNames(array('project_funding','project_staffing')); +$x->addMember($x->getInputName(0),'inadequate', 0, 20, 40 ,LINFINITY); +$x->addMember($x->getInputName(0),'marginal' , 20, 50, 80 ,TRIANGLE); +$x->addMember($x->getInputName(0),'adequate' , 60, 80, 100,RINFINITY); +$x->addMember($x->getInputName(1),'small', 0, 30, 70,LINFINITY); +$x->addMember($x->getInputName(1),'large',30, 70,100,RINFINITY); +$x->SetOutputNames(array('risk')); +$x->addMember($x->getOutputName(0),'low',0, 20 ,40 ,LINFINITY); +$x->addMember($x->getOutputName(0),'normal',20, 50 ,80 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'high',60, 80 , 100 ,RINFINITY); +$x->clearRules(); +$x->addRule('IF project_funding.adequate OR project_staffing.small THEN risk.low'); +$x->addRule('IF project_funding.marginal AND project_staffing.large THEN risk.normal'); +$x->addRule('IF project_funding.inadequate THEN risk.high'); + +$project_funding = (isset($_GET['project_funding'])) ? $_GET['project_funding'] : 35; +$project_staffing = (isset($_GET['project_staffing'])) ? $_GET['project_staffing'] : 65; + +$x->setRealInput('project_funding', $project_funding ); +$x->setRealInput('project_staffing' , $project_staffing ); +$fuzzy_arr = $x->calcFuzzy(); +$risk = $fuzzy_arr['risk']; +$bar_width = 320; +?> + + + +Calculate Risk Project + + + + + +
+

Calculate Risk Project

+
+
+
+
+ + \ No newline at end of file diff --git a/demo/fuzzy-logic-tank.php b/demo/fuzzy-logic-tank.php new file mode 100644 index 0000000..c48527a --- /dev/null +++ b/demo/fuzzy-logic-tank.php @@ -0,0 +1,138 @@ +clearMembers(); +/* ---------- set input members ---------*/ +$x->setInputNames(array('ERROR','RATE')); + +$x->addMember($x->getInputName(0),'E_NEG',-1 ,-0.9 , 0 ,LINFINITY); +$x->addMember($x->getInputName(0),'E_OK' ,-0.1 , 0 , 0.1,TRIANGLE); +$x->addMember($x->getInputName(0),'E_POS', 0 , 0.9 , 1 ,RINFINITY); + +$x->addMember($x->GetInputName(1),'R_NEG',-0.10,-0.07 ,0 ,LINFINITY); +$x->addMember($x->GetInputName(1),'R_OK', -0.07, 0 ,0.07 ,TRIANGLE); +$x->addMember($x->GetInputName(1),'R_POS', 0 , 0.07 ,0.1 ,RINFINITY); + +/* ---------- set output members ---------*/ +$x->setOutputNames(array('OUT')); + +$x->addMember($x->getOutputName(0),'CF',-1.0, -0.9 ,-0.8 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'CS',-0.6, -0.5 ,-0.4 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'NC',-0.1, 0.0 , 0.1 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'OS', 0.4, 0.5 , 0.6 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'OF', 0.8, 0.9 , 1.0 ,TRIANGLE); +/* ---------- set rule table ------------ */ + +/* ---------- set rule table ------------ */ +/* ---------- set rule table ------------ */ +$x->clearRules(); + +$x->addRule('IF ERROR.E_NEG THEN OUT.CF'); +$x->addRule('IF ERROR.E_OK THEN OUT.NC'); +$x->addRule('IF ERROR.E_POS THEN OUT.OF'); +$x->addRule('IF ERROR.E_OK AND RATE.R_POS THEN OUT.CS'); +$x->addRule('IF ERROR.E_OK AND RATE.R_NEG THEN OUT.OS'); + +$x->setFuzzyTable(array( +// IN(0,0) IN(0,1) OUT(0) +// ------ ------- ------- + array('E_NEG', NULL , 'CF'), + array('E_OK' , NULL , 'NC'), + array('E_POS', NULL , 'OF'), + array('E_OK' , 'R_POS', 'CS'), + array('E_OK' , 'R_NEG', 'OS') +)); + + +/*------------ Tank parameters----------------*/ +$Theight = 1.0 ; // tank max level +$TEmergencyRange = array(0.1,0.1,0.1,0.1); +$Tinit = 0.1 ; // tank init +$IitA = 0.1 ; +$IitB = 0.1 ; +$IitC = 0.1 ; +$IitD = 0.1 ; +$InputValve = 1.0 ; +$Tdemand = 0.7 ; // tank demand level +$Toverflow = 0.9 ; // tank overflow signal + + +/*------------- Valve parameters -------------*/ +$Tout_stream = 0.03 ; // output stream by time period +$Vinp_max = 0.05 ; // max input stream for power valve +/*-------------- Initialise ------------------*/ +$Level = $Tinit; +$LastLevel = $Level; +$elevel = $Tinit; +$erate = 0; +$Vinput = 0; +$Valve = 0; +$Fuzzy = 0; +$WaterInput = 0; +echo "
\n";
+echo "This is a simulation of fuzzy-logic controller. The controller controls the desired level of water in the tank. 
+ The controller closes the water inlet valve so as to offset the amount of water flowing from the water flowing. 
+ Parameters
+ ------------
+ Valve adjustment range 0 to 1 
+ The amount of water input flowing per unit time: $Vinp_max
+ The amount of water output flowing per unit time: $Tout_stream
+ Startup water level: $Tinit  
+ Desired level of water: $Tdemand 
+ ------------
+ Plot Values: 
+ ------------
+ L - current level 
+ V - the level of the valve opening 
+ F - error output controller 
+ -------------- 
+";
+/* ----------- Controll Loop ----------------*/
+for ($i=1;$i<=80;$i++) {
+//if ($i>40) $Tout_stream = 0.0;
+
+
+//if ($i>40) $WaterInput = 0;
+list($erate,$elevel) = getLastErrors($Tdemand,$Level,$LastLevel);
+
+$x->SetRealInput('ERROR',	$elevel	);
+$x->SetRealInput('RATE' ,	$erate	);
+
+//$fuzzy_arr = $x->calcFuzzyAlt();
+//
+//$Fuzzy = $fuzzy_arr[0];
+$fuzzy_arr = $x->calcFuzzy();
+
+$Fuzzy = $fuzzy_arr['OUT'];
+
+//print_r($fuzzy_arr);
+$LastLevel = $Level;
+$Level = $Level - $Tout_stream + $WaterInput;
+list($Valve,$WaterInput) = getValve($Fuzzy,$Valve,$Vinp_max,0,1);
+
+$dotline = str_repeat('.',100);
+$dotline[round($Level*99)]='#';
+echo $dotline,sprintf("L:%1.3f F:%1.3f V:%1.3f",$Level,$Fuzzy,$Valve),"\n";
+}
+print_r($x->StateOutput);
+echo "
\n"; + +/*---- required additional function ------------*/ +function getValve($Fuzzy,$Valve,$inpMax,$lb,$ub) { + $xdot = $Valve+$Fuzzy; + if ($xdot<=$lb) $Valve = $lb; + elseif ($xdot>=$ub) $Valve = $ub; + else $Valve=min(max($xdot,$lb),$ub); +return array($Valve,$Valve * $inpMax); +} + +function getLastErrors($demandLevel,$currentLevel,$lastLevel) { + $erate = $currentLevel-$lastLevel; + if ($erate < -0.1) $erate =-0.1; + if ($erate > 0.1) $erate = 0.1; + $elevel = $demandLevel-$currentLevel ; +return array($erate,$elevel); +} +?> \ No newline at end of file diff --git a/demo/fuzzy-logic-x-ajax-tank.php b/demo/fuzzy-logic-x-ajax-tank.php new file mode 100644 index 0000000..0c74351 --- /dev/null +++ b/demo/fuzzy-logic-x-ajax-tank.php @@ -0,0 +1,699 @@ +=$ub) $Valve = $ub; + else $Valve=min(max($xdot,$lb),$ub); +return array($Valve,$Valve * $inpMax); +} + +function getLastErrors($demandLevel,$currentLevel,$lastLevel) { + $erate = $currentLevel-$lastLevel; + if ($erate < -0.1) $erate =-0.1; + if ($erate > 0.1) $erate = 0.1; + $elevel = $demandLevel-$currentLevel ; +return array($erate,$elevel); +} + + +class Member { + + protected + $FName, // Member Name + $FMiddle, // Middle Member point + $FA, // Start Member point + $FB, // End member point + $FType; // Member type TRIANGLE,LINFINITY,RFINFINITY, TRAPEZOID + + public function __construct($Name=NULL,$start=NULL,$medium=NULL,$stop=NULL,$type=NULL){ + if($Name == NULL) return; + $this->FName = $Name; + $this->FMiddle = $medium; + $this->FA = $start; + $this->FB = $stop; + $this->FType = $type; + } + + public function __toString(){ + return "Member\tname: $this->FName, + middle: $this->FMiddle, + start : $this->FA, + fb : $this->FB, + type : $this->FType"; + } + + +/** +* Calculates the ratio of belonging to a set of defined function shape. +* $ratio = Fuzzification($pontX); +* @param float $poinX +* return float +*/ + public function Fuzzification($P=0.0) { + + if (($P<$this->FA) OR ($P>$this->FB)) return 0; //P is out this segment... + + if ($P==$this->FMiddle) return 1; + + if ($this->FType==LINFINITY) { + if ($P<=$this->FMiddle) return 1; + if (($P>$this->FMiddle) AND ($P<$this->FB)) return ($this->FB-$P)/($this->FB-$this->FMiddle); + } + + if ($this->FType==RINFINITY) { + if ($P>=$this->FMiddle) return 1; + if (($P<$this->FMiddle) AND ($P>$this->FA)) return ($P-$this->FA)/($this->FMiddle-$this->FA); + } + + if ($this->FType==TRIANGLE) { + if(($P<$this->FMiddle) AND ($P>$this->FA)) return ($P-$this->FA)/($this->FMiddle-$this->FA); + if(($P>$this->FMiddle) AND ($P<$this->FB)) return ($this->FB-$P)/($this->FB-$this->FMiddle); + } + + if ($this->FType==TRAPEZOID) { + if(($P<$this->FMiddle[0]) AND ($P>$this->FA)) return ($P-$this->FA)/($this->FMiddle[0]-$this->FA); + if(($P>$this->FMiddle[1]) AND ($P<$this->FB)) return ($this->FB-$P)/($this->FB-$this->FMiddle[1]); + if (($P>=$this->FMiddle) and ($P<=$this->FMiddle)) return 1; + } + return 0; +} + +} // class Member + +class Fuzzify extends Member { + + protected $FMin = array(); + protected $FMax = array(); + protected $members = array(); + + public function setMinMax($idx,$A=0,$B=0) { + If ($A<=$B) { + $this->FMin[$idx] = $A; + $this->FMax[$idx] = $B; + } else { + $this->FMin[$idx] = $B; + $this->FMax[$idx] = $A; + } + } + + public function clearMembers() { + $this->members = NULL; + } + + public function addMember($idx,$Name='New',$start=0.0,$medium=0.0,$stop=0.0,$type=TRIANGLE) { + $member = new Member($Name,$start,$medium,$stop,$type); + if ($member->FA < (float)$this->FMin[$idx]) $this->setMinMax($idx, $member->FA ,(float)$this->FMax[$idx]); + if ($member->FB > (float)$this->FMax[$idx]) $this->setMinMax($idx , (float)$this->FMin[$idx] , $member->FB); + $this->members[$idx][] = $member; + } + + public function setMembers($idx,$m = array()) { + $this->members[$idx] = $m; + } + + public function getMembers($idx,$id = NULL) { + if ($id) return $this->members[$idx][$id]; + else return $this->members[$idx]; + } + + public function getMembersIndex($idx,$value = NULL) { + foreach ($this->members[$idx] as $idx => $member) + if ($value==$member->FName) return $idx; + return FALSE; + } + + public function getMemberByName($idx,$name = NULL) { + foreach ($this->members[$idx] as $idx => $member) + if ($name==$member->FName) return $member; + return FALSE; + } + + } // end class fuzzify + +class Rules extends Fuzzify{ + + public $FXValues = array(); + public $FYValues = array(); + public $FRealInput = array(); + public $FOutputs = array(); + + private $InputNames = NULL; + private $OutputNames = NULL; + private $rules = NULL; + +/** +* Set private properties $this->InputNames +* example : +* $fuzzy->setInputNames(array('Name1','Name2')); +* @param array of string +* return none +**/ + + public function setInputNames($val) { + $this->InputNames = $val; + } + +/** +* Set private properties $this->OutputNames +* example : +* $fuzzy->setOutputNames(array('Name1','Name2')); +* @param array of string +* return none +**/ + + public function setOutputNames($val) { + $this->OutputNames = $val; + } + +/** +* Return private properties $this->InputNames +* example : +* $names = $fuzzy->getInputNames(); +* @param none +* return array of string +**/ + + public function getInputNames() { + return $this->InputNames; + } + +/** +* Return private properties $this->OutputNames +* example : +* $names = $fuzzy->getOututNames(); +* @param none +* return array of string +**/ + + public function getOutputNames() { + return $this->OutputNames; + } + +/** +* Return private properties $this->InputNames[$idx] +* example : +* $names = $fuzzy->getInputNames($idx); +* @param none +* return string +**/ + + public function getInputName($idx) { + return $this->InputNames[$idx]; + } + +/** +* Return private properties $this->OutputNames[$idx] +* example : +* $names = $fuzzy->getOutputNames($idx); +* @param none +* return string +**/ + + public function getOutputName($idx=0) { + return $this->OutputNames[$idx]; + } + +/** +* Clear all rules +* example : +* $fuzzy->clearRules(); +* @param none +* return none +**/ + + public function clearRules() { + $this->rules = NULL; + } + +/** +* Return array as Rules +* example : +* $fuzzy->getRules(); +* @param none +* return array of string +**/ + + public function getRules() { + return $this->rules; + } + +/** +* Return Rule as String +* example : +* $fuzzy->getRule($id); +* @param integer $id (key) +* return string +**/ + + public function getRule($id) { + return $this->rules[$id]; + } + +/** +* Add Rule as String to private properties Rules Array +* example : +* $fuzzy->addRule('IF input1.High AND input2.Slow Then Out1.Run'); +* @param string +* return none +**/ + + public function addRule($val) { + $this->rules[] = $val; + } + +/** +* Find parenthis fragments of Rule as string +* example : +* $fragment = $this->rSplit('IF input1.High AND (input2.Slow OR input3.Fast) Then Out1.Run'); +* @param string +* return string 'input2.Slow OR input3.Fast' +**/ + + private function rSplit($string) { + if (preg_match("/\((([^()]*|(?R))*)\)/",$string,$matches)) + return $matches[1]; + } +/** +* Get last nested parenthis fragments of Rule as string +* example : +* $fragment = $this->getLastParent('IF input1.High AND (input2.Slow OR (input3.Fast AND input4.Warm)) Then Out1.Run'); +* @param string +* return string 'input3.Fast AND input4.Warm' +**/ + private function getLastParent($a) { + do { + $a = $this->rSplit($a); + if ($a) $ret=$a; + } while($a); + return $ret; + } + +/** +* Fuzzy Logic OR operation on array of values +* example : +* $val = $this->_FuzzyOR(array(1,0.5)); +* @param array float values +* return float (max value) = 0.5 +**/ + + private function _FuzzyOR($arr) { + return (max($arr)); + } + +/** +* Fuzzy Logic OR operation on array of values +* example : +* $val = $this->rSplit(array(1,0.5)); +* @param array float values +* return float (min value) = 1 +**/ + private function _FuzzyAND($arr) { + return (min($arr)); + } + +/** +* Calculate Rule.Parser And Interpreter for Rule. +* Rule has text line example: +* IF input1.High AND input2.Slow Then Out1.Run +* Where +* Operator : IF +* Argument Input 1 : input1.High +* where InputName = input1 +* DotSeparator = . +* MemberName = Run +* Operator : AND Operation for Arg1 , Arg 2 values +* Argument Input 2 : input2.Slow +* where InputName = input2 +* DotSeparator = . +* MemberName = Slow +* Operator : Then +* Argument Output 1 : Out1.Run (InputName,DotSeparator,MemberName) +* +* +* example : +* $val = $fuzzy->processRule('IF input1.High AND input2.Slow Then Out1.Run'); +* @param string Rule +* return float (calculated fuzzy value as Rule cryteria) +**/ + + public function processRule($rule) { + while ($in_parent = $this->getLastParent($rule)) { + $pos=strpos($rule,$in_parent); + $len=strlen($in_parent); + $tmparr=array(); + $items=preg_split("/\s+/",$in_parent); + $operation='and'; + foreach($items as $item) { + $inp=strtolower($item); + if (($inp=='or') or ($inp=='and')) $operation=$inp; else { + list($inputName,$memberName) = preg_split("/\./",$item); + // get value from + $mem_idx = $this->getMembersIndex($inputName,$memberName); + $tmparr[] =$this->FOutputs[$inputName][$mem_idx]; + } + } + $value1 = ($operation == 'or') ? $this->_FuzzyOR($tmparr) : $this->_FuzzyAND($tmparr); + $rule=substr($rule,0,$pos-1).$value1.substr($rule,$pos+$len+1); + } + + $items=preg_split("/\s+/",$rule); + $operation='and'; + $firstop = array_shift($items); + $outitem = array_pop($items); + $tmparr=array(); + foreach($items as $item) { + $inp=strtolower($item); + if (($inp=='or') or ($inp=='and')) $operation=$inp; + elseif (($inp=='then') or ($inp=='for')) continue; + else { + // split names + list($inputName,$memberName) = preg_split("/\./",$item); + // get value from FOutputs + $mem_idx = $this->getMembersIndex($inputName,$memberName); + $tmparr[] =$this->FOutputs[$inputName][$mem_idx]; + } + } + + $value1 = ($operation == 'or') ? $this->_FuzzyOR($tmparr) : $this->_FuzzyAND($tmparr); + return array($outitem,$value1); + } + +} //class Rules + +class Fuzzy_Logic extends Rules { + + protected $FuzzyTable = NULL; + public $StateOutput = array(); + protected $AgregatePoints = 100; +/* +* Clear all solutions arrays in class and next calculations is Ready +* example : +* $this->ClearSolution(); +* @param none +* return none +*/ + private function ClearSolution() { + $this->FXValues = array(); + $this->FYValues = array(); + } + +/* +* Set protected properties FuzzyTable +* example : +* $x->setFuzzyTable(array( +* // IF input1 AND input2 Then Output +* // For OR use pair input1 , NULL +* // NULL , input 2 +* // ------ ------- ------- +* array('adequate', NULL , 'low'), +* array(NULL , 'small' , 'low'), +* array('marginal', 'large' , 'normal'), +* array('inadequate' , NULL , 'high'), +* )); +* @param array +* return none +*/ + + + public function SetFuzzyTable($A = array()) { + $this->FuzzyTable = $A; + } + +/* +* Set Real Input Value =$X for Input named $idx +* example : +* $fuzzy->SetRealInput('input1',0.23); +* @param string $idx +* @param float $X +* return none +*/ + + public function SetRealInput($idx,$X = 0.0) { + $this->FRealInput[$idx] = $X; + $this->FOutputs[$idx] = array(); + For ($i=0;$imembers[$idx]);$i++) { + $this->FOutputs[$idx][] = $this->members[$idx][$i]->Fuzzification($this->FRealInput[$idx]); + } + } + +/* +* Agregate All Rules Result for Defuzification +* example : +* $fuzzy->FuzzyAgregate($outname,$Member,$AlphaCut=0.0) +* @param string $output_name +* @param object $member_object +* @param float $calculate_rule_value +* return none +*/ + + public function FuzzyAgregate($outname,$Member,$AlphaCut=0.0) { + foreach($this->FXValues[$outname] as $index=>$pointX) { + if ($pointX<$Member->FA) continue; + if ($pointX>$Member->FB) break; + $ms = $Member->Fuzzification($pointX); + $mem_val = min($ms,$AlphaCut); + $this->FYValues[$outname][$index] = max($this->FYValues[$outname][$index],$mem_val); + } + } + +/* +* Calculate Defuzification Fuzzy Result for method AVG (required set FuzzyTable) +* example : +* $fuzzy->calcFuzzy() +* @param none +* return array of outputs values (no associated keys) +*/ + + public function calcFuzzyAlt() { + $MaxAverage = 0; + $this->ClearSolution(); + //$count_inputs = count($this->InputNames); + $sum = 0; + $tmpx=array(); + $sum = array(); + $cnt = array(); + // fill output agregate table + foreach($this->getOutputNames() as $outname) { + $AgregateDeltaX = ($this->FMax[$outname]-$this->FMin[$outname])/$this->AgregatePoints; + $this->FXValues[$outname] = Range($this->FMin[$outname],$this->FMax[$outname],$AgregateDeltaX); + $this->FYValues[$outname] = array_fill ( 0 , count($this->FXValues[$outname]), 0.0 ); + } + + foreach ($this->FuzzyTable as $row_idx => $line_rule) { + $sum = 0.0; + $cnt = 0.0; + $count_inputs = count($line_rule)-1; // last is output + foreach ($line_rule as $col => $member_name) { + $out_idx =$col - $count_inputs; + $outname = $this->getOutputName($out_idx); + if (!is_null($member_name)) { + + if ($col<$count_inputs) { // is input + $inp_name = $this->getInputName($col); + $mem_idx = $this->getMembersIndex($inp_name,$member_name); + $val =$this->FOutputs[$inp_name][$mem_idx]; // get members value + if ($val>0) { + $sum+=$val; // sum members values + $cnt++; + } else { + //$sum=0; + //$cnt=0; + break; + } + } else { //is output + + $member=$this->getMemberByName($outname,$member_name); // get OUTPUT member + if ($cnt == 0) $avg_sum = 0; else $avg_sum = $sum/$cnt; + $this->StateOutput[$member_name] = $avg_sum; + if ($avg_sum>0) $this->FuzzyAgregate($outname,$member,$avg_sum); + $sum = 0.0; + $cnt = 0.0; + } + } // if $member_name + } // foreach rule + } // foreach rule_row + + $result = array(); + + foreach($this->getOutputNames() as $outname) { + $suma=0.0; + $sumb=0.0; + + foreach($this->FXValues[$outname] as $id=>$x) { + $y=$this->FYValues[$outname][$id]; + if ($y>0) { + $suma+=($x*$y); + $sumb+=$y; + } + } + if ($sumb == 0) $result[]= 0; else $result[] = $suma/$sumb; + } + return $result; +} + +/* +* Calculate Defuzification Fuzzy Result for method MIN,MAX (required set Rules) +* example : +* $fuzzy->calcFuzzyAlt() +* @param none +* return array of outputs values (associated keys) +*/ + + public function calcFuzzy() { + $this->ClearSolution(); + + $sum = 0; + $tmpx=array(); + $sum = array(); + $cnt = array(); + // fill output agregate table + foreach($this->getOutputNames() as $outname) { + $AgregateDeltaX = ($this->FMax[$outname]-$this->FMin[$outname])/$this->AgregatePoints; + $this->FXValues[$outname] = Range($this->FMin[$outname],$this->FMax[$outname],$AgregateDeltaX); + $this->FYValues[$outname] = array_fill ( 0 , count($this->FXValues[$outname]), 0.0 ); + } + + $rules=$this->getRules(); + foreach ($rules as $key=>$rule) { + list($outItem,$value) = $this->processRule($rule); + list($outputName,$memberName) = preg_split("/\./",$outItem); + $this->StateOutput[$memberName] = $value; + $member=$this->getMemberByName($outputName,$memberName); // get OUTPUT member + if ($value>0) $this->FuzzyAgregate($outputName,$member,$value); + } + + $result = array(); + + foreach($this->getOutputNames() as $outname) { + $suma=0.0; + $sumb=0.0; + + foreach($this->FXValues[$outname] as $id=>$x) { + $y=$this->FYValues[$outname][$id]; + if ($y>0) { + $suma+=($x*$y); + $sumb+=$y; + } + } + if ($sumb == 0) $result[$outname]= 0; else $result[$outname] = $suma/$sumb; + } + return $result; +} + +} //class + + + +/*--------------------------- start tank demo controll --------*/ +$x = new Fuzzy_Logic(); + +$x->clearMembers(); +/* ---------- set input members ---------*/ +$x->setInputNames(array('ERROR','RATE')); + +$x->addMember($x->getInputName(0),'E_NEG',-1 ,-0.9 , 0 ,LINFINITY); +$x->addMember($x->getInputName(0),'E_OK' ,-0.1 , 0 , 0.1,TRIANGLE); +$x->addMember($x->getInputName(0),'E_POS', 0 , 0.9 , 1 ,RINFINITY); + +$x->addMember($x->getInputName(1),'R_NEG',-0.10,-0.07 ,0 ,LINFINITY); +$x->addMember($x->getInputName(1),'R_OK', -0.07, 0 ,0.07 ,TRIANGLE); +$x->addMember($x->getInputName(1),'R_POS', 0 , 0.07 ,0.1 ,RINFINITY); + +/* ---------- set output members ---------*/ +$x->setOutputNames(array('OUT')); + +$x->addMember($x->getOutputName(0),'CF',-1.0, -0.9 ,-0.8 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'CS',-0.6, -0.5 ,-0.4 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'NC',-0.1, 0.0 , 0.1 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'OS', 0.4, 0.5 , 0.6 ,TRIANGLE); +$x->addMember($x->getOutputName(0),'OF', 0.8, 0.9 , 1.0 ,TRIANGLE); + + +/* ---------- set rules table ------------ */ +$x->clearRules(); + +$x->addRule('IF ERROR.E_NEG THEN OUT.CF'); +$x->addRule('IF ERROR.E_OK THEN OUT.NC'); +$x->addRule('IF ERROR.E_POS THEN OUT.OF'); +$x->addRule('IF ERROR.E_OK AND RATE.R_POS THEN OUT.CS'); +$x->addRule('IF ERROR.E_OK AND RATE.R_NEG THEN OUT.OS'); + +/*------------ Remote parameters----------------*/ + + +$get = $_GET['table']; + +$tankLevel = $get["currTanksLevel"]; +$tankLastLevel = $get["lastTanksLevel"]; +$tankValve = $get["valveTanksInput"]; + +$set = $_GET['setmode']; + +$InputMaxValve = $set["mainInput"]; +$OutputXMaxValve = $set["mainOutputX"]; +$OutputYMaxValve = $set["mainOutputY"]; +$tankDemandLevel = $set["demandTanksLevel"]; +$tankInpMax = $set["remoteTanksInput"]; +$tankOutMax = $set["remoteTanksOutput"]; +$tankMaxWorkLevel = $set["tankMaxWorkLevel"]; +$tankMinWorkLevel = $set["tankMinWorkLevel"]; + + +/*------------- Valve parameters -------------*/ +$ToutX_stream = 0.02 ; // output stream by time period +$ToutY_stream = 0.03 ; // output stream by time period +$Tinp_stream = 0.07 ; +/*-------------- Initialise ------------------*/ + +$tankName = array('A', 'B', 'C', 'D', 'E', 'X' , 'Y' ); +$tankInputRefKey = array(-1 , 0 , 1 , 2 , 3 , 4 , 3 ); +$tankOutputRefKey = array(0 , 1 , 2 , 3 , 4 , -1 , 4 ); + +$tankMaxLevel = array(1.0,1.0,1.0,1.0,1.0,1.0,1.0); +$tankInpDT = array(0.07,0.07,0.07,0.07,0.07,0.07,0.07); +$tankOutDT = array(0.05,0.05,0.05,0.05,0.05,0.05,0.05); +$tankFuzzy = array(0.0,0.0,0.0,0.0,0.0,0.0,0.0); + +/* ----------- Fuzzy Controll Loop ----------------*/ + for($tank=0;$tank<7;$tank++) { + $name=$tankName[$tank]; + list($erate,$elevel) = getLastErrors($tankDemandLevel[$tank],$tankLevel[$tank],$tankLastLevel[$tank]); + $x->SetRealInput('ERROR', $elevel ); + $x->SetRealInput('RATE' , $erate ); + $fuzzy_arr = $x->calcFuzzy(); + $tankFuzzy[$tank] = $fuzzy_arr['OUT']; + $tankLastLevel[$tank] = $tankLevel[$tank]; + $key_input_ref = $tankInputRefKey[$tank]; + if($key_input_ref>=0) + $Vinp_max = $tankInpMax[$tank]*$tankInpDT[$tank]*(int)(($tankLevel[$tank]<=$tankMaxWorkLevel[$tank]) and ($tankLevel[$key_input_ref]>$tankMinWorkLevel[$key_input_ref])); + else + $Vinp_max = $InputMaxValve*$Tinp_stream *(int)($tankLevel[$tank]<$tankMaxWorkLevel[$tank]); + + list($tankValve[$tank],$WaterInput) = getValve($tankFuzzy[$tank],$tankValve[$tank],$Vinp_max,0,1); + + $key_output_ref = $tankOutputRefKey[$tank]; + + if($key_output_ref>=0) + $VOut_max = $tankOutMax[$tank]*$tankOutDT[$tank]*(int)($tankLevel[$key_output_ref]>$tankMinWorkLevel[$key_output_ref]); + else //-1 + $VOut_max = $OutputXMaxValve*$ToutX_stream*(int)($tankLevel[$tank]>$tankMinWorkLevel[$tank]); + + $tankLevel[$tank] = min($tankMaxLevel[$tank],$tankLevel[$tank] - $VOut_max + $WaterInput); + } + + +$out =array( +"currTanksLevel" => $tankLevel , +"lastTanksLevel" => $tankLastLevel , +"valveTanksInput" => $tankValve ); + +echo json_encode($out); + +?> \ No newline at end of file diff --git a/demo/hydro9x.svg b/demo/hydro9x.svg new file mode 100644 index 0000000..e52687b --- /dev/null +++ b/demo/hydro9x.svg @@ -0,0 +1,3068 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + CASCADE AERATOR + STILLINGCHAMBER + PARSHALFLUME + FLASHMIXER + CLARIFIERFLOCULATOR + VALVE PIT + GRAVITY FILTER + CHLORINATINGSYSTEM + FILTERED WATER RESERVOIR + PUMP HOUSE II + PUMP HOUSE I + A + B + C + D + E + X + Y + F + G + + + + + + + + + + + + + + + + + + + + + + + + + + + 100% + 40% + 50% + 70% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + zawór kanalowy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/hydrodemo_x_ajax.html b/demo/hydrodemo_x_ajax.html new file mode 100644 index 0000000..c688ded --- /dev/null +++ b/demo/hydrodemo_x_ajax.html @@ -0,0 +1,124 @@ + + + + + +Hydro Demo + + + + + + + + + + + + + + + + + +
+ +
+
Valves(inp)
+

A

+
+

B

+
+

C

+
+

D

+
+

E

+
+

X

+
+

Y

+
+
+
+
+ +
+
+ +
+
Water supply100
+
Industrial consumption50
+
Municipal consumption50
+
Desired tank(Y) level85
+
+
+
+
+
+
+
+
(c) wojtek jarzęcki 2011
+ + +