SoftTimur: since your problem is related to non-linear arithmetic (in the objective function) over integers, Z3 will most likely answer “unknown” to your problem, even if you can solve other problems that you have encountered. Non-linear integer arithmetic is unsolvable, and it is unlikely that the current solver in Z3 can effectively handle your problem with quantifiers. (Of course, amazing Z3 people can only fine-tune their solver to solve this particular problem, but the unsolvability problem remains the whole.) Even if you didn't have any nonlinear constructions, quantifiers are a soft spot for SMT and you are unlikely to go far with a quantitative approach.
So, you essentially abandoned Philip’s idea of using iteration. I want to emphasize, however, that the two methods (iteration versus quantification) are not equivalent! Theoretically, the quantitative approach is more powerful. For example, if you ask Z3 to give you the largest integer value (a simple maximization problem where cost is the value of the whole itself), it will correctly tell you that such an integer does not exist. However, if you follow an iterative approach, you will go in cycles forever. In the general case, an iterative approach will fail if the global maximum / minimum is not set for optimization. Ideally, a quantifier-based approach can deal with such cases, but then it obeys other constraints that you yourself have observed.
Like Z3 (and SMT solvers in general), programming them with SMT-Lib is a bit painful. This is why many people create easier-to-use interfaces. If you are open to using Haskell, for example, you can try SBV bindings that will allow you to script Z3 from Haskell. In fact, I encoded your problem in Haskell: http://gist.github.com/1485092 . (Keep in mind that I may have misunderstood your SMTLib code or may have made a coding error, so please double check.)
The Haskell SBV library allows you to optimize both quantitative and iterative approaches to optimization. When I try z3 with quantifiers, Z3 really returns "unknown", which means the problem is not solvable. (See the "test1" function in the program.) When I tried to execute the iterative version (see the "test2" function), it continues to find the best and best solutions, I killed it after about 10 minutes with the following solution found:
*** Round 3128 **************************** *** Solution: [4,42399,-1,0] *** Value : 42395 :: SInteger
Do you know if this particular instance of your problem really has the optimal solution? If this happens, you can let the program work longer, and in the end it will find it, otherwise it will be forever.
Let me know if you decide to explore the Haskell path, and if you have any problems with it.