Sign in to follow this  
Followers 0
Mat

Negative bases

30 posts in this topic

Here's a fun little bit of theory for you :) I wouldn't usually ask this sort of stuff, I'd spend days trying to figure it out myself, but I think other people are going to like this one.

123.456 in base -10 should be: 284.664

Why? Well, if you apply the rules for normal numeric bases, it is possible:

2 * (-10)^2 = 200

8 * (-10)^1 = -80

4 * (-10)^0 = 4

6 * (-10)^-1 = -0.6

6 * (-10)^-2 = 0.06

4 * (-10)^-3 = -0.004

The sum of all of those is 123.456, so it works *in theory*.

Has anyone got any idea how that would look as a computer program? Obviously the traditional method is not going to work. I've been racking my brains to try and describe the method of doing it by hand as a program but it made me realise I was using trial and error a lot of the time.

I suppose a related problem is log-b(a), as it should be complex, but ceiling(log) is also supposed to be the number of digits needed to display the number.

For those interested, here is my version for positive bases (greater than 2). Ideally I need a simple modification to support negatives. Not going to happen though.

#include <stdio.h>
#include <stdlib.h>

char* tobase( int, int );
unsigned int ilog2( unsigned int );

int main( int argc, char* argv[] )
{
    int ret;
    int n;
    int base;
    char* t;

    if ( argc != 3 )
    {
        puts( "Usage: tobase NUMBER BASE" );
        ret = 1;
    }
    else
    {
        n = atoi( argv[1] );
        base = atoi( argv[2] );

        t = tobase( n, base );

        if ( t == NULL )
        {
            ret = 2;
            puts( "Error." );
        }
        else
        {
            puts( t );
            free( t );
            ret = 0;
        }
    }

    return ret;
}

char* tobase( int i, int base )
{
    const char symbols[] =
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";

    char* ret;
    int lbn;
    int neg;
    int c;

    if ( ( base < 2 ) || ( base > 64 ) )
    {
        ret = NULL;
    }
    else
    {
        if ( i < 0 )
        {
            neg = 1;
            i = -i;
        }
        else
        {
            neg = 0;
        }

        lbn = ilog2( i ) / ilog2( base ) + 1;

        c = lbn + neg;
        ret = ( char* )malloc( ( c + 1 ) * sizeof( char ) );
        ret[c--] = '\0';

        if ( neg )
        {
            ret[0] = '-';
        }

        do
        {
            ret[c--] = symbols[i % base];
            i /= base;
        }
        while ( i );
    }

    return ret;
}

unsigned int ilog2( unsigned int i )
{
    unsigned int ret;

    ret = 0;

    if ( i > 0xFFFF )
    {
        ret = 16;
        i >>= 16;
    }

    if ( i > 0xFF )
    {
        i >>= 8;
        ret |= 8;
    }

    if ( i > 0xF )
    {
        i >>= 4;
        ret |= 4;
    }

    if ( i > 0x3 )
    {
        i >>= 2;
        ret |= 2;
    }

    ret |= ( i >> 1 );

    return ret;
}

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Please excuse my dear Aunt Sally.

2 * -10 ^ 2 = X

-10 ^ 2 = 100

2 * 100 = 200

x = 200

Nevermind, you knew that already. I thought you were wanting to multiply (2 * -10) and then raise.

Edited by LaCastiglione

Share this post


Link to post
Share on other sites

Is this the naive method?

Global Const $arr1[6] = [2, 8, 4, 6, 6, 4]

Global $total = 0
Global $j = 0

For $i = 2 To -3 Step -1
    $total += $arr1[$j] * (-10 ^ $i)
    $j += 1
Next

ConsoleWrite($total & @CRLF)

Share this post


Link to post
Share on other sites

Hahaha; and I thought the things I try out were crazy. You have created a non-contingeous numeric system. :)

Share this post


Link to post
Share on other sites

It's very weird counting in negative bases.... Goes up in length by two digits rather than 1. There is definitely a pattern though, it's just difficult to describe.

10  |    -2    | -10  |
-----+----------+------+
 1   |  1       |  1   |
 2   |  110     |  2   |
 3   |  111     |  3   |
 4   |  100     |  4   |
 5   |  101     |  5   |
 6   |  11010   |  6   |
 7   |  11011   |  7   |
 8   |  11000   |  8   |
 9   |  11001   |  9   |
 10  |  11110   |  190 |
 11  |  11111   |  191 |
 12  |  11100   |  192 |
 13  |  11101   |  193 |
 14  |  10010   |  194 |
 15  |  10011   |  195 |
 16  |  10000   |  196 |
 17  |  10001   |  197 |
 18  |  10110   |  198 |
 19  |  10111   |  199 |
 20  |  10100   |  180 |
 21  |  10101   |  181 |
 22  |  1101010 |  182 |
 ... |    ...   |  ... |

I'd like to see addition using these :) Possibly an interesting way to encrypt data:

132 101 108 108 291 164 172 127 291 294 108 100 173

Share this post


Link to post
Share on other sites

??? ...

Yes, there are negative bases. They aren't used much, but they are

quite interesting. They allow you to represent both positive and

negative numbers with only positive digits. For example, if the base

is -2, then you have the following equalities:

Base 10 Base -2

-11 110101

-10 1010

-9 1011

-8 1000

-7 1001

-6 1110

-5 1111

-4 1100

-3 1101

-2 10

-1 11

0 0

1 1

2 110

3 111

4 100

5 101

6 11010

7 11011

