<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Nathan Brixius : Project</title><link>http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx</link><description>Tags: Project</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Writing high performance code</title><link>http://blogs.msdn.com/natbr/archive/2009/12/10/writing-high-performance-code.aspx</link><pubDate>Fri, 11 Dec 2009 04:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935518</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9935518.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9935518</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9935518</wfw:comment><description>&lt;P&gt;During &lt;A href="http://www.hanselman.com/blog/HanselminutesPodcast191SolverFoundationAndOptimizationWithNathanBrixius.aspx" target=_blank mce_href="http://www.hanselman.com/blog/HanselminutesPodcast191SolverFoundationAndOptimizationWithNathanBrixius.aspx"&gt;Scott Hanselman's&amp;nbsp;podcast&lt;/A&gt; we briefly discussed managed code performance.&amp;nbsp; Here are a few of my thoughts about writing high performance code. In the spirit of a &lt;A href="http://www.amazon.com/Five-Dysfunctions-Team-Leadership-Lencioni/dp/0787960756/ref=pd_sim_b_1" target=_blank mce_href="http://www.amazon.com/Five-Dysfunctions-Team-Leadership-Lencioni/dp/0787960756/ref=pd_sim_b_1"&gt;cheesy business book&lt;/A&gt; (or &lt;A href="http://www.hulu.com/watch/4183/saturday-night-live-down-by-the-river" target=_blank mce_href="http://www.hulu.com/watch/4183/saturday-night-live-down-by-the-river"&gt;motivational speaker&lt;/A&gt;), I will give away my main points in the form of controversial-sounding statements before proceeding to flog them to death:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Don't trust anyone.&lt;/LI&gt;
&lt;LI&gt;Managed is better.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Some background: before I came to Microsoft I built solvers for both discrete and continuous optimization problems, primarily in C/C++, with a bit of Fortran thrown in.&amp;nbsp; Back in 2002 when I was on the &lt;A href="http://blogs.msdn.com/project/" mce_href="http://blogs.msdn.com/project/"&gt;Project Server&lt;/A&gt; team we were faced with the decision of whether to rebuild our scheduling engine in C++ or C#.&amp;nbsp; For the past year or so I have worked on the &lt;A href="http://www.solverfoundation.com/" target=_blank mce_href="http://www.solverfoundation.com"&gt;Solver Foundation&lt;/A&gt; team, which is pure C#.&amp;nbsp; We build solvers that solve a range of large-scale optimization problems, and they are “industrial grade”:&amp;nbsp; tens or hundreds of thousands of constraints are not uncommon.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Don't trust anyone.&lt;/STRONG&gt; &lt;A href="http://blogs.msdn.com/ricom" mce_href="http://blogs.msdn.com/ricom"&gt;Rico Mariani&lt;/A&gt; says the first rule of performance is to measure.&amp;nbsp; &lt;A href="http://blogs.msdn.com/ricom/archive/2003/12/02/40779.aspx" target=_blank mce_href="http://blogs.msdn.com/ricom/archive/2003/12/02/40779.aspx"&gt;Listen to Rico&lt;/A&gt;.&amp;nbsp; There are many reasons for this.&amp;nbsp; The first is that nobody has ever written code that is doing exactly what you are trying to do.&amp;nbsp; Otherwise (being a smart programmer) you should just call their code or (being a smart business person) you should just buy their code, try to do it better, or do something different entirely (perhaps mixed martial arts).&amp;nbsp; So you should seek to understand how the code behaves, otherwise you will never find out - until it is too late.&lt;/P&gt;
&lt;P&gt;The second is that you know your scenarios and priorities better than others do.&amp;nbsp; You should already&amp;nbsp;have an idea of how fast the code is supposed to be. Now sometimes the requirement truly is "make it as fast as possible".&amp;nbsp; For numerical libraries this is often the case because many problems can be made to be arbitrarily complicated.&amp;nbsp; For example, if you are modeling fluid dynamics you could use tighter meshes and get more accurate results.&amp;nbsp; In most other cases (perhaps in a user interface) you have a hard number you need to hit. Of course, there are some simple guidelines that may apply in most situations.&amp;nbsp; If you never go to the database, your server app will be fast. If you never allocate memory, your numeric code will fly. True or false? Well…measure.&lt;/P&gt;
&lt;P&gt;The third is that even if someone else has measured code that seems to be similar to yours, their results may be misleading.&amp;nbsp; For example, you depend on different collection classes, or you are running on a different processor.&amp;nbsp; Or your input data is different in some subtle way.&amp;nbsp; To take a very simple example, suppose you want to sort lists of 1 million integers, and somebody says, "hey, I measured different sorting algorithms on arrays of 1 million integers and quicksort is best."&amp;nbsp; And they hand over the code and all of their results.&amp;nbsp; Well, what do those arrays look like?&amp;nbsp; Because if the data is mostly sorted then something like insertion sort may work better.&lt;/P&gt;
&lt;P&gt;If you follow this advice you may end up with more questions: doesn't this take a lot of time and effort? How do I know when to stop measuring, or stop optimizing my code?&amp;nbsp; If you start profiling at the very start of development, and build some simple skills, it's not too bad (and you learn a lot).&amp;nbsp; If, for example, you are considering whether to use managed or unmanaged code for a project, prototype a couple of key sections in C++ and C# and measure.&amp;nbsp; I did this on the Project Server team and that was the best way to settle the argument.&amp;nbsp; These things often get way too philosophical – just try it and see.&amp;nbsp; I did standard critical path scheduling in both C# and C++ and found that the C# version was only 10-15% slower.&amp;nbsp; We went with C# and in the course of development we were able to find algorithmic improvements that resulted in a faster implementation that the original C++ codebase. Get good at writing simple programs that answer one specific performance question.&amp;nbsp; For example: should I use a list or an array?&amp;nbsp; How should I read this data set?&amp;nbsp; Be a scientist and seek to answer specific questions by controlling the conditions and varying only one thing at a time.&amp;nbsp; And pick the right thing based on your knowledge of the customer scenario.&amp;nbsp;&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;STRONG&gt;Managed or unmanaged?&lt;/STRONG&gt; My blunt opinion is: unless your computation is dominated by &lt;A href="http://www.netlib.org/blas/" target=_blank mce_href="http://www.netlib.org/blas/"&gt;BLAS&lt;/A&gt;-style computations you are better off using C# because of productivity, stability, and maintainability concerns.&amp;nbsp; &lt;BR&gt;&amp;nbsp;&lt;BR&gt;Here are a couple of “pros” for C#:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;There are clear performance differences, but in many cases when you look at the overall system performance they can be washed away due to other factors: I/O, a webservice call, DB access, etc.&lt;/LI&gt;
&lt;LI&gt;Many programmers (myself included) are much more productive writing C# code.&amp;nbsp; This gives me more time to investigate possible algorithmic improvements, write good unit tests, etc. There are opportunity costs!&lt;/LI&gt;
&lt;LI&gt;I&amp;nbsp;think it is easier to make use of multiple cores. For example, the parallel extensions available for .Net 3.5 (and built into 4.0) are very easy to use.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;There are also some clear downsides:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It is easy to get lazy, or to unintentionally use constructs that are not efficient.&amp;nbsp; People start using List&amp;lt;&amp;gt; and Dictionary&amp;lt;&amp;gt; when a good ol’ array will do.&amp;nbsp; It’s also easy to miss unnecessary memory allocations, because everything is garbage collected.&amp;nbsp; So you need to be vigilant about profiling the code.&lt;/LI&gt;
&lt;LI&gt;There is a lot of unnecessary array bounds checking that slows things down.&amp;nbsp; In particular, with &lt;A href="http://www.netlib.org/lapack/" target=_blank mce_href="http://www.netlib.org/lapack/"&gt;LAPACK&lt;/A&gt;-style routines with tight, nested loops.&lt;/LI&gt;
&lt;LI&gt;As far as I know, the managed code compilers do not make use of SSE2 instructions.&amp;nbsp;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Others have different opinions and I’m not saying they’re wrong - so long as they have measured.&amp;nbsp; Otherwise they are bullshitting you.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935518" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Software+Development/default.aspx">Software Development</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category></item><item><title>Resource constrained scheduling; OML tutorials</title><link>http://blogs.msdn.com/natbr/archive/2009/03/31/resource-constrained-scheduling-oml-tutorials.aspx</link><pubDate>Wed, 01 Apr 2009 05:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9524968</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9524968.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9524968</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9524968</wfw:comment><description>&lt;P&gt;Two weeks back I posted &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx"&gt;two&lt;/A&gt; &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/06/project-scheduling-and-solver-foundation-links-and-constraints.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/06/project-scheduling-and-solver-foundation-links-and-constraints.aspx"&gt;articles&lt;/A&gt; showing how easy it is to model critical path scheduling using &lt;A href="http://www.solverfoundation.com/" mce_href="http://www.solverfoundation.com"&gt;Microsoft Solver Foundation&lt;/A&gt;.&amp;nbsp; I received a few emails asking about various extensions; I will be covering those in upcoming posts.&amp;nbsp; Julian just wrote &lt;A href="http://brightsparc.wordpress.com/2009/03/31/scheduling-algorithm-in-gams-ampl-mfs-and-lp_solve/" mce_href="http://brightsparc.wordpress.com/2009/03/31/scheduling-algorithm-in-gams-ampl-mfs-and-lp_solve/"&gt;a great blog post&lt;/A&gt; that covers the most commonly requested extension - resource constrained scheduling.&amp;nbsp; If you are getting started with Solver Foundation and want to see an interesting, instructive example, I encourage you to check out his post.&amp;nbsp; Two things that I really like about his OML:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;He separates the data from the model description using Parameters.&lt;/LI&gt;
&lt;LI&gt;He relies on the Foreach construct to define his constraints.&amp;nbsp; It results in a very clean model definition.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Julian mentions it in his post, but I also want to call out another great resource for learning OML.&amp;nbsp; Erwin Kalvalagen has written an &lt;A href="http://www.amsterdamoptimization.com/models/msf/oml.pdf" mce_href="http://www.amsterdamoptimization.com/models/msf/oml.pdf"&gt;OML tutorial&lt;/A&gt; which includes several interesting examples.&amp;nbsp; It's a great complement to the &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799" mce_href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799"&gt;Excel Programming Primer&lt;/A&gt; that is part of the Solver Foundation documentation.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9524968" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</category><category domain="http://blogs.msdn.com/natbr/archive/tags/combinatorial+optimization/default.aspx">combinatorial optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/OML/default.aspx">OML</category><category domain="http://blogs.msdn.com/natbr/archive/tags/project+scheduling/default.aspx">project scheduling</category></item><item><title>Project Scheduling and Solver Foundation: links and constraints</title><link>http://blogs.msdn.com/natbr/archive/2009/03/06/project-scheduling-and-solver-foundation-links-and-constraints.aspx</link><pubDate>Fri, 06 Mar 2009 19:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9462979</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9462979.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9462979</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9462979</wfw:comment><description>&lt;P&gt;&lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx"&gt;Yesterday&lt;/A&gt; I introduced a simple OML model for computing project schedules.&amp;nbsp; The model has the following sections:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Parameters&lt;/STRONG&gt;: input data that comes from Excel.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Decisions&lt;/STRONG&gt;: the values that I want to solve for.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Constraints&lt;/STRONG&gt;: the relationships that decisions and parameters need to satisfy.&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Goals&lt;/STRONG&gt;: the objective - what I want to optimize.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The exciting cliffhanger from &lt;A href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx" mce_href="http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx"&gt;my previous post&lt;/A&gt; was to model precedence links.&amp;nbsp; Let's think about how I could specify the links in Excel.&amp;nbsp; One way to do it is to have a table that simply lists the "predecessor" and "successor" tasks.&amp;nbsp; For example:&lt;/P&gt;
&lt;TABLE border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;Pred&lt;/TD&gt;
&lt;TD&gt;Succ&lt;/TD&gt;
&lt;TR&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;1&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;1&lt;/TD&gt;
&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;The first row says that task 0 is the predecessor of task 1, i.e. task 1 should start after task 0 finishes.&amp;nbsp; If we want to bind this data to our model, we should introduce a Set and a Parameter, just like we did for Tasks:&lt;/P&gt;&lt;PRE&gt;  Parameters[Sets, Links],
  Parameters[Integers, Pred[Links], Succ[Links]],
