Module: Quicopt::Conditions Private

Defined in:
lib/quicopt/indicators.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

The mapping from a comparison to its 0/1 form, and the model a term belongs to.

Class Method Summary collapse

Class Method Details

.argument_key(expr) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

An expression as an interning key: its constant and its terms in model order. Factors are interned, so they key by identity.



140
141
142
# File 'lib/quicopt/indicators.rb', line 140

def argument_key(expr)
  [expr.constant, expr.linear.sort_by { |f, _| f.order }, expr.quadratic.sort_by { |(a, b), _| [a.order, b.order] }]
end

.holds(residual, sense, tol) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

residual is lhs − rhs; the result follows the table in this file's header.



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/quicopt/indicators.rb', line 90

def holds(residual, sense, tol)
  return Expression.new(constant: truth(residual.constant, sense, tol) ? 1.0 : 0.0) if residual.constant?

  negated = residual.scale(-1.0)
  case sense
  when :le then term(:step, negated.plus(Expression.new(constant: tol)))
  when :ge then term(:step, residual.plus(Expression.new(constant: tol)))
  when :lt then one_minus(term(:step, residual.plus(Expression.new(constant: -tol))))
  when :gt then one_minus(term(:step, negated.plus(Expression.new(constant: -tol))))
  when :eq then tol.positive? ? term(:near, residual, tol) : one_minus(term(:indicator, residual))
  when :ne then tol.positive? ? one_minus(term(:near, residual, tol)) : term(:indicator, residual)
  end
end

.one_minus(expr) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

1 − e.



124
125
126
# File 'lib/quicopt/indicators.rb', line 124

def one_minus(expr)
  Expression.new(constant: 1.0).plus(expr.scale(-1.0))
end

.owner(factors) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The one model every factor in factors belongs to.

Raises:

  • (ArgumentError) —

    if they belong to more than one



131
132
133
134
135
136
# File 'lib/quicopt/indicators.rb', line 131

def owner(factors)
  models = factors.map(&:model).uniq(&:object_id)
  raise ArgumentError, "the terms of one expression belong to different Quicopt::Models" if models.size > 1

  models.first
end

.term(op, argument, tol = 0.0) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The interned Condition op over argument, as an expression.



117
118
119
120
121
# File 'lib/quicopt/indicators.rb', line 117

def term(op, argument, tol = 0.0)
  model = owner(argument.factors)
  key = [:condition, op, argument_key(argument), tol]
  Expression.new(linear: { model.intern(key) { Condition.new(model, op, argument, tol, model.next_order) } => 1.0 })
end

.truth(value, sense, tol) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Whether a comparison between two numbers (value = lhs − rhs) holds.



105
106
107
108
109
110
111
112
113
114
# File 'lib/quicopt/indicators.rb', line 105

def truth(value, sense, tol)
  case sense
  when :le then -value + tol >= 0
  when :ge then value + tol >= 0
  when :lt then (value - tol).negative?
  when :gt then (-value - tol).negative?
  when :eq then tol.positive? ? value.abs <= tol : value.zero?
  when :ne then tol.positive? ? value.abs > tol : !value.zero?
  end
end