8 11000

9 11001

10 11110

11 11111

12 11100

13 11101

14 10010

15 10011

16 10000

( http://mathforum.org/library/drmath/view/55710.html )

Aha, Making a little more sense.


"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

A use, yes, but how practical is that? Shouldn't negatives be clearly distinguishable from their positive counterpart?

Share this post


Link to post
Share on other sites

Perhaps it's not practical. But it's possible. I'm not interested in this for a specific practical use.

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

It's late. That was the hardest thing I think I've ever tried to code. Was it worth it? Hell yeah.

Base converter up to base +-64 using only integer arithmetic, and it calculates the buffer size first. Bases greater than ip-like form should be a piece of cake. Negative bases less than -64? F***.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* tobase( int, int );
unsigned int ilog2( unsigned int );
int py_div( int, int );
int py_mod( int, int );

int main( int argc, char* argv[] )
{
    int ret;
    int n;
    int base;
    char* t;

    if ( argc != 3 )
    {
        puts( "Usage: tobase NUMBER BASE" );
        ret = 1;
    }
    else
    {
        n = atoi( argv[1] );
        base = atoi( argv[2] );

        t = tobase( n, base );

        if ( t == NULL )
        {
            ret = 2;
            puts( "Error." );
        }
        else
        {
            puts( t );
            free( t );
            ret = 0;
        }
    }

    return ret;
}

char* tobase( int i, int base )
{
    const char symbols[] =
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";

    char* ret;
    int lbn;
    int neg;
    int c;
    int rem;

    if ( ( ( base > -2 ) && ( base < 2 ) ) || ( base > 64 ) || ( base < -64 ) )
    {
    ret = NULL;
    }
    else if ( base < 0 )
    {
        if ( i < 0 )
        {
            neg = 1;
            lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );
        }
        else
        {
            neg = 0;
            lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );
        }
    
        if ( lbn % 2 == neg )
        {
            lbn++;
        }

        c = lbn;
        ret = ( char* )malloc( c + 1 );
        ret[c--] = '0';

        do
        {
            rem = py_mod(i, base);

            i = py_div(i, base);

            if ( rem < 0 )
            {
                i++;
                rem -= base;
            }

            ret[c--] = symbols[rem];
        } while ( i );
    }
    else
    {
        if ( i < 0 )
        {
            neg = 1;
            i = -i;
        }
        else
        {
            neg = 0;
        }

        lbn = ilog2( i ) / ilog2( base ) + 1;

        c = lbn + neg;
        ret = ( char* )malloc( ( c + 1 ) * sizeof( char ) );
        ret[c--] = '0';

        if ( neg )
        {
            ret[0] = '-';
        }

        do
        {
            ret[c--] = symbols[i % base];
            i /= base;
        }
        while ( i );
    }

    return ret;
}

unsigned int ilog2( unsigned int n )
{
    unsigned int ret;

    if (n == 0)
        return -1;

    ret = 0;

    if (n >= (1 <<16)) { n >>= 16; ret += 16; }
    if (n >= (1 << 8)) { n >>=  8; ret +=  8; }
    if (n >= (1 << 4)) { n >>=  4; ret +=  4; }
    if (n >= (1 << 2)) { n >>=  2; ret +=  2; }
    if (n >= (1 << 1)) {           ret +=  1; }

    return ret;
}

int py_div( int a, int b )
{
    int ret;

    ret = ( a - py_mod( a, b ) ) / b;

    return ret;
}

int py_mod( int a, int b )
{
    int ret;

    if ( a < 0 )
    {
        if ( b < 0 )
        {
            ret = -((-a) % (-b));
        }
        else
        {
            ret = a % b;
        }
    }
    else
    {
        if ( b < 0 )
        {
            ret = a % -b;
            if ( ret )
            {
                ret += b;
            }
        }
        else
        {
            ret = a % b;
        }
    }

    return ret;
}

Edit: Final version (apart from floats which will follow shortly):

Only bases it won't do are those that can't be expressed as integers, and 1, 0 and -1. Not sure if they are defined at all though. Base 1 is just a tally right? 111111 = 510 etc.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char symbols[] =
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";

char* tobase( int, int );
char* tobase_neg( int, int );
char* tobase_pos( int, int );
char* tobase_neg64( int, int );
char* tobase_pos64( int, int );
unsigned int ilog2( unsigned int );
int py_div( int, int );
int py_mod( int, int );

int main( int argc, char* argv[] )
{
    int ret;
    int n;
    int base;
    char* t;

    if ( argc != 3 )
    {
        puts( "Usage: tobase NUMBER BASE" );
        ret = 1;
    }
    else
    {
        n = atoi( argv[1] );
        base = atoi( argv[2] );

        printf( "%i to base %in", n, base );

        t = tobase( n, base );

        if ( t == NULL )
        {
            ret = 2;
            puts( "Error." );
        }
        else
        {
            puts( t );
            free( t );
            ret = 0;
        }
    }

    return ret;
}

char* tobase_neg( int i, int base )
{
    char* ret;
    int lbn;
    char** parts;
    int n;
    int l;
    int rem;

    if ( i < 0 )
    {
        lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );

        if ( lbn % 2 != 0 )
        {
            lbn++;
        }
    }
    else
    {
        lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );

        if ( lbn % 2 == 0 )
        {
            lbn++;
        }
    }

    parts = ( char** )malloc( sizeof( char* ) * lbn );

    n = lbn - 1;

    do
    {
        rem = py_mod(i, base);

        i = py_div(i, base);

        if ( rem < 0 )
        {
            i++;
            rem -= base;
        }

        l += asprintf( &parts[n--], "%i", rem );
    } while ( i );

    l += lbn;
    ret = ( char* )malloc( l + 1 );
    ret[0] = '0';

    for ( n = 0; n < lbn; n++ )
    {
        strcat( ret, parts[n] );

        if ( n + 1 < lbn )
        {
            strcat( ret, "." );
        }

        free( parts[n] );
    }

    free( parts );

    return ret;
}

