Feature #4219
closedСхлопывание константных выражений
100%
Description
Можно ли вычислять константные выражения при запуске солвера. Дело в том, что у меня используются свои (неполноценные) классы для Value и Variable. Из-за чего происходит NullPointerException.
см. #4127.
Updated by Sergey Smolov over 11 years ago
- Status changed from New to Feedback
- Assignee changed from Sergey Smolov to Alexander Kamkin
Саша, схлопывание константных выражений осуществляется на этапе конструирования объектов-операций (Operation), входящих в состав ограничения (Constraint), т.е. ещё до запуска собственно солвера. Сделано это потому, что все ключевые объекты, составляющие внутреннее представление ограничений в библиотеке (классы Constraint, Syntax, Function, Operation, etc.) фактически, неизменяемы (большинство полей имеет атрибут final), и модифицировать их "потом" нельзя.
Таким образом, схлопывание константных выражений превращается в сугубо внутреннюю оптимизацию библиотеки. По моему мнению, пользователи вообще не должны об этом знать, посему метод performConstant, выполняющий схлопывание, задумывался приватным. То, что сейчас он публичный - мой косяк.
Updated by Alexander Kamkin over 11 years ago
- Assignee changed from Alexander Kamkin to Sergey Smolov
Мысль понял. Попробую что-нибудь придумать.
P.S. Вычисление константных выражений компиляторщики называют "Constant folding". Предлагаю переименовать метод performConstant
в foldConstants
.
Updated by Alexander Kamkin over 11 years ago
@Override
public int calculate()
{
switch(this.getData().getType().getType())
{
case LOGIC_INTEGER:
return (Integer) this.getData().getValue();
case BIT_VECTOR:
return ((BigInteger)this.getData().getValue()).intValue();
case LOGIC_BOOLEAN:
if ((Boolean) this.getData().getValue())
return 1;
else
return 0;
case LOGIC_REAL:
return ((Double)this.getData().getValue()).intValue();
case UNKNOWN:
break;
}
return 0;
}
Думаю, правильнее вместо этого switch
добавить в интерфейс IData
метод intValue
, осуществляющий конвертацию значения в тип int
.
Updated by Alexander Kamkin over 11 years ago
Возможно правильнее использовать не int
, а BigInteger
.
Updated by Alexander Kamkin over 11 years ago
Кстати, схлопывание констант делается только для параметров (для repeat
и подобных конструкций)? Для HDL-кода нужно аккуратно делать вычисление констант, поскольку так в основном битовые вектора, причем с поддержкой неопределенных значений (X
, Z
). Лучше вычисления делать только для параметров.
Updated by Alexander Kamkin over 11 years ago
Я подозреваю (не проверял), что NullPointerException
происходит из-за того, что в моей реализации IVariable
метод getData
возвращает null
(такая задумка - у переменной нет значения). Если в выражении присутствует переменная, схлопывания не должно происходить. Схлопываться должны только выражения, состоящие из значений.
Updated by Alexander Kamkin over 11 years ago
Еще у моих данных getType()
возвращает null
.
switch(this.getData().getType().getType()) {...}
Это я как-нибудь доделаю. Но причина не только в этом.
Updated by Alexander Kamkin over 11 years ago
Даже если избавиться от NPE
возникнет CastException
. Так как мой getValue()
возвратит объект моего класса, а не Integer
и т.п.
Возможное решение у IData
сделать метод, получающий значение нужно типа. Нужно обсудить с Андреем.
Updated by Andrei Tatarnikov over 11 years ago
См. таск #4246
Я написал калькулятор для основных стандартных операций EStandardOperation (MINUS, PLUS, ADD, SUB, MUL, DIV, REM, MOD) и API-классы для создания/расширения калькуляторов (см. класс syntax.Calculator). А у класса Operation появился метод для схлопывания подвыражений:
public ISyntaxElement reduce(ICalculator calculator, int flags)
Его можно использовать следующим образом
syntax.addFormula(
new Formula(
new Operation(
EStandardOperation.EQ,
a,
new Operation(
EStandardOperation.ADD,
new Value(intType.valueOf("2", 10)),
new Value(intType.valueOf("3", 10))).reduce(CalculatorForStandard.getInstance(), 0)
)
)
);
Данный код помогает упростить выражение (+ 2 3) в число 5.
Updated by Andrei Tatarnikov over 11 years ago
Сергей, посмотри старую релизацию (старые методы calculate в операциях и других классов). Возможно, они больше не нужны.
Updated by Andrei Tatarnikov over 11 years ago
- % Done changed from 0 to 100
Реализовано. Старый ненужный код удалён. См. r98.
Updated by Andrei Tatarnikov over 11 years ago
- Status changed from Feedback to Resolved
Updated by Sergey Smolov over 11 years ago
- Status changed from Resolved to Closed
- Published in build set to 0.2.2