I am trying to port an existing PSPICE model (the HP Memristor Model) to ngspice... is there an absolute value function for ngspice?
Original PSPICE Model:
.SUBCKT modelmemristor plus minus PARAMS: +phio=0.95 Lm=0.0998 w1=0.1261 foff=3.5e-6 +ioff=115e-6 aoff=1.2 fon=40e-6 ion=8.9e-6 +aon=1.8 b=500e-6 wc=107e-3
G1 plus internal value={sgn(V(x))*(1/V(dw))^2*0.0617* (V(phiI)*exp(-V(B)*V(sr))-(V(phiI)+abs(V(x)))* exp(-V(B)*V(sr2)))}
Esr sr 0 value={sqrt(V(phiI))}
Esr2 sr2 0 value={sqrt(V(phiI)+abs(V(x)))} Rs internal minus 215
Eg x 0 value={V(plus)-V(internal)} Elamda Lmda 0 value={Lm/V(w)}
Ew2 w2 0 value={w1+V(w)- (0.9183/(2.85+4*V(Lmda)-2*abs(V(x))))}
EDw dw 0 value={V(w2)-w1}
EB B 0 value={10.246*V(dw)}
ER R 0 value={(V(w2)/w1)*(V(w)-w1)/(V(w)-V(w2))} EphiI phiI 0 value= {phio-abs(V(x))*((w1+V(w2))/(2*V(w)))- 1.15*V(Lmda)*V(w)*log(V(R))/V(dw)}
C1 w 0 1e-9 IC=1.2
R w 0 1e8MEG
Ec c 0 value={abs(V(internal)-V(minus))/215}
Emon1 mon1 0 value={((V(w)-aoff)/wc)-(V(c)/b)} Emon2 mon2 0 value={(aon-V(w))/wc-(V(c)/b)}
Goff 0 w value={foff*sinh(stp(V(x))*V(c)/ioff)* exp(-exp(V(mon1))-V(w)/wc)}
Gon w 0 value={fon*sinh(stp(-V(x))*V(c)/ion)* exp(-exp(V(mon2))-V(w)/wc)}
.ENDS modelmemristor
* test memristor
xmemr 1 0 modelmemristor phio=0.95 Lm=0.0998 w1=0.1261 foff=3.5e-6 ioff=115e-6 aoff=1.2 fon=40e-6 ion=8.9e-6 aon=1.8 b=500e-6 wc=107e-3
.SUBCKT modelmemristor plus minus phio=0.95 Lm=0.0998 w1=0.1261 foff=3.5e-6 ioff=115e-6 aoff=1.2 fon=40e-6 ion=8.9e-6 aon=1.8 b=500e-6 wc=107e-3
G1 plus internal cur={sgn(V(x))*(1/V(dw))^2*0.0617* (V(phiI)*exp(-V(B)*V(sr))-(V(phiI)+abs(V(x)))* exp(-V(B)*V(sr2)))}
Esr sr 0 vol={sqrt(V(phiI))}
Esr2 sr2 0 vol={sqrt(V(phiI)+abs(V(x)))}
Rs internal minus 215
Eg x 0 vol={V(plus)-V(internal)}
Elamda Lmda 0 vol={Lm/V(w)}
Ew2 w2 0 vol={w1+V(w)- (0.9183/(2.85+4*V(Lmda)-2*abs(V(x))))}
EDw dw 0 vol={V(w2)-w1}
EB B 0 vol={10.246*V(dw)}
ER R 0 vol={(V(w2)/w1)*(V(w)-w1)/(V(w)-V(w2))}
EphiI phiI 0 vol= {phio-abs(V(x))*((w1+V(w2))/(2*V(w)))- 1.15*V(Lmda)*V(w)*log(V(R))/V(dw)}
C1 w 0 1e-9 IC=1.2
R w 0 1e8MEG
Ec c 0 vol={abs(V(internal)-V(minus))/215}
Emon1 mon1 0 vol={((V(w)-aoff)/wc)-(V(c)/b)}
Emon2 mon2 0 vol={(aon-V(w))/wc-(V(c)/b)}
Goff 0 w cur={foff*sinh(u(V(x))*V(c)/ioff)* exp(-exp(V(mon1))-V(w)/wc)} $ stp -> u
Gon w 0 cur={fon*sinh(u(-V(x))*V(c)/ion)* exp(-exp(V(mon2))-V(w)/wc)} $ stp -> u
.ENDS modelmemristor
Regards
Holger
Related
I have m input variables I_1, ..., I_m to a decision. Each variable may have n possible values. The decision outcome D is binary.
A decision rule R is a mapping from set D x I_1 x ... x I_m onto the set {0, 1} such that for any (i_1, ..., i_m) in I_1 x ... x I_m it holds that 1 = sum_(d in D) R(d, i_1, ..., i_m). That is: for any combination of input values only one decision is possible.
For example without any input variable you have two decision rules:
D R1 R2
a 0 1
b 1 0
That is the rule R1 selects decision b while R2 selects a.
With one binary input variable I you have four possible decision rules:
I D R1 R2 R3 R4
0 a 0 0 1 1
0 b 1 1 0 0
1 a 0 1 0 1
1 b 1 0 1 0
That is the decision rule R2 selects b if input is 0 and it selects a if input is 1.
With two binary input variables I and K you have 16 possible decision rules
I K D R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
0 0 a 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 b 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
1 0 a 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 0 b 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
0 1 a 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 b 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 a 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 b 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
My question how can I enumerate all possible decision rules for an arbitrary set of input variables?
Disclaimer: This is part of a homework. However the homework is restricted to the case with one binary input variable such that one can simply enumerate all four cases. I passed this part of my homework - actually an enumeration is not necessary at all - but I am interested in a general solution in matlab.
How can I enumerate all possible decision rules for an
arbitrary set of input variables?
First by analyzing and understanding the repetitive patterns that are visible when we write down the binary permutations of the decision rules (R), based on the number (n) of input variables (V). And then building a set functions that generate these permutations automatically and display a table with the results like you would do it by hand.
In terms of code, there are many different valid approaches to solve this problem, but from my point of view, I think that working with a matrix of logicals is a good way to do it. I will call this matrix (M). This matrix has three parts (like the tables in your description):
Left: n columns for the input variables (V)
Center: 1 column for the decision (D)
Right: 2^(2^n) columns for the decision rules (R)
And since your problem has two decisions (A and B), we can treate them as logical values too:
A = 0
B = 1
Note: I chose this values for A and B, and not the opposite ones, because it allows us to generate the binary permutations (which I will call "states") of the input variables (V) and the decision (D) using natural binary count.
For n = 0, M looks like:
0 0 1
1 1 0
For n = 1, M looks like:
0 0 0 0 1 1
0 1 1 1 0 0
1 0 0 1 0 1
1 1 1 0 1 0
For n = 2, M looks like:
0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
1 0 0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
And the size of M grows up pretty quickly as you mentioned:
Rows ("states") grow at a rate of 2^(n + 1)
Columns grow at a rate of (n + 1) + 2^(2^n): n columns for input variables + 1 column for decision (D) + 2^(2^n) columns for decision rules (R).
From the previous matrices we can hardly tell apart any repetitive patterns, but if we use colors we can clearly see some patterns in the decision rules (R) region:
For n = 0:
For n = 1:
For n = 2:
We can see that there are row-wise copies of the same "unit pattern" (boxed digits). Each "unit pattern" is 2 rows wide and 2^(2^n)/k columns wide (where k is the number of repetitions of a pattern for every two rows). The first pattern in M is always a single copy (k = 1), and k duplicates every 2 rows.
We will use all this information to create a set of functions that will allow us to enumerate all the possible decision rules through the use of a table that I will call (T).
I wrote a function called CalcParams which calculates all the necessary parameters of the problem (such as number of rows and columns of M, etc.) based on n:
function[a, b, c, d, e] = CalcParams(n)
% Calculate necessary parameters.
% Inputs:
% n - number of input variables.
% Number of states (rows).
a = 2^(n + 1);
% Number of decision rules (R) (decision rules columns).
b = 2^(2^n);
% Column index of first decision rule (R1).
c = n + 2;
% Number of columns of input variables (V) and decision (D).
d = n + 1;
% Total number of columns.
e = d + b;
end
Then I wrote a function called ValidDecRules which given n and M, checks if the input decision rules meet the requirement:
For any combination of input variables only one decision is possible.
If the decision rules meet the requirement the function returns 1 and displays the message VALID decision rules, otherwise the function returns 0 and displays the message INVALID decision rules.
function[val] = ValidDecRules(n, M)
% This function checks if the input decision rules meet the requirement:
% For any combination of input variables only one decision is possible.
% Inputs:
% n - number of input variables.
% M - binary matrix.
% Calculate necessary parameters.
[~, ~, c, ~, e] = CalcParams(n);
% Invalid decision rules by default.
val = 0;
% Extract odd rows from decision rules (R).
M_odd = M(1:2:end, c:e);
% Extract even rows from decision rules (R).
M_even = M(2:2:end, c:e);
% Check that all elements of the odd rows are different than the elements
% of the even rows.
if(all(all(M_odd ~= M_even, 1), 2))
% Valid decision rules.
val = 1;
disp('VALID decision rules');
else
% Invalid decision rules.
disp('INVALID decision rules');
end
end
Then I wrote a function called GenM which generates the binary matrix M based on n, and if you use the optional argument 'plot' it will plot the decision rules of M using imagesc.
function[M] = GenM(n, varargin)
% This function generates the binary matrix M.
% Inputs:
% n - number of input variables.
% Options:
% 'plot' - plot decision rules of M.
% Calculate necessary parameters.
[a, b, c, d, e] = CalcParams(n);
% Anonymous functions.
f1 = #(v, k) uint8(repmat(v, 1, k));
f2 = #(v, k) f1([v; ~v], k);
f3 = #(b, k) f2([false(1, b/(2*k)), ~false(1, b/(2*k))], k);
% Binary permutations of input variables (V) and decision (D).
Dec = 0:a-1; % Array: decimal representation of every state.
Bin = dec2bin(Dec); % Array: binary representation of every state.
% Preallocate matrix M.
M(length(Bin), d) = 0;
% Loop: input variables (V) and decision (D).
% Writes binary states in matrix M.
for i = 1:d
M(:, i) = uint8(str2num(Bin(:, i)));
end
% Loop: decision rules.
% Writes binary permutations of decision rules (R) in matrix (M).
% Start with k = 1.
k = 1;
for i = 1:2:a
M(i:(i + 1), c:e) = f3(b, k);
k = k*2;
end
% Continue only if decision rules (R) are valid.
if(ValidDecRules(n, M))
% Plot decision rules if 'plot' option is used.
if(~isempty(varargin))
if(any(strcmp(varargin, 'plot')))
% Visualize decision rules as image.
imagesc(M(:, c:e));
title('Decision Rules (R)');
colormap summer;
axis off;
end
end
else
% If decision rules are invalid, return empty output.
M = [];
end
end
Finally I wrote a function called EnumDecRules which takes n and generates a table T very similar to the ones on the description of your question. The function also returns the binary matrix M that was used to generate T. And if you use the 'plot' optional argument, it will plot the decision rules of M (like the GenM function).
The EnumDecRules function is the one that really answers your question because it has the behaviour that you are asking for.
function[T, M] = EnumDecRules(n, varargin)
% This function generates the table (T) with the results and also returns
% the binary matrix M that was used to generate T.
% Inputs:
% n - number of input variables.
% Options:
% 'plot' - plot decision rules of M.
% Calculate necessary parameters.
[a, ~, ~, d, e] = CalcParams(n);
% Generate the binary matrix M.
M = GenM(n, varargin{:});
if(~isempty(M))
% Loop: variable names to diplay in table header.
% Initialize indexes for numbering.
Vi = 1; % Input variable numbering index.
Ri = 1; % Decision rules numbering index.
for i = 1:e
if i <= n
% Input variables.
% Write V[Vi].
Names{i} = ['V', sprintf('%d', Vi)];
% Increase index.
Vi = Vi + 1;
elseif i == d
% Decision.
% Write D.
Names{i} = 'D';
elseif i > d
% Decision rules.
% Write R[Ri].
Names{i} = ['R', sprintf('%d', Ri)];
% Increase index.
Ri = Ri + 1;
end
end
% Generate table with results.
T = array2table(M, ...
'VariableNames', Names);
% Modify decision column (D) of table.
% Replace 0 with 'A'.
% Replace 1 with 'B'.
T.D = repmat({'A'; 'B'}, a/2, 1);
else
% If M is empty, return empty output.
T = [];
end
end
Usage example:
Make sure you save all the functions correctly in the same directory.
Example 1:
Call the EnumDecRules function to enumerate all possible decisions rules for n = 1:
[T, M] = EnumDecRules(1)
These are the outputs:
VALID decision rules
T =
V1 D R1 R2 R3 R4
__ ___ __ __ __ __
0 'A' 0 0 1 1
0 'B' 1 1 0 0
1 'A' 0 1 0 1
1 'B' 1 0 1 0
M =
0 0 0 0 1 1
0 1 1 1 0 0
1 0 0 1 0 1
1 1 1 0 1 0
Example 2:
Call the EnumDecRules function to enumerate all possible decisions rules for n = 2 and also plot the decision rules:
[T, M] = EnumDecRules(2, 'plot')
These are the outputs:
VALID decision rules
T =
V1 V2 D R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16
__ __ ___ __ __ __ __ __ __ __ __ __ ___ ___ ___ ___ ___ ___ ___
0 0 'A' 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 'B' 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 1 'A' 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 1 'B' 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0
1 0 'A' 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0 'B' 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0
1 1 'A' 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 'B' 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
M =
Columns 1 through 9
0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1
0 1 0 0 0 0 0 1 1
0 1 1 1 1 1 1 0 0
1 0 0 0 0 1 1 0 0
1 0 1 1 1 0 0 1 1
1 1 0 0 1 0 1 0 1
1 1 1 1 0 1 0 1 0
Columns 10 through 18
0 0 1 1 1 1 1 1 1
1 1 0 0 0 0 0 0 0
1 1 0 0 0 0 1 1 1
0 0 1 1 1 1 0 0 0
1 1 0 0 1 1 0 0 1
0 0 1 1 0 0 1 1 0
0 1 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1
Column 19
1
0
1
0
1
0
1
0
And the plot:
Since this type of algorithm grows so fast, using EnumDecRules or GenM for n >= 5 can result in an out of memory error.
I really hope this will be helpful. If you have any questions about specific instructions of the code please leave a comment and I will be happy to answer them.
Suppose I have a 2 by 5 matrix:
d1= 3 3 1 1 2
4 4 2 3 4
and there is a 4 by 5 zero matrix :
z1= 0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Each column of d1 shows the positions of 1's in the corresponding column in z1. Specifically, I want to get a result like:
r1= 0 0 1 1 0
0 0 1 0 1
1 1 0 1 0
1 1 0 0 1
I am looking for an efficient way to obtain r1 from d1 and z1.
Convert d1 to linear indices, and use them to index z1:
% Prior to R2016b:
I = bsxfun(#plus, d1, (0:size(d1,2)-1) * size(z1,1));
% On or after R2016b:
I = d1 + (0:size(d1,2)-1) * size(z1,1));
% Index using the linearized indices
z1(I) = 1
I wrote naive gauss elimination without pivoting:
function [x] = NaiveGaussianElimination(A, b)
N = length(b);
x = zeros(N,1);
mulDivOp = 0;
subAddOp = 0;
for column=1:(N-1)
for row = (column+1):N
mul = A(row,column)/A(column,column);
A(row,:) = A(row,:)-mul*A(column,:);
b(row) = b(row)-mul*b(column);
mulDivOp = mulDivOp+N-column+2;
subAddOp = subAddOp +N-column+1;
end
end
for row=N:-1:1
x(row) = b(row);
for i=(row+1):N
x(row) = x(row)-A(row,i)*x(i);
end
x(row) = x(row)/A(row,row);
mulDivOp = mulDivOp + N-row + 1;
subAddOp = subAddOp + N-row;
end
x = x';
mulDivOp
subAddOp
return
end
but I am curious if I can reduce the number of multiplications/divisions and additions/subtractions in case I know which elements of matrix are 0:
For N = 10:
A =
96 118 0 0 0 0 0 0 0 63
154 -31 -258 0 0 0 0 0 0 0
0 -168 257 -216 0 0 0 0 0 0
0 0 202 24 308 0 0 0 0 0
0 0 0 -262 -36 -244 0 0 0 0
0 0 0 0 287 -308 171 0 0 0
0 0 0 0 0 197 229 -258 0 0
0 0 0 0 0 0 -62 -149 186 0
0 0 0 0 0 0 0 -43 255 -198
-147 0 0 0 0 0 0 0 -147 -220
(non-zero values are from randi). In general, non-zero elements are a_{1, N}, a_{N,1} and a_{i,j} when abs(i-j) <= 1.
Probably not. There are nice algorithms for reducing tridiagonal matrices (which these aren't, but they are close) to diagonal matrices. Indeed, this is one way in which the SVD of a matrix is produced, using orthogonal similarity transformations, not Gaussian elimination.
The problem is that when you use Gaussian elimination to remove the nonzero entries in the first column, you will have introduced additional nonzero entries in the other columns. The further you proceed, the more you destroy the structure of the matrix. It may be that Gaussian elimination is simply the wrong approach for the problem you are trying to solve, at least if you are trying to exploit the structure of the matrix.
Suppose I have a matrix A of size 3-by-3:
A = [a11, a12, a13; a21, a22, a23; a31, a32, a33];
Then I specify a parameter K, saying K is 2, then what I want is to make A become
a11 0 0 a12 0 0 a13 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
a21 0 0 a22 0 0 a23 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
a31 0 0 a32 0 0 a33 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
where, I insert K rows and columns of zeros between the original elements.
Is there any official function to do it in MATLAB?
For square matrix, A
Code
%%// Parameter
K = 3;
[x1,y1] = meshgrid(0:size(A,1)-1,0:size(A,1)-1)
x1 = bsxfun(#times,x1,K)+1
y1 = bsxfun(#times,y1,K)+1
Anew = zeros(size(A)*K)
Anew(sub2ind(size(Anew),y1(:),x1(:)))=A
Two alternative methods
Indexing:
initalise out as zeros and then fill in the required elements using indexing
out=zeros(size(A)*(K+1));
out(1:K+1:end,1:K+1:end)=A
Kronecker tensor product:
generate a matrix to multiply each element with, then use kron function
temp=zeros(K+1),temp(1)=1
out=kron(A,temp)
Does anyone have any thoughts on ways to create a matrix to identify one-period lagged dependent variable for use in tscs/panel analysis where the panel size varies? I can make this when there is a constant sample size, but it gets trickier (for me) with varying sample sizes. For example, if I had a 3 actor (A, B, C) 3 Period (1, 2, 3) model, but C was only present for the last 2 periods I would want:
A1 B1 A2 B2 C2 A3 B3 C3
A1 0 0 0 0 0 0 0 0
B1 0 0 0 0 0 0 0 0
A2 1 0 0 0 0 0 0 0
B2 0 1 0 0 0 0 0 0
C2 0 0 0 0 0 0 0 0
A3 0 0 1 0 0 0 0 0
B3 0 0 0 1 0 0 0 0
C3 0 0 0 0 1 0 0 0
I'd imagine it's just a loop which constructs an identity matrix for each panel-year, but I'm just not sure how this notation would look. (Just for clarity the matrix need not hold the values of the lagged-dv, merely identify the relevant observations) Thanks for any help!