char* tobase_pos( int i, int base )
{
    char* ret;
    int lbn;
    int neg;
    char** parts;
    int n;
    int l;

    if ( i < 0 )
    {
        neg = 1;
        i = -i;
    }
    else
    {
        neg = 0;
    }

    lbn = ilog2( i ) / ilog2( base ) + 1;

    parts = ( char** )malloc( sizeof( char* ) * lbn );

    n = lbn - 1;

    do
    {
        l += asprintf( &parts[n--], "%i", i % base );
        i /= base;
    }
    while ( i );

    l += lbn + neg;
    ret = ( char* )malloc( l + 1 );

    if ( neg )
    {
        ret[0] = '-';
        ret[1] = '0';
    }
    else
    {
        ret[0] = '0';
    }

    for ( n = 0; n < lbn; n++ )
    {
        strcat( ret, parts[n] );

        if ( n + 1 < lbn )
        {
            strcat( ret, "." );
        }

        free( parts[n] );
    }

    free( parts );

    return ret;
}

char* tobase_neg64( int i, int base )
{
    char* ret;
    int lbn;
    int neg;
    int c;
    int rem;

    if ( i < 0 )
    {
        neg = 1;
        lbn = ( ilog2( -i * -base + -i + base ) / ilog2( -base ) );
    }
    else
    {
        neg = 0;
        lbn = ( ilog2( i * -base + i + base ) / ilog2( -base ) );
    }

    if ( lbn % 2 == neg )
    {
        lbn++;
    }

    c = lbn;
    ret = ( char* )malloc( c + 1 );
    ret[c--] = '0';

    do
    {
        rem = py_mod(i, base);

        i = py_div(i, base);

        if ( rem < 0 )
        {
            i++;
            rem -= base;
        }

        ret[c--] = symbols[rem];
    } while ( i );

    return ret;
}

char* tobase_pos64( int i, int base )
{
    char* ret;
    int lbn;
    int neg;
    int c;

    if ( i < 0 )
    {
        neg = 1;
        i = -i;
    }
    else
    {
        neg = 0;
    }

    lbn = ilog2( i ) / ilog2( base ) + 1;

    c = lbn + neg;
    ret = ( char* )malloc( ( c + 1 ) * sizeof( char ) );
    ret[c--] = '0';

    if ( neg )
    {
        ret[0] = '-';
    }

    do
    {
        ret[c--] = symbols[i % base];
        i /= base;
    }
    while ( i );

    return ret;
}

char* tobase( int i, int base )
{
    char* ret;

    if ( base < -64 )
    {
        ret = tobase_neg( i, base );
    }
    else if ( base <= -2 )
    {
        ret = tobase_neg64( i, base );
    }
    else if ( base > 64 )
    {
        ret = tobase_pos( i, base );
    }
    else if ( base >= 2 )
    {
        ret = tobase_pos64( i, base );
    }
    else
    {
        ret = NULL;
    }

    return ret;
}

unsigned int ilog2( unsigned int n )
{
    unsigned int ret;

    if (n == 0)
        return -1;

    ret = 0;

    if (n >= (1 <<16)) { n >>= 16; ret += 16; }
    if (n >= (1 << 8)) { n >>=  8; ret +=  8; }
    if (n >= (1 << 4)) { n >>=  4; ret +=  4; }
    if (n >= (1 << 2)) { n >>=  2; ret +=  2; }
    if (n >= (1 << 1)) {           ret +=  1; }

    return ret;
}

int py_div( int a, int b )
{
    int ret;

    ret = ( a - py_mod( a, b ) ) / b;

    return ret;
}

int py_mod( int a, int b )
{
    int ret;

    if ( a < 0 )
    {
        if ( b < 0 )
        {
            ret = -((-a) % (-b));
        }
        else
        {
            ret = a % b;
        }
    }
    else
    {
        if ( b < 0 )
        {
            ret = a % -b;
            if ( ret )
            {
                ret += b;
            }
        }
        else
        {
            ret = a % b;
        }
    }

    return ret;
}
Edited by Mat

Share this post


Link to post
Share on other sites

Actually this is interesting from a theoretical perspective. The negative base idea is still a bit baffling and I still can't think of any uses outside encryption.

I just got to thinking about the standard nomenclature for larger numeric bases and figured that adding additional letters and symbols is overly confusing. Using double digits makes more sense. We do this with sexagesimal every time we look at a clock, and it doesn't cause any problems. If two hex digits were used to represent each number we can increase the number of practical bases to 254.

Share this post


Link to post
Share on other sites

Thats plausible, but the common way to do it is put dots between the 'digits' like you get in an ip address. An ip address is just a base 256 number.

Share this post


Link to post
Share on other sites

Of course. ;):)

I might experiment a bit with this, perhaps make a base 240 clock which rolls over every 4 hours (240 mins) or something.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Base 1 is just a tally right? 111111 = 510 etc.

That's correct and you can use any symbol to represent it, not just 1 (at least that's what a professor told me).