&lt;/PRE&gt;
&lt;P&gt;The domain for Pred and Succ is Integers because the table stores indexes for the tasks.&amp;nbsp; Now I need to change the model to enforce the links.&amp;nbsp; That's a constraint, which is expressed straightforwardly using a Foreach:&lt;/P&gt;&lt;PRE&gt;    Foreach[{l, Links}, Start[Succ[l]] &amp;gt;=Finish[Pred[l]] ]
&lt;/PRE&gt;
&lt;P&gt;If I setup the data binding for Links and re-solve, then I will see that the links are honored.&amp;nbsp; If you compare to Project's schedule, you may spot a problem: some of the tasks (for example t3) are scheduled later than they are in Project.&amp;nbsp; This is totally valid according to our model - t3 has "slack" and can move around without affecting the project schedule.&amp;nbsp; Think about how you could fix up the model to match Project, so that all tasks are scheduled "as soon as possible".&lt;/P&gt;
&lt;P&gt;On to the "extra credit" problem: how to model "start no earlier than" (SNET) constraints.&amp;nbsp; This is actually not too hard if we just consider the SNET date to be another parameter just like Duration.&amp;nbsp; The constraint is straightforward:&lt;/P&gt;&lt;PRE&gt;  Parameters[Reals, SNET[Tasks]],
  Constraints[ Foreach[{t, Tasks}, Start[t] &amp;gt;= SNET[t] ]]
