AI and Self Modifying Code

This topic is 4338 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I just had a thought one night... I have heard alot about the mis-uses of the goto command because of it's tendency to lead to spagetti code... I was thinking spagetti code would be alright for AI if it was implemented correctly (and I don't mean a programmer figuring out the sequence of jumps)... But what if a program had the ability to program itself with the sequencing of jumps so that you enter the code in certain places and exit in other places and depending on the outcome of the exit, the program could change the sequence of jumps in order to give the intended result... Sorta like a neural net I don't know how easily it is to do self-modifying code from within Windows indeed if it is possible at all... It also came to mind that it might best be done on a dual core processor.

-me

Share on other sites
You should check out CoreWars :)

There is a windows Interpretter called WinCore

Share on other sites

Self modifying code is usually efficient only when the code change is made once by some decision making process that selects the appropriate options (what to run and what code to bypass) which may be a complicated set of calculations/logic. The decision is based on some logic evaluating the situational state and matching up which precanned code block solutions are best. The generated code would then be re-executed numerous times using that decision with the minimum amount of code execution (otherwise you might as well use conventional methods imbedding all the IF-THEN-ELSE logic).

Nothing says you couldnt do jump table offsets (using ASM) based on the content of an options data array (in variablespace where its readwriteable). It would be marginally more costly execution-wise than direct GOTO jumps. One of the problem with true self modifying code is that its not useable for instancing. Having each thread/fiber instance control its own custom code option block would get around that limitation (and might eliminate alot of the VirtualProtect() calls and other overhead.)

This of course is for code that cannot be done simply by using callbacks -- like numerous (twisty??) small/finegrained code chunks (where many callbacks to small chunks of code would have excessive overhead for context parameters...) and combinatorics precludes having many coarse grained callback functions that cover the range of combinations (like substituting sort functions).

An example I can think of for AI would be building filter logic to be used by some behavioral code -- a sensory filter that is applied to ALOT of situational data and which doesnt change very often -- it would be built up from an object's abilities/unique attributes. The patterns would not be simple matching, but more complex AND/OR/NOT clauses and Value Range tests (and custom function calls) for multiple attribute factors -- something that would run horribly slow if it had to be 'interpreted' and generalized.

Which brings up the use of self-modifying code in script languages. Having a script build another script to do a customized operation (and preferably a bytecode style script system to speed operations) would not require OS level write permissions (as it is already program data). Such code building code is usually quite ugly and large and generalized (and slow), but can pay off in performance as the custom code is executed millions/billions of times over its lifetime (consider how incredibly slow it would be if a generalized script doing the same thing had to be run instead).

Share on other sites
A program can't change itself. This is because it is running and depends on itself to run the program. When a file is saved it completly wipes the file and then saves over it so the program would glitch. So what you need is another copy of the program and a source. Then a file that rights the new programs.

The program will send a command to the source saying that it needs to change itself and the source will activate the writing program to write over your copy then the copy will send a string saying it is updated and working and it will turn on the second copy and auto enter all values in the first so whatever it's other function is won't be restarted. Then the first will be deactivated and rewriten. Then this will send a string to the source telling it that it is ready to take control back over the program.

Share on other sites
C# can generate its own code procedurally, compile it, and run it all without restarting the main app.

And there's nothing stopping you from generating native code on the fly in any other language with direct access to memory, but you'd have to do a lot more work yourself.

Share on other sites
Quote:
 Original post by tjweb92A program can't change itself. This is because it is running and depends on itself to run the program. When a file is saved it completly wipes the file and then saves over it so the program would glitch. So what you need is another copy of the program and a source. Then a file that rights the new programs.The program will send a command to the source saying that it needs to change itself and the source will activate the writing program to write over your copy then the copy will send a string saying it is updated and working and it will turn on the second copy and auto enter all values in the first so whatever it's other function is won't be restarted. Then the first will be deactivated and rewriten. Then this will send a string to the source telling it that it is ready to take control back over the program.
You're completely wrong. Machine code can be changed in memory, and it's not impossible (though not easy) to save it back to the file. The reason saving the changes is difficult is twofold, with neither part being the reason you stated. First, windows loads executables by mapping the file to memory, which causes it to be locked as long as it remains open. Luckily, ntdll.dll exports a function that allows you to unmap the executable, but it must be used with caution because simply calling the funciton in a standard executable would cause the code to be unloaded as well, so special measures must be taken in the code to prevent that from happening. The second problem is that executables are not stored on disk in the same layout they are stored in memory, so there would need to be a transformation function to adjust addresses, padding, etc.

