Boolean logic simplification wy'+wx'y+wxyz+wxz' am I doing this right? - boolean

I'm studying for my digital logic test tomorrow, and I'm doing some practice problems. I'm having problems with this one specifically. I think I solved it, but I'm not confident in my answer. Can anyone verify the logic and explain it? I have looked elsewhere but can't find the answer previously recorded anywhere.
wy'+wx'y+wxyz+wxz'
1. I factored wy out of wx'y and wxyz to get wy(x'+xz) which equates to wy(x'+z). Using the rule A+A'B = A+B
This changes the equation to wy'+wyx'+wyz+wxz'
2. I factored w out of wy' and wyx' to get w(y'+yx') which equates to w(y'+x'). Using the rule A+ A'B = A+B.
This changes the equation to wy'+wx'+wyz+wxz'
3. I factored w out of wy' and wyz to get w(y'+yz) which equates to w(y'+z'). Using the same rule again.
This changes the equation to wy'+wz'+wyx'+wxz'
4. I factored w out of wz' and wxz' to get w(z'+z'x) which equates to w(z') using the rule A+AB=A.
This changes the equation to wz'+wy'+wyx'
5. I factored w out of wy' and wyx' to get w(y'+yx') which equates to w(y'+x') using the rule A+A'B = A+B.
This changes the equation to wy'+wx'+wz' - This is where I am stuck, I feel like there are more steps to do, but I can't find anything.

You have a mistake in Step 3
you start with
wy'+wx'+wyz+wxz' (equivalent to wy'+wyz+wx'+wxz')
you then correctly factor w out of wy' and wyz to get w(y'+yz)
but then you suggest w(y'+yz) is equal to w(y'+z') (which is incorrect)
w(y'+yz) is equal to w(y'+z)
which leaves you with wy'+wz+wyx'+wxz' (instead of wy'+wz'+wyx'+wxz')
after which the remaining logic after Step 3 will need to be adjusted

Related

Clingo: Operation undefined while doing computations inside the testing rules

I am new to ASP programming and finding it a bit hard to understand how ASP works. I am using clingo tool for ASP coding. Currently, I am working on a seating arrangement problem. The original problem is a bit complicated as it involves lots of variables and constraints. I have started with a basic version of it which is as follows:
4 persons need to be seated in a horizontal row having 4 seats. There are no constraints among these persons. Each person can move left/right to any other person. The final goal is straightforward
"any person can sit at any location provided it is available"
The only condition is to save the individual steps about how the goal is reached.
To solve it, I have used a predicate
seated(A,B,Shift,Dir,t) which says that at time t A has shifted Shift units in the Dir from B
Example
seated(A,B,left,2,t) implies A has shifted 2 units to the left of B at time t
I have used two files
init.lp describing the initial positions and final goal
person(a).
person(b).
person(c).
person(d).
init(pos(a,0)).
init(pos(b,0)).
init(pos(c,0)).
init(pos(d,0)).
goal(pos(a,1)).
goal(pos(b,2)).
goal(pos(c,3)).
goal(pos(d,4)).
rules.lp where the rules are written
#include<incmode>.
#program base.
% Define
holds(F,0) :- init(F).
%{possible_location(X,Y,1) : person(X),Y = 1..4}.
%%possible_location(X,Y,1) : person(X),Y = 1..4.
#program step(t).
% Generate any seating arrangement
1 { seated(X,Z,Shift,Dir,t) : person(X), person(Z), X != Z,Shift = 1..3, Dir = (left;right) } 1.
% Test
% Remove the seated predicates which the shift is not possible
:- seated(X,Z,Shift,right,t), holds(pos(Z,Pos),t-1), Shift + Pos > 4.
:- seated(X,Z,Shift,left,t), holds(pos(Z,Pos),t-1), Pos - Shift < 1.
% Remove the seated predicates if the final position after shifting is already occupied
:- seated(X,Z,Shift,right,t), holds(pos(Z,Pos),t-1), Pos>0, holds(pos(A,Shift + Pos),t-1), A!=X.
:- seated(X,Z,Shift,left,t), holds(pos(Z,Pos1),t-1), Pos1>0, holds(pos(A,Pos1 - Shift),t-1), A!=X.
% Define
seateded(X,t) :- seated(X,Z,Shift,Dir,t).
% Relating the current move to the current state %
holds(pos(X,Y),t) :- seated(X,Y,Shift,Dir,t).
% This is for shifting the state to the next time %
holds(pos(X,Z),t) :- holds(pos(X,Z),t-1), not seateded(X,t).
#program check(t).
% Test
:- query(t), goal(F), not holds(F,t).
% Display
#show seated/5.
#show query/1.
On running the above files, it gives an error
rule_new.lp:21:75-87: info: operation undefined:
(Pos1-Shift)
I have googled it and found out that this error comes when I have not handled any edge case such as X/Y and Y=0 is not handled. In this case, I don't see any edge case. Hence, I am not able to rectify the error.
I have documented the rules so that I can explain the thought process behind writing the rules. I have spent a couple of hours solving it and still couldn't figure out the solution. If my thinking is not in the right direction then I would appreciate if I can get some other solution to the above problem.
I'm afraid I didn't manage to understand your solution (or problem), but using the option --text can help you figure this error out.
According to the error message the problem is in this rule:
seated(X,Z,Shift,left,t),holds(pos(Z,Pos1),t-1), Pos1 >0, holds(pos(A,Pos1 - Shift),t-1), A !=X.
You try to subtract Shift from Pos1. Both Variables should be substituted by integers to make this work.
Shift comes from the seated predicate and can take a value between 1..3, fine.
Pos1 comes from the holds(pos(_,Pos1),_) predicate.
In your rule:
holds(pos(X,Y),t) :- seated(X,Y,Shift,Dir,t).
You clearly derive holds predicates where Y is a person, aka. a, b, c, or d.
So you try to compute 3-a which clingo refuses to do and drops the according rule, raising this warning.

In OpenMDAO, is there a way to ensure that the constraints are respected before proceeding with a computation?

I have a constrained nonlinear optimization problem, "A". Inside the computation is an om.Group which I'll call "B" that requires a nonlinear solve. Whether "B" finds a solution or crashes seems to depend on its initial conditions. So far I've found that some of the initial conditions given to "B" are inconsistent with the constraints on "A", and that this seems to be contributing to its propensity for crashing. The constraints on "A" can be computed before "B".
If the objective of "A" could be computed before "B" then I would put "A" in its own group and have it pass its known-good solution to "B". However, the objective of "A" can only be computed as a result of the converged solution of "B". Is there a way to tell OpenMDAO or the optimizer (right now I'm using ScipyOptimizerDriver and the SLSQP method) that when it chooses a new point in design-variable space, it should check that the constraints of "A" hold before proceeding to "B"?
A slightly simpler example (without the complication of an initial guess) might be:
There are two design variables 0 < x1 < 1, 0 < x2 < 1.
There is a constraint that x2 >= x1.
Minimize f(sqrt(x2 - x1), x1) where f crashes if given imaginary inputs. How can I make sure that the driver explores the design space without giving f a bad input?
I have two proposed solutions. The best one is highly problem dependent. You can either raise an AnalysisError or use numerical clipping.
import numpy as np
import openmdao.api as om
class SafeComponent(om.ExplicitComponent):
def setup(self):
self.add_input('x1')
self.add_input('x2')
self.add_output('y')
def compute(self, inputs, outputs):
x1 = inputs['x1']
x2 = inputs['x2']
diff = x1 - x2
######################################################
# option 1: raise an error, which causes the
# optimizer line search to backtrack
######################################################
# if (diff < 0):
# raise om.AnalysisError('invalid inputs: x2 > x1')
######################################################
# option 2: use numerical clipping
######################################################
if (diff < 0):
diff = 0.
outputs['y'] = np.sqrt(diff)
# build the model
prob = om.Problem()
prob.model.add_subsystem('sc', SafeComponent(), promotes=['*'])
prob.setup()
prob['x1'] = 10
prob['x2'] = 20
prob.run_model()
print(prob['y'])
Option 1: raise an AnalysisError
Some optimizers are set up to handle this well. Others are not.
As of V3.7.0, the OpenMDAO wrappers for SLSQP from scipy and pyoptsparse, and the SNOPT/IPOPT wrappers from pyoptsparse all handle AnalysisErrors gracefully.
When the error is raised, the execution stops and the optimizer recognizes a failed case. It backtracks on the linesearch a bit to try and get out of the situation. It will usually try a few steps backwards, but at some point it will give up. So the success of this situation depends a bit on why you ended up in the bad part of the space and how much the gradients are pushing you back into it.
This solution works very well with fully analytic derivatives. The reason is that (most) gradient based optimizers will only ever ask for function evaluations along a line search operation. So that means that, as long as a clean point is found, you're always able to be able to compute derivatives at that point as well.
If you're using finite-differences, you could end a line search right near the error condition, but not violating it (e.g. x1=1, x2=.9999999). Then during the FD step to compute derivatives, you might end up tripping the error condition and raising the error. The optimizer is not going to be able to recover from this condition. Errors during FD steps will effectively kill the whole opt.
So, for this reason I never recommend the AnalysisError approach if you're suing FD.
Option 2: Numerical Clipping
If you optimizer wrapper does not have the ability to handle an AnalysisError, you can try some numerical clipping instead. You can add a filter in your calcs to to keep the values numerically safe. However, you obviously need to use this very carefully. You should at least add an additional constraint that forces the optimizer to keep away from the error condition when converged (e.g. x1 >= x2).
One important note: if you provide analytic derivatives, include the clipping in them!
Sometimes the optimizer just wants to pass through this bad region on its way to the answer. In that case, the simple clipping I show here is probably fine. Other times it wants to ride the constraint (be sure you add that constraint!!!) and then you probably want a more smoothly varying type of clipping. In other words don't use a simple if-condition. Smooth the round corner a bit, and maybe make the value asymptotically approach 0 from a very small value. This way you have a c1 continuous function and the derivatives won't got to exactly 0 for these inputs.

How Double QN works?

What is the idea behind double QN?
The Bellman equation used to calculate the Q values to update the online network follows the equation:
value = reward + discount_factor * target_network.predict(next_state)[argmax(online_network.predict(next_state))]
The Bellman equation used to calculate the Q value updates in the original DQN is:
value = reward + discount_factor * max(target_network.predict(next_state))
but the target network for evaluating the action is updated using weights of the
online_network and the value and fed to the target value is basically old q value of the action.
any ideas how adding another networks based on weights from the first network helps?
I really liked the explanation from here:
https://becominghuman.ai/beat-atari-with-deep-reinforcement-learning-part-2-dqn-improvements-d3563f665a2c
"This is actually quite simple: you probably remember from the previous post that we were trying to optimize the Q function defined as follows:
Q(s, a) = r + γ maxₐ’(Q(s’, a’))
Because this definition is recursive (the Q value depends on other Q values), in Q-learning we end up training a network to predict its own output, as we pointed out last time.
The problem of course is that at each minibatch of training, we are changing both Q(s, a) and Q(s’, a’), in other words, we are getting closer to our target but also moving our target! This can make it a lot harder for our network to converge.
It thus seems like we should instead use a fixed target so as to avoid this problem of the network “chasing its own tail”, but of course that isn’t possible since the target Q function should get better and better as we train."

Modelica - Modeling a slider element in OpenModelica

Rheological models are usually build using three (or four) basics elements, which are :
The spring (existing in Modelica.Mechanics.Translational.Components for example). Its equation is f = c * (s_rel - s_rel0);
The damper (dashpot) (also existing in Modelica.Mechanics.Translational.Components). Its equation is f = d * v_rel; for a linear damper, an could be easily modified to model a non-linear damper : f = d * v_rel^(1/n);
The slider, not existing (as far as I know) in this library... It's equation is abs(f)<= flim. Unfortunately, I don't really understand how I could write the corresponding Modelica model...
I think this model should extend Modelica.Mechanics.Translational.Interfaces.PartialCompliant, but the problem is that f (the force measured between flange_b and flange_a) should be modified only when it's greater than flim...
If the slider extends PartialCompliant, it means that it already follows the equations flange_b.f = f; and flange_a.f = -f;
Adding the equation f = if abs(f)>flim then sign(f)*flim else f; gives me an error "An independent subset of the model has imbalanced number of equations and variables", which I couldn't really explain, even if I understand that if abs(f)<=flim, the equation f = f is useless...
Actually, the slider element doesn't generate a new force (just like the spring does, depending on its strain, or just like the damper does, depending on its strain rate). The force is an input for the slider element, which is sometime modified (when this force becomes greater than the limit allowed by the element). That's why I don't really understand if I should define this force as an input or an output....
If you have any suggestion, I would greatly appreciate it ! Thanks
After the first two comments, I decided to add a picture that, I hope, will help you to understand the behaviour I'm trying to model.
On the left, you can see the four elements used to develop rheological models :
a : the spring
b : the linear damper (dashpot)
c : the non-linear damper
d : the slider
On the right, you can see the behaviour I'm trying to reproduce : a and b are two associations with springs and c and d are respectively the expected stress / strain curves. I'm trying to model the same behaviour, except that I'm thinking in terms of force and not stress. As i said in the comment to Marco's answer, the curve a reminds me the behaviour of a diode :
if the force applied to the component is less than the sliding limit, there is no relative displacement between the two flanges
if the force becomes greater than the sliding limit, the force transmitted by the system equals the limit and there is relative displacement between flanges
I can't be sure, but I suspect what you are really trying to model here is Coulomb friction (i.e. a constant force that always opposes the direction of motion). If so, there is already a component in the Modelica Standard Library, called MassWithStopAndFriction, that models that (and several other flavors of friction). The wrinkle is that it is bundled with inertia.
If you don't want the inertia effect it might be possible to set the inertia to zero. I suspect that could cause a singularity. One way you might be able to avoid the singularity is to "evaluate" the parameter (at least that is what it is called in Dymola when you set the Evaluate flat to be true in the command line). No promises whether that will work since it is model and tool dependent whether such a simplification can be properly handled.
If Coulomb friction is what you want and you really don't want inertia and the approach above doesn't work, let me know and I think I can create a simple model that will work (so long as you don't have inertia).
A few considerations:
- The force is not an input and neither an output, but it is just a relation that you add into the component in order to define how the force will be propagated between the two translational flanges of the component. When you deal with acausal connectors I think it is better to think about the degrees of freedom of your component instead of inputs and outputs. In this case you have two connectors and independently at which one of the two frames you will recieve informations about the force, the equation you implement will define how that information will be propagated to the other frame.
- I tested this:
model slider
extends
Modelica.Mechanics.Translational.Interfaces.PartialCompliantWithRelativeStates;
parameter Real flim = 1;
equation
f = if abs(f)>flim then sign(f)*flim else f;
end slider;
on Dymola and it works. It is correct modelica code so it should be work also in OpenModelica, I can't think of a reason why it should be seen as an unbalance mathematical model.
I hope this helps,
Marco

event location questions in MATLAB

Suppose in matlab the following:
[t, x, te, xe, ie] = ode15s(#myfunc, [tStart tFinal], x0, odeset('Events', #events));
Question 1
1a) The function events is called only after a successful step of the solver. Is this true?
1b) Just after the solver has made a successful step, is it possible that the last call of myfunc not be the call that lead to the successful step?
1c) If the events function contains multiple terminal events and upon a successful step it is detected that two of them (not just one) have occured, what would be the behavior of the solver?
Question 2
Suppose that myfunc contains the following code
if (check(x) > 2)
dx(3) = x(1)*x(2);
else
dx(3) = x(2)^2;
end
where check is some function of x.
One way to solve this problem is not use an events function. In my experience the ode solver can solve such problems that way.
The other way to solve this problem is use an events function to locate check(x) - 2 == 0, one terminal event for direction = 1 and another one for direction = -1. After the solver stops on either of the events a global variable eg myvar is set appropriately to distinguish between the two events, and then the simulation continues from where it stopped. In that case the code in myfunc will be
if (myvar == 1)
dx(3) = x(1)*x(2);
else
dx(3) = x(2)^2;
end
Both way yield correct results in simple cases. However I am trying to solve a very complex problem (additional events than the above and discontinous right-hand parts of the differential equations that are proven to be solvable at some cases) and I am trying to find out if the first way would yield different results than the second one.
One might tell that the ode would either fail to return a solution before tFinal or return a correct solution, but due to the discontinuity of the right-hand part the solver might not return a solution while a solution exists.
So in some sense, the question is: what is the practical-theoretical difference between using the first way and the second way?
Since I've spent some effort on these questions, I'm posting back some feedback.
Question 1
1a) Yes this is true. For reference see for example the ode15s.m matlab solver. However note that before the solver continues solving, the events function may be called several times for the sake of a more accurate te value.
1b) Yes this is also true.
1c) In this case the solver would terminate returning an ie vector containing the two (or even more) indexes of the events that stopped the solver. In that case, the te vector would contain equal elements (te(1) == te(2) will always return true). This is the only way to distiguish "double events" (meaning events that simultaneously stopped the solver after the same successful step) from "fake" events that are recorded when the ode solver continues solving after a terminal event (to understand better what I'm saying also read ode solver event location index in MATLAB ).
Tracing the odezero function will make 1c answer very clear.
Question 2
Now this is a tricky answer. **In general* both ways return correct results. However (and most naturally) they are not bound to return the exact solution points at the exact time points with the exact number of steps.
The notable difference between the two ways is that in the second one, we have a branch change only when a check(x)-2 sign change occurs using only the currently active branch. For example, suppose that the currently active branch is the first one. When the solver notices a sign change in check(x) - 2 after a successful step that was produced using only that branch, only then changes to the second branch. In simple words, both successful and unsuccessful steps are calculated using the very same branch before a use of the other branch can occur. However if we use the first way we may notice a use of the non-active branch during (for example) an unsucessful step.
With these in mind comes the verdict; the most general and strictly correct way to choose is the second one (using events). The first way should also return correct results. HOWEVER, due to the difference between the two ways, the first one could fail in very specific/extreme problems. I'm very tempted to provide information about my case, in which ONLY the second way could be safely used, but it truly is a long way to go.