| /* For copyright information, see olden_v1.0/COPYRIGHT */ |
| |
| /* compute.c |
| * |
| * By: Martin C. Carlisle |
| * 6/15/94 |
| * |
| * Implements computation phase of the Power Pricing problem |
| * based on code by: Steve Lumetta, Sherry Li, and Ismail Khalil |
| * University of California at Berkeley |
| * |
| */ |
| |
| #include "power.h" |
| |
| /*----------------------------------------------------------------------*/ |
| /* Leaf optimization 'global' variables */ |
| |
| static double P=1.0; |
| static double Q=1.0; |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* Leaf optimization procedures */ |
| |
| void optimize_node (double pi_R, double pi_I); |
| double find_g (); |
| double find_h (); |
| double find_gradient_f (double pi_R, double pi_I, double* gradient); |
| double find_gradient_g (double* gradient); |
| double find_gradient_h (double* gradient); |
| void find_dd_grad_f (double pi_R, double pi_I, double* dd_grad); |
| double make_orthogonal (double* v_mod, double* v_static); |
| |
| |
| void Compute_Tree(Root r) { |
| int i; |
| Lateral l; |
| Demand a; |
| Demand tmp; |
| double theta_R,theta_I; |
| |
| tmp.P = 0.0; |
| tmp.Q = 0.0; |
| for (i=0; i<NUM_FEEDERS; i++) { |
| l = r->feeders[i]; |
| theta_R = r->theta_R; |
| theta_I = r->theta_I; |
| a = Compute_Lateral(l,theta_R,theta_I,theta_R,theta_I); |
| tmp.P += a.P; |
| tmp.Q += a.Q; |
| } |
| r->D.P = tmp.P; |
| r->D.Q = tmp.Q; |
| } |
| |
| Demand Compute_Lateral(Lateral l, double theta_R, double theta_I, |
| double pi_R, double pi_I) { |
| Demand a1; |
| Demand a2; |
| double new_pi_R, new_pi_I; |
| double a,b,c,root; |
| Lateral next; |
| Branch br; |
| |
| new_pi_R = pi_R + l->alpha*(theta_R+(theta_I*l->X)/l->R); |
| new_pi_I = pi_I + l->beta*(theta_I+(theta_R*l->R)/l->X); |
| |
| next = l->next_lateral; |
| if (next != NULL) |
| a1 = Compute_Lateral(next,theta_R,theta_I,new_pi_R,new_pi_I); |
| |
| br = l->branch; |
| a2 = Compute_Branch(br,theta_R,theta_I,new_pi_R,new_pi_I); |
| |
| if (next != NULL) { |
| l->D.P = a1.P + a2.P; |
| l->D.Q = a1.Q + a2.Q; |
| } else { |
| l->D.P = a2.P; |
| l->D.Q = a2.Q; |
| } |
| |
| /* compute P,Q */ |
| a = l->R*l->R + l->X*l->X; |
| b = 2*l->R*l->X*l->D.Q - 2*l->X*l->X*l->D.P - l->R; |
| c = l->R*l->D.Q - l->X*l->D.P; |
| c = c*c + l->R*l->D.P; |
| root = (-b-sqrt(b*b-4*a*c))/(2*a); |
| l->D.Q = l->D.Q + ((root-l->D.P)*l->X)/l->R; |
| l->D.P = root; |
| |
| /* compute alpha, beta */ |
| a = 2*l->R*l->D.P; |
| b = 2*l->X*l->D.Q; |
| l->alpha = a/(1-a-b); |
| l->beta = b/(1-a-b); |
| return l->D; |
| } |
| |
| Demand Compute_Branch(Branch br, double theta_R, double theta_I, |
| double pi_R, double pi_I) { |
| Demand a2,tmp; |
| double new_pi_R, new_pi_I; |
| double a,b,c,root; |
| Leaf l; |
| Branch next; |
| int i; |
| Demand a1; |
| |
| new_pi_R = pi_R + br->alpha*(theta_R+(theta_I*br->X)/br->R); |
| new_pi_I = pi_I + br->beta*(theta_I+(theta_R*br->R)/br->X); |
| |
| next = br->next_branch; |
| if (next != NULL) { |
| a1 = Compute_Branch(next,theta_R,theta_I,new_pi_R,new_pi_I); |
| } |
| |
| /* Initialize tmp */ |
| tmp.P = 0.0; tmp.Q = 0.0; |
| |
| for (i=0; i<LEAVES_PER_BRANCH; i++) { |
| l = br->leaves[i]; |
| a2 = Compute_Leaf(l,new_pi_R,new_pi_I); |
| tmp.P += a2.P; |
| tmp.Q += a2.Q; |
| } |
| if (next != NULL) { |
| br->D.P = a1.P + tmp.P; |
| br->D.Q = a1.Q + tmp.Q; |
| } else { |
| br->D.P = tmp.P; |
| br->D.Q = tmp.Q; |
| } |
| |
| /* compute P,Q */ |
| a = br->R*br->R + br->X*br->X; |
| b = 2*br->R*br->X*br->D.Q - 2*br->X*br->X*br->D.P - br->R; |
| c = br->R*br->D.Q - br->X*br->D.P; |
| c = c*c + br->R*br->D.P; |
| root = (-b-sqrt(b*b-4*a*c))/(2*a); |
| br->D.Q = br->D.Q + ((root-br->D.P)*br->X)/br->R; |
| br->D.P = root; |
| /* compute alpha, beta */ |
| a = 2*br->R*br->D.P; |
| b = 2*br->X*br->D.Q; |
| br->alpha = a/(1-a-b); |
| br->beta = b/(1-a-b); |
| |
| return br->D; |
| } |
| |
| Demand Compute_Leaf(Leaf l, double pi_R, double pi_I) { |
| P = l->D.P; |
| Q = l->D.Q; |
| |
| optimize_node(pi_R,pi_I); |
| |
| if (P<0.0) { |
| P = 0.0; |
| Q = 0.0; |
| } |
| l->D.P = P; |
| l->D.Q = Q; |
| return l->D; |
| } |
| |
| /*----------------------------------------------------------------------*/ |
| |
| void optimize_node (double pi_R, double pi_I) |
| { |
| double g; |
| double h; |
| |
| double grad_f[2]; |
| double grad_g[2]; |
| double grad_h[2]; |
| double dd_grad_f[2]; |
| double magnitude; |
| |
| int i; |
| double total; |
| double max_dist; |
| |
| do { |
| /* Move onto h=0 line */ |
| h=find_h (); |
| if (fabs (h)>H_EPSILON) { |
| magnitude=find_gradient_h (grad_h); |
| total=h/magnitude; |
| P-=total*grad_h[0]; |
| Q-=total*grad_h[1]; |
| } |
| |
| /* Check that g is still valid */ |
| g=find_g (); |
| if (g>G_EPSILON) { |
| magnitude=find_gradient_g (grad_g); |
| find_gradient_h (grad_h); |
| magnitude*=make_orthogonal (grad_g,grad_h); |
| total=g/magnitude; |
| P-=total*grad_g[0]; |
| Q-=total*grad_g[1]; |
| } |
| |
| /* Maximize benefit */ |
| magnitude=find_gradient_f (pi_R,pi_I,grad_f); |
| find_dd_grad_f (pi_R,pi_I,dd_grad_f); |
| total=0.0; |
| for (i=0; i<2; i++) |
| total+=grad_f[i]*dd_grad_f[i]; |
| magnitude/=fabs (total); |
| find_gradient_h (grad_h); |
| magnitude*=make_orthogonal (grad_f,grad_h); |
| find_gradient_g (grad_g); |
| total=0.0; |
| for (i=0; i<2; i++) |
| total+=grad_f[i]*grad_g[i]; |
| if (total>0) { |
| max_dist=-find_g ()/total; |
| if (magnitude>max_dist) |
| magnitude=max_dist; |
| } |
| P+=magnitude*grad_f[0]; |
| Q+=magnitude*grad_f[1]; |
| |
| h=find_h (); |
| g=find_g (); |
| find_gradient_f (pi_R,pi_I,grad_f); |
| find_gradient_h (grad_h); |
| |
| } while (fabs (h)>H_EPSILON || g>G_EPSILON || |
| (fabs (g)>G_EPSILON && |
| fabs (grad_f[0]*grad_h[1]-grad_f[1]*grad_h[0])>F_EPSILON)); |
| } |
| |
| double find_g () |
| { |
| return (P*P+Q*Q-0.8); |
| } |
| |
| double find_h () |
| { |
| return (P-5*Q); |
| } |
| |
| double find_gradient_f (double pi_R, double pi_I, double* gradient) |
| { |
| int i; |
| double magnitude=0.0; |
| |
| gradient[0]=1/(1+P)-pi_R; |
| gradient[1]=1/(1+Q)-pi_I; |
| for (i=0; i<2; i++) |
| magnitude+=gradient[i]*gradient[i]; |
| magnitude=sqrt (magnitude); |
| for (i=0; i<2; i++) |
| gradient[i]/=magnitude; |
| |
| return magnitude; |
| } |
| |
| double find_gradient_g (double* gradient) |
| { |
| int i; |
| double magnitude=0.0; |
| |
| gradient[0]=2*P; |
| gradient[1]=2*Q; |
| for (i=0; i<2; i++) |
| magnitude+=gradient[i]*gradient[i]; |
| magnitude=sqrt (magnitude); |
| for (i=0; i<2; i++) |
| gradient[i]/=magnitude; |
| |
| return magnitude; |
| } |
| |
| double find_gradient_h (double* gradient) |
| { |
| int i; |
| double magnitude=0.0; |
| |
| gradient[0]=1.0; |
| gradient[1]=-5.0; |
| for (i=0; i<2; i++) |
| magnitude+=gradient[i]*gradient[i]; |
| magnitude=sqrt (magnitude); |
| for (i=0; i<2; i++) |
| gradient[i]/=magnitude; |
| |
| return magnitude; |
| } |
| |
| void find_dd_grad_f (double pi_R, double pi_I, double* dd_grad) |
| { |
| double P_plus_1_inv=1/(P+1); |
| double Q_plus_1_inv=1/(Q+1); |
| double P_grad_term=P_plus_1_inv-pi_R; |
| double Q_grad_term=Q_plus_1_inv-pi_I; |
| double grad_mag; |
| |
| grad_mag=sqrt (P_grad_term*P_grad_term+Q_grad_term*Q_grad_term); |
| |
| dd_grad[0]=-P_plus_1_inv*P_plus_1_inv*P_grad_term/grad_mag; |
| dd_grad[1]=-Q_plus_1_inv*Q_plus_1_inv*Q_grad_term/grad_mag; |
| } |
| |
| double make_orthogonal (double* v_mod, double* v_static) |
| { |
| int i; |
| double total=0.0; |
| double length=0.0; |
| |
| for (i=0; i<2; i++) |
| total+=v_mod[i]*v_static[i]; |
| for (i=0; i<2; i++) { |
| v_mod[i]-=total*v_static[i]; |
| length+=v_mod[i]*v_mod[i]; |
| } |
| length=sqrt (length); |
| for (i=0; i<2; i++) |
| v_mod[i]/=length; |
| |
| if (1-total*total<0) /* Roundoff error--vectors are parallel */ |
| return 0; |
| |
| return sqrt (1-total*total); |
| } |
| |
| /*----------------------------------------------------------------------*/ |