How do I simplify minterms of a truth table? - cpu-architecture

I have a truth table and I need to convert it into sum-of-product canonical form. Here is my equation from the truth table.
We have 4 variables A, B, C, D and an output Y
Y = !A!B!C!D + !A!BC!D + !A!BCD + !ABC!D + !ABCD + A!B!C!D + A!BC!D
My question is, can I simply using the hamming distance of 1 trick?
For example, Y = AB + A!B = A because the B and !B would cancel out.
Here is what I did
1) !A!B!C!D + !A!BC!D = !A!B!D
2) !A!BCD + !ABC!D = !AC
3) !ABCD + A!B!C!D = nothing because they all cancel out
4) A!BC!D = A!BC!D
That gives me
Y = !A!B!D + !AC + A!BC!D
Would this be correct? or does ALL of the products need to have a hamming distance of 1 in order for me to cancel them out?

No, this is not correct. For example, if A=1, and the rest are 0, then the second-last term from the original equation is satisfied, so Y=1, but none of your three new terms are satisfied, which would imply that Y=0.
You can only eliminate one variable at a time using this method. So your first step was correct (and the fourth step was trivial, but correct), but the second and third step were wrong.
It's a lot easier to reduce this case using a Karnaugh map. If you do, I think you'll find that it just reduces to !AC+!B!D.

Related

Matlab AR digital fiter computation w/o loops

I'm given the a(k) matrix and e(n) and I need to compute y(n) from the following eq:
y(n) = sum(k = 1 to 10 )( a(k)*y(n-k) ) + e(n).
I have the a matrix(filter coefficients) and the e matrix (the residual), therefore there is only 1 unknown: y, which is built by the previous 10 samples of y.
An example to this equation:
say e(0) (my first residual sample) = 3
and y(-10) to y(-1) = 0
then y(0), my first sample in the signal y, would just be e(0) = 3:
y(0) = a(1)*y(-1) + a(2)*y(-2) + .... + a(10)*y(-10) + e(0) = e(0) = 3
and if e(1) = 4, and a(1) = 5, then
y(1) = a(1)*y(0) + a(2)*y(-1) + a(3)&y(-2) + ... + a(10)*y(-9) + e(1) = 19
The problem is
I don't know how to do this without loops because, say, y(n) needs y(n-1), so I need to immediately append y(n-1) into my matrix in order to get y(n).
If n (the number of samples) = say, 10,000,000, then using a loop is not ideal.
What I've done so far
I have not implemented anything. The only thing I've done for this particular problem is research on what kind of Matlab functions I could use.
What I need
A Matlab function that, given an equation and or input matrix, computes the next y(n) and automatically appends that to the input matrix, and then computes the next y(n+1), and automatically append that to the input matrix and so on.
If there is anything regarding my approach
That seems like it's on the wrong track, or my question isn't clear enough, of if there is no such matlab function that exists, then I apologize in advance. Thank you for your time.

Calculate roots of characteristic equation of symbolic matrix