I've been lurking for 7 years. Finally decided to post.

Edited by JohnQSmith
1 person likes this

Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Share this post


Link to post
Share on other sites

Lurker or no lurker... Welcome to the forums :) You've been here longer than me. Twice as long as me actually ;)

To keep consistent it should be a zero. What about decimals in base 1 :D Now that is a very interesting question. I don't think it's possible but ah well.

Share this post


Link to post
Share on other sites

Here's what Wikipedia says about unary numbers. They don't mention decimals or would that be unimals?


Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

111111 = 510

To keep consistent it should be a zero.

Your sure about that ... zero not really being a value, other than indication the lack of one. (Romans did there math(well, counting) whiteout it ... poor basters. :) ) Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • scintilla4evr
      By scintilla4evr
      An advanced mathematics UDF written in AutoIt.
      Features:
      Extending the default mathematical library with functions like Sec, ACsc... Advanced mathematical functions like Riemann's zeta, etc. Differentiating functions Calculating the probability of an event Working with natural numbers (GCD, LCM, primes, ...) Number sequences Working with points in 2D-space Finding paths in a graph And more!
    • RTFC
      By RTFC
      Simulated Annealing (SA) is a simple technique for finding an acceptable solution (but not necessarily always the absolute best one that exists!) to very hard combinatorial problems, that is, ones for which a brute-force approach of cycling through all possible alternatives to find the global optimum just takes too darn long. Typically, one would be seeking some specific sequence or permutation of a (sub)set, and the number of possibilities is astronomically large. In addition, for SA to be applicable, you'll need to be able to quantify in some way how good any particular trial solution is, or how far distant from the ideal result. The real power of SA lies in these so-called cost functions; you can define as many as you like, with different weights if you like, and these conditions are even allowed to be conflicting. User-defined settings define how tenaciously it should be exploring solution space before homing in on a region with desirable properties, and finding its minimum. You can think of it as a learning algorithm that is allowed to make lots of mistakes in the beginning, before gradually avoiding ever more potentially bad decisions.
      A simple Analogy:
      You're standing in the middle of an extensive, rough terrain with hills, ridges, bumps, valleys, and tiny, deep depressions. You've got a GPS altimeter to tell you how high above sea-level you currently are, but this area is perpetually shrouded in thick fog. Now find the lowest point. And quickly please. Now what? There's no time to systematically grid and traverse the entire area, and you cannot see more than a few feet ahead. Following the local gradient down-slope will likely get you stuck at a very local minimum, whereas a much lower point may be just beyond the hext hill.
      Luckily, you brought your magic boots (the red ones with the twinkling silver stars). These allow you to make huge leaps through the fog, landing safely somewhere else. And although you don't know in advance where you'll end up, the boots magically remember their last-previous departure point, so if you don't like your new surroundings, you can go back one jump (but never more than that). Now to find the lowest point in the landscape, you keep tracking your altimeter changes with every jump. Some jumps will get you to higher ground, others might land you in a deep valley. The trick is not to settle for ever-lower heights immediately, but to allow going back up ever so often, so you can get beyond some high ridge behind which you might find a much lower depression than your best-previous result. Crucially, to decide whether or not to gain height in the misty terrain, you roll some dice you've got in your pocket, and the more jumps you've made, the lower you make the upper bound below which you would still go back uphill. So in the beginning you'll be jumping all over the place (allowing you to sample the terrain extensively), but eventually you'll be limiting yourself to some deep valley you've found, which might be the deepest one all round, but even if not, it will still be a pretty good guess. And you will have found this deep valley in a tiny fraction of the time it would take to do a full land survey.
      Simulated annealing needs to be defined in terms of the specific problem you're trying to solve. So it's not possible to provide you with a generic UDF that'll figure out in advance what your ideal solution would look like (for example, in the analogy above, we might be looking for the highest point instead of the lowest one). You need to define that ideal in terms of one or more cost functions that SA will then attempt to minimise. What can be done is to provide you with specific examples.
      Example 1.
      From a list of user-defined pre-supplied values, select the fewest terms that sum to (or approximate) a predefined target total. This solution was written in response to this thread. Current cost updates are periodically written to console. This example attempts to satisfy two conditions simultaneously: getting a sum that matches the target, and using the smallest number of terms.
      ; Simulated Annealing example (combinatorial minimisation), by RTFC (22 Feb 2016) ; Note that this algorithm converges on A *local* minimum (in terms of the ; user-defined cost-function(s)), which is not necessarily THE *global* minimum. ; Note also that the search path, duration, and final result may differ from run to run. ; Several parameters can be tweaked to adjust this. #include <Array.au3> #include <Math.au3> Global $temperat,$path,$kk,$nswap,$nswapstep,$cost,$altcost,$tempstep Global $costadjust,$ttlsites,$totalcost,$factor,$maxsumlength,$maxsize Global $site1,$site2,$index1,$index2,$weight_sum,$weight_length Global $options,$sumlength,$prevlength ; initialise SRandom(@SEC+@AutoItPID) ; initialise radnomising seed $verbose=True ; T: write regular progress updates to console $factor=1 ; optional Oracle-response adjustment (not used here) $prevlength=$sumlength ; to enable reverting to previous state after _TryChange $minsumlength=0 ; if nothing else is know, we'll start with a single array entry (base-0) $options=10 ; larger value = larger likelihood of swapping vs changing sumlength if $options<3 then Exit ; minimum size for this set-up (see Func _TrySwap) ; adjust the balance of conditions here (see _Cost function) $weight_sum=1 ; relative importance of matching condition 1 (sum = target) $weight_length=1 ; relative importance of matching condition 2 (lowest number of terms) ; summation results buffer Global $bestsum[10] Global $bestsumlength=UBound($bestsum) ; define the summation result we wish to achieve (try different values here!) $target = 27 ; Note: if you change this value, you may have to adjust $minsumlength below as well! ; define our array of summation terms to select from $dim=9 ; this is just the way this problem was presented $ttlsites=$dim*$dim $maxsize=$ttlsites-1 $maxsumlength=$ttlsites-2 ; need at least one tail slot for swapping ; enable this for the predefined problem... $doIntegerTest=True ; False if $doIntegerTest Then Global $aArray = [9,2,2,3,1,1,6,3,4, _ 4,2,3,4,5,6,7,8,7, _ 7,2,3,4,5,1,7,2,2, _ 2,2,3,1,5,5,7,1,4, _ 3,2,1,2,3,6,6,6,4, _ 3,2,3,4,5,6,7,8,3, _ 2,2,3,8,1,4,7,1,2, _ 1,7,3,5,5,6,7,1,2, _ 7,2,3,7,5,1,7,8,9] ; in this specific case, we already know that we'll need at least 4 terms ; because a) 9=max value in array, b) there are only 2 nines in the array, and c) target =3x9 $minsumlength=3 ; base-0, so 4 entries altogether Else ; OR use this for random floats in range 1-$dim (just as an example) Global $aArray[$ttlsites] For $cc=0 to $maxsize $aArray[$cc]=random(1,$dim,0) ; non-integer values used here! Next ; no clue about this constraint in this case $minsumlength=0 ; one entry (base-0) EndIf ;______START OF ANNEALING ROUTINE____________ $nover =1000 ; maximum number of changes at any temperature (for more complicated problems, set this several orders of magnitude higher) $nlimit=Int($nover/4) ; maximum number of successful changes before continuing $nwrite=Int($nover/5) ; default status update interval if verbose=.t. $tempsteps=100 ; number of temperature steps to try $tfactor=0.95 ; annealing schedule: temperature is reduced by this factor after each step While True $temperat=0.5 ; initial temperature; smaller = more aggressive + more myopic search $absimp=0 ; counter $nswapstepzero=0 ; counter $sumlength=$minsumlength ; base-0 ; prep the cost vars $totalcost=_Cost() $cost=$totalcost $lowestcost=$totalcost $initcost=$totalcost ; main loop starts here For $tempstep=1 to $tempsteps ; try up to N temperature steps $nswap=0 $nswapstep=0 For $kk=1 to $nover _TrySwap() ; swap and determine cost adjustment Switch _AskOracle() ; Feel the Force, Luke. Case True $nswap+=1 $totalcost+=$costadjust $cost=$altcost If $lowestcost>$totalcost Then $nswapstep+=1 $absimp+=1 $lowestcost=$totalcost ; ensure results buffer is sufficiently large If $bestsumlength<=$sumlength Then $bestsumlength+=5 ReDim $bestsum[$bestsumlength] EndIf ; flush current-best summation For $bc=0 to $sumlength-1 $bestsum[$bc]=$aArray[$bc] Next ; pad tail with zeroes For $bc=$sumlength to $bestsumlength-1 $bestsum[$bc]=0 Next _ScreenOut() If $totalcost<=0 Then ExitLoop Endif Case Else ; restore the previous state $sumlength=$prevlength $aArray[$index1]=$site1 $aArray[$index2]=$site2 EndSwitch ; show we're still alive If $verbose And mod($kk,$nwrite)=0 Then _ScreenOut() If $nswap>=$nlimit Or $lowestcost<=0 then ExitLoop Next ; optional early-out scenario (disable for a more thorough search) If $nswapstep=0 then $nswapstepzero+=1 If $nswapstepzero=10 then ExitLoop ; no more improvements in the last N temperature steps ; reduce temperature = likelihood of following a trajectory away from the nearest LOCAL optimum (in the hope of getting nearer to the GLOBAL optimum) $temperat*=$tfactor Next ; present final result _Arraysort($bestsum) ; just for clarity $summation="Best result so far (at a cost of " & $lowestcost & ") is: " & @CRLF $terms=0 $result=0 For $cc=0 to $sumlength If $aArray[$cc]>0 then $summation&=$aArray[$cc] & "+" $result+=$aArray[$cc] $terms+=1 Endif Next $summation=StringTrimRight($summation,1) & " = " & $result & " (target = " & $target & ")" & @CRLF $summation&="Number of summation terms: " & $terms & @CR & "Temperature steps: " & $tempstep & @CR & @CR & "Press <Ok> to try again, <Cancel> to Quit" if Msgbox($MB_OKCANCEL,"Simulated Annealing Test Result",$summation)=$IDCANCEL then Exit ; shuffle entries a bit for variety For $cc=1 to $maxsize*10 $index1=random(0,$maxsize,1) $index2=random(0,$maxsize,1) $tmp=$aArray[$index1] $aArray[$index1]=$aArray[$index2] $aArray[$index2]=$tmp Next WEnd Exit Func _AskOracle() If $costadjust<0 Then Return True Else ; this is where all the magic happens! Return (random()<Exp(-($costadjust*$factor)/$temperat)) Endif EndFunc Func _TrySwap() $index1=0 ; these vars are all Globals $index2=0 $altcost=0 $prevlength=$sumlength ; decide whether to reduce/increase number of terms, or swap an existing term Switch Random(1,$options,1) Case 1 ; crop $sumlength=_Max($minsumlength,$sumlength-1) Case 2 ; extend $sumlength=_Min($maxsumlength,$sumlength+1) Case Else ; this likelhood is determined by the value of $options (>=3) $index1=random(0,$sumlength,1) $index2=random($sumlength+1,$maxsize,1) EndSwitch ; store current contents, in case we decide later that this was a bad idea $site1=$aArray[$index1] $site2=$aArray[$index2] ; swap contents for now $aArray[$index1]=$site2 $aArray[$index2]=$site1 ; compute the new sum (as either length or content has changed) $altcost=_Cost() ; performance difference between original and new state $costadjust=$altcost-$cost ; $cost is already filled in previous pass EndFunc Func _Cost() Local $cc,$result=0 For $cc=0 to $sumlength $result+=$aArray[$cc] Next Return (Abs($result-$target)*$weight_sum) + (($sumlength-$minsumlength)*$weight_length) EndFunc Func _ScreenOut() ConsoleWrite("Simulated Annealing. Initial total cost: " & $initcost & @CRLF) ConsoleWrite("Step: " & $tempstep & " of " & $tempsteps & "; Temperature: " & $temperat & @CRLF) ConsoleWrite("Executed Swaps: " & $nswap & "; Lowest Cost so far: " & $lowestcost & @CRLF) ConsoleWrite("Total Improvements: " & $absimp & "; Improvements this step: " & $nswapstep & @CRLF & @CRLF) EndFunc  
      Example 2. The Travelling Salesman problem (TSP)
      This is a classic combinatorial minimisation problem, and relevant to real-world logistics: to find the shortest route for visiting all cities exactly once, before returning to the original starting point. As it is quite entertaining to see how the algorithm gradually solves this brain teaser,  I've added a simple GUI that visualises the cities (red circles) and the changing routes between them (blue). The problem becomes exponentially harder to solve when the number of cities is increased. This example (adapted from Press et al., Numerical recipes, 2nd ed., pp. 438-443) employs a single cost function of the total route distance.
      TSP.au3
      It's important to stress that simulated annealing cannot guarantee that the global optimum will always be found, only that it will likely come up with a fairly good solution, and much faster than brute force ever could. If that's good enough for you, then those red, silver-starred boots might fit you too.
       
       
    • Wicked_Caty
      By Wicked_Caty
      I've written a short program that calculates all values of a mathematical function in a user-defined interval. The data is written to an user-defined file during that process. Unfortunately, there is no file. I don't have a clue what's wrong with my program, and I've been trying to solve that for nearly 2 hours now. Obviously without success.
      The calculation is done properly (added a ConsoleWrite() to check that), so it must be the FileWrite() that doesn't work.
      Thanks for the help!
      Values.au3
    • MattX
      By MattX
      Can someone please let me know if I have this is correct - I've sort of tested it and it seems to work but I need a second opinion.
      I'm hoping someone will agree that it will only call the RUN line if the size is over 20 gig ?


      $mail_que = FileGetSize('C:\Program Files\Microsoft\Exchange Server\TransportRoles\data\Queue\mail.que') $mail_que = $mail_que / 1024 If $mail_que > 20000000 Then Run('c:\matt\mail_que_email_alert.exe', 'c:\matt') EndIf Exit
    • stormbreaker
      By stormbreaker
      Hello everyone!! While solving some maths problems I thought of something and came up with this so-called 'tricky' game. Read instructions and Enjoy playing!!!


      #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3>$Form1 = GUICreate("MKISH's Magic Window", 564, 668, 393, 83) GuiSetBkColor(0xffffff) Global $Button[104] Global Const $ANS = Chr(Random(1,100,1)) $Label3 = GUICtrlCreateLabel(" 1-20 21-40 41-60 61-80 81-100", 24, 16, 515, 25) GUICtrlSetFont(-1, 11, 800, 0, "Comic Sans MS") $Button[1] = GUICtrlCreateButton("", 24, 48, 51, 49, $WS_GROUP) $Button[2] = GUICtrlCreateButton("", 74, 48, 51, 49, $WS_GROUP) $Button[3] = GUICtrlCreateButton("", 24, 96, 51, 49, $WS_GROUP) $Button[4] = GUICtrlCreateButton("", 74, 96, 51, 49, $WS_GROUP) $Button[5] = GUICtrlCreateButton("", 24, 144, 51, 49, $WS_GROUP) $Button[6] = GUICtrlCreateButton("", 74, 144, 51, 49, $WS_GROUP) $Button[7] = GUICtrlCreateButton("", 24, 192, 51, 49, $WS_GROUP) $Button[8] = GUICtrlCreateButton("", 74, 192, 51, 49, $WS_GROUP) $Button[9] = GUICtrlCreateButton("", 24, 240, 51, 49, $WS_GROUP) $Button[10] = GUICtrlCreateButton("", 74, 240, 51, 49, $WS_GROUP) $Button[11] = GUICtrlCreateButton("", 24, 288, 51, 49, $WS_GROUP) $Button[12] = GUICtrlCreateButton("", 74, 288, 51, 49, $WS_GROUP) $Button[13] = GUICtrlCreateButton("", 24, 336, 51, 49, $WS_GROUP) $Button[14] = GUICtrlCreateButton("", 74, 336, 51, 49, $WS_GROUP) $Button[15] = GUICtrlCreateButton("", 24, 384, 51, 49, $WS_GROUP) $Button[16] = GUICtrlCreateButton("", 74, 384, 51, 49, $WS_GROUP) $Button[17] = GUICtrlCreateButton("", 24, 432, 51, 49, $WS_GROUP) $Button[18] = GUICtrlCreateButton("", 74, 432, 51, 49, $WS_GROUP) $Button[19] = GUICtrlCreateButton("", 24, 480, 51, 49, $WS_GROUP) $Button[20] = GUICtrlCreateButton("", 74, 480, 51, 49, $WS_GROUP) $Button[21] = GUICtrlCreateButton("", 128, 48, 51, 49, $WS_GROUP) $Button[22] = GUICtrlCreateButton("", 178, 48, 51, 49, $WS_GROUP) $Button[23] = GUICtrlCreateButton("", 128, 96, 51, 49, $WS_GROUP) $Button[24] = GUICtrlCreateButton("", 178, 96, 51, 49, $WS_GROUP) $Button[25] = GUICtrlCreateButton("", 128, 144, 51, 49, $WS_GROUP) $Button[26] = GUICtrlCreateButton("", 178, 144, 51, 49, $WS_GROUP) $Button[27] = GUICtrlCreateButton("", 128, 192, 51, 49, $WS_GROUP) $Button[28] = GUICtrlCreateButton("", 178, 192, 51, 49, $WS_GROUP) $Button[29] = GUICtrlCreateButton("", 128, 240, 51, 49, $WS_GROUP) $Button[30] = GUICtrlCreateButton("", 178, 240, 51, 49, $WS_GROUP) $Button[31] = GUICtrlCreateButton("", 128, 288, 51, 49, $WS_GROUP) $Button[32] = GUICtrlCreateButton("", 178, 288, 51, 49, $WS_GROUP) $Button[33] = GUICtrlCreateButton("", 128, 336, 51, 49, $WS_GROUP) $Button[34] = GUICtrlCreateButton("", 178, 336, 51, 49, $WS_GROUP) $Button[35] = GUICtrlCreateButton("", 128, 384, 51, 49, $WS_GROUP) $Button[36] = GUICtrlCreateButton("", 178, 384, 51, 49, $WS_GROUP) $Button[37] = GUICtrlCreateButton("", 128, 432, 51, 49, $WS_GROUP) $Button[38] = GUICtrlCreateButton("", 178, 432, 51, 49, $WS_GROUP) $Button[39] = GUICtrlCreateButton("", 128, 480, 51, 49, $WS_GROUP) $Button[40] = GUICtrlCreateButton("", 178, 480, 51, 49, $WS_GROUP) $Button[41] = GUICtrlCreateButton("", 232, 48, 51, 49, $WS_GROUP) $Button[42] = GUICtrlCreateButton("", 282, 48, 51, 49, $WS_GROUP) $Button[43] = GUICtrlCreateButton("", 232, 96, 51, 49, $WS_GROUP) $Button[44] = GUICtrlCreateButton("", 282, 96, 51, 49, $WS_GROUP) $Button[45] = GUICtrlCreateButton("", 232, 144, 51, 49, $WS_GROUP) $Button[46] = GUICtrlCreateButton("", 282, 144, 51, 49, $WS_GROUP) $Button[47] = GUICtrlCreateButton("", 232, 192, 51, 49, $WS_GROUP) $Button[48] = GUICtrlCreateButton("", 282, 192, 51, 49, $WS_GROUP) $Button[49] = GUICtrlCreateButton("", 232, 240, 51, 49, $WS_GROUP) $Button[50] = GUICtrlCreateButton("", 282, 240, 51, 49, $WS_GROUP) $Button[51] = GUICtrlCreateButton("", 232, 288, 51, 49, $WS_GROUP) $Button[52] = GUICtrlCreateButton("", 282, 288, 51, 49, $WS_GROUP) $Button[53] = GUICtrlCreateButton("", 232, 336, 51, 49, $WS_GROUP) $Button[54] = GUICtrlCreateButton("", 282, 336, 51, 49, $WS_GROUP) $Button[55] = GUICtrlCreateButton("", 232, 384, 51, 49, $WS_GROUP) $Button[56] = GUICtrlCreateButton("", 282, 384, 51, 49, $WS_GROUP) $Button[57] = GUICtrlCreateButton("", 232, 432, 51, 49, $WS_GROUP) $Button[58] = GUICtrlCreateButton("", 282, 432, 51, 49, $WS_GROUP) $Button[59] = GUICtrlCreateButton("", 232, 480, 51, 49, $WS_GROUP) $Button[60] = GUICtrlCreateButton("", 282, 480, 51, 49, $WS_GROUP) $Button[61] = GUICtrlCreateButton("", 336, 48, 51, 49, $WS_GROUP) $Button[62] = GUICtrlCreateButton("", 386, 48, 51, 49, $WS_GROUP) $Button[63] = GUICtrlCreateButton("", 336, 96, 51, 49, $WS_GROUP) $Button[64] = GUICtrlCreateButton("", 386, 96, 51, 49, $WS_GROUP) $Button[65] = GUICtrlCreateButton("", 336, 144, 51, 49, $WS_GROUP) $Button[66] = GUICtrlCreateButton("", 386, 144, 51, 49, $WS_GROUP) $Button[67] = GUICtrlCreateButton("", 336, 192, 51, 49, $WS_GROUP) $Button[68] = GUICtrlCreateButton("", 386, 192, 51, 49, $WS_GROUP) $Button[69] = GUICtrlCreateButton("", 336, 240, 51, 49, $WS_GROUP) $Button[70] = GUICtrlCreateButton("", 386, 240, 51, 49, $WS_GROUP) $Button[71] = GUICtrlCreateButton("", 336, 288, 51, 49, $WS_GROUP) $Button[72] = GUICtrlCreateButton("", 386, 288, 51, 49, $WS_GROUP) $Button[73] = GUICtrlCreateButton("", 336, 336, 51, 49, $WS_GROUP) $Button[74] = GUICtrlCreateButton("", 386, 336, 51, 49, $WS_GROUP) $Button[75] = GUICtrlCreateButton("", 336, 384, 51, 49, $WS_GROUP) $Button[76] = GUICtrlCreateButton("", 386, 384, 51, 49, $WS_GROUP) $Button[77] = GUICtrlCreateButton("", 336, 432, 51, 49, $WS_GROUP) $Button[78] = GUICtrlCreateButton("", 386, 432, 51, 49, $WS_GROUP) $Button[79] = GUICtrlCreateButton("", 336, 480, 51, 49, $WS_GROUP) $Button[80] = GUICtrlCreateButton("", 386, 480, 51, 49, $WS_GROUP) $Button[81] = GUICtrlCreateButton("", 440, 48, 51, 49, $WS_GROUP) $Button[82] = GUICtrlCreateButton("", 490, 48, 51, 49, $WS_GROUP) $Button[83] = GUICtrlCreateButton("", 440, 96, 51, 49, $WS_GROUP) $Button[84] = GUICtrlCreateButton("", 490, 96, 51, 49, $WS_GROUP) $Button[85] = GUICtrlCreateButton("", 440, 144, 51, 49, $WS_GROUP) $Button[86] = GUICtrlCreateButton("", 490, 144, 51, 49, $WS_GROUP) $Button[87] = GUICtrlCreateButton("", 440, 192, 51, 49, $WS_GROUP) $Button[88] = GUICtrlCreateButton("", 490, 192, 51, 49, $WS_GROUP) $Button[89] = GUICtrlCreateButton("", 440, 240, 51, 49, $WS_GROUP) $Button[90] = GUICtrlCreateButton("", 490, 240, 51, 49, $WS_GROUP) $Button[91] = GUICtrlCreateButton("", 440, 288, 51, 49, $WS_GROUP) $Button[92] = GUICtrlCreateButton("", 490, 288, 51, 49, $WS_GROUP) $Button[93] = GUICtrlCreateButton("", 440, 336, 51, 49, $WS_GROUP) $Button[94] = GUICtrlCreateButton("", 490, 336, 51, 49, $WS_GROUP) $Button[95] = GUICtrlCreateButton("", 440, 384, 51, 49, $WS_GROUP) $Button[96] = GUICtrlCreateButton("", 490, 384, 51, 49, $WS_GROUP) $Button[97] = GUICtrlCreateButton("", 440, 432, 51, 49, $WS_GROUP) $Button[98] = GUICtrlCreateButton("", 490, 432, 51, 49, $WS_GROUP) $Button[99] = GUICtrlCreateButton("", 440, 480, 51, 49, $WS_GROUP) $Button[100] = GUICtrlCreateButton("", 490, 480, 51, 49, $WS_GROUP) $Button[101] = GUICtrlCreateButton("I am Done !!", 80, 576, 123, 57, $WS_GROUP) $Button[102] = GUICtrlCreateButton("Instructions", 208, 576, 123, 57, $WS_GROUP) $Button[103] = GUICtrlCreateButton("Go Home!!", 336, 576, 123, 57, $WS_GROUP) For $i = 1 to 100 GUICtrlSetFont($Button[$i], 16, 400, 4, "Wingdings") GuiCtrlSetData($Button[$i], Chr(Random(101, $i+150, 1))) GUICtrlSetTip($Button[$i], "" & $i) Next For $i = 0 to 100 step 9 GuiCtrlSetData($Button[$i], $ANS) Next $Label1 = GUICtrlCreateLabel("", 8, 544, 548, 4, $SS_SUNKEN) GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE, $Button[103] Exit Case $Button[101] GuiSetstate(@SW_DISABLE, $Form1) $Form2 = GUICreate("Answer", 316, 184, -1, -1, BitOR($WS_SYSMENU,$WS_POPUP,$WS_POPUPWINDOW,$WS_BORDER,$WS_CLIPSIBLINGS)) GuiSetBkColor(0xffffff) $GroupBox1 = GUICtrlCreateGroup("", 8, 1, 297, 129) $Labelx1 = GUICtrlCreateLabel("The symbol is:", 80, 24, 153, 34) GUICtrlSetFont(-1, 16, 800, 0, "Comic Sans MS") $Labelx22 = GUICtrlCreateLabel("", 96, 90, 139, 30) GUICtrlSetFont(-1, 18, 800, 0, "Wingdings") GuiCtrlSetData(-1, $ANS) GUICtrlCreateGroup("", -99, -99, 1, 1) GUISetState(@SW_SHOW) Case $Button[102] msgbox(64, "Instructions", "> Think of a number b/w 10 and 100" & @crlf & "> Subtract from it the sum of its digits" & @crlf & "> Look for the symbol corresponding to answer on the list" & @CRLF & "> Click 'I am Done !!' button and Bingo", Default, $Form1) EndSwitch WEnd
      muttley Easy, isn't it?

      EDIT: Now looks fine..