IntegerExpressions.cs
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 namespace Google.OrTools.Sat
15 {
16  using System;
17  using System.Collections.Generic;
18  using Google.OrTools.Util;
19 
20  // Helpers.
21 
22  // IntVar[] helper class.
23  public static class IntVarArrayHelper
24  {
25  [Obsolete("This Sum method is deprecated, please use LinearExpr.Sum() instead.")]
26  public static LinearExpr Sum(this IntVar[] vars)
27  {
28  return LinearExpr.Sum(vars);
29  }
30  [Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
31  public static LinearExpr ScalProd(this IntVar[] vars, int[] coeffs)
32  {
33  return LinearExpr.ScalProd(vars, coeffs);
34  }
35  [Obsolete("This ScalProd method is deprecated, please use LinearExpr.ScalProd() instead.")]
36  public static LinearExpr ScalProd(this IntVar[] vars, long[] coeffs)
37  {
38  return LinearExpr.ScalProd(vars, coeffs);
39  }
40  }
41 
42  public interface ILiteral
43  {
44  ILiteral Not();
45  int GetIndex();
46  }
47 
48  // Holds an linear expression.
49  public class LinearExpr
50  {
51 
52  public static LinearExpr Sum(IEnumerable<IntVar> vars)
53  {
54  return new SumArray(vars);
55  }
56 
57  public static LinearExpr Sum(IEnumerable<LinearExpr> exprs)
58  {
59  return new SumArray(exprs);
60  }
61 
62  public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
63  {
64  return new SumArray(vars, coeffs);
65  }
66  public static LinearExpr ScalProd(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
67  {
68  return new SumArray(vars, coeffs);
69  }
70 
71  public int Index
72  {
73  get { return GetIndex(); }
74  }
75 
76  public virtual int GetIndex()
77  {
78  throw new NotImplementedException();
79  }
80 
81  public virtual string ShortString()
82  {
83  return ToString();
84  }
85 
87  {
88  return new SumArray(a, b);
89  }
90 
91  public static LinearExpr operator +(LinearExpr a, long v)
92  {
93  return new SumArray(a, v);
94  }
95 
96  public static LinearExpr operator +(long v, LinearExpr a)
97  {
98  return new SumArray(a, v);
99  }
100 
102  {
103  return new SumArray(a, Prod(b, -1));
104  }
105 
106  public static LinearExpr operator -(LinearExpr a, long v)
107  {
108  return new SumArray(a, -v);
109  }
110 
111  public static LinearExpr operator -(long v, LinearExpr a)
112  {
113  return new SumArray(Prod(a, -1), v);
114  }
115 
116  public static LinearExpr operator *(LinearExpr a, long v)
117  {
118  return Prod(a, v);
119  }
120 
121  public static LinearExpr operator *(long v, LinearExpr a)
122  {
123  return Prod(a, v);
124  }
125 
127  {
128  return Prod(a, -1);
129  }
130 
132  {
133  return new BoundedLinearExpression(a, b, true);
134  }
135 
137  {
138  return new BoundedLinearExpression(a, b, false);
139  }
140 
142  {
143  return new BoundedLinearExpression(a, v, true);
144  }
145 
147  {
148  return new BoundedLinearExpression(a, v, false);
149  }
150 
152  {
153  return new BoundedLinearExpression(v, a, Int64.MaxValue);
154  }
155 
157  {
158  return a <= v;
159  }
160 
162  {
163  return new BoundedLinearExpression(v + 1, a, Int64.MaxValue);
164  }
165 
167  {
168  return a < v;
169  }
170 
172  {
173  return new BoundedLinearExpression(Int64.MinValue, a, v);
174  }
175 
177  {
178  return a >= v;
179  }
180 
182  {
183  return new BoundedLinearExpression(Int64.MinValue, a, v - 1);
184  }
185 
187  {
188  return a > v;
189  }
190 
192  {
193  return new BoundedLinearExpression(0, a - b, Int64.MaxValue);
194  }
195 
197  {
198  return new BoundedLinearExpression(1, a - b, Int64.MaxValue);
199  }
200 
202  {
203  return new BoundedLinearExpression(Int64.MinValue, a - b, 0);
204  }
205 
207  {
208  return new BoundedLinearExpression(Int64.MinValue, a - b, -1);
209  }
210 
211  public static LinearExpr Prod(LinearExpr e, long v)
212  {
213  if (v == 1)
214  {
215  return e;
216  }
217  else if (e is ProductCst)
218  {
219  ProductCst p = (ProductCst)e;
220  return new ProductCst(p.Expr, p.Coeff * v);
221  }
222  else
223  {
224  return new ProductCst(e, v);
225  }
226  }
227 
228  public static long GetVarValueMap(LinearExpr e,
229  long initial_coeff,
230  Dictionary<IntVar, long> dict)
231  {
232  List<LinearExpr> exprs = new List<LinearExpr>();
233  List<long> coeffs = new List<long>();
234  if ((Object)e != null)
235  {
236  exprs.Add(e);
237  coeffs.Add(initial_coeff);
238  }
239  long constant = 0;
240 
241  while (exprs.Count > 0)
242  {
243  LinearExpr expr = exprs[0];
244  exprs.RemoveAt(0);
245  long coeff = coeffs[0];
246  coeffs.RemoveAt(0);
247  if (coeff == 0 || (Object)expr == null) continue;
248 
249  if (expr is ProductCst)
250  {
251  ProductCst p = (ProductCst)expr;
252  if (p.Coeff != 0)
253  {
254  exprs.Add(p.Expr);
255  coeffs.Add(p.Coeff * coeff);
256  }
257  }
258  else if (expr is SumArray)
259  {
260  SumArray a = (SumArray)expr;
261  constant += coeff * a.Constant;
262  foreach (LinearExpr sub in a.Expressions)
263  {
264  if (sub is IntVar)
265  {
266  IntVar i = (IntVar)sub;
267  if (dict.ContainsKey(i))
268  {
269  dict[i] += coeff;
270  }
271  else
272  {
273  dict.Add(i, coeff);
274  }
275  }
276  else if (sub is ProductCst && ((ProductCst)sub).Expr is IntVar)
277  {
278  ProductCst sub_prod = (ProductCst)sub;
279  IntVar i = (IntVar)sub_prod.Expr;
280  long sub_coeff = sub_prod.Coeff;
281 
282  if (dict.ContainsKey(i))
283  {
284  dict[i] += coeff * sub_coeff;
285  }
286  else
287  {
288  dict.Add(i, coeff * sub_coeff);
289  }
290  }
291  else
292  {
293  exprs.Add(sub);
294  coeffs.Add(coeff);
295  }
296  }
297  }
298  else if (expr is IntVar)
299  {
300  IntVar i = (IntVar)expr;
301  if (dict.ContainsKey(i))
302  {
303  dict[i] += coeff;
304  }
305  else
306  {
307  dict.Add(i, coeff);
308  }
309  }
310  else if (expr is NotBooleanVariable)
311  {
312  IntVar i = ((NotBooleanVariable)expr).NotVar();
313  if (dict.ContainsKey(i))
314  {
315  dict[i] -= coeff;
316  }
317  else
318  {
319  dict.Add(i, -coeff);
320  }
321  constant += coeff;
322  }
323  else
324  {
325  throw new ArgumentException("Cannot interpret '" + expr.ToString() +
326  "' in an integer expression");
327  }
328  }
329  return constant;
330  }
331  }
332 
333  public class ProductCst : LinearExpr
334  {
335  public ProductCst(LinearExpr e, long v)
336  {
337  expr_ = e;
338  coeff_ = v;
339  }
340 
341  public LinearExpr Expr
342  {
343  get { return expr_; }
344  }
345 
346  public long Coeff
347  {
348  get { return coeff_; }
349  }
350 
351  private LinearExpr expr_;
352  private long coeff_;
353 
354  }
355 
356  public class SumArray : LinearExpr
357  {
359  {
360  expressions_ = new List<LinearExpr>();
361  AddExpr(a);
362  AddExpr(b);
363  constant_ = 0L;
364  }
365 
366  public SumArray(LinearExpr a, long b)
367  {
368  expressions_ = new List<LinearExpr>();
369  AddExpr(a);
370  constant_ = b;
371  }
372 
373  public SumArray(IEnumerable<LinearExpr> exprs)
374  {
375  expressions_ = new List<LinearExpr>(exprs);
376  constant_ = 0L;
377  }
378 
379  public SumArray(IEnumerable<IntVar> vars)
380  {
381  expressions_ = new List<LinearExpr>(vars);
382  constant_ = 0L;
383  }
384 
385  public SumArray(IntVar[] vars, long[] coeffs)
386  {
387  expressions_ = new List<LinearExpr>(vars.Length);
388  for (int i = 0; i < vars.Length; ++i)
389  {
390  AddExpr(Prod(vars[i], coeffs[i]));
391  }
392  constant_ = 0L;
393  }
394  public SumArray(IEnumerable<IntVar> vars, IEnumerable<long> coeffs)
395  {
396  List<IntVar> tmp_vars = new List<IntVar>();
397  foreach (IntVar v in vars)
398  {
399  tmp_vars.Add(v);
400  }
401  List<long> tmp_coeffs = new List<long>();
402  foreach (long c in coeffs)
403  {
404  tmp_coeffs.Add(c);
405  }
406  if (tmp_vars.Count != tmp_coeffs.Count)
407  {
408  throw new ArgumentException(
409  "in SumArray(vars, coeffs), the two lists do not have the same length");
410  }
411  IntVar[] flat_vars = tmp_vars.ToArray();
412  long[] flat_coeffs = tmp_coeffs.ToArray();
413  expressions_ = new List<LinearExpr>(flat_vars.Length);
414  for (int i = 0; i < flat_vars.Length; ++i)
415  {
416  expressions_.Add(Prod(flat_vars[i], flat_coeffs[i]));
417  }
418  constant_ = 0L;
419  }
420 
421  public SumArray(IEnumerable<IntVar> vars, IEnumerable<int> coeffs)
422  {
423  List<IntVar> tmp_vars = new List<IntVar>();
424  foreach (IntVar v in vars)
425  {
426  tmp_vars.Add(v);
427  }
428  List<long> tmp_coeffs = new List<long>();
429  foreach (int c in coeffs)
430  {
431  tmp_coeffs.Add(c);
432  }
433  if (tmp_vars.Count != tmp_coeffs.Count)
434  {
435  throw new ArgumentException(
436  "in SumArray(vars, coeffs), the two lists do not have the same length");
437  }
438  IntVar[] flat_vars = tmp_vars.ToArray();
439  long[] flat_coeffs = tmp_coeffs.ToArray();
440  expressions_ = new List<LinearExpr>(flat_vars.Length);
441  for (int i = 0; i < flat_vars.Length; ++i)
442  {
443  expressions_.Add(Prod(flat_vars[i], flat_coeffs[i]));
444  }
445  constant_ = 0L;
446  }
447 
448  public void AddExpr(LinearExpr expr)
449  {
450  if ((Object)expr != null)
451  {
452  expressions_.Add(expr);
453  }
454  }
455 
456  public List<LinearExpr> Expressions
457  {
458  get { return expressions_; }
459  }
460 
461  public long Constant
462  {
463  get { return constant_; }
464  }
465 
466  public override string ShortString()
467  {
468  return String.Format("({0})", ToString());
469  }
470 
471  public override string ToString()
472  {
473  string result = "";
474  foreach (LinearExpr expr in expressions_)
475  {
476  if ((Object)expr == null) continue;
477  if (!String.IsNullOrEmpty(result))
478  {
479  result += String.Format(" + ");
480  }
481 
482  result += expr.ShortString();
483  }
484  return result;
485  }
486 
487  private List<LinearExpr> expressions_;
488  private long constant_;
489  }
490 
491  public class IntVar : LinearExpr, ILiteral
492  {
493  public IntVar(CpModelProto model, Domain domain, string name)
494  {
495  model_ = model;
496  index_ = model.Variables.Count;
497  var_ = new IntegerVariableProto();
498  var_.Name = name;
499  var_.Domain.Add(domain.FlattenedIntervals());
500  model.Variables.Add(var_);
501  negation_ = null;
502  }
503 
504  public int Index
505  {
506  get { return index_; }
507  }
508 
509  public override int GetIndex()
510  {
511  return index_;
512  }
513 
515  {
516  get { return var_; }
517  set { var_ = value; }
518  }
519 
520  public override string ToString()
521  {
522  return var_.ToString();
523  }
524 
525  public override string ShortString()
526  {
527  if (var_.Name != null)
528  {
529  return var_.Name;
530  }
531  else
532  {
533  return var_.ToString();
534  }
535  }
536 
537  public string Name()
538  {
539  return var_.Name;
540  }
541 
542  public ILiteral Not()
543  {
544  foreach (long b in var_.Domain)
545  {
546  if (b < 0 || b > 1)
547  {
548  throw new ArgumentException(
549  "Cannot call Not() on a non boolean variable");
550  }
551  }
552  if (negation_ == null)
553  {
554  negation_ = new NotBooleanVariable(this);
555  }
556  return negation_;
557  }
558 
559 
560  private CpModelProto model_;
561  private int index_;
562  private List<long> bounds_;
563  private IntegerVariableProto var_;
564  private NotBooleanVariable negation_;
565  }
566 
568  {
569  public NotBooleanVariable(IntVar boolvar)
570  {
571  boolvar_ = boolvar;
572  }
573 
574  public override int GetIndex()
575  {
576  return -boolvar_.Index - 1;
577  }
578 
579  public ILiteral Not()
580  {
581  return boolvar_;
582  }
583 
584  public IntVar NotVar()
585  {
586  return boolvar_;
587  }
588 
589  public override string ShortString()
590  {
591  return String.Format("Not({0})", boolvar_.ShortString());
592  }
593 
594  private IntVar boolvar_;
595  }
596 
598  {
599  public enum Type
600  {
601  BoundExpression,
602  VarEqVar,
603  VarDiffVar,
604  VarEqCst,
605  VarDiffCst,
606  }
607 
608  public BoundedLinearExpression(long lb, LinearExpr expr, long ub)
609  {
610  left_ = expr;
611  right_ = null;
612  lb_ = lb;
613  ub_ = ub;
614  type_ = Type.BoundExpression;
615  }
616 
618  bool equality)
619  {
620  left_ = left;
621  right_ = right;
622  lb_ = 0;
623  ub_ = 0;
624  type_ = equality ? Type.VarEqVar : Type.VarDiffVar;
625  }
626 
627  public BoundedLinearExpression(LinearExpr left, long v, bool equality)
628  {
629  left_ = left;
630  right_ = null;
631  lb_ = v;
632  ub_ = 0;
633  type_ = equality ? Type.VarEqCst : Type.VarDiffCst;
634  }
635 
636  bool IsTrue()
637  {
638  if (type_ == Type.VarEqVar)
639  {
640  return (object)left_ == (object)right_;
641  }
642  else if (type_ == Type.VarDiffVar)
643  {
644  return (object)left_ != (object)right_;
645  }
646  return false;
647  }
648 
649  public static bool operator true(BoundedLinearExpression bie)
650  {
651  return bie.IsTrue();
652  }
653 
654  public static bool operator false(BoundedLinearExpression bie)
655  {
656  return !bie.IsTrue();
657  }
658 
659  public override string ToString()
660  {
661  switch (type_)
662  {
663  case Type.BoundExpression:
664  return String.Format("{0} <= {1} <= {2}", lb_, left_, ub_);
665  case Type.VarEqVar:
666  return String.Format("{0} == {1}", left_, right_);
667  case Type.VarDiffVar:
668  return String.Format("{0} != {1}", left_, right_);
669  case Type.VarEqCst:
670  return String.Format("{0} == {1}", left_, lb_);
671  case Type.VarDiffCst:
672  return String.Format("{0} != {1}", left_, lb_);
673  default:
674  throw new ArgumentException("Wrong mode in BoundedLinearExpression.");
675  }
676  }
677 
679  long v)
680  {
681  if (a.CtType != Type.BoundExpression || a.Ub != Int64.MaxValue)
682  {
683  throw new ArgumentException(
684  "Operator <= not supported for this BoundedLinearExpression");
685  }
686  return new BoundedLinearExpression(a.Lb, a.Left, v);
687  }
688 
690  long v)
691  {
692  if (a.CtType != Type.BoundExpression || a.Ub != Int64.MaxValue)
693  {
694  throw new ArgumentException(
695  "Operator < not supported for this BoundedLinearExpression");
696  }
697  return new BoundedLinearExpression(a.Lb, a.Left, v - 1);
698  }
699 
701  long v)
702  {
703  if (a.CtType != Type.BoundExpression || a.Lb != Int64.MinValue)
704  {
705  throw new ArgumentException(
706  "Operator >= not supported for this BoundedLinearExpression");
707  }
708  return new BoundedLinearExpression(v, a.Left, a.Ub);
709  }
710 
712  long v)
713  {
714  if (a.CtType != Type.BoundExpression || a.Lb != Int64.MinValue)
715  {
716  throw new ArgumentException(
717  "Operator < not supported for this BoundedLinearExpression");
718  }
719  return new BoundedLinearExpression(v + 1, a.Left, a.Ub);
720  }
721 
722  public LinearExpr Left
723  {
724  get { return left_; }
725  }
726 
727  public LinearExpr Right
728  {
729  get { return right_; }
730  }
731 
732  public long Lb
733  {
734  get { return lb_; }
735  }
736 
737  public long Ub
738  {
739  get { return ub_; }
740  }
741 
742  public Type CtType
743  {
744  get { return type_; }
745  }
746 
747  private LinearExpr left_;
748  private LinearExpr right_;
749  private long lb_;
750  private long ub_;
751  private Type type_;
752  }
753 
754 } // namespace Google.OrTools.Sat
string Name
For debug/logging only.
Definition: CpModel.pb.cs:266
static BoundedLinearExpression operator<=(LinearExpr a, long v)
long [] FlattenedIntervals()
Definition: Domain.cs:84
SumArray(IEnumerable< IntVar > vars)
SumArray(LinearExpr a, LinearExpr b)
void AddExpr(LinearExpr expr)
SumArray(IntVar[] vars, long[] coeffs)
ProductCst(LinearExpr e, long v)
static BoundedLinearExpression operator >(LinearExpr a, LinearExpr b)
static BoundedLinearExpression operator !=(LinearExpr a, LinearExpr b)
static BoundedLinearExpression operator >=(LinearExpr a, LinearExpr b)
static BoundedLinearExpression operator >(LinearExpr a, long v)
static LinearExpr operator+(LinearExpr a, LinearExpr b)
static BoundedLinearExpression operator >=(BoundedLinearExpression a, long v)
static LinearExpr operator -(LinearExpr a)
static BoundedLinearExpression operator >=(LinearExpr a, long v)
BoundedLinearExpression(long lb, LinearExpr expr, long ub)
static BoundedLinearExpression operator==(LinearExpr a, LinearExpr b)
static LinearExpr operator -(LinearExpr a, long v)
SumArray(IEnumerable< IntVar > vars, IEnumerable< long > coeffs)
static BoundedLinearExpression operator<=(BoundedLinearExpression a, long v)
static LinearExpr operator *(LinearExpr a, long v)
static LinearExpr Sum(IEnumerable< IntVar > vars)
pbc::RepeatedField< long > Domain
The variable domain given as a sorted list of n disjoint intervals [min, max] and encoded as [min_0,...
Definition: CpModel.pb.cs:293
static LinearExpr operator *(long v, LinearExpr a)
IntVar(CpModelProto model, Domain domain, string name)
static BoundedLinearExpression operator >=(long v, LinearExpr a)
static LinearExpr operator -(LinearExpr a, LinearExpr b)
static LinearExpr Prod(LinearExpr e, long v)
A constraint programming problem.
Definition: CpModel.pb.cs:5198
static LinearExpr ScalProd(IEnumerable< IntVar > vars, IEnumerable< int > coeffs)
BoundedLinearExpression(LinearExpr left, long v, bool equality)
static BoundedLinearExpression operator >(long v, LinearExpr a)
static LinearExpr ScalProd(IEnumerable< IntVar > vars, IEnumerable< long > coeffs)
IntegerVariableProto Proto
static LinearExpr Sum(IEnumerable< LinearExpr > exprs)
static BoundedLinearExpression operator !=(LinearExpr a, long v)
static LinearExpr ScalProd(this IntVar[] vars, long[] coeffs)
static BoundedLinearExpression operator >(BoundedLinearExpression a, long v)
static long GetVarValueMap(LinearExpr e, long initial_coeff, Dictionary< IntVar, long > dict)
SumArray(IEnumerable< LinearExpr > exprs)
static BoundedLinearExpression operator<(LinearExpr a, long v)
BoundedLinearExpression(LinearExpr left, LinearExpr right, bool equality)
static BoundedLinearExpression operator<(BoundedLinearExpression a, long v)
static LinearExpr Sum(this IntVar[] vars)
SumArray(IEnumerable< IntVar > vars, IEnumerable< int > coeffs)
static LinearExpr ScalProd(this IntVar[] vars, int[] coeffs)
SumArray(LinearExpr a, long b)
static LinearExpr operator -(long v, LinearExpr a)
pbc::RepeatedField< global::Google.OrTools.Sat.IntegerVariableProto > Variables
The associated Protos should be referred by their index in these fields.
Definition: CpModel.pb.cs:5260