I have 3 data matrices A,B,C (all 3x3), with which I use the following code to calculate roots of D(p)X = 0
syms p
D = A + B*p + C*(p^2)
solP = double(solve(det(D)))
From this, I get 6 values for solP. But when I try substituting it back into the symbolic matrix D, as follows, I get non-zero values of det(D) sometimes
for i = 1:6
p = solP(i)
det(double(subs(D)) % Should be zero always as we are substituting roots
end
Please help me understand this behaviour.
EDIT ::
Example :
A =
1.0e+11 *
4.8976 7.0936 6.7970
4.4559 7.5469 6.5510
6.4631 2.7603 1.6261
B =
1.0e+11 *
3.9223 7.0605 0.4617
6.5548 0.3183 0.9713
1.7119 2.7692 8.2346
C =
1.0e+11 *
6.9483 0.3445 7.6552
3.1710 4.3874 7.9520
9.5022 3.8156 1.8687
solP =
0.1061 + 0.0000i
1.5311 + 0.0000i
-0.3432 + 0.9356i
-0.3432 - 0.9356i
0.4228 - 0.5465i
0.4228 + 0.5465i
det(D) =
2.2143e+19
-5.4911e+20
-8.6415e+19 + 4.5024e+19i
-8.6415e+19 - 4.5024e+19i
-1.4547e+19 + 9.1135e+19i
-1.4547e+19 - 9.1135e+19i
The problem is related to the relative accuracy of floating point values, typically 1e-16.
The input matrices are of the order 1e+11 - 1e+12, the solution is of the order 1e+0, so the elements of D are also of the order 1e+11 - 1e+12. To calculate a determinant of a 3x3 matrix, one should take products of three matrix elements and add/subtract them. So, each term is of the order of 1e+33 - 1e+36. If you subtract such a values to obtain the determinant, the expected accuracy is in the order of 1e+17 - 1e+20. Indeed, this corresponds with the values you get. Given the relative accuracy, you are not able to reach further to zero.
Note that if you scale your input matrices, i.e. divide it by 1e+11, the solutions are indeed the same, but the determinants are probably more what you would expect.

Integration via trapezoidal sums in MATLAB

I need help finding an integral of a function using trapezoidal sums.
The program should take successive trapezoidal sums with n = 1, 2, 3, ...
subintervals until there are two neighouring values of n that differ by less than a given tolerance. I want at least one FOR loop within a WHILE loop and I don't want to use the trapz function. The program takes four inputs:
f: A function handle for a function of x.
a: A real number.
b: A real number larger than a.
tolerance: A real number that is positive and very small
The problem I have is trying to implement the formula for trapezoidal sums which is
Δx/2[y0 + 2y1 + 2y2 + … + 2yn-1 + yn]
Here is my code, and the area I'm stuck in is the "sum" part within the FOR loop. I'm trying to sum up 2y2 + 2y3....2yn-1 since I already accounted for 2y1. I get an answer, but it isn't as accurate as it should be. For example, I get 6.071717974723753 instead of 6.101605982576467.
Thanks for any help!
function t=trapintegral(f,a,b,tol)
format compact; format long;
syms x;
oldtrap = ((b-a)/2)*(f(a)+f(b));
n = 2;
h = (b-a)/n;
newtrap = (h/2)*(f(a)+(2*f(a+h))+f(b));
while (abs(newtrap-oldtrap)>=tol)
oldtrap = newtrap;
for i=[3:n]
dx = (b-a)/n;
trapezoidsum = (dx/2)*(f(x) + (2*sum(f(a+(3:n-1))))+f(b));
newtrap = trapezoidsum;
end
end
t = newtrap;
end
The reason why this code isn't working is because there are two slight errors in your summation for the trapezoidal rule. What I am precisely referring to is this statement:
trapezoidsum = (dx/2)*(f(x) + (2*sum(f(a+(3:n-1))))+f(b));
Recall the equation for the trapezoidal integration rule:
Source: Wikipedia
For the first error, f(x) should be f(a) as you are including the starting point, and shouldn't be left as symbolic. In fact, you should simply get rid of the syms x statement as it is not useful in your script. a corresponds to x1 by consulting the above equation.
The next error is the second term. You actually need to multiply your index values (3:n-1) by dx. Also, this should actually go from (1:n-1) and I'll explain later. The equation above goes from 2 to N, but for our purposes, we are going to go from 1 to N-1 as you have your code set up like that.
Remember, in the trapezoidal rule, you are subdividing the finite interval into n pieces. The ith piece is defined as:
x_i = a + dx*i; ,
where i goes from 1 up to N-1. Note that this starts at 1 and not 3. The reason why is because the first piece is already taken into account by f(a), and we only count up to N-1 as piece N is accounted by f(b). For the equation, this goes from 2 to N and by modifying the code this way, this is precisely what we are doing in the end.
Therefore, your statement actually needs to be:
trapezoidsum = (dx/2)*(f(a) + (2*sum(f(a+dx*(1:n-1))))+f(b));
Try this and let me know if you get the right answer. FWIW, MATLAB already implements trapezoidal integration by doing trapz as #ADonda already pointed out. However, you need to properly structure what your x and y values are before you set this up. In other words, you would need to set up your dx before hand, then calculate your x points using the x_i equation that I specified above, then use these to generate your y values. You then use trapz to calculate the area. In other words:
dx = (b-a) / n;
x = a + dx*(0:n);
y = f(x);
trapezoidsum = trapz(x,y);
You can use the above code as a reference to see if you are implementing the trapezoidal rule correctly. Your implementation and using the above code should generate the same results. All you have to do is change the value of n, then run this code to generate the approximation of the area for different subdivisions underneath your curve.
Edit - August 17th, 2014
I figured out why your code isn't working. Here are the reasons why:
The for loop is unnecessary. Take a look at the for loop iteration. You have a loop going from i = [3:n] yet you don't reference the i variable at all in your loop. As such, you don't need this at all.
You are not computing successive intervals properly. What you need to do is when you compute the trapezoidal sum for the nth subinterval, you then increment this value of n, then compute the trapezoidal rule again. This value is not being incremented properly in your while loop, which is why your area is never improving.
You need to save the previous area inside the while loop, then when you compute the next area, that's when you determine whether or not the difference between the areas is less than the tolerance. We can also get rid of that code at the beginning that tries and compute the area for n = 2. That's not needed, as we can place this inside your while loop. As such, this is what your code should look like:
function t=trapintegral(f,a,b,tol)
format long; %// Got rid of format compact. Useless
%// n starts at 2 - Also removed syms x - Useless statement
n = 2;
newtrap = ((b-a)/2)*(f(a) + f(b)); %// Initialize
oldtrap = 0; %// Initialize to 0
while (abs(newtrap-oldtrap)>=tol)
oldtrap = newtrap; %//Save the old area from the previous iteration
dx = (b-a)/n; %//Compute width
%//Determine sum
trapezoidsum = (dx/2)*(f(a) + (2*sum(f(a+dx*(1:n-1))))+f(b));
newtrap = trapezoidsum; % //This is the new sum
n = n + 1; % //Go to the next value of n
end
t = newtrap;
end
By running your code, this is what I get:
trapezoidsum = trapintegral(#(x) (x+x.^2).^(1/3),1,4,0.00001)
trapezoidsum =
6.111776299189033
Caveat
Look at the way I defined your function. You must use element-by-element operations as the sum command inside the loop will be vectorized. Take a look at the ^ operations specifically. You need to prepend a dot to the operations. Once you do this, I get the right answer.
Edit #2 - August 18th, 2014
You said you want at least one for loop. This is highly inefficient, and whoever specified having one for loop in the code really doesn't know how MATLAB works. Nevertheless, you can use the for loop to accumulate the sum term. As such:
function t=trapintegral(f,a,b,tol)
format long; %// Got rid of format compact. Useless
%// n starts at 3 - Also removed syms x - Useless statement
n = 3;
%// Compute for n = 2 first, then proceed if we don't get a better
%// difference tolerance
newtrap = ((b-a)/2)*(f(a) + f(b)); %// Initialize
oldtrap = 0; %// Initialize to 0
while (abs(newtrap-oldtrap)>=tol)
oldtrap = newtrap; %//Save the old area from the previous iteration
dx = (b-a)/n; %//Compute width
%//Determine sum
%// Initialize
trapezoidsum = (dx/2)*(f(a) + f(b));
%// Accumulate sum terms
%// Note that we multiply each term by (dx/2), but because of the
%// factor of 2 for each of these terms, these cancel and we thus have dx
for n2 = 1 : n-1
trapezoidsum = trapezoidsum + dx*f(a + dx*n2);
end
newtrap = trapezoidsum; % //This is the new sum
n = n + 1; % //Go to the next value of n
end
t = newtrap;
end
Good luck!

Finding an estimated solution of the equation

I have a truncation function defined as:
function f = phi_b(x, b)
if b == 0
f = sign(x);
else
f = -1 * (x<-b) + 1*(x>b) + (1/b) * x .* ((x>=-b & x<=b));
end;
It is used to truncate the observations which in my particular case corresponds to white noise:
model = arima('Constant',0,'AR',{0},'Variance',1);
y = simulate(model, 100);
The function I need in the end is:
r = #(b) (1/100) * sum((phi_b(y,b)).^2);
The problem is in finding the solution of the equation r(b)==0.1. Usual procedures like the one below will not work:
solve(r(b)==0.1, b)
Is there any way to solve such types of equations?
If the result of r(b) is a vector, you could invoke the min function and see where in this vector the closest value would be to 0.1. You can do something like:
result = r(b);
[val,index] = min(abs(result - 0.1));
val will contain how "close" 0.1 is with the best element in the vector that matches this criteria and index will tell you where in the result vector this element is. For example, if val = 0.00001 and index = 7, this means that the best value in result is 0.00001 away from 0.1. Also, index 7 in result is where this best element is located. To see what the actual value is, do r(7) or r(index).
Interestingly enough, you can use val as a way of measuring the resolution of your data. In other words, if val is very large, this could mean that you need to introduce more values in your vector at a smaller step size. If val is quite small, this could mean that what you originally specified as your b vector is adequate enough. I'm not familiar with the function so I have not considered whether or not there could be no solutions to the data you have provided to your r function.

Use value in previous cell of matlab matrix for use in equation

Hi I am working with the following code (Brute force method).
"PV_supply" and "WT_supply" and "Demand" are 48x1 size.
what I am trying to do is calculate the "Energy_battery" value for each of the 48 rows. However to do this I need to use the value of "Energy_battery" from the previous row in the calculations of each row which I haven't figured out how to code and was hoping for some help on this. therefore the equation for "Energy_battery" in row 1 uses the "Energy_battery" value in row 1 for the equation etc
My code is:
for number_panels = 0:5
for number_turbines = 0:3
for h=1:24 %# hours
for d = 1:number_of_days %# which day
n = h + 24*(d-1);
Energy_battery(number_panels + 1, number_turbines + 1,1,1) = 100;
Energy_battery(number_panels + 1, number_turbines + 1,n+1,1) =...
Energy_battery(number_panels + 1, number_turbines + 1,h,1) + ...
((PV_supply(n)*number_panels + WT_supply(n)*number_turbines) - ...
Demand(n)/inverter_efficiency)*battery_charging_efficiency;
This is an extended comment, only an answer to parts of your question, though I think it has relevance to your other recent questions too.
It's helpful to think of Matlab as an array processing language, the natural 'unit' of computation is an array rather than a scalar as in many other languages. If you find yourself writing loops to iterate over the elements of an array stop and think, there is likely to be a more 'natural' way of expressing the same calculation without the loops. There's nothing absolutely wrong with loops but over-reliance on them can have 2 deleterious effects:
Matlab code without loops is often (much) faster than the equivalent with loops;
Code with loops is often more cluttered, and requires more variables to be used, than the equivalent without loops. The clutter is a hindrance when it comes to understanding the code
So, for example, your statement
Energy_battery(number_panels + 1, number_turbines + 1,1,1) = 100;
could be lifted out of your loop nest entirely and rewritten as
Energy_battery(:,:,1,1) = 100;
Now, for the main bulk of your code, if I've understood it correctly, you want to update each element at Energy_battery(:,:,n+1,1) based on the values in Energy_battery(:,:,n,1) and in element n of the other vectors you have. First, let's tidy this up
((PV_supply(n)*number_panels + WT_supply(n)*number_turbines) - Demand(n)/inverter_efficiency)*battery_charging_efficiency
could be rewritten as
((PV_supply*number_panels + WT_supply*number_turbines) - Demand/inverter_efficiency)*battery_charging_efficiency
for Matlab multiplying an array by a scalar applies the multiplication to each element of the array. And again, this doesn't need a loop over the values of an index such as n.
I'm afraid I have to go and do some work now, will come back later and finish the lesson if no-one else does. Feel free to edit this answer if you want to.