GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/arith/matrix.h Lines: 307 401 76.6 %
Date: 2021-05-22 Branches: 252 1116 22.6 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Mathias Preiner, Morgan Deters
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 * Sparse matrix implementations for different types.
13
 *
14
 * Sparse matrix implementations for different types.
15
 * This defines Matrix<T>, IntegerEqualityTables and Tableau.
16
 */
17
18
#include "cvc5_private.h"
19
20
#pragma once
21
22
#include <queue>
23
#include <utility>
24
#include <vector>
25
26
#include "base/output.h"
27
#include "theory/arith/arithvar.h"
28
#include "util/dense_map.h"
29
#include "util/index.h"
30
31
namespace cvc5 {
32
namespace theory {
33
namespace arith {
34
35
typedef Index EntryID;
36
const EntryID ENTRYID_SENTINEL = std::numeric_limits<EntryID>::max();
37
38
typedef Index RowIndex;
39
const RowIndex ROW_INDEX_SENTINEL  = std::numeric_limits<RowIndex>::max();
40
41
9459
class CoefficientChangeCallback {
42
public:
43
94149
  virtual ~CoefficientChangeCallback() {}
44
  virtual void update(RowIndex ridx, ArithVar nb, int oldSgn, int currSgn) = 0;
45
  virtual void multiplyRow(RowIndex ridx, int Sgn) = 0;
46
  virtual bool canUseRow(RowIndex ridx) const = 0;
47
};
48
49
84690
class NoEffectCCCB : public CoefficientChangeCallback {
50
public:
51
 void update(RowIndex ridx, ArithVar nb, int oldSgn, int currSgn) override;
52
 void multiplyRow(RowIndex ridx, int Sgn) override;
53
 bool canUseRow(RowIndex ridx) const override;
54
};
55
56
template<class T>
57
53747247
class MatrixEntry {
58
private:
59
  RowIndex d_rowIndex;
60
  ArithVar d_colVar;
61
62
  EntryID d_nextRow;
63
  EntryID d_nextCol;
64
65
  EntryID d_prevRow;
66
  EntryID d_prevCol;
67
68
  T d_coefficient;
69
70
public:
71
679973
  MatrixEntry():
72
    d_rowIndex(ROW_INDEX_SENTINEL),
73
    d_colVar(ARITHVAR_SENTINEL),
74
    d_nextRow(ENTRYID_SENTINEL),
75
    d_nextCol(ENTRYID_SENTINEL),
76
    d_prevRow(ENTRYID_SENTINEL),
77
    d_prevCol(ENTRYID_SENTINEL),
78
679973
    d_coefficient()
79
679973
  {}
80
81
24955497
  MatrixEntry(RowIndex row, ArithVar col, const T& coeff):
82
     d_rowIndex(row),
83
     d_colVar(col),
84
     d_nextRow(ENTRYID_SENTINEL),
85
     d_nextCol(ENTRYID_SENTINEL),
86
     d_prevRow(ENTRYID_SENTINEL),
87
     d_prevCol(ENTRYID_SENTINEL),
88
24955497
     d_coefficient(coeff)
89
24955497
  {}
90
91
private:
92
24570603
  bool unusedConsistent() const {
93
    return
94
49334746
      (d_rowIndex == ROW_INDEX_SENTINEL && d_colVar == ARITHVAR_SENTINEL) ||
95
24957683
      (d_rowIndex != ROW_INDEX_SENTINEL && d_colVar != ARITHVAR_SENTINEL);
96
  }
97
98
public:
99
100
314591484
  EntryID getNextRowEntryID() const {
101
314591484
    return d_nextRow;
102
  }
103
104
70024258
  EntryID getNextColEntryID() const {
105
70024258
    return d_nextCol;
106
  }
107
24377063
  EntryID getPrevRowEntryID() const {
108
24377063
    return d_prevRow;
109
  }
110
111
24377063
  EntryID getPrevColEntryID() const {
112
24377063
    return d_prevCol;
113
  }
114
115
39003140
  void setNextRowEntryID(EntryID id) {
116
39003140
    d_nextRow = id;
117
39003140
  }
118
43303679
  void setNextColEntryID(EntryID id) {
119
43303679
    d_nextCol = id;
120
43303679
  }
121
49050562
  void setPrevRowEntryID(EntryID id) {
122
49050562
    d_prevRow = id;
123
49050562
  }
124
48652969
  void setPrevColEntryID(EntryID id) {
125
48652969
    d_prevCol = id;
126
48652969
  }
127
128
73635626
  RowIndex getRowIndex() const{
129
73635626
    return d_rowIndex;
130
  }
131
132
215371376
  ArithVar getColVar() const{
133
215371376
    return d_colVar;
134
  }
135
136
242266990
  const T& getCoefficient() const {
137
242266990
    return d_coefficient;
138
  }
139
140
69069347
  T& getCoefficient(){
141
69069347
    return d_coefficient;
142
  }
143
144
  void setCoefficient(const T& t){
145
    d_coefficient = t;
146
  }
147
148
24377063
  void markBlank() {
149
24377063
    d_rowIndex = ROW_INDEX_SENTINEL;
150
24377063
    d_colVar = ARITHVAR_SENTINEL;
151
24377063
  }
152
153
24570603
  bool blank() const{
154
24570603
    Assert(unusedConsistent());
155
156
24570603
    return d_rowIndex == ROW_INDEX_SENTINEL;
157
  }
158
}; /* class MatrixEntry<T> */
159
160
template<class T>
161
18918
class MatrixEntryVector {
162
private:
163
  typedef MatrixEntry<T> EntryType;
164
  typedef std::vector<EntryType> EntryArray;
165
166
  EntryArray d_entries;
167
  std::queue<EntryID> d_freedEntries;
168
169
  uint32_t d_size;
170
171
public:
172
18918
  MatrixEntryVector():
173
18918
    d_entries(), d_freedEntries(), d_size(0)
174
18918
  {}
175
176
602192823
  const EntryType& operator[](EntryID id) const{
177
602192823
    Assert(inBounds(id));
178
602192823
    return d_entries[id];
179
  }
180
181
460116704
  EntryType& get(EntryID id){
182
460116704
    Assert(inBounds(id));
183
460116704
    return d_entries[id];
184
  }
185
186
24377063
  void freeEntry(EntryID id){
187
24377063
    Assert(get(id).blank());
188
24377063
    Assert(d_size > 0);
189
190
24377063
    d_freedEntries.push(id);
191
24377063
    --d_size;
192
24377063
  }
193
194
24955497
  EntryID newEntry(){
195
    EntryID newId;
196
24955497
    if(d_freedEntries.empty()){
197
661055
      newId = d_entries.size();
198
661055
      d_entries.push_back(MatrixEntry<T>());
199
    }else{
200
24294442
      newId = d_freedEntries.front();
201
24294442
      d_freedEntries.pop();
202
    }
203
24955497
    ++d_size;
204
24955497
    return newId;
205
  }
206
207
  uint32_t size() const{ return d_size; }
208
  uint32_t capacity() const{ return d_entries.capacity(); }
209
210
211
private:
212
1062309527
  bool inBounds(EntryID id) const{
213
1062309527
    return id <  d_entries.size();
214
  }
215
}; /* class MatrixEntryVector<T> */
216
217
template <class T, bool isRow>
218
class MatrixVector {
219
private:
220
  EntryID d_head;
221
  uint32_t d_size;
222
223
  MatrixEntryVector<T>* d_entries;
224
225
  class Iterator {
226
  private:
227
    EntryID d_curr;
228
    const MatrixEntryVector<T>* d_entries;
229
230
  public:
231
33924421
    Iterator(EntryID start, const MatrixEntryVector<T>* entries) :
232
33924421
      d_curr(start), d_entries(entries)
233
33924421
    {}
234
235
  public:
236
237
89038066
    EntryID getID() const {
238
89038066
      return d_curr;
239
    }
240
241
266137667
    const MatrixEntry<T>& operator*() const{
242
266137667
      Assert(!atEnd());
243
266137667
      return (*d_entries)[d_curr];
244
    }
245
246
335861616
    Iterator& operator++(){
247
335861616
      Assert(!atEnd());
248
335861616
      const MatrixEntry<T>& entry = (*d_entries)[d_curr];
249
335861616
      d_curr = isRow ? entry.getNextRowEntryID() : entry.getNextColEntryID();
250
335861616
      return *this;
251
    }
252
253
823032373
    bool atEnd() const {
254
823032373
      return d_curr == ENTRYID_SENTINEL;
255
    }
256
257
    bool operator==(const Iterator& i) const{
258
      return d_curr == i.d_curr && d_entries == i.d_entries;
259
    }
260
261
141005175
    bool operator!=(const Iterator& i) const{
262
141005175
      return !(d_curr == i.d_curr && d_entries == i.d_entries);
263
    }
264
  }; /* class MatrixVector<T, isRow>::Iterator */
265
266
public:
267
232603
  MatrixVector(MatrixEntryVector<T>* mev)
268
232603
    : d_head(ENTRYID_SENTINEL), d_size(0), d_entries(mev)
269
232603
  {}
270
271
  MatrixVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
272
    : d_head(head), d_size(size), d_entries(mev)
273
  {}
274
275
  typedef Iterator const_iterator;
276
26176649
  const_iterator begin() const {
277
26176649
    return Iterator(d_head, d_entries);
278
  }
279
7747772
  const_iterator end() const {
280
7747772
    return Iterator(ENTRYID_SENTINEL, d_entries);
281
  }
282
283
  EntryID getHead() const { return d_head; }
284
285
60504356
  uint32_t getSize() const { return d_size; }
286
287
49910994
  void insert(EntryID newId){
288
    if(isRow){
289
24955497
      d_entries->get(newId).setNextRowEntryID(d_head);
290
291
24955497
      if(d_head != ENTRYID_SENTINEL){
292
24870807
        d_entries->get(d_head).setPrevRowEntryID(newId);
293
      }
294
    }else{
295
24955497
      d_entries->get(newId).setNextColEntryID(d_head);
296
297
24955497
      if(d_head != ENTRYID_SENTINEL){
298
24818193
        d_entries->get(d_head).setPrevColEntryID(newId);
299
      }
300
    }
301
302
49910994
    d_head = newId;
303
49910994
    ++d_size;
304
49910994
  }
305
48754126
  void remove(EntryID id){
306
48754126
    Assert(d_size > 0);
307
48754126
    --d_size;
308
    if(isRow){
309
24377063
      EntryID prevRow = d_entries->get(id).getPrevRowEntryID();
310
24377063
      EntryID nextRow = d_entries->get(id).getNextRowEntryID();
311
312
24377063
      if(d_head == id){
313
10329420
        d_head = nextRow;
314
      }
315
24377063
      if(prevRow != ENTRYID_SENTINEL){
316
14047643
        d_entries->get(prevRow).setNextRowEntryID(nextRow);
317
      }
318
24377063
      if(nextRow != ENTRYID_SENTINEL){
319
24179755
        d_entries->get(nextRow).setPrevRowEntryID(prevRow);
320
      }
321
    }else{
322
24377063
      EntryID prevCol = d_entries->get(id).getPrevColEntryID();
323
24377063
      EntryID nextCol = d_entries->get(id).getNextColEntryID();
324
325
24377063
      if(d_head == id){
326
6028881
        d_head = nextCol;
327
      }
328
329
24377063
      if(prevCol != ENTRYID_SENTINEL){
330
18348182
        d_entries->get(prevCol).setNextColEntryID(nextCol);
331
      }
332
24377063
      if(nextCol != ENTRYID_SENTINEL){
333
23834776
        d_entries->get(nextCol).setPrevColEntryID(prevCol);
334
      }
335
    }
336
48754126
  }
337
}; /* class MatrixVector<T, isRow> */
338
339
template <class T>
340
  class RowVector : public MatrixVector<T, true>
341
{
342
private:
343
  typedef MatrixVector<T, true> SuperT;
344
public:
345
  typedef typename SuperT::const_iterator const_iterator;
346
347
84690
  RowVector(MatrixEntryVector<T>* mev) : SuperT(mev){}
348
  RowVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
349
    : SuperT(head, size, mev){}
350
};/* class RowVector<T> */
351
352
template <class T>
353
  class ColumnVector : public MatrixVector<T, false>
354
{
355
private:
356
  typedef MatrixVector<T, false> SuperT;
357
public:
358
  typedef typename SuperT::const_iterator const_iterator;
359
360
147913
  ColumnVector(MatrixEntryVector<T>* mev) : SuperT(mev){}
361
  ColumnVector(EntryID head, uint32_t size, MatrixEntryVector<T>* mev)
362
    : SuperT(head, size, mev){}
363
};/* class ColumnVector<T> */
364
365
template <class T>
366
18918
class Matrix {
367
public:
368
  typedef MatrixEntry<T> Entry;
369
370
protected:
371
 typedef cvc5::theory::arith::RowVector<T> RowVectorT;
372
 typedef cvc5::theory::arith::ColumnVector<T> ColumnVectorT;
373
374
public:
375
  typedef typename RowVectorT::const_iterator RowIterator;
376
  typedef typename ColumnVectorT::const_iterator ColIterator;
377
378
protected:
379
  // RowTable : RowID |-> RowVector
380
  typedef std::vector< RowVectorT > RowTable;
381
  RowTable d_rows;
382
383
  // ColumnTable : ArithVar |-> ColumnVector
384
  typedef std::vector< ColumnVectorT > ColumnTable;
385
  ColumnTable d_columns;
386
387
  /* The merge buffer is used to store a row in order to optimize row addition. */
388
  typedef std::pair<EntryID, bool> PosUsedPair;
389
  typedef DenseMap< PosUsedPair > RowToPosUsedPairMap;
390
  RowToPosUsedPairMap d_mergeBuffer;
391
392
  /* The row that is in the merge buffer. */
393
  RowIndex d_rowInMergeBuffer;
394
395
  uint32_t d_entriesInUse;
396
  MatrixEntryVector<T> d_entries;
397
398
  std::vector<RowIndex> d_pool;
399
400
  T d_zero;
401
402
public:
403
  /**
404
   * Constructs an empty Matrix.
405
   */
406
  Matrix()
407
  : d_rows(),
408
    d_columns(),
409
    d_mergeBuffer(),
410
    d_rowInMergeBuffer(ROW_INDEX_SENTINEL),
411
    d_entriesInUse(0),
412
    d_entries(),
413
    d_zero(0)
414
  {}
415
416
18918
  Matrix(const T& zero)
417
  : d_rows(),
418
    d_columns(),
419
    d_mergeBuffer(),
420
    d_rowInMergeBuffer(ROW_INDEX_SENTINEL),
421
    d_entriesInUse(0),
422
    d_entries(),
423
18918
    d_zero(zero)
424
18918
  {}
425
426
  Matrix(const Matrix& m)
427
  : d_rows(),
428
    d_columns(),
429
    d_mergeBuffer(m.d_mergeBuffer),
430
    d_rowInMergeBuffer(m.d_rowInMergeBuffer),
431
    d_entriesInUse(m.d_entriesInUse),
432
    d_entries(m.d_entries),
433
    d_zero(m.d_zero)
434
  {
435
    d_columns.clear();
436
    for(typename ColumnTable::const_iterator c=m.d_columns.begin(), cend = m.d_columns.end(); c!=cend; ++c){
437
      const ColumnVectorT& col = *c;
438
      d_columns.push_back(ColumnVectorT(col.getHead(),col.getSize(),&d_entries));
439
    }
440
    d_rows.clear();
441
    for(typename RowTable::const_iterator r=m.d_rows.begin(), rend = m.d_rows.end(); r!=rend; ++r){
442
      const RowVectorT& row = *r;
443
      d_rows.push_back(RowVectorT(row.getHead(),row.getSize(),&d_entries));
444
    }
445
  }
446
447
  Matrix& operator=(const Matrix& m){
448
    d_mergeBuffer = (m.d_mergeBuffer);
449
    d_rowInMergeBuffer = (m.d_rowInMergeBuffer);
450
    d_entriesInUse = (m.d_entriesInUse);
451
    d_entries = (m.d_entries);
452
    d_zero = (m.d_zero);
453
    d_columns.clear();
454
    for(typename ColumnTable::const_iterator c=m.d_columns.begin(), cend = m.d_columns.end(); c!=cend; ++c){
455
      const ColumnVector<T>& col = *c;
456
      d_columns.push_back(ColumnVector<T>(col.getHead(), col.getSize(), &d_entries));
457
    }
458
    d_rows.clear();
459
    for(typename RowTable::const_iterator r=m.d_rows.begin(), rend = m.d_rows.end(); r!=rend; ++r){
460
      const RowVector<T>& row = *r;
461
      d_rows.push_back(RowVector<T>(row.getHead(), row.getSize(), &d_entries));
462
    }
463
    return *this;
464
  }
465
466
protected:
467
468
24955497
  void addEntry(RowIndex row, ArithVar col, const T& coeff){
469
24955497
    Debug("tableau") << "addEntry(" << row << "," << col <<"," << coeff << ")" << std::endl;
470
471
24955497
    Assert(coeff != 0);
472
24955497
    Assert(row < d_rows.size());
473
24955497
    Assert(col < d_columns.size());
474
475
24955497
    EntryID newId = d_entries.newEntry();
476
24955497
    Entry& newEntry = d_entries.get(newId);
477
24955497
    newEntry = Entry(row, col, coeff);
478
479
24955497
    Assert(newEntry.getCoefficient() != 0);
480
481
24955497
    ++d_entriesInUse;
482
483
24955497
    d_rows[row].insert(newId);
484
24955497
    d_columns[col].insert(newId);
485
24955497
  }
486
487
24377063
  void removeEntry(EntryID id){
488
24377063
    Assert(d_entriesInUse > 0);
489
24377063
    --d_entriesInUse;
490
491
24377063
    Entry& entry = d_entries.get(id);
492
493
24377063
    RowIndex ridx = entry.getRowIndex();
494
24377063
    ArithVar col = entry.getColVar();
495
496
24377063
    Assert(d_rows[ridx].getSize() > 0);
497
24377063
    Assert(d_columns[col].getSize() > 0);
498
499
24377063
    d_rows[ridx].remove(id);
500
24377063
    d_columns[col].remove(id);
501
502
24377063
    entry.markBlank();
503
504
24377063
    d_entries.freeEntry(id);
505
24377063
  }
506
507
 private:
508
84690
  RowIndex requestRowIndex(){
509
84690
    if(d_pool.empty()){
510
84690
      RowIndex ridx = d_rows.size();
511
84690
      d_rows.push_back(RowVectorT(&d_entries));
512
84690
      return ridx;
513
    }else{
514
      RowIndex rid = d_pool.back();
515
      d_pool.pop_back();
516
      return rid;
517
    }
518
  }
519
520
  void releaseRowIndex(RowIndex rid){
521
    d_pool.push_back(rid);
522
  }
523
524
public:
525
526
  size_t getNumRows() const {
527
    return d_rows.size();
528
  }
529
530
279806
  size_t getNumColumns() const {
531
279806
    return d_columns.size();
532
  }
533
534
147913
  void increaseSize(){
535
147913
    d_columns.push_back(ColumnVector<T>(&d_entries));
536
147913
  }
537
538
  void increaseSizeTo(size_t s){
539
    while(getNumColumns() < s){
540
      increaseSize();
541
    }
542
  }
543
544
36328603
  const RowVector<T>& getRow(RowIndex r) const {
545
36328603
    Assert(r < d_rows.size());
546
36328603
    return d_rows[r];
547
  }
548
549
8571888
  const ColumnVector<T>& getColumn(ArithVar v) const {
550
8571888
    Assert(v < d_columns.size());
551
8571888
    return d_columns[v];
552
  }
553
554
8903104
  uint32_t getRowLength(RowIndex r) const{
555
8903104
    return getRow(r).getSize();
556
  }
557
558
2847126
  uint32_t getColLength(ArithVar x) const{
559
2847126
    return getColumn(x).getSize();
560
  }
561
562
  /**
563
   * Adds a row to the matrix.
564
   * The new row is equivalent to:
565
   *   \f$\sum_i\f$ coeffs[i] * variables[i]
566
   */
567
84690
  RowIndex addRow(const std::vector<T>& coeffs,
568
                  const std::vector<ArithVar>& variables){
569
570
84690
    RowIndex ridx = requestRowIndex();
571
572
    //RowIndex ridx = d_rows.size();
573
    //d_rows.push_back(RowVectorT(&d_entries));
574
575
84690
    typename std::vector<T>::const_iterator coeffIter = coeffs.begin();
576
84690
    std::vector<ArithVar>::const_iterator varsIter = variables.begin();
577
84690
    std::vector<ArithVar>::const_iterator varsEnd = variables.end();
578
579
474922
    for(; varsIter != varsEnd; ++coeffIter, ++varsIter){
580
195116
      const T& coeff = *coeffIter;
581
195116
      ArithVar var_i = *varsIter;
582
195116
      Assert(var_i < getNumColumns());
583
195116
      addEntry(ridx, var_i, coeff);
584
    }
585
586
84690
    return ridx;
587
  }
588
589
590
238002
  void loadRowIntoBuffer(RowIndex rid){
591
238002
    Assert(d_mergeBuffer.empty());
592
238002
    Assert(d_rowInMergeBuffer == ROW_INDEX_SENTINEL);
593
594
238002
    RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
595
10461622
    for(; i != i_end; ++i){
596
5111810
      EntryID id = i.getID();
597
5111810
      const MatrixEntry<T>& entry = *i;
598
5111810
      ArithVar colVar = entry.getColVar();
599
10223620
      d_mergeBuffer.set(colVar, std::make_pair(id, false));
600
    }
601
602
238002
    d_rowInMergeBuffer = rid;
603
238002
  }
604
605
238002
  void clearBuffer() {
606
238002
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
607
608
238002
    d_rowInMergeBuffer = ROW_INDEX_SENTINEL;
609
238002
    d_mergeBuffer.purge();
610
238002
  }
611
612
  /* to *= mult */
613
  void multiplyRowByConstant(RowIndex to, const T& mult){
614
    RowIterator i = getRow(to).begin();
615
    RowIterator i_end = getRow(to).end();
616
    for( ; i != i_end; ++i){
617
      EntryID id = i.getID();
618
      Entry& entry = d_entries.get(id);
619
      T& coeff = entry.getCoefficient();
620
      coeff *= mult;
621
    }
622
  }
623
624
  /**  to += mult * from.
625
   * Use the more efficient rowPlusBufferTimesConstant() for
626
   * repeated use.
627
   */
628
  void rowPlusRowTimesConstant(RowIndex to, RowIndex from, const T& mult){
629
    Assert(to != from);
630
    loadRowIntoBuffer(from);
631
    rowPlusBufferTimesConstant(to, mult);
632
    clearBuffer();
633
  }
634
635
  /**  to += mult * buffer.
636
   * Invalidates coefficients on the row.
637
   * (mult should never be a direct copy of a coefficient!)
638
   */
639
  void rowPlusBufferTimesConstant(RowIndex to, const T& mult){
640
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
641
    Assert(to != ROW_INDEX_SENTINEL);
642
643
    Debug("tableau") << "rowPlusRowTimesConstant("
644
                     << to << "," << mult << "," << d_rowInMergeBuffer << ")"
645
                     << std::endl;
646
647
    Assert(debugNoZeroCoefficients(to));
648
    Assert(debugNoZeroCoefficients(d_rowInMergeBuffer));
649
650
    Assert(mult != 0);
651
652
    RowIterator i = getRow(to).begin();
653
    RowIterator i_end = getRow(to).end();
654
    while(i != i_end){
655
      EntryID id = i.getID();
656
      Entry& entry = d_entries.get(id);
657
      ArithVar colVar = entry.getColVar();
658
659
      ++i;
660
661
      if(d_mergeBuffer.isKey(colVar)){
662
        EntryID bufferEntry = d_mergeBuffer[colVar].first;
663
        Assert(!d_mergeBuffer[colVar].second);
664
        d_mergeBuffer.get(colVar).second = true;
665
666
        const Entry& other = d_entries.get(bufferEntry);
667
        T& coeff = entry.getCoefficient();
668
        coeff += mult * other.getCoefficient();
669
670
        if(coeff.sgn() == 0){
671
          removeEntry(id);
672
        }
673
      }
674
    }
675
676
    i = getRow(d_rowInMergeBuffer).begin();
677
    i_end = getRow(d_rowInMergeBuffer).end();
678
679
    for(; i != i_end; ++i){
680
      const Entry& entry = *i;
681
      ArithVar colVar = entry.getColVar();
682
683
      if(d_mergeBuffer[colVar].second){
684
        d_mergeBuffer.get(colVar).second = false;
685
      }else{
686
        Assert(!(d_mergeBuffer[colVar]).second);
687
        T newCoeff =  mult * entry.getCoefficient();
688
        addEntry(to, colVar, newCoeff);
689
      }
690
    }
691
692
    Assert(mergeBufferIsClear());
693
694
    if(Debug.isOn("matrix")) { printMatrix(); }
695
  }
696
697
  /**  to += mult * buffer. */
698
3561345
  void rowPlusBufferTimesConstant(RowIndex to, const T& mult, CoefficientChangeCallback& cb){
699
3561345
    Assert(d_rowInMergeBuffer != ROW_INDEX_SENTINEL);
700
3561345
    Assert(to != ROW_INDEX_SENTINEL);
701
702
7122690
    Debug("tableau") << "rowPlusRowTimesConstant("
703
3561345
                     << to << "," << mult << "," << d_rowInMergeBuffer << ")"
704
                     << std::endl;
705
706
3561345
    Assert(debugNoZeroCoefficients(to));
707
3561345
    Assert(debugNoZeroCoefficients(d_rowInMergeBuffer));
708
709
3561345
    Assert(mult != 0);
710
711
3561345
    RowIterator i = getRow(to).begin();
712
3561345
    RowIterator i_end = getRow(to).end();
713
132723523
    while(i != i_end){
714
64581089
      EntryID id = i.getID();
715
64581089
      Entry& entry = d_entries.get(id);
716
64581089
      ArithVar colVar = entry.getColVar();
717
718
64581089
      ++i;
719
720
64581089
      if(d_mergeBuffer.isKey(colVar)){
721
35575094
        EntryID bufferEntry = d_mergeBuffer[colVar].first;
722
35575094
        Assert(!d_mergeBuffer[colVar].second);
723
35575094
        d_mergeBuffer.get(colVar).second = true;
724
725
35575094
        const Entry& other = d_entries.get(bufferEntry);
726
35575094
        T& coeff = entry.getCoefficient();
727
35575094
        int coeffOldSgn = coeff.sgn();
728
35575094
        coeff += mult * other.getCoefficient();
729
35575094
        int coeffNewSgn = coeff.sgn();
730
731
35575094
        if(coeffOldSgn != coeffNewSgn){
732
28246971
          cb.update(to, colVar, coeffOldSgn,  coeffNewSgn);
733
734
28246971
          if(coeffNewSgn == 0){
735
24377063
            removeEntry(id);
736
          }
737
        }
738
      }
739
    }
740
741
3561345
    i = getRow(d_rowInMergeBuffer).begin();
742
3561345
    i_end = getRow(d_rowInMergeBuffer).end();
743
744
124062915
    for(; i != i_end; ++i){
745
60250785
      const Entry& entry = *i;
746
60250785
      ArithVar colVar = entry.getColVar();
747
748
60250785
      if(d_mergeBuffer[colVar].second){
749
35575094
        d_mergeBuffer.get(colVar).second = false;
750
      }else{
751
24675691
        Assert(!(d_mergeBuffer[colVar]).second);
752
49351382
        T newCoeff =  mult * entry.getCoefficient();
753
24675691
        addEntry(to, colVar, newCoeff);
754
755
24675691
        cb.update(to, colVar, 0,  newCoeff.sgn());
756
      }
757
    }
758
759
3561345
    Assert(mergeBufferIsClear());
760
761
3561345
    if(Debug.isOn("matrix")) { printMatrix(); }
762
3561345
  }
763
764
3561345
  bool mergeBufferIsClear() const{
765
3561345
    RowToPosUsedPairMap::const_iterator i = d_mergeBuffer.begin();
766
3561345
    RowToPosUsedPairMap::const_iterator i_end = d_mergeBuffer.end();
767
124062915
    for(; i != i_end; ++i){
768
60250785
      RowIndex rid = *i;
769
60250785
      if(d_mergeBuffer[rid].second){
770
        return false;
771
      }
772
    }
773
3561345
    return true;
774
  }
775
776
protected:
777
778
292595
  EntryID findOnRow(RowIndex rid, ArithVar column) const {
779
292595
    RowIterator i = d_rows[rid].begin(), i_end = d_rows[rid].end();
780
6527569
    for(; i != i_end; ++i){
781
3410082
      EntryID id = i.getID();
782
3410082
      const MatrixEntry<T>& entry = *i;
783
3410082
      ArithVar colVar = entry.getColVar();
784
785
3410082
      if(colVar == column){
786
292595
        return id;
787
      }
788
    }
789
    return ENTRYID_SENTINEL;
790
  }
791
792
94485
  EntryID findOnCol(RowIndex rid, ArithVar column) const{
793
94485
    ColIterator i = d_columns[column].begin(), i_end = d_columns[column].end();
794
486949
    for(; i != i_end; ++i){
795
290717
      EntryID id = i.getID();
796
290717
      const MatrixEntry<T>& entry = *i;
797
290717
      RowIndex currRow = entry.getRowIndex();
798
799
290717
      if(currRow == rid){
800
94485
        return id;
801
      }
802
    }
803
    return ENTRYID_SENTINEL;
804
  }
805
806
193540
  EntryID findEntryID(RowIndex rid, ArithVar col) const{
807
193540
    bool colIsShorter = getColLength(col) < getRowLength(rid);
808
193540
    EntryID id = colIsShorter ? findOnCol(rid, col) : findOnRow(rid,col);
809
193540
    return id;
810
  }
811
  MatrixEntry<T> d_failedFind;
812
public:
813
814
  /** If the find fails, isUnused is true on the entry. */
815
193540
  const MatrixEntry<T>& findEntry(RowIndex rid, ArithVar col) const{
816
193540
    EntryID id = findEntryID(rid, col);
817
193540
    if(id == ENTRYID_SENTINEL){
818
      return d_failedFind;
819
    }else{
820
193540
      return d_entries[id];
821
    }
822
  }
823
824
  /**
825
   * Prints the contents of the Matrix to Debug("matrix")
826
   */
827
  void printMatrix(std::ostream& out) const {
828
    out << "Matrix::printMatrix"  << std::endl;
829
830
    for(RowIndex i = 0, N = d_rows.size(); i < N; ++i){
831
      printRow(i, out);
832
    }
833
  }
834
  void printMatrix() const {
835
    printMatrix(Debug("matrix"));
836
  }
837
838
  void printRow(RowIndex rid, std::ostream& out) const {
839
    out << "{" << rid << ":";
840
    const RowVector<T>& row = getRow(rid);
841
    RowIterator i = row.begin();
842
    RowIterator i_end = row.end();
843
    for(; i != i_end; ++i){
844
      printEntry(*i, out);
845
      out << ",";
846
    }
847
    out << "}" << std::endl;
848
  }
849
  void printRow(RowIndex rid) const {
850
    printRow(rid, Debug("matrix"));
851
  }
852
853
  void printEntry(const MatrixEntry<T>& entry, std::ostream& out) const {
854
    out << entry.getColVar() << "*" << entry.getCoefficient();
855
  }
856
  void printEntry(const MatrixEntry<T>& entry) const {
857
    printEntry(entry, Debug("matrix"));
858
  }
859
public:
860
14306
  uint32_t size() const {
861
14306
    return d_entriesInUse;
862
  }
863
  uint32_t getNumEntriesInTableau() const {
864
    return d_entries.size();
865
  }
866
  uint32_t getEntryCapacity() const {
867
    return d_entries.capacity();
868
  }
869
870
  void manipulateRowEntry(RowIndex row, ArithVar col, const T& c, CoefficientChangeCallback& cb){
871
    int coeffOldSgn;
872
    int coeffNewSgn;
873
874
    EntryID id = findEntryID(row, col);
875
    if(id == ENTRYID_SENTINEL){
876
      coeffOldSgn = 0;
877
      addEntry(row, col, c);
878
      coeffNewSgn = c.sgn();
879
    }else{
880
      Entry& e = d_entries.get(id);
881
      T& t = e.getCoefficient();
882
      coeffOldSgn = t.sgn();
883
      t += c;
884
      coeffNewSgn = t.sgn();
885
    }
886
887
    if(coeffOldSgn != coeffNewSgn){
888
      cb.update(row, col, coeffOldSgn,  coeffNewSgn);
889
    }
890
    if(coeffNewSgn == 0){
891
      removeEntry(id);
892
    }
893
  }
894
895
  void removeRow(RowIndex rid){
896
    RowIterator i = getRow(rid).begin();
897
    RowIterator i_end = getRow(rid).end();
898
    for(; i != i_end; ++i){
899
      EntryID id = i.getID();
900
      removeEntry(id);
901
    }
902
    releaseRowIndex(rid);
903
  }
904
905
  double densityMeasure() const{
906
    Assert(numNonZeroEntriesByRow() == numNonZeroEntries());
907
    Assert(numNonZeroEntriesByCol() == numNonZeroEntries());
908
909
    uint32_t n = getNumRows();
910
    if(n == 0){
911
      return 1.0;
912
    }else {
913
      uint32_t s = numNonZeroEntries();
914
      uint32_t m = d_columns.size();
915
      uint32_t divisor = (n *(m - n + 1));
916
917
      Assert(n >= 1);
918
      Assert(m >= n);
919
      Assert(divisor > 0);
920
      Assert(divisor >= s);
921
922
      return (double(s)) / divisor;
923
    }
924
  }
925
926
  void loadSignQueries(RowIndex rid, DenseMap<int>& target) const{
927
928
    RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
929
    for(; i != i_end; ++i){
930
      const MatrixEntry<T>& entry = *i;
931
      target.set(entry.getColVar(), entry.getCoefficient().sgn());
932
    }
933
  }
934
935
protected:
936
  uint32_t numNonZeroEntries() const { return size(); }
937
938
  uint32_t numNonZeroEntriesByRow() const {
939
    uint32_t rowSum = 0;
940
    for(RowIndex rid = 0, N = d_rows.size(); rid < N; ++rid){
941
      rowSum += getRowLength(rid);
942
    }
943
    return rowSum;
944
  }
945
946
  uint32_t numNonZeroEntriesByCol() const {
947
    uint32_t colSum = 0;
948
    for(ArithVar v = 0, N = d_columns.size(); v < N; ++v){
949
      colSum += getColLength(v);
950
    }
951
    return colSum;
952
  }
953
954
955
7207380
  bool debugNoZeroCoefficients(RowIndex ridx){
956
132419410
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
957
125212030
      const Entry& entry = *i;
958
125212030
      if(entry.getCoefficient() == 0){
959
        return false;
960
      }
961
    }
962
7207380
    return true;
963
  }
964
84690
  bool debugMatchingCountsForRow(RowIndex ridx){
965
464846
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
966
380156
      const Entry& entry = *i;
967
380156
      ArithVar colVar = entry.getColVar();
968
380156
      uint32_t count = debugCountColLength(colVar);
969
1140468
      Debug("tableau") << "debugMatchingCountsForRow "
970
380156
                       << ridx << ":" << colVar << " " << count
971
760312
                       <<" "<< getColLength(colVar) << std::endl;
972
380156
      if( count != getColLength(colVar) ){
973
        return false;
974
      }
975
    }
976
84690
    return true;
977
  }
978
979
380156
  uint32_t debugCountColLength(ArithVar var){
980
380156
    Debug("tableau") << var << " ";
981
380156
    uint32_t count = 0;
982
7485768
    for(ColIterator i=getColumn(var).begin(); !i.atEnd(); ++i){
983
7105612
      const Entry& entry = *i;
984
7105612
      Debug("tableau") << "(" << entry.getRowIndex() << ", " << i.getID() << ") ";
985
7105612
      ++count;
986
    }
987
380156
    Debug("tableau") << std::endl;
988
380156
    return count;
989
  }
990
  uint32_t debugCountRowLength(RowIndex ridx){
991
    uint32_t count = 0;
992
    for(RowIterator i=getRow(ridx).begin(); !i.atEnd(); ++i){
993
      ++count;
994
    }
995
    return count;
996
  }
997
998
};/* class Matrix<T> */
999
1000
}  // namespace arith
1001
}  // namespace theory
1002
}  // namespace cvc5