If you dig F#, or you dig Solver Foundation, or if you dig cool things, then you should check out this presentation by Anton Schwaighofer. Anton works in Microsoft Research and was instrumental in getting "units of measure" support into Solver Foundation. The presentation covers units of measure in F# generally as well as how to build Solver Foundation models with units of measure using the F# ODSL.
The Solver Foundation part is about 30 minutes in, but you should watch the whole thing.
[I am not a Windows expert and this is all probably totally obvious.]
There has been some buzz about "God mode" in Windows 7. What am I talking about? It's an undocumented way to create a special folder that has a bunch of commonly used control panel settings. A recent article by Ina Fried provides more details, including a list of more undocumented settings folders (via Steven Sinofsky). Here are the folders given in the article (thanks to a hilariously-named commenter in the Ina Fried article):
To try it out, create a folder (anywhere) whose name has the following pattern: <name>.<ID>, where <ID> is one of the strings in the second column of the table above. Once you create the folder, Windows will magically change the icon and remove the ID. Example: on my laptop I like to change power options - when I am doing dev stuff like compiling code or running tests I want high performance, otherwise I want to preserve battery life. So I created the "power options" folder and stuck it on my desktop (and also stuck it on the taskbar in the third slot, so that Windows Key + 3 will pop it up). Nice!
I'd like to spend the next couple posts on "everyday" use of Solver Foundation Services for model building. In many models it is necessary to build up goals and constraints programmatically. In Solver Foundation this is done using the Term class. At first, trying to figure out how to do this can be tricky. Hopefully this post helps somebody out there.
I want to focus on the APIs themselves right now - in a future post I will use these APIs in a worked-out example. Terms come into play when defining goals and constraints on a Model object:
public Constraint AddConstraint(string name, Term constraint); public Goal AddGoal(string name, GoalKind direction, Term goal);
The Term class does not have a constructor. You can build Terms using: Constants. Bools, ints, doubles are implicitly converted into constant terms. Constants by themselves are usually not very interesting goals or constraints… Parameters and decisions. Parameters or decisions are terms. Every meaningful constraint or goal will always contain at least one decision!
model.AddGoal("goal", GoalKind.Minimize, x + y);
Operators. Term has operator overloads for most common arithmetic and logic operators. In particular, <, >, !=, and so on are often used in constraints:
model.AddConstraint("c1", x + y >= 5); model.AddConstraint("c2", color[0, 0] != color[0, 1]);
Static methods on Model. The Model class has a bunch of static methods that provide mathematical, logical, and type conversion functions. The OML reference has a complete listing. A few highlights:
Foreach, ForeachWhere and Sum. Actually these should be included in the previous category, but I list them separately because they are so important. Foreach and ForeachWhere are special because they work with Sets. Sets allow you to create indexed (list- or table-valued) decisions or parameters. Most of the models you think of will probably involve Sets. After specifying the set to iterate over, you then need to specify a function that maps members of the sets to Terms. This is typically done using anonymous functions. In the case of ForeachWhere, you also provide a function that represents the filter. Here's a silly example - suppose you want you're running a restaurant and you want to make sure that all the tables near windows have at least 4 chairs. If you had an indexed parameter "nearWindow" and decision "chairs", then the constraint could be written as follows.
model.AddConstraint("c", Model.ForEachWhere(tables, t => chairs[t] >= 4, t => nearWindow[t]));
Sum is often used to wrap a Foreach or ForeachWhere. (The usage is a little different from OML.)
You can build up all kinds of different goals and constraints using these building blocks. Sometimes figuring out how to express the model you have in mind can be difficult. I will avoid making this post a long fluffy sermon - except to say that the techniques for writing good code apply to writing good SFS code too. In particular, you can encapsulate calls to SFS methods inside of classes and methods. In this post I talked about using extension methods to do just that.
In my next post I will show how to get good performance using these APIs. Creating Terms means allocating memory, and it is (unfortunately) easy to build models that have a lot of bloat. Keeping a few simple facts in mind will help to avoid this pitfall.