Painter!
At long last I have a demo of Painter that does something interesting. Click on it below to have it start.
At long last I have a demo of Painter that does something interesting. Click on it below to have it start.
I’ve been persuaded to do some more work with Genetic Image. I am not sure what is going to result out of this, but it’s possible that there may be some nice new stuff on the way. I’ve created a few new large renders, and I’m thinking about making a step by step guide that shows how the program actually turns mathematical functions into pretty pictures.
I’ve also been wanting to do some more work on Painter, but it will be a while before anything happens with that. My next qualifying exam is on May 1st. Why is it that whenever some big huge update deadline approaches that I suddenly feel motivated to work on my independent projects?
I am really interested in metaprogramming, writing programs which can modify themselves dynamically. More notably, users of metaprograms will be able to change their functional operation. The advantage of being able to do this is that it enables a great deal of power for development and creating things, but primarily, it’s just a lot of fun. There is something about being able to call functions using reflection that just is really pleasing and entertaining to me.
Most commonly scripting frameworks are used to create secure environments for scripts, and often these scripts will be developed ahead of time, but they also enable a possibility of dynamic scripting, where a scripting environment may be able to do interesting things during run time. Possible examples of run time uses are controlling agents within a world by issuing commands and writing code for an agent’s “brain”, then loading to that into the agent which is live in the world. It would be possible to create a dynamic music or image making program, where the artist can control what is being played or drawn using the scripted code.
With the recent release of Java 1.6, we now have standardized implementation of JSR 223, also known as the scripting framework, which enables some exciting metaprogramming possibilities. This allows one to script on top of Java. So, it would be possible to interact with Python, Ruby, Javascript, or any other sort of scripting language through this one framework. Interestingly, it is also possible to use Java as a scripting language. Thus, you can script for a Java program… in Java. This may seem ridiculous to some, but I think this is simply delightful.
Here is an example of the scripting framework in use. Note, to actually run this, you must add the java-engine.jar, found in jsr223-engines.zip to the classpath.
package scripttest; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; import javax.script.Bindings; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; /** * * @author Calvin Ashmore */ public class Main { /** * @param args the command line arguments */ public static void main(String[] args) { ScriptEngineManager mgr = new ScriptEngineManager(); ScriptEngine scriptEngine = mgr.getEngineByName("java"); System.out.println(scriptEngine); Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); for (Entry<String, Object> entry : bindings.entrySet()) { System.out.println(" " + entry); } System.out.println(scriptEngine.getContext()); try { scriptEngine.put(ScriptEngine.FILENAME, "Toasty.java"); String script = "public class Toasty {" + " private float myStuff;" + " public Toasty(float stuff) {" + " myStuff = stuff;" + " }" + " public String toString() {" + " return \"I have a thingy! \"+myStuff;" + " }" + " public int performWombat(String theWombat, float multiplier) {" + " int toast = Integer.valueOf(theWombat);" + " float thingy = toast * multiplier;" + " double d = Math.sqrt(1 + thingy*thingy);" + " return (int) d;" + " }" + "}"; Class toastyClass = (Class) scriptEngine.eval(script); Constructor c = toastyClass.getConstructor(float.class); Method m = toastyClass.getMethod("performWombat", String.class, float.class); Object toasty = c.newInstance(1.0f); System.out.println("My toasty: " + toasty); System.out.println("This will work:"); System.out.println("result: " + m.invoke(toasty, "234", 1.23f)); System.out.println("This will not:"); System.out.println("result: " + m.invoke(toasty, "eek", 1.23f)); } catch (Exception ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } }
(Apologies for the strange variable names) It generates the output:
com.sun.script.java.JavaScriptEngine@1abc7b9 javax.script.SimpleScriptContext@c55e36 My toasty: I have a thingy! 1.0 This will work: result: 287 This will not: Jan 21, 2009 9:27:15 PM scripttest.Main main SEVERE: null java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at scripttest.Main.main(Main.java:70) Caused by: java.lang.NumberFormatException: For input string: "eek" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:447) at java.lang.Integer.valueOf(Integer.java:553) at Toasty.performWombat(Unknown Source) ... 5 more
This example is able to instantiate and call methods on a simple object effectively. However, in order to do the more interesting things described above, we need to make use of interfaces. So, the scripted class will implement an interface defined by the main program. That interface will define the contract for operation. So, instead of using reflection to call methods, we can simply cast the object to belong to the interface and call the methods directly. I’m not going to write this yet, but maybe soon.
For my eventual monster programming project that will eventually (I hope) be the fruit of my labors as a PhD student (in addition to a big stack of paper that will make up the dissertation), I have been doing a bit of preliminary research. Mainly, I want to plan an architecture that is as clean and clear as possible. A challenge with academic projects is that they often stumble or run into problems after exposure to the outside world. My project is a system for simulating (and interacting with) characters in fictional worlds. This sort of thing requires many architectural layers, and in my experience, lots of trouble can come from letting the layers mingle too much.
So one natural question is: how to keep layers separate, and also have the project be extensible so that it can flourish after emerging from the comforting coccoon of academia? The problems I have run into the most frequently in extending my projects tend to fall under the categories of 1) organization, 2) persistence, and 3) networking. These questions are easily ignored when building experiments and prototypes, but when those are transformed into full fledged development, not having considered them can wreak havoc on a project. So, I’m doing these experiments in trying to figure out good architectures that could be used. I was thinking about networking and discovered the Java RMI framework. I looked at their tutorial which is deliciously short and extremely comprehensible. You would think that this sort of networking would be more cumbersome, but it’s really not.
I think I am going to plan on using RMI and design the character simulation system as a service. This will force me to think of interactions at a client-server level, and also make liberal use of Java interfaces. The RMI framework also relies on serialized objects for communication, so that means that messy and complex objects can’t just be handed from the client to the server. This is the sort of problem that occured with developing persistence in the InTEL project, and the sooner pinned down, the better.
Okay, I have been wanting to play around with this for a while, and just had the chance to investigate Sun’s fascinating and dramatically named Project Darkstar. Darkstar is actually a game server that is designed for facilitating networked games. It reminds me of just the basic infrastructure behind Multiverse, without anything else whatsoever. For small or versatile projects, that may be a very good thing. I can imagine this plugging into Java Monkey Engine very nicely. I am thinking about using it for some small experimental projects, as well as a potential platform for eventual research.
My research project (fictional adaptation and character simulation) needs to have a flexible, modular, and very very pluggable architecture. I want to be able to use it with other things, and allow others to plug it into their own systems. This is always an ambition in these rough and tumble academic projects, but I really hope to do it right. Developing a client/server system that is multiplayer/multiuser ready is a potentially very good start, as long as the overhead is not too much.
Also, all of Darkstar uses Maven, which I have never used before, but looks to be extremely promising as a powerful project organizational and build tool. I definitely want to try using it for new projects. But, as for Darkstar itself, I’ll play around with it and post updates if I make something interesting.
So, I spent some time fiddling around with the Henon applet. It’s possible to discover and get a feel for several properties of the map just through experimenting, and that’s a really positive sign. You can easily identify the two fixed points, and it’s possible to tell what their relative stabilities are. It’s also possible to make some other interesting visual observations.
One thing that stands out in mind is a way in which the Henon map is different from, let’s say, a Julia set. The filled in gray region represents the space where the orbit of every point in the set does not diverge. Generally, points in this region will fall into the characteristic parabola saddle shape shown by the white points. This means that points in this region have a chaotic orbit. Points in this region that are somewhat apart will eventually be separated no matter how close they start together. However, if you choose any point on the border of the gray region, it will converge to the unstable fixed point on the left of the map. Even though this point is unstable along one axis, it is very compressed along the other. I don’t have a proof for this, but it seems visually evident.
What is interesting about this, is that the situation here is exactly the opposite of Julia sets in the canonical z->z^2+c map. In these cases, the border of the filled-in Julia set is chaotic, any two points on this border will eventually become separated. Whereas points within the filled-in set will always converge to some cycle.
It seems, given this, that the filled-in region is actually the Henon map’s Julia set, whereas the border is the “filled-in” Julia set. Or maybe there’s a different term for it. It’s been a while since I’ve done math, so it’s hard to know.
It will help quite a bit to establish exactly what will be needed from the various systems involved. It is clear that a knowledge system will allow characters to have reflective models of the world, of themselves, and so on, but it is less clear exactly how this information will be accessed or modified. What are the entry and exit points? What are the procedures? What is the greatest, clearest layer of abstraction that can be drawn here?
Similar questions can be raised for the other components as well. There are lots of resources on how to write modular and robust APIs, but these presuppose understanding what they are going to be used for precisely. Answering this question seems like the next logical step.
I’ve been familiar with Cellular Automata for a while, and I generally tend to approve of them. Especially when they have some nice evocative qualities. We read and discussed Wolfram’s A New Kind of Science in one of my classes, which was a lot of fun. We really tore into it. My problem with the book is that while I appreciate and respect the ideas behind his work, the mathematician in me wants to wring the book until theorems come out, which of course they don’t, because there are no proofs.
I feel especially frustrated on that account because of the work I did with strange attractors. I found significant visual evidence that the parameter space for the attractors has fractal characteristics, but I was never able to prove it. Very sad.
Anyway, revisiting Wolfram led me to remember my use of cellular automata in GeneticImage, and thinking about how they could be used in Painter or other projects. I was quite pleased with the last applet posted regarding Painter, so due to this, I think I will post one with a cellular automata generator. This is primarily intended for artistic rather than any other purpose. Please fiddle with knobs and levers to your heart’s content!
In my copious spare time, I’ve been working on Painter. Today I was able to get it to produce some sort of image. Amazing! Painter is essentially a metaprogramming project, and it generates its own programming control structures. Generally what I’m trying to do with it is put in some sort of automatic Processing. Eventually it will be able to do a lot more. But, we all must start small.
I have revised the GP code posted previously so that entities can now plant trees. It’s not a lot better than before, but it is still a step in the right direction. A tree will drop some quantity of food after it is planted, but it takes a significant number of turns for it to do so. Furthermore, they are expensive in terms of energy cost to plant. Thus, entities can balance between not planting and saving energy, and planting which will consume energy, but lead to better health in the long term.
After a few minutes of milling about, the entities should reach a stable pattern of planting trees and then looping around to consume the food that the trees drop. If you look at the entity code, you’ll see that Command.2 (the plant tree command) tends to wind up inside of a conditional. This is more or less the behavior I was hoping for, so hooray.
Now it’s just a question of what they can do next.