How to simplify expressions with absolute values in Maple - maple

For problem simplify(abs(1-b)+abs(1+b)), I want maple to take out the abs and get results for different ranges of b.

Conversion of your expression to Maple's piecewise structure gets you started.
restart;
expr1 := abs(1-b)+abs(1+b);
expr1 := |b - 1| + |1 + b|
convert(expr1, piecewise, b);
/ -2 b b < -1
|
< 2 b < 1
|
\ 2 b 1 <= b
And you can even turn that into a list.
PiecewiseTools:-ToList(%);
[[b < -1, -2 b], [b < 1, 2], [1 <= b, 2 b]]
But for either of the above representations you can notice that some of the information is implicit. The expr1 is identically equal to 2 when b<1 AND the prior condition(s) don't hold. It's implicit that you also need the negation of the first condition in order to get to the second. Maple handles that by proceeding through the conditions until it gets one that's satisfied, when it evaluates a piecewise at a particular point (ie, at a value for b).
We can write a procedure to obtain a more explicit (if somewhat redundant) representation.
F1 := proc(ee, x::name)
local T;
T := PiecewiseTools:-ToList(convert(ee,piecewise,x));
piecewise(seq([`and`(solve(`and`(seq(`not`(T[j,1]),j=1..i-1),
T[i,1]),{x})[]),
T[i,2]][],i=1..nops(T)));
end proc:
And, using that,
F1(expr1, b);
/ -2 b b < -1
|
< 2 -1 <= b and b < 1
|
\ 2 b 1 <= b
PiecewiseTools:-ToList(%);
[[b < -1, -2 b], [-1 <= b and b < 1, 2], [1 <= b, 2 b]]
Observe the difference between that and what we got before. Now the middle condition explicitly expresses the negation of the first.
We could write another procedure to express b in terms of real ranges.
F2 := proc(ee, x::name)
local T;
T := PiecewiseTools:-ToList(convert(ee,piecewise,x));
piecewise(seq([x::solve(`and`(seq(`not`(T[j,1]),j=1..i-1),
T[i,1]),x),
T[i,2]][],i=1..nops(T)));
end proc:
And, using that,
F2(expr1, b);
/ -2 b b::(RealRange(-infinity, Open(-1)))
|
< 2 b::(RealRange(-1, Open(1)))
|
\ 2 b b::(RealRange(1, infinity))
PiecewiseTools:-ToList(%);
[[b::(RealRange(-infinity, Open(-1))), -2 b],
[b::(RealRange(-1, Open(1))), 2], [b::(RealRange(1, infinity)), 2 b]]
Note that those may not each be the widest ranges. We could have alternatively used solve to find b::RealRange(-1,1) for the second condition, since 2 = 2*b when b=1. The expression is continuous at b=1 where the second and third conditions meet. And similarly for the other conditions.
solve(expr1 = -2*b, b);
RealRange(-infinity, -1)
solve(expr1 = 2, b);
RealRange(-1, 1)
solve(expr1 = 2*b, b);
RealRange(1, infinity)
A similar thing holds for the inequality results from F1. Obtaining these wider results with intervals closed at some ends (or non-strict inequalities) could be done using modified versions of the procedures, to use solve instead of just negating all prior conditions at each stage. I haven't done that here.
Let's look at another example, for fun,
expr2 := abs(1-c)+abs(1+c)-abs(3-c)-abs(7+c);
expr2 := |c - 1| + |1 + c| - |c - 3| - |7 + c|
convert(expr2, piecewise, c);
/ 4 c < -7
|
| -2 c - 10 c < -1
|
< -8 c < 1
|
| 2 c - 10 c < 3
|
\ -4 3 <= c
F1(expr2, c);
/ 4 c < -7
|
| -2 c - 10 -7 <= c and c < -1
|
< -8 -1 <= c and c < 1
|
| 2 c - 10 1 <= c and c < 3
|
\ -4 3 <= c
PiecewiseTools:-ToList(%);
[[c < -7, 4], [-7 <= c and c < -1, -2 c - 10],
[-1 <= c and c < 1, -8],
[1 <= c and c < 3, 2 c - 10], [3 <= c, -4]]
F2(expr2, c);
/ 4 c::(RealRange(-infinity, Open(-7)))
|
| -2 c - 10 c::(RealRange(-7, Open(-1)))
|
< -8 c::(RealRange(-1, Open(1)))
|
| 2 c - 10 c::(RealRange(1, Open(3)))
|
\ -4 c::(RealRange(3, infinity))
PiecewiseTools:-ToList(%);
[[c::(RealRange(-infinity, Open(-7))), 4],
[c::(RealRange(-7, Open(-1))), -2 c - 10],
[c::(RealRange(-1, Open(1))), -8],
[c::(RealRange(1, Open(3))), 2 c - 10],
[c::(RealRange(3, infinity)), -4]]
We could plot these results (which I won't inline here).
plots:-display(Array([[plot(expr2,c=-8..4),
plot(convert(expr2,piecewise,c),c=-8..4)],
[plot(F1(expr2,c),c=-8..4),
plot(F2(expr2,c),c=-8..4)]]));
We could even handle other unknowns, although conversion to piecewise might require assumptions.
expr3 := abs(1-c) + abs(1+c) - abs(3-c) - abs(K-c):
convert(expr3, piecewise, c) assuming K>1, K<3;
/ -3 - K c < -1
|
| -1 + 2 c - K c < 1
|
< 4 c - 3 - K c <= K
|
| 2 c - 3 + K c < 3
|
\ 3 + K 3 <= c
F1(expr3, c) assuming K>1, K<3;
/ -3 - K c < -1
|
| -1 + 2 c - K -1 <= c and c < 1
|
< 4 c - 3 - K 1 <= c and c <= K
|
| 2 c - 3 + K K < c and c < 3
|
\ 3 + K 3 <= c

Related

Boolean Simplification - Q=A.B.(~B+C)+B.C+B

I've been struggling with boolean simplification in class, and took it to practice some more at home. I found a list of questions, but they don't have any answers or workings. This one I'm stuck on, if you could answer clearly showing each step I'd much appreciate:
Q=A.B.(~B+C)+B.C+B
I tried looking for a calculator to give me the answer and then to work out how to get to that, but I'm lost
(I'm new to this)
Edit: ~B = NOT B
I've never done this, so I'm using this site to help me.
A.B.(B' + C) = A.(B.B' + B.C) = A.(0 + B.C) = A.(B.C)
So the expression is now A.(B.C) + B.C + B.
Not sure about this, but I'm guessing A.(B.C) + (B.C) = (A + 1).(B.C).
This equals A.(B.C).
So the expression is now A.(B.C) + B.
As A.(B + C) = B.(A.C), the expression is now B.(A.C) + B, which equals (B + 1).(A.C) = B.(A.C).
NOTE: This isn't complete yet, so please avoid downvoting as I'm not finished yet (posted this to help the OP understand the first part).
Let's be lazy and use sympy, a Python library for symbolic computation.
>>> from sympy import *
>>> from sympy.logic import simplify_logic
>>> a, b, c = symbols('a, b, c')
>>> expr = a & b & (~b | c) | b & c | b # A.B.(~B+C)+B.C+B
>>> simplify_logic(expr)
b
There are two ways to go about such a formula:
Applying simplifications,
Brute force
Let's look at brute force first. The following is a dense truth table (for a better looking table, look at Wα), enumerating all possible value for a, b and c, alongside the values of the expression.
a b c -- a & b & (~b | c) | b & c | b = Q
0 0 0 0 0 10 1 0 0 0 0 0 = 0
0 0 1 0 0 10 1 1 0 0 1 0 = 0
0 1 0 0 1 01 0 0 1 0 0 1 = 1
0 1 1 0 1 01 1 1 1 1 1 1 = 1
1 0 0 1 0 10 1 0 0 0 0 0 = 0
1 0 1 1 0 10 1 1 0 0 1 0 = 0
1 1 0 1 1 01 1 0 1 0 0 1 = 1
1 1 1 1 1 01 1 1 1 1 1 1 = 1
You can also think of the expression as a tree, which will depend on the precedence rules (e.g. usually AND binds stronger than OR, see also this question on math.se).
So the expression:
a & b & (~b | c) | b & c | b
is a disjunction of three terms:
a & b & (~b | c)
b & c
b
You can try to reason about the individual terms, knowing that only one has to be true (as this is a disjunction).
The last two will be true, if and only if b is true. For the first, this a bit harder to see, but if you look closely: you have now a conjunction (terms concatenated by AND): All of them must be true, for the whole expression to be true, so a and b must be true. Especially b must be true.
In summary: For the whole expression to be true, in all three top-level cases, b must be true (and it will be false, if b is false). So it simplifies to just b.
Explore more on Wolfram Alpha:
https://www.wolframalpha.com/input/?i=a+%26+b+%26+(~b+%7C+c)+%7C+b+%26+c+%7C+b
A.B.(~B+C) + B.C + B = A.B.~B + A.B.C + B.C + B ; Distribution
= A.B.C + B.C + B ; Because B.~B = 0
= B.C + B ; Because A.B.C <= B.C
= B ; Because B.C <= B

Sort matlab matrix rows based on function

Let's say I have a Nx3 matrix M.
Consider, for example, a function Map(v) that receives as input a 1x3 array and returns a double.
How can I sort the rows of M so that the rows with smallest Map should come first?
That is, the row i should be the first if Map(M(i,:)) ≤ Map(M(j,:)) for all 1 ≤ j ≤ N and j ≠ i ?
example:
M = |1 2 3|
|4 5 6|
|7 8 9|
Map(v){
if (v(1) == 1 && v(2) == 2 && v(3) == 3) return 2
if (v(1) == 4 && v(2) == 5 && v(3) == 6) return 3
if (v(1) == 7 && v(2) == 8 && v(3) == 9) return 1
}
So the sorting should leave M like this:
M = |7 8 9|
|1 2 3|
|4 5 6|
% initialize an N-by-3 matrix where N=10...
M = [
1 0 3;
4 2 2;
0 1 0;
7 5 6;
3 3 8;
2 1 4;
0 0 6;
3 1 2;
5 0 0;
1 6 2
];
% sum its rows...
M_sum = sum(M,2);
% sort the vector of sums in ascending order...
[~,idx] = sort(M_sum);
% reorder the matrix rows based on the sorting result...
M = M(idx,:);

Quadratic Program formulation: Matlab

Given this objective function:
Minimize:
f = (Ax + By)' * G * (Ax + By)
subject to some equalities and inequalities.
where x and y are real-valued vectors (decision variables) with p and q elements, respectively. A of size m * p, B of size m * q, G is a symmetric matrix of size m * m.
My question is how to write f in the form v' * G * v, such that it can be easily be used in quadprog. In other words, how to mix A, B and G?
This looks incompletely specified!
It seems, for whatever reason, you want to model in terms of two variable components. Now you did not specify how they interact with each other.
As most optimizers work on a single variable-vector, you need to concatenate yours.
As you did not show G, i'm assuming you got one G for x and one for y, let's call it H.
(Remark: not a matlab user; don't take example-syntax for granted!)
z = [x y]
P = blkdiag(G,H)
assuming x and y independent in regards to quadratic-term
e.g. no x0*y1 like terms
Solve: for z` P z
Example:
x = [x0 x1 x2]
y = [y0 y1]
G = [6 2 1; 2 5 2; 1 2 4]
H = [8 2; 2 10]
# G
6 2 1
2 5 2
1 2 4
# H
8 2
2 8
z = [x0 x1 x2 y0 y1]
P = [6 2 1 0 0; 2 5 2 0 0; 1 2 4 0 0; 0 0 0 8 2; 0 0 0 2 8]
# P
6 2 1 0 0
2 5 2 0 0
1 2 4 0 0
0 0 0 8 2
0 0 0 2 8

How to subtract each item of a matrix from each coressponding row of another matrix

A = [1 2 3; 7 6 5]
B = [3 7];
A-B = [1-3 2-3 3-3; 7-7 6-7 5-7];
ans =[-2 -1 0; 0 -1 -2]
This is the operation I want to have done. How could I do it by matrix functions other than the iterative solutions?
You do this most conveniently with bsxfun, which automatically expands the arrays to match in size (so that you don't need to use repmat). Note that I need to transpose B so that it's a 2-by-1 array.
A = [1 2 3; 7 6 5]
B = [3 7];
result = bsxfun(#minus,A,B')
result =
-2 -1 0
0 -1 -2
I think that Jonas answer is the best. But just for the record, here is the solution using an explicit repmat:
A = [1 2 3; 7 6 5];
B = [3 7];
sz = size(A);
C = A - repmat(B', [1 sz(2:end)]);
Not only is Jonas' answer simpler, it is actually faster by a factor of 2 for large matrices on my machine.
It's also interesting to note that in the case where A is an n-d array, both these solutions do something quite reasonable. The matrix C will have the following property:
C(k,:,...,:) == A(k,:,...,:) - B(k)
In fact, Jonas' answer will run, and very likely do what you want, in the case where B is m-d, as long as the initial dimensions of A and B' have the same size. You can change the repmat solution to mimic this ... at which point you are starting to reimplement bsxfun!
Normally you can't. Iterative solutions will be necessary, because the problem is poorly defined. Matrix addition/subtraction is only defined for matrices of the same dimensions.
ie:
A = | 1 2 3 |
| 7 6 5 |
B = | 3 7 |
It makes no sense to subtract a 1x2 matrix from a 2x3 matrix.
However, if you multiplied B by some intermediate matrix to make the result a 2x3 matrix, that would work, ie:
B' * Y = | 3 3 3 |
| 7 7 7 |
eg:
B' = diag(B)
= | 3 0 |
| 0 7 |
B' * Y = | 3 3 3 |
| 7 7 7 |
Y = | 1 1 1 |
| 1 1 1 |
Therefore, A-B'*Y gives a valid, non-iterative solution.
A-(B'*Y) = | 1 2 3 | - | 3 3 3 |
| 7 6 5 | | 7 7 7 |
= A - (diag(B) * Y )
The only "cheat" here is the use of the diag() function, which converts a vector to a strictly-diagonal-matrix. There is a way to manually decompose a set of matrix/vector multiplication operations to manually re-create the diag() function, but that would be more work than my solution above itself.
Good luck!

Can all boolean expressions be written sequentially?

I'm working with some tools, and the only way it can determine if a particular transaction is successful is if it passes various checks. However, it is limited in the way that it can only do one check at a time, and it must be sequential. Everything must be computed from left to right.
For example,
A || C && D
It will be computed with A || C first, and then the result will be AND'ed with D.
It gets tougher with parenthesis. I am unable to compute an expression like this, since B || C would need to be compututed first. I cannot work with any order of operations;
A && ( B || C)
I think I've worked this down to this sequential boolean expression,
C || B && A
Where C || B is computed first, then that result is AND'd with A
Can all boolean expressions be successfully worked into a sequential boolean expression? (Like the example I have)
The answer is no:
Consider A || B && C || D which has the truth table:
A | B | C | D |
0 | 0 | 0 | 0 | 0
0 | 0 | 0 | 1 | 0
0 | 0 | 1 | 0 | 0
0 | 0 | 1 | 1 | 0
0 | 1 | 0 | 0 | 0
0 | 1 | 0 | 1 | 1
0 | 1 | 1 | 0 | 1
0 | 1 | 1 | 1 | 1
1 | 0 | 0 | 0 | 0
1 | 0 | 0 | 1 | 1
1 | 0 | 1 | 0 | 1
1 | 0 | 1 | 1 | 1
1 | 1 | 0 | 0 | 0
1 | 1 | 0 | 1 | 1
1 | 1 | 1 | 0 | 1
1 | 1 | 1 | 1 | 1
If it were possible to evaluate sequentially there would have to be a last expression which would be one of two cases:
Case 1:
X || Y such that Y is one of A,B,C,D and X is any sequential boolean expression.
Now, since there is no variable in A,B,C,D where the entire expression is true whenever that variable is true, none of:
X || A
X || B
X || C
X || D
can possibly be the last operation in the expression (for any X).
Case 2:
X && Y: such that Y is one of A,B,C,D and X is any sequential boolean expression.
Now, since there is no variable in A,B,C,D where the entire expression is false whenever that variable is false, none of:
X && A
X && B
X && C
X && D
can possibly be the last operation in the expression (for any X).
Therefore you cannot write (A || B) && (C || D) in this way.
The reason you are able to do this for some expressions, like: A && ( B || C) becoming C || B && A is because that expression can be built recursively out of expressions which have one of the two properties above:
IE.
The truth table for A && ( B || C) is:
A | B | C |
0 | 0 | 0 | 0
0 | 0 | 1 | 0
0 | 1 | 0 | 0
0 | 1 | 1 | 0
1 | 0 | 0 | 0
1 | 0 | 1 | 1
1 | 1 | 0 | 1
1 | 1 | 1 | 1
Which we can quickly see has the property that it is false whenever A is 0. So Our expression Could be X && A.
Then we take A out of the truth table and look at only the rows where A is 1 is the original:
B | C
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 1
Which has the property that it is True whenever B is 1 (or C, we can pick here). So we can write the expression as
X || B and the entire expression becomes X || B && A
Then we reduce the table again to the portion where B was 0 and we get:
C
0 | 0
1 | 1
X is just C. So the final expression is C || B && A
This is a problem of rewriting an expression so that no parentheses occur on the right. Logical AND (∧) and OR (∨) are both commutative:
A ∧ B = B ∧ A
A ∨ B = B ∨ A
So you can rewrite any expression of the form “X a (Y)” as “(Y) a X”:
A ∧ (B ∧ C) = (A ∧ B) ∧ C
A ∧ (B ∨ C) = (B ∨ C) ∧ A
A ∨ (B ∧ C) = (B ∧ C) ∨ A
A ∨ (B ∨ C) = (B ∨ C) ∨ A
They are also distributive, by the following laws:
(A ∧ B) ∨ (A ∧ C)
= A ∧ (B ∨ C)
= (B ∨ C) ∧ A
(A ∨ B) ∧ (A ∨ C)
= A ∨ (B ∧ C)
= (B ∧ C) ∨ A
So many Boolean expressions can be rewritten without parentheses on the right. But, as a counter­example, there is no way to rewrite an expression such as (A ∧ B) ∨ (C ∧ D) if A ≠ C, because of the lack of common factors.
Can't you just do this:
(( A || C ) && D)
and for your second example:
((( A && C ) || B ) && A )
Would that work for you?
Hope that helps...
You'll hit problems if you need to do something like (A || B) && (C || D) unless you can store the intermediate values for later use.
If you're allowed to construct more than one chain and try them all until either one of them passes or they all fail (so each chain is effectively ORed with the next) then I should think you can handle any combination. The example above would become (where each line is a separate query):
(A && C) ||
(A && D) ||
(B && C) ||
(B && D)
However, for a very complex check this could easily get out of hand!