Class: Cassowary::LinearExpression

Inherits:
Object
  • Object
show all
Includes:
Equalities
Defined in:
lib/linear_expression.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Equalities

#cn_equal, #cn_geq, #cn_leq

Constructor Details

#initializeLinearExpression

Returns a new instance of LinearExpression.



15
16
17
18
# File 'lib/linear_expression.rb', line 15

def initialize
  self.constant = 0.0
  self.terms = {}
end

Instance Attribute Details

#constantObject

Returns the value of attribute constant.



7
8
9
# File 'lib/linear_expression.rb', line 7

def constant
  @constant
end

#termsObject

Returns the value of attribute terms.



7
8
9
# File 'lib/linear_expression.rb', line 7

def terms
  @terms
end

Class Method Details

.new_with_symbolic_weightObject



9
10
11
12
13
# File 'lib/linear_expression.rb', line 9

def self.new_with_symbolic_weight
  result = self.new
  result.constant = SymbolicWeight::Zero
  result
end

Instance Method Details

#*(x) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/linear_expression.rb', line 113

def *(x)
  return x * constant if constant?

  n = if x.is_a? Numeric
        x.to_f
      else
        expr = x.as_linear_expression
        raise NonLinearResult unless expr.constant?
        expr.constant
      end
  result = LinearExpression.new
  result.constant = n * constant
  terms.each_pair do |v, c|
    result.terms[v] = n * c
  end
  result
end

#+(x) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/linear_expression.rb', line 137

def +(x)
  expr = x.as_linear_expression
  result = LinearExpression.new
  result.constant = constant + expr.constant
  terms.each_pair do |v, c|
    result.terms[v] = c
  end
  expr.each_variable_and_coefficient do |v, c|
    result.add_variable(v, c)
  end
  result
end

#-(x) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/linear_expression.rb', line 150

def -(x)
  expr = x.as_linear_expression
  result = LinearExpression.new
  result.constant = constant - expr.constant
  terms.each_pair do |v, c|
    result.terms[v] = c
  end
  expr.each_variable_and_coefficient do |v, c|
    result.add_variable(v, -c)
  end
  result
end

#/(x) ⇒ Object

Raises:



131
132
133
134
135
# File 'lib/linear_expression.rb', line 131

def /(x)
  expr = x.as_linear_expression
  raise NonLinearResult unless expr.constant?
  self * (1.0 / expr.constant)
end

#add_expression(expr, times, subject = nil, solver = nil) ⇒ Object



65
66
67
68
69
70
# File 'lib/linear_expression.rb', line 65

def add_expression(expr, times, subject = nil, solver = nil)
  increment_constant(times * expr.constant)
  expr.each_variable_and_coefficient do |v, c|
    add_variable(v, times * c, subject, solver)
  end
end

#add_variable(variable, coefficient, subject = nil, solver = nil) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/linear_expression.rb', line 50

def add_variable(variable, coefficient, subject = nil, solver = nil)
  if terms.has_key? variable
    new_coeff = coefficient + terms[variable]
    if new_coeff.cl_approx_zero
      terms.delete variable
      solver.note_removed_variable(variable, subject) if solver
    else
      terms[variable] = new_coeff
    end
  else
    terms[variable] = coefficient
    solver.note_added_variable(variable, subject) if solver
  end
end

#any_variableObject



20
21
22
23
24
25
26
# File 'lib/linear_expression.rb', line 20

def any_variable
  if terms.any?
    terms.keys.first
  else
    raise InternalError, "expression is constant"
  end
end

#as_linear_expressionObject



28
29
30
# File 'lib/linear_expression.rb', line 28

def as_linear_expression
  self
end

#change_subject(old, new) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/linear_expression.rb', line 80

def change_subject(old, new)
  reciprocal = 1.0 / terms.delete(new)
  nreciprocal = -reciprocal
  self.constant *= nreciprocal
  terms.each_pair do |v, c|
    terms[v] = c * nreciprocal
  end
  terms[old] = reciprocal
end

#coefficient_for(variable) ⇒ Object



32
33
34
# File 'lib/linear_expression.rb', line 32

def coefficient_for(variable)
  terms[variable] || 0.0
end

#constant?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/linear_expression.rb', line 36

def constant?
  terms.empty?
end

#each_variable_and_coefficient(&block) ⇒ Object



46
47
48
# File 'lib/linear_expression.rb', line 46

def each_variable_and_coefficient(&block)
  terms.each_pair(&block)
end

#increment_constant(num) ⇒ Object



90
91
92
# File 'lib/linear_expression.rb', line 90

def increment_constant(num)
  self.constant += num
end

#inspectObject



163
164
165
166
167
# File 'lib/linear_expression.rb', line 163

def inspect
  terms.keys.inject(constant.inspect) do |str, v|
    "#{str}+#{terms[v].inspect}*#{v.inspect}"
  end
end

#new_subject(subject) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/linear_expression.rb', line 72

def new_subject(subject)
  nreciprocal = -(1.0 / terms.delete(subject))
  self.constant *= nreciprocal
  terms.each_pair do |v, c|
    terms[v] = c * nreciprocal
  end
end

#substitute_variable(var, expr, subject, solver) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/linear_expression.rb', line 94

def substitute_variable(var, expr, subject, solver)
  multiplier = terms.delete(var)
  increment_constant(multiplier * expr.constant)
  expr.each_variable_and_coefficient do |v, c|
    if old_coeff = terms[v]
      new_coeff = old_coeff + (multiplier * c)
      if new_coeff.cl_approx_zero
        terms.delete v
        solver.note_removed_variable v, subject
      else
        terms[v] = new_coeff
      end
    else
      terms[v] = multiplier * c
      solver.note_added_variable v, subject
    end
  end
end

#valueObject



40
41
42
43
44
# File 'lib/linear_expression.rb', line 40

def value
  terms.keys.inject(constant) do |memo, v|
    memo + coefficient_for(v) * v.value
  end
end