In C or C++, making a self-modifying executable would be extremely difficult and would require non-standard extensions to the languages. In machine code/assembly, it's possible but not easy, and in higher level languages such as Common Lisp, the only hard part is saving the changes (and that might not be too hard depending on the implementation).

Share on other sites
Code which changes its behaviour over time, is NOT the same as self-modifying code, which literally modifies itself. An AI algorithm could gradually change its behaviour without needing to modify itself.

Self modifying code was used historically to save a bit of space occasionally in assembly language, and as an obfuscation method.

There is no case for self modifying code any more.

Almost as bad, is code-writing-code - of which you could argue, one example is a compiler. But some applications do create code from other code, this code generation is considered a more reasonable technique.

So it might be feasible even, to have an application which outputs source code for a new (modified) version of itself, feeds it into the compiler then chains that. However, it would be very weird :)

Mark

Share on other sites
Quote:
 Original post by markr[...]So it might be feasible even, to have an application which outputs source code for a new (modified) version of itself, feeds it into the compiler then chains that. However, it would be very weird :)[...]
That's called "reflection", and it's not weird at all. Also, self-modifying code isn't so bad in languages like Lisp, where code is data is code in a proper fashion. Of course, it's not the same as self-modifying machine code, but it does the same thing of modifying code (in place or not depending on the garbage collector etc) without having separate "generate code, compile, replace old code" steps.

The general term for this kind of thing is "metaprogramming", and it's done all the time with templates in C++, preprocessor statements in C, Common Lisp macros, etc.

Share on other sites
Java programmers might play with self modifying executable code safely (most bad types of resulting source files, actually arrays, would return error code in compilation thus amount of crashes would be greatly reduced), at the cost of writing theirs own class loader.
Of course there are some isues, like what rights would have that self modified code.

Share on other sites
If you are exploring this area, be aware that OS writers (including those writing console operating systems) are slowly backing away from self modifying code.

Basically, it is seen as a security risk. If code is marked as 'read only', the system can trap virus/buffer-exploit attempts at taking control of the system. This is particularly risky on platforms where security is critical (ie the 360 and PS3).

If you go this route, be aware that your code might not work on some platforms in the future.

Share on other sites
I guess one way for me to do it is to write code into a DLL file and then load and execute that portion of code which would make security less of a problem. When I need to update the code I could just unload the file write my code into it and reload it again.

Share on other sites
In Prolog (like in Lisp, but maybe even more so) self-modifying code is nothing special, mainly because there's no difference between (in c/c++ terms) is date and program, the program is data and data forms a program. Data/Programs consist of facts and rules, generating rules/data in memory and saving them to file (or directly to file) is easy.

There is a good Prolog (Free, as in beer) called SWI-Prolog, it has an extensive c/c++ interface and you can integrate the prolog engine in your c/c++ program, the opposite is equally possible (for speeding up (imperative) procedures, since it's not always the fastest language.

But having said so, you can write a rule-based decision system in no time, and will be easy to maintain, and as I pointed out in the above, dynamically changing that rule-base is fully possible, so your program/agent can learn as it goes along.

Share on other sites

Thinking again about where the trouble of implementing 'Self-Modifying Code' would pay off (specificly an AI usage) :

One would be filters/classifiers for sensory data customized to a specific objects behavioral patterns. My long term project has objects that inherit skills and abilities (potentially hundreds of them) and each skill has one or more behavioral 'solution' for a situational factor. Every new object that comes into an objects sensor awareness is to be classified (and its significance can change depending on distance, requiring re-evaluation). Priorities also shift depending on the objects internal state (ie- when hungry, identifying food increases in importance).

The constant reevaluation of dynamic sensory data (and on a rich detail world) is one of my concerns as to whether there will be enough CPU to run one such object let alone many of them. Optomizations like caching classifications as tracking data and only reevaluating periodicly (different periods depending on the initial classification...). Even with such measures the AI CPU load can still be prohibitive. Consider the overhead of calling over a hundred callbacks against each target object and each callback having to be generalized
in its logic.

The 'code' self-modify rebuilding process is equivalent to the interpretation scan that whould have to be done against the object's skill/ability set (which would all have to be done every classifier execution if self-modifying code isnt implemented). Each inheritable 'skill/ability' would have its own code building method (which may have options depending on some interrelation complexity and insertion of constants based on the objects current attributes/states). Macros no doubt will clean up implementing this part. Optomizing schemes like ordering the test logic so that all the highest priority evaluations are done first and a quick-exit (bypassing evaluations of a lower quantum of priority) could be done. Of course it would complicate the 'code building' process -- require sorting and appending to quantum blocks which are assembled/stitched together at the end...

Most of the code is a sequence of IF-THEN tests against attributes of the target object, including dynamic relations like range and possibly the objects 'stance' (ie- Objx Isa Troll AND Objx.Range<

Share on other sites
#$%^$%^& imbedded html \$%^&%^ glad i saved it on a file or I would be really pissed....

continued :

SafeRange AND Objx.stance==ANGRY ). Such logic is fairly regular and generating native code straightforward.
The matching THEN directive usually calls a function that adds a potential action/reaction or generalization to a result list and would include a Priority (which itself may be an equation/calculation to be semi-fuzzy). At the end of the classification, the result list (probably sorted by priority on the insert) allows the highest priority to be selected or further processing to be done to pick a proper reaction (ie- whats the best path to run from a group of lions when the result list has 3 of them identified as significant threats).
There may even be multiple result lists for specific classification types.
The classifiers output data can become input data for one of more risk/resource analysis.

If the code clauses are very regular, a bytecode mini-interpretor may be possible that wouldn't lose too much performance over native code. Having the
'code' be data would eliminate the 'write' permission access complication as well as be platform independant.

How often would the modifiable code need to be modified/rebuilt?..... it would be possible to break into two code blocks and put the logic blocks that change frequently in a second set to decrease the task of rebuilding (but that might interfere with sorting and starts to look real ugly to implement...). The periodic rebuilding may be a shorter interval for more intelligent objects (or ones that are schitzo in their behavior). Its workable as long as the cost of rebuilding is offset adaquately by the execution efficiency.

I will have to look more into this. Ive written several mini-interpretors before and a simple opcode/stack based/static parameter function/minimal imbedded math equation/single block depth type is fairly easy. The patterns for native code generation are actually mostly the same (just more bytes emitted).

Share on other sites
Actually, if we are looking at AI scripts, then there's no reason why it can't be modified in real-time. Well, its just how you define "modify." You can fairly easily "swap" behavior sets.

So, if you have a creature and 10 sets of behavior scripts, you can cycle through them and see how well each one performs, then modify them as they get swapped out. Kind of like what you do in Genetic Programming. However, there's a reason why GP isn't very popular or used alot. There are infinite looping issues with solutions generated in GP, especially if you want to support looping as a feature. It gets really nasty because its not trivial to tell the difference between an infinite loop and one that's just executing a large number of times. Apart from that, if you maintain strong type checks, GP should work pretty well.

Share on other sites
Quote:
 Original post by WeirdoFuActually, if we are looking at AI scripts, then there's no reason why it can't be modified in real-time. Well, its just how you define "modify." You can fairly easily "swap" behavior sets. So, if you have a creature and 10 sets of behavior scripts, you can cycle through them and see how well each one performs, then modify them as they get swapped out. Kind of like what you do in Genetic Programming. However, there's a reason why GP isn't very popular or used alot. There are infinite looping issues with solutions generated in GP, especially if you want to support looping as a feature. It gets really nasty because its not trivial to tell the difference between an infinite loop and one that's just executing a large number of times. Apart from that, if you maintain strong type checks, GP should work pretty well.

The usage is a bit more complex than a simple modal 'switch'. Even if you have a object with a set of simultaneous behaviors (genes) that can be substituted (effectivly my objects with inheritted skills/abilities are something of like this), the mechanism that causes the code chunks to execute and how fine the customization can be is the issue.
Doing it either via 'switch' statements (very static/clumsy) or a more versatile link list of callbacks, there is still the overhead AND the code chunks themselves remain unoptimized (generalized). If you try to make the cistomization finer, then you multiply the number of callbacks or add option parameters to them.

If you rebuild (self-modify) code, you can within each chunk do simplifications (like value calculation to imbed as constant) and situationally select modal options (subchunks-- fine level customization) and possibly have reordering. You certainly cut out the selection logic and callback overhead.
The code chunk is pared down to only the code needed.

For my project such a system has merits because my AI objects are highly polymorphic (true polymorphism...) and the AI is a heavyweight planner/simultaneouus task system tied to a realtime simulation.
I need the processing savings that self-modifying code can probably deliver.
The sensor pre-filtering/classification function would be my first use.