&lt;/PRE&gt;
&lt;P&gt;In my Excel spreadsheet, I added a SNET column with the date for the constraint for each task.&amp;nbsp; If a task does not have a SNET constraint, I just fill in a dummy date (e.g. 1/1/2009).&amp;nbsp; But I need a number, not a date, so in the adjacent column I add the formula "=C2-TODAY()" to give me the number of days since the project start date.&amp;nbsp; That's what I want to bind to.&lt;/P&gt;
&lt;P&gt;For reference, here is the data in my spreadsheet:&lt;/P&gt;
&lt;P&gt;&lt;IMG title="Excel data" alt="Excel data" src="http://blogs.msdn.com/photos/nathan_brixius/images/9462930/original.aspx" mce_src="http://blogs.msdn.com/photos/nathan_brixius/images/9462930/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And here are the data bindings I created using the "Binding" button in the Solver Foundation ribbon:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH: 453px; HEIGHT: 110px" title="OML data binding" alt="OML data binding" src="http://blogs.msdn.com/photos/nathan_brixius/images/9462934/original.aspx" width=453 height=110 mce_src="http://blogs.msdn.com/photos/nathan_brixius/images/9462934/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you've been working with the spreadsheet, you may have been annoyed by a couple of things:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If I add new tasks, I need to change the data binding to include the new cells.&lt;/LI&gt;
&lt;LI&gt;The conversion between dates and numbers is kind of bothersome.&lt;/LI&gt;
&lt;LI&gt;This is getting complicated.&amp;nbsp; For example, Project has eight different constraint types.&amp;nbsp; If I wanted to model them all the same way I modeled SNET, I would need to add a whole bunch of spreadsheet columns.&amp;nbsp; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Maybe it's time to turn this OML model into a C# program that directly calls Solver Foundation Services to model and solve project schedules.&amp;nbsp; Next time we will do just that.&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9462979" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category></item><item><title>Project Scheduling using Solver Foundation</title><link>http://blogs.msdn.com/natbr/archive/2009/03/05/project-scheduling-using-solver-foundation.aspx</link><pubDate>Thu, 05 Mar 2009 21:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9460343</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/natbr/comments/9460343.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=9460343</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=9460343</wfw:comment><description>&lt;P&gt;I'd like to work through a few examples of how to model real problems using Solver Foundation.&amp;nbsp; If you &lt;A href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799" target=_blank mce_href="http://code.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799"&gt;download the Solver Foundation Express Edition&lt;/A&gt;, you can follow along:&amp;nbsp;start Excel, click the Solver Foundation tab, then click on the Model button to get a blank modeling pane.&lt;/P&gt;
&lt;P&gt;I spent my first five years at Microsoft on the Project team, writing the project scheduling engine for Project Server.&amp;nbsp; Project is a great team and an awesome product, and I still have a soft spot for project scheduling.&amp;nbsp; My intent is not to reinvent Project - just to make a connection with a familiar problem so I can show off the Solver Foundation platform while introducing some key concepts. For those who don't know Project, the goal is to come up with a schedule for a list of tasks in a project.&amp;nbsp; Here are a few of the basics:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Tasks have a start, finish, and duration.&lt;/LI&gt;
&lt;LI&gt;No task starts before a given project start date.&lt;/LI&gt;
&lt;LI&gt;The finish date is computed as start + duration.&lt;/LI&gt;
&lt;LI&gt;A pair of tasks can be linked by precedence relationships.&amp;nbsp; When there is a link from a task&amp;nbsp;A to a task B, the&amp;nbsp;B's start&amp;nbsp;must occur on or after&amp;nbsp;A's finish&amp;nbsp;date.&lt;/LI&gt;
&lt;LI&gt;The project finish date is defined as the latest finish date of any task in the project.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Given these requirements, we would like to compute the start and finish dates for all of the tasks in the project, and we want to find a schedule ends as soon as possible.&amp;nbsp; Let's use the Solver Foundation to create a model in OML (Solver Foundation's declarative language) and compute some schedules.&amp;nbsp; I always find it helpful to work out an example before I try and model a problem.&amp;nbsp; Here's a simple schedule in Project with five tasks, and two links that connect t0, t1, t2.&amp;nbsp; To compute the schedule by hand I could use a simple &lt;A href="http://en.wikipedia.org/wiki/Critical_path_method" target=_blank mce_href="http://en.wikipedia.org/wiki/Critical_path_method"&gt;critical path scheduling&lt;/A&gt; algorithm. &lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH: 483px; HEIGHT: 122px" title="A simple project" alt="A simple project" src="http://blogs.msdn.com/photos/nathan_brixius/images/9460351/original.aspx" width=483 height=122 mce_src="http://blogs.msdn.com/photos/nathan_brixius/images/9460351/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Right away you can spot a few issues:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I haven't taken calendars into account - normally I don't want to schedule work on Saturdays and Sundays.&lt;/LI&gt;
&lt;LI&gt;I haven't taken resources into account - in real life, people (or machines, or rooms) are assigned to work on tasks, and their availability may affect my schedule.&lt;/LI&gt;
&lt;LI&gt;There are lots of cool Project features that I haven't taken into account - e.g. task constraints, summary tasks, etc.&lt;/LI&gt;
&lt;LI&gt;I haven't taken uncertainty into account - in real life, durations aren't known precisely.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I will revisit some of these points in future posts - these are all things that I can address with Solver Foundation.&amp;nbsp; For now, I am going to stick with a simple version of the problem.&amp;nbsp; I'd rather get a correct model on a simplified version of the problem than an incorrect model on a more complex one!&amp;nbsp; In this sense, modeling is no different from writing an essay or&amp;nbsp;designing software.&lt;/P&gt;
&lt;P&gt;There are a few questions to ask yourself when building an OML model:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;What are the key objects or entities that I will be working with? (tasks, links)&lt;/LI&gt;
&lt;LI&gt;What do I want the solver to compute? (start and finish dates for tasks)&lt;/LI&gt;
&lt;LI&gt;What do I know?&amp;nbsp; (the durations on the tasks)&lt;/LI&gt;
&lt;LI&gt;What are my restrictions? (links enforce an ordering on tasks, start + duration = finish)&lt;/LI&gt;
&lt;LI&gt;What do I want to optimize? (the finish date on the project)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;If you have good answers to these questions, and start simple, you can usually come up with an OML model that describes the problem.&amp;nbsp; Let's start by modeling the start and finish dates of the tasks, since that is ultimately what we want to find out.&amp;nbsp; Each task has a start and a finish - these are dates.&amp;nbsp; Solver Foundation does not directly support date values, so let's say that start and finish are real numbers, representing the number of days since the project start date.&amp;nbsp; To express the idea that each start and finish is associated with a task, we define a "set" &lt;STRONG&gt;Parameter&lt;/STRONG&gt;.&amp;nbsp; The start and finish dates are the values that we want the solver to figure out, so these are &lt;STRONG&gt;Decisions&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;Model[
 Parameters[Sets, Tasks],  
 
 Decisions[
     Reals[0, Infinity], Start[Tasks], Finish[Tasks]
  ],
&lt;/PRE&gt;
&lt;P&gt;Notice the syntax for Decisions: the first argument indicates the possible values (domain) for the decisions.&amp;nbsp; We could have used Integers[0, Infinity] for the first argument, but then we would not be able to model fractional days.&amp;nbsp;Loosely speaking, the start and finish dates are the "output".&amp;nbsp; What's input?&amp;nbsp; The durations.&amp;nbsp; Let's suppose that the durations are entered into our spreadsheet like this:&lt;/P&gt;
&lt;TABLE border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;Task&lt;/TD&gt;
&lt;TD&gt;Dur&lt;/TD&gt;
&lt;TR&gt;
&lt;TD&gt;t0&lt;/TD&gt;
&lt;TD&gt;1&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;t1&lt;/TD&gt;
&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;t2&lt;/TD&gt;
&lt;TD&gt;3&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;t3&lt;/TD&gt;
&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;t4&lt;/TD&gt;
&lt;TD&gt;4&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;We will define Duration as a Parameter so that we can use data binding to determine the values.&amp;nbsp; Just like Start and Finish, Duration is indexed by Task.&amp;nbsp; &lt;/P&gt;&lt;PRE&gt;Parameters[Reals, Duration[Tasks]],&lt;/PRE&gt;
&lt;P&gt;After entering&amp;nbsp;the duration&amp;nbsp;data into Excel I can use the Binding&amp;nbsp;button to add a binding from the range B2:B6 to Duration.&amp;nbsp; When I solve the model, Solver Foundation will use whatever values are entered in the spreadsheet.&amp;nbsp; But let's not get ahead of ourselves...next let's express the relation between Start, Finish, and Duration.&amp;nbsp; Relationships that need to be enforced&amp;nbsp;are described using&amp;nbsp;&lt;STRONG&gt;Constraints&lt;/STRONG&gt;.&amp;nbsp; OML provides a&amp;nbsp;bunch of operators and expressions for describing constraints.&amp;nbsp; In this case, we have one constraint per task.&amp;nbsp; This is easy to express using Foreach:&lt;/P&gt;&lt;PRE&gt; Constraints[
    Foreach[{t, Tasks}, Start[t] + Duration[t] == Finish[t] ]
 ] 
&lt;/PRE&gt;
&lt;P&gt;We almost have a working model -&amp;nbsp;the last thing we need to express is our &lt;STRONG&gt;Goal&lt;/STRONG&gt;: that we want the project to finish as soon as possible.&amp;nbsp; So let's introduce ProjectFinish as another decision:&lt;/P&gt;&lt;PRE&gt; Decisions[
     Reals[0, Infinity], Start[Tasks], Finish[Tasks], ProjectFinish
  ]
&lt;/PRE&gt;
&lt;P&gt;The ProjectFinish is the maximum finish date of any task in the model.&amp;nbsp; In other words, it is at least as big as the Finish date of each task, so we add this constraint.&lt;/P&gt;&lt;PRE&gt;  Foreach[{t, Tasks}, ProjectFinish &amp;gt;= Finish[t] ]
&lt;/PRE&gt;
&lt;P&gt;Now we can express our goal: minimize the project finish:&lt;/P&gt;&lt;PRE&gt;  Goals[ Minimize[finish -&amp;gt; ProjectFinish ] ]
&lt;/PRE&gt;
&lt;P&gt;The "-&amp;gt;" syntax simply gives a label to our goal, it's optional.&amp;nbsp; Here's the complete model: &lt;PRE&gt;Model[
  Parameters[Sets, Tasks],  
  Parameters[Reals, Duration[Tasks]],

  Decisions[
     Reals[0, Infinity], Start[Tasks], Finish[Tasks], ProjectFinish
  ],

  Constraints[
    Foreach[{t, Tasks}, Start[t] + Duration[t] == Finish[t] ],
    Foreach[{t, Tasks}, ProjectFinish &amp;gt;= Finish[t] ],
  ],
 
  Goals[ Minimize[ finish -&amp;gt; ProjectFinish ]  ]
]
&lt;/PRE&gt;
&lt;P&gt;If you have entered this into the modeling pane, and used the Binding button to define the data binding between the spreadsheet data and Duration, you can hit Solve and observe the Start and Finish dates.&amp;nbsp; You will see something like this:&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH: 306px; HEIGHT: 351px" title="Solver Foundation Results" alt="Solver Foundation Results" src="http://blogs.msdn.com/photos/nathan_brixius/images/9460363/original.aspx" width=306 height=351 mce_src="http://blogs.msdn.com/photos/nathan_brixius/images/9460363/original.aspx"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you want to turn the starts and finishes into dates, you can enter a formula like "=now() + C5" in the adjacent column.&amp;nbsp; Actually I put this formula in a column next to my duration values, so I can see the&amp;nbsp;durations, starts, and finishes&amp;nbsp;all in one place.&lt;/P&gt;
&lt;P&gt;You should be thoroughly unimpressed by this model (as I am ;)), because it doesn't do all that much.&amp;nbsp; All I'm doing is letting Solver Foundation compute finish = start + duration, which I could have done very easily in Excel.&amp;nbsp; I need to model "links": a link causes the start date of the successor task to be later than the finish of the predecessor task.&amp;nbsp; If you've made it this far, you have all the building blocks you need to&amp;nbsp;model this in OML.&amp;nbsp; Feel free to post your solution here, or just wait until tomorrow for my solution.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Extra credit:&lt;/STRONG&gt; if you use Project, you know that you can define "constraints" on tasks.&amp;nbsp; For example, I can double click on a task and say that a task must "Start No Earlier Than March 30, 2009".&amp;nbsp; These constraints need to be honored,&amp;nbsp;in addition to links.&amp;nbsp; How can I model SNET constraints using OML?&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9460343" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</category><category domain="http://blogs.msdn.com/natbr/archive/tags/Solver+Foundation/default.aspx">Solver Foundation</category><category domain="http://blogs.msdn.com/natbr/archive/tags/optimization/default.aspx">optimization</category><category domain="http://blogs.msdn.com/natbr/archive/tags/OML/default.aspx">OML</category></item><item><title>Testing Columns in a Project DataSet</title><link>http://blogs.msdn.com/natbr/archive/2007/01/08/testing-columns-in-a-project-dataset.aspx</link><pubDate>Mon, 08 Jan 2007 21:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1435310</guid><dc:creator>Nathan Brixius</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/natbr/comments/1435310.aspx</comments><wfw:commentRss>http://blogs.msdn.com/natbr/commentrss.aspx?PostID=1435310</wfw:commentRss><wfw:comment>http://blogs.msdn.com/natbr/rsscomments.aspx?PostID=1435310</wfw:comment><description>&lt;P mce_keep="true"&gt;Larry Duff of the Project team wrote a very nice article describing how to test column values when making calls to the Project Server PSI:&amp;nbsp; &lt;A href="http://blogs.msdn.com/lduff/archive/2006/12/06/testing-columns-in-a-dataset.aspx" mce_href="http://blogs.msdn.com/lduff/archive/2006/12/06/testing-columns-in-a-dataset.aspx"&gt;http://blogs.msdn.com/lduff/archive/2006/12/06/testing-columns-in-a-dataset.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;DavidK remarked in a comment that the PSI offers methods to handle the case where a column in the result set does not have a value.&amp;nbsp; If you use these, you don't need to do a try-catch:&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;SPAN style="COLOR: #0000ff"&gt;private string &lt;/SPAN&gt;GetWSSSite(&lt;SPAN style="COLOR: #0000ff"&gt;Guid&lt;/SPAN&gt; projectGuid) &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProjectWS.ProjectDataSet pds = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProjWebSvc.ReadProject(projectGuid,ProjectWS.DataStoreEnum.PublishedStore);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; (pds == &lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|| (pds.Project.Rows.Count == 0) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|| pds.Project[0].IsWPROJ_STS_SUBWEB_NAMENull() ?&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: #008080"&gt;String&lt;/SPAN&gt;.Empty : pds.Project[0].WPROJ_STS_SUBWEB_NAME;&lt;BR&gt;}&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Courier New"&gt;&lt;/P&gt;&lt;/SPAN&gt;I don't believe that the subweb name is a mandatory field, so it's appropriate to return String.Empty as a result rather than throwing an exception.&amp;nbsp; (But if the ReadProject call returns no results you may want to think about throwing an exception if you expect that projectGuid refers to a valid project.)&amp;nbsp; Another note: the IsXXXNull() method exists for all columns in all DataRow classes in the PSI. If you write code against the PSI you should get in the habit of taking advantage of these methods.&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1435310" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/natbr/archive/tags/Project/default.aspx">Project</category></item></channel></rss>