Solving a simple puzzle in prolog - c

I solved a puzzle in C and tried to do the same in Prolog but i'm having some trouble expressing the facts and goals in this language.
The very simplified version of the problem is this: there's two levers in a room. Each lever control a mechanism that can move either forward or backward in four different positions (which i noted 0, 1, 2 or 3). If you move a mechanism four times in the same direction, it'll be in the same position as before.
The lever n°1 move the mechanism n°1 two positions forward.
The lever n°2 move the mechanism n°2 one position forward.
Initially, the mechanism n°1 is in position 2 and the mechanism n°2 is in position 1.
The problem is to find the quickest way to move both mechanisms in position 0 and get the sequence of lever that lead to each solution.
Of course here the problem is trivial and you only need to pull the lever n°1 one time and the lever n°2 three times to have a solution.
Here's a simple code in C which gives the sequence of lever to pull to solve this problem by pulling less than 5 levers:
int pos1 = 2, pos2 = 1;
int main()
{
resolve(0,5);
return 0;
}
void lever1(){
pos1 = (pos1 + 2) % 4;
}
void undolever1(){
pos1 = (pos1 - 2) % 4;
}
void lever2(){
pos2 = (pos2 + 1) % 4;
}
void undolever2(){
pos2 = (pos2 - 1) % 4;
}
void resolve(l, k){
if(k == 0){
return;
}
if(pos1 == 0 && pos2 == 0){
printf("Solution: %d\n", l);
return;
}
if(k>0){
k--;
lever1();
resolve(l*10+1,k);
undolever1();
lever2();
resolve(l*10+2,k);
undolever2();
}
}
My code in Prolog looks like this so far:
lever(l1).
lever(l2).
mechanism(m1).
mechanism(m2).
position(m1,2).
position(m2,1).
pullL1() :- position(m1, mod(position(m1,X)+2,4)).
pullL2() :- position(m2, mod(position(m2,X)+1,4)).
solve(k) :- solve_(k, []).
solve_(0, r) :- !, postion(m1, p1), postion(m2, p2), p1 == 0, p2 == 0.
solve_(k, r) :- k > 0, pullL1(), k1 is k - 1, append(r, [1], r1), solve_(k1, r1).
solve_(k, r) :- k > 0, pullL2(), k1 is k - 1, append(r, [2], r2), solve_(k1, r2).
I'm pretty sure there's multiple problems in this code but I'm not sure how to fix it.
Any help would be really appreciated.

I think this is a very interesting Problem. I suppose you want a general solution -> one lever can move multiple mechanisms. In the case the problem is like yours, where one lever only controls one mechanism the solution is trivial. You just move every lever for the amount of time until the mechanism is at state zero.
But I want to provide a more general solution, so where one lever can move multiple mechanisms. But first a little bit math. Don't worry i'll end up doing an example too.
Lets define
as being n levers and
being m mechanisms. Then lets define every lever by a vector:
where is the amount of steps moves forward.
For the mechanisms we define:
beeing the bias of the mechanisms -> so is in initial state and
being the amount of states for every mechanism. So now we can describe our whole system like this:
wher is the amount of times we have to activate . If we want to set all mechanisms to zero. If you are not familiar with the notation this just means that a%m = b%m.
can we rewritten as:
where k can be any natural number. So we can rewrite our system to an equation system:
prolog can solve for us such a equation system.
(there are different solutions to solve diophantine equation systems look at https://en.wikipedia.org/wiki/Diophantine_equation)
Ok now lets make an example: let say we have two levers and three mechanisms with 4 states. The fist lever moves M1 one forward and M3 two forward. The second lever moves M2 one forward and M3 one forward. M1 is in State 2. M2 is in State 3. M3 is in State 3. So our equation system looks like this:
in prolog we can solve this with the clpfd libary.
?- [library(clpfd)].
and then solve like this:
?- X1+(-4)*K1+2 #= 0, 1*X2+(-4)*K2+3 #= 0, 2*X1+X2+(-4)*K3+3 #= 0,Vs = [X1,X2], Vs ins 0..100,label(Vs).
which gives us the solution
Vs = [2, 1]
-> so X1 = 2 and X2 = 1 which is correct. Prolog can give you more solutions.

Related

may you explain this algorithm of calculate to average for noise

I am working on embedded programming with written code by other people.
this algorithm be used in calculate average for mic and accelerometer
sound_value_Avg = 0;
sound_value = 0;
memset((char *)soundRaw, 0x00, SOUND_COUNT*2);
for(int i2=0; i2 < SOUND_COUNT; i2++)
{
soundRaw[i2] = analogRead(PIN_ANALOG_IN);
if (i2 == 0)
{
sound_value_Avg = soundRaw[i2];
}
else
{
sound_value_Avg = (sound_value_Avg + soundRaw[i2]) / 2;
}
}
sound_value = sound_value_Avg;
acceleromter is similar to this
n1=p1
(n2+p1)/2 = p2
(n3+p2)/2 = p3
(n4+p3)/2 = p4
...
avg(n1~nx)=px
it not seems to be correct.
can someone explain why he used this algorithm?
is it specific way for sin graph? like noise, vibration?
It appears to be a flawed attempt at maintaining a cumulative mean. The error is in believing that:
An+1 = (An + sn) / 2
when in fact it should be:
An+1 = ((An * n) + s) / (n + 1)
However it is computationally simpler to maintain a running sum and generate an average in the usual manner:
S = S + s
An = S / n
It is possible that the intent was to avoid overflow when the sum grows large, but the attempt is mathematically flawed.
To see how wrong this statement is consider:
True
n s Running Avg. (An + sn) / 2
--------------------------------------
1 20 20 20
2 21 20.5 20.25
3 22 21 20.625
In this case however, nothing is done with the intermediate mean value, so you don'e in fact need to maintain a running mean at all. You simply need to accumulate a running sum and calculate the average at the end. For example:
sum = 0 ;
sound_value = 0 ;
for( int i2 = 0; i2 < SOUND_COUNT; i2++ )
{
soundRaw[i2] = analogRead( PIN_ANALOG_IN ) ;
sum += soundRaw[i2] ;
}
sound_value = sum / SOUND_COUNT ;
In this you do need to make sure that the data type forsum can accommodate a value of the maximum analogRead() return multiplied by SOUND_COUNT.
However you say that this is used for some sort of signal conditioning or processing of both a microphone and an accelerator. These devices have rather dissimilar bandwidth and dynamics, and it seems rather unlikely that the same filter would suit both. Applying robust DSP techniques such as IIR or FIR filters with suitably calculated coefficients would make a great deal more sense. You'd also need a suitable fixed sample rate that I am willing to bet is not achieved by simply reading the ADC in a loop with no specific timing

How to optimize valve simulation logic? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
This is an simple logic-programming and optimisation etude, that I've created for myself, and somewhat stumbled upon it.
I have a numerical simulation of simple scheme. Consider some reservoir (or a capacitor) Cm, which is constantly pumping up with pressure. Lets call its current state Vm:
At its output it has a valve, or a gate, G, that could be open or closed, according to following logic:
Gate opens, when pressure(or voltage) Vm exceeds some threshold, call it Vopen: Vm > Vopen
Gate remains open, while current outrush Ia is greater than some Ihold: Ia > IHold
Gate conducts power only out of reservoir (like a diode)
I am doing numerical ODE solving of this, i.e. determining Vm and Ia at each (equal, small) timestep dt. Have three variants of this:
Variable types:
float Vm=0.0, Ia=0.0, Vopen, Ihold, Ra, dt;
int G=0;
Loop body v1 (serial):
Vm = Vm + (-Ia*G)*dt;
G |= (Vm > Vopen);
Ia = Ia + (Vm*Ra*G)*dt;
G &= (Ia > Ihold);
Loop body v2 (serial, with temp var, ternary conditionals):
int Gv; // temporary var
Vm = Vm + (-Ia*G)*dt;
Gv = (Vm > Vopen) ? 1 : G;
Ia = Ia + (Vm*Ra*Gv)*dt;
G = (Ia > Ihold) ? Gv : 0;
Loop body v3 (parallel, with cache):
// cache new state first
float Vm1 = Vm + (-Ia*G)*dt;
float Ia1 = Ia + (Vm*Ra*G)*dt;
// update memory
G = ( Vm1 > Vopen ) || (( Ia1 > Ihold ) && G);
Vm = Vm1;
Ia = Ia1; // not nesesary to cache, done for readibility
the G was taken from building up the following truth table, plus imagination:
Q:
Which is correct? Are they?
How third variant(parallel logic) differs from first two(serial logic)?
Are there more effective ways of doing this logic?
PS. I am trying to optimize it for SSE, and then (separately) for OpenCL (if that gives optimisation hints)
PPS. For those who is curious, here is my working simulator, involving this gate (html/js)
By the overall description they are the same and should all fulfil your needs.
Your serial code will produce half-steps. That means if you break it down to the discrete description V(t) can be described as being 1/2 dt in front of I(t). The fist one will keep G changing in every half-step and the second one will synchronise it to I. But since you are not evaluating G in between in doesn't really matter. There is also no real problem with V and I being a half step apart but you should keep it in mind but maybe you should use for plotting/evaluation the vector {V(t),(I(t-1)+I(t))/2,G(t)}.
The parallel code will keep them all in the same time step.
For your pure linear problem the direct integration is a good solution. Higher order ode solver won't buy you anything. State-space representation for pure linear systems only write the same direct integration in a different way.
For SIMD optimisation there isn't munch to do. You need to evaluate step-wise since you are updating I by V and V by I. That means you can't run the steps in parallel which makes many interesting optimisation not possible.

In C, how to convert several boolean to int whose bits value are the results of differents tests

I want to convert several tests to an int which bits are the results of a test:
int i=0;
if (m>speed0) i|=0B00001;
if (m>speed1) i|=0B00010;
if (m>speed2) i|=0B00100;
if (m>speed3) i|=0B01000;
That seems very slow. Are there a better way ? Speed is very important (i'm on arduino)
One thing you could try is to build an "if-ladder" to only make one write to i; by rolling the lower bits into each the higher test's value, and reversing the order of the tests.
int i;
if (m > speed3) i = B00001111;
else if(m > speed2) i = B00000111;
else if(m > speed1) i = B00000011;
else if(m > speed0) i = B00000001;
else
i = 0;
This also cuts away the read-modify-write, since it always does a single write to i. You're still going to have to profile this, I really can't say if it's going to be faster.
Oh, and the thing that looks like a binary prefix (the B) is an Arduino-ism, not standard in C. I think it's just 256 preprocessor macros.
What about this one:
int i = (m>speed0) |
((m>speed1)<<1) |
((m>speed2)<<2) |
((m>speed3)<<3)
This will remove the branches so you will not suffer from branch mispredictions. This code should be very fast. However, note that a very good optimizing compiler might be able to transform your code to equivalent code and elide the branches. But with my solution, you can be sure that you will not suffer branch misses even with a poor optimizer.
Edit:
However, since you are on Arduino, branch misses are not an issue. Then, your code should be fine as well. Simply benchmark it. If yours is too slow try mine. But I guess, both should be fine.
I would go with an "if binary tree" since it is scalable and should have a performance of log2(n):
int i = 0; // Default m < speed 0
if(m > speed2)
if (m > speed3)
i = B00001111; // m > speed 3
else
i = B00000111; // m > speed 2
else
if(m > speed1)
i = B00000011; // m > speed 1
else if(m > speed0)
i = B00000001; // m > speed 0
Do profile this since jumps and memory access times are highly dependent on hardware architecture.

Noise cancellation setup - combining the microphone's signals intelligently [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I built a noise cancellation setup with two microphones and two different microphone preamplifiers that go to two different channels of a stereo recording.
Here is a sample
http://filestore.to/?d=U5FN2IH96K
I tried
char ergebnis[80];
sprintf(ergebnis, "%s.neu.raw", Datei);
FILE* ausgabe = fopen(ergebnis, "wb");
FILE* f = fopen(Datei, "rb");
if (f == NULL)
{
return;
}
int i = -1;
int r1 = 0;
int r2 = 0;
int l1 = 0;
int l2 = 0;
int l = 0;
int r = 0;
int wo = 0;
int dif = 0;
while (wo != EOF)
{
wo = getc(f);
i++;
if (i == 0)
{
r1 = (unsigned)wo;
}
if (i == 1)
{
r2 = (unsigned)wo;
r = (r2 << 8) + r1; //r1 | r2 << 8;
}
if (i == 2)
{
l1 = (unsigned)wo;
}
if (i == 3)
{
l2 = (unsigned)wo;
l = (l2 << 8) + l1; //l1 | l2 << 8;
dif = r - (l * 2);
putc((char)( (unsigned)dif & 0xff), ausgabe);
putc((char)(((unsigned)dif >> 8) & 0xff), ausgabe);
i = -1;
}
}
when the magic happens in
dif = r - (l * 2);
But this does not eliminate the noise surrounding it, all it does is create crackling sounds.
How could I approach this task with my setup instead? I prefer practical solutions over "read this paper only the author of the paper understands".
While we are at it, how do I normalize the final mono output to make it as loud as possible without clipping?
I don't know why you would expect this
dif = r - (l * 2);
to cancel noise, but I can tell you why it "create[s] crackling sounds". The value in dif is often going to be out of range of 16-bit audio. When this happens, your simple conversion function:
putc((char)( (unsigned)dif & 0xff), ausgabe);
putc((char)(((unsigned)dif >> 8) & 0xff), ausgabe);
will fail. Instead of a smooth curve, your audio will jump from large positive to large negative values. If that confuses you, maybe this post will help.
Even if you solve that problem, a few things aren't clear, not the least of which is that for active noise canceling to work you usually assume that one mike provides a source of noise and the other provides signal + noise. Which is which in this case? Did you just place two mikes next to each other and hope to hear some sound source with less ambient noise after some simple arithmetic? That won't work, since they are both hearing different combinations of signal and noise (not just in amplitude, but time as well). So you need to answer 1. which mike is the source of signal and which is the source of noise? 2. what kind of noise are you trying to cancel? 3. what distinguishes the mikes in their ability to hear signal and noise? 4. etc.
Update: I'm still not clear on your setup, but here's something that might help:
You might have a setup where your signal is strong in one mike and weak in the other, and a noise is applied to both mikes. In all likelyhood, there will be signal leak into both mikes. Nevertheless, we will assume
l = noise1
r = signal + noise2
Note that I have not assumed the same noise values for l and r, this reflects the reality that the two mikes will be picking up different noise values due to time delays and other factors. However, it is often the case (and may or may not be the case in your setup) that noise1 and noise2 are correlated at low frequencies. Thus, if we have a low pass filter, lp, we can achieve some noise reduction in the low frequencies as follows:
out = r - lp(l) = signal + noise2 - lp(noise1)
This, of course, assumes that the noise level at l and r is the same, which it may or may not be, depending on your setup. You may want to leave a manual parameter for this purpose for manual tuning at the end:
out = r - g*lp(l)
where g is your tuning parameter and close to 1. I believe in some high-end noise reduction systems, g is constantly tuned automatically.
Selecting a cutoff frequency for your lp filter is all that remains. An approximation you could use is that the highest frequency you can cancel has a wavelength equal to 1/4 the distance between the mikes. Of course, I'm REALLY waving my arms with that, because it depends a lot on where the sound is coming from, how directional your mikes are and so on, but it's a starting point.
Sample calculation for mikes that are 3 inches apart:
Speed of sound = 13 397 inches / sec
desired wavelength = 4*3 inches = 12 inches
frequency = 13,397 / 12 = 1116 Hz
So your filter should have a cutoff frequency of 1116 Hz if the mikes are 3 inches apart.
Expect this setup to cancel a significant amount of your signal below the cutoff frequency as well, if there is bleed.

How to make my robot move in a rectangular path along the black tape?

I am working on a robot, it's part of the summer robotics workshop in our college. We are using C-STAMP micro controllers by A-WIT. I was able to make it move, turn left, turn right, move backward. I have even managed to make it go along the black tape using a contrast sensor.
I send the robot at 30-45 degrees toward the black tape on the table and it aligns itself and starts to move along the black tape. It jerks a little, probably due to my programming logic below, it's running a while-loop and constantly checking if-statements, so it ends up trying to turn left and right every few milliseconds, which explains the jerking part. But it's okay, it works, not as smooth as I want it to work but it works! Problem is that I can't make my robot go into a rectangular path of the black tape. As soon as it reaches the corner of the black tape it just keeps going straight instead of making left or right turn.
My 2 sensors are located right underneath the robot, next to the front wheel, almost at the floor level. It has "index" value ranging from 0 to 8. Eight being the brightest contrast and zero being the darkest contrast. So when the robot moves into the black-tape-zone, the index value drops, and based on that, I have an if-statement telling my robot to either turn left or right.
Here's my attempt. To avoid confusion I didn't post the entire source code, but only the logical part responsible for the movement of my robot along the black tape.
while(1) {
// don't worry about these.
// 10 and 9 represent Sensor's PIN location on the motherboard
V = ANALOGIN(10, 1, 0, 0, 0);
V2 = ANALOGIN(9, 1, 0, 0, 0);
// i got this "formula" from the example in my Manual.
// V stands for voltage of the sensor.
// it gives me the index value of the sensor. 0 = darkest, 8 = lightest.
index = ((-(V - 5) / 5) * 8 + 0.5);
index2 = ((-(V2 - 5) / 5) * 8 + 0.5);
// i've tweaked the position of the sensors so index > 7 is just right number.
// the robot will move anywhere on the table just fine with index > 7.
// as soon as it drops to or below 7 (i.e. finds black tape), the robot will
// either turn left or right and then go forward.
// lp & rp represent left-wheel pin and right-wheel pin, 1 means run forever.
// if i change it from 1 to 100, it will go forward for 100ms.
if (index > 7 && index2 > 7)
goForward(lp, rp, 1);
if (index <= 7) {
turnLeft(lp, rp, 1);
goForward(lp, rp, 1);
// this is the tricky part. i've added this code last minute
// trying to make my robot turn, but i didn't work.
if (index > 4) {
turnLeft(lp, rp, 1);
goForward(lp, rp, 1);
}
}
else if (index2 <= 7) {
turnRight(lp, rp, 1);
goForward(lp, rp, 1);
// this is also the last minute addition. it's same code as above
// but it's for the 2nd sensor.
if (index2 > 4) {
turnRight(lp, rp, 1);
goForward(lp, rp, 1);
}
}
}
I've spent the entire day trying to figure it out. I've pretty much exhausted all avenues. Asking for the solution on stackoverflow is my very last option now.
Thanks in advance!
If you have any questions about the code, let me know, but comments should be self-explanatory.
This is my goForward function in case anyone wonders:
void goForward(BYTE lp, BYTE rp, WORD t)
{
WORD i;
for(i = 0; i < t; i = i + 1){
PULSOUT(lp, 400, 1, 1);
PULSOUT(rp, 800, 1, 1);
PAUSE(17);
}
}
UPDATE: Here's what I've come up with so far. I've erased all my if-statements that I've posted earlier and decided to write the logic from scratch:
// if there's enough bright light in both sensors at the same time
// robot will move forward forever.
if (index > 7 && index2 > 7)
goForward(lp, rp, 1);
// but if there's not enough bright light anymore (i.e. reached black tape)
// proceed to the else-statement.
else {
// if left sensor detects the black tape then turn right
// if doesn't detect the black tape then keep going forward
if (index2 <= 7)
turnRight(lp, rp, 1);
else
goForward(lp, rp, 1);
// if right sensor detects the black tape then turn left
// if it doesn't detect the black tape then keep going forward
if (index <= 7)
turnLeft(lp, rp, 1);
else
goForward(lp, rp, 1);
}
// The reason for turnLeft and turnRight is to keep robot re-alligning
// to the black tape. It will happen so fast (every 1ms) that the jerking
// shouldn't even be noticeable.
You need to trap the sudden occurrence: [cycle n] "I see the tape" -> [cycle n+1] "I don't see the tape" that happens when you encounter a corner.
A state machine is a good way of handling this type of problem. With a state machine the code for a specific state is isolated, it only runs when the state is true. This isolation prevents "cross-talk" and gives you one known code block for each state.
Given your example the flow might be something like:
:Loop
State == Moving forward and on tape.
read sensors
delta = abs(valueLastCycle - valueThisCycle);
if (delta >= bigChangeValue){
// the tape was just gone.
// change state and handle this situation.
CurrentState = suddenValueChange;
}else
if (index <= 7) {
turnLeft(lp, rp, 1);
goForward(lp, rp, 1);
else if (index2 <= 7) {
turnRight(lp, rp, 1);
goForward(lp, rp, 1);
}
...
State == suddenValueChange
...
code that handles sudden value change event
maybe:
Stop Robot;
Move backwards slowly until on tape or distance x
etc...
Goto Loop
Increasing the scan rate might seem to help....but the faster the robot moves the faster your scan rate....i.e. You might still jump from on tape -> off tape in which case your current code flounders.
My guess is that the goForward immediately after the turnLeft/TurnRight "cancels" the turning?
It depends on how turning is implemented though
Make sure your "plan" makes sense before worrying about the code.
Start by moving the robot around by hand and observing when the sensors pass over black and white areas. Try to come up with a behaviour, and simulate it by hand. If this doesn't work as you want, then you need to revise the behaviour.
A suggestion: You may wish to add some more loops to ensure that if something seems wrong, the robot corrects itself before resuming normal behaviour. (E.g. rather than turning right/left for 100ms, do that behaviour as long as it takes for the sensors to see the right thing.)
Does your while loop run fast enough to catch a corner? If both sensors report that they are on the tape, and in the next cycle both sensors are off the tape, you can't detect that, right? The sensor reports the same values (8) for being on the tape and off the tape?
Try making your code faster. Without seeing the entire code, it's hard to make a recommendation, but it seems that you might be evaluating if statements that are not necessary. Add an ELSE after the first IF, once you know that you are going straight.
It seems that your goforward implementation is blocking the loop for too long. 1 does not mean run forever, it does one pass of the for-loop, and then you PAUSE 17 (msec?). What's the PAUSE for? Remove it. This probably causes the jerking, and it prevents the next set of sensor values from coming in.
Right now, by the looks of your code, every time the robot sees black, it goes forward forever. I'm not really sure how going forward is implemented.
In pseudocode, your code says:
if you see black
go forward forever
if you don't see black
turn left or right
Do you see how your robot would go forward forever with that kind of logic? Again, I have no idea how going forward is implemented so I could be wrong.

Resources