Skip to content

Commit 2d788ae

Browse files
gselzerctrueden
authored andcommitted
SimplificationInfoChainGeneration work
1 parent ec49244 commit 2d788ae

10 files changed

Lines changed: 327 additions & 114 deletions

File tree

scijava/scijava-ops-api/src/main/java/org/scijava/ops/api/OpEnvironment.java

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,35 +99,59 @@ <T> T op(final String opName, final Nil<T> specialType,
9999
<T> T op(final String opName, final Nil<T> specialType,
100100
final Nil<?>[] inTypes, final Nil<?> outType, Hints hints);
101101

102+
/**
103+
* Returns an {@link InfoChain} fitting the provided arguments. NB
104+
* implementations of this method likely depend on the {@link Hints} set by
105+
* {@link OpEnvironment#setDefaultHints(Hints)}, which provides no guarantee
106+
* of thread-safety. Users interested in parallel Op matching should consider
107+
* using {@link OpEnvironment#op(String, Nil, Nil[], Nil, Hints)} instead.
108+
*
109+
* @param opName the name of the Op
110+
* @param specialType the generic {@link Type} of the Op
111+
* @param inTypes the arguments (inputs) to the Op
112+
* @param outType the return of the Op (note that it may also be an argument)
113+
* @return an instance of an Op aligning with the search parameters
114+
*/
115+
InfoChain infoChain(final String opName, final Nil<?> specialType,
116+
final Nil<?>[] inTypes, final Nil<?> outType);
117+
118+
/**
119+
* Returns an {@link InfoChain} fitting the provided arguments.
120+
*
121+
* @param opName the name of the Op
122+
* @param specialType the generic {@link Type} of the Op
123+
* @param inTypes the arguments (inputs) to the Op
124+
* @param outType the return of the Op (note that it may also be an argument)
125+
* @param hints the {@link Hints} that should guide this matching call
126+
* @return an instance of an Op aligning with the search parameters
127+
*/
128+
InfoChain infoChain(final String opName, final Nil<?> specialType,
129+
final Nil<?>[] inTypes, final Nil<?> outType, Hints hints);
130+
102131
/**
103132
* Returns an Op fitting the provided arguments. NB implementations of this
104133
* method likely depend on the {@link Hints} set by
105134
* {@link OpEnvironment#setDefaultHints(Hints)}, which provides no guarantee of
106135
* thread-safety. Users interested in parallel Op matching should consider
107-
* using {@link OpEnvironment#op(String, Nil, Nil[], Nil, Hints)} instead.
136+
* using {@link OpEnvironment#opFromInfo(String, Nil, Hints)} instead.
108137
*
109138
* @param <T> the {@link Type} of the Op
110139
* @param info the {@link OpInfo}
111140
* @param specialType the generic {@link Type} of the Op
112-
* @param inTypes the arguments (inputs) to the Op
113-
* @param outType the return of the Op (note that it may also be an argument)
114141
* @return an instance of an Op aligning with the search parameters
115142
*/
116-
<T> T opFromInfo(OpInfo info, Nil<T> specialType, Nil<?>[] inTypes, Nil<?> outType);
143+
<T> T opFromInfo(OpInfo info, Nil<T> specialType);
117144

118145
/**
119146
* Returns an Op fitting the provided arguments.
120147
*
121148
* @param <T> the {@link Type} of the Op
122149
* @param info the {@link OpInfo}
123150
* @param specialType the generic {@link Type} of the Op
124-
* @param inTypes the arguments (inputs) to the Op
125-
* @param outType the return of the Op (note that it may also be an argument)
126151
* @param hints the {@link Hints} that should guide this matching call
127152
* @return an instance of an Op aligning with the search parameters
128153
*/
129-
<T> T opFromInfo(OpInfo info, Nil<T> specialType, Nil<?>[] inTypes, Nil<?> outType,
130-
Hints hints);
154+
<T> T opFromInfo(OpInfo info, Nil<T> specialType, Hints hints);
131155

132156
<T> T opFromInfoChain(InfoChain chain, Nil<T> specialType);
133157

@@ -164,6 +188,8 @@ <T> T opFromID(final String opID, final Nil<T> specialType,
164188

165189
InfoChain chainFromID(final String signature);
166190

191+
InfoChain chainFromInfo(final OpInfo info, final Nil<?> specialType);
192+
167193
default OpBuilder op(final String opName) {
168194
return new OpBuilder(this, opName);
169195
}

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/impl/DefaultOpEnvironment.java

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.scijava.ops.engine.matcher.OpMatchingException;
7676
import org.scijava.ops.engine.matcher.impl.DefaultOpMatcher;
7777
import org.scijava.ops.engine.matcher.impl.DefaultOpRef;
78+
import org.scijava.ops.engine.matcher.impl.InfoMatchingOpRef;
7879
import org.scijava.ops.engine.matcher.impl.OpAdaptationInfo;
7980
import org.scijava.ops.engine.matcher.impl.OpClassInfo;
8081
import org.scijava.ops.engine.simplify.SimplifiedOpInfo;
@@ -215,28 +216,56 @@ public <T> T op(final String opName, final Nil<T> specialType,
215216
@Override
216217
public <T> T op(final String opName, final Nil<T> specialType, final Nil<?>[] inTypes, final Nil<?> outType, Hints hints) {
217218
try {
218-
return findOp(opName, specialType, inTypes, outType, hints);
219+
return findOp(opName, specialType, inTypes, outType, hints).asOpType();
220+
} catch (OpMatchingException e) {
221+
throw new IllegalArgumentException(e);
222+
}
223+
}
224+
225+
@Override
226+
public InfoChain infoChain(String opName, Nil<?> specialType,
227+
Nil<?>[] inTypes, Nil<?> outType)
228+
{
229+
return infoChain(opName, specialType, inTypes, outType, getDefaultHints());
230+
}
231+
232+
@Override
233+
public InfoChain infoChain(String opName, Nil<?> specialType,
234+
Nil<?>[] inTypes, Nil<?> outType, Hints hints)
235+
{
236+
try {
237+
return findOp(opName, specialType, inTypes, outType, hints).infoChain();
219238
} catch (OpMatchingException e) {
220239
throw new IllegalArgumentException(e);
221240
}
222241
}
223242

224243
@Override
225-
public <T> T opFromInfo(final OpInfo info, final Nil<T> specialType, final Nil<?>[] inTypes, final Nil<?> outType, Hints hints) {
244+
public <T> T opFromInfo(final OpInfo info, final Nil<T> specialType, Hints hints) {
245+
try {
246+
return findOp(info, specialType, hints).asOpType();
247+
} catch (OpMatchingException e) {
248+
throw new IllegalArgumentException(e);
249+
}
250+
}
251+
252+
@Override
253+
public <T> T opFromInfo(final OpInfo info, final Nil<T> specialType) {
226254
try {
227-
return findOp(info, specialType, inTypes, outType, hints);
255+
return findOp(info, specialType, getDefaultHints()).asOpType();
228256
} catch (OpMatchingException e) {
229257
throw new IllegalArgumentException(e);
230258
}
231259
}
232260

233261
@Override
234-
public <T> T opFromInfo(final OpInfo info, final Nil<T> specialType, final Nil<?>[] inTypes, final Nil<?> outType) {
262+
public InfoChain chainFromInfo(OpInfo info, Nil<?> specialType) {
235263
try {
236-
return findOp(info, specialType, inTypes, outType, getDefaultHints());
264+
return findOp(info, specialType, getDefaultHints()).infoChain();
237265
} catch (OpMatchingException e) {
238266
throw new IllegalArgumentException(e);
239267
}
268+
240269
}
241270

242271
@Override
@@ -304,22 +333,20 @@ public void register(final OpInfo info) {
304333
}
305334

306335
@SuppressWarnings("unchecked")
307-
private <T> T findOp(final String opName, final Nil<T> specialType, final Nil<?>[] inTypes,
336+
private <T> RichOp<T> findOp(final String opName, final Nil<T> specialType, final Nil<?>[] inTypes,
308337
final Nil<?> outType, Hints hints) {
309338
final OpRef ref = DefaultOpRef.fromTypes(opName, specialType.getType(), outType != null ? outType.getType() : null,
310339
toTypes(inTypes));
311340
MatchingConditions conditions = generateCacheHit(ref, hints);
312-
return (T) wrapViaCache(conditions);
341+
return (RichOp<T>) wrapViaCache(conditions);
313342
}
314343

315344
@SuppressWarnings("unchecked")
316-
private <T> T findOp(final OpInfo info, final Nil<T> specialType, final Nil<?>[] inTypes,
317-
final Nil<?> outType, Hints hints) throws OpMatchingException
345+
private <T> RichOp<T> findOp(final OpInfo info, final Nil<T> specialType, Hints hints) throws OpMatchingException
318346
{
319-
OpRef ref = DefaultOpRef.fromTypes(null, specialType.getType(), outType.getType(),
320-
toTypes(inTypes));
347+
OpRef ref = new InfoMatchingOpRef(info, specialType);
321348
MatchingConditions conditions = insertCacheHit(ref, hints, info);
322-
return (T) wrapViaCache(conditions);
349+
return (RichOp<T>) wrapViaCache(conditions);
323350
}
324351

325352
private Type[] toTypes(Nil<?>... nils) {
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package org.scijava.ops.engine.matcher.impl;
2+
3+
import java.lang.reflect.ParameterizedType;
4+
import java.lang.reflect.Type;
5+
import java.lang.reflect.TypeVariable;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
9+
import org.scijava.ops.api.OpInfo;
10+
import org.scijava.ops.api.OpRef;
11+
import org.scijava.types.Nil;
12+
import org.scijava.types.Types;
13+
import org.scijava.types.inference.GenericAssignability;
14+
15+
16+
public class InfoMatchingOpRef implements OpRef {
17+
18+
/** Name of the op, or null for any name. */
19+
private final String name;
20+
21+
/** Type which the op must match. */
22+
private final Type type;
23+
24+
/** The op's output parameter types, or null for no constraints. */
25+
private final Type outType;
26+
27+
/** Arguments to be passed to the op. */
28+
private final Type[] args;
29+
30+
/**
31+
* Mapping of TypeVariables of the {@link OpInfo} to the {@link Type}s of
32+
* {@code specialType}
33+
*/
34+
private final Map<TypeVariable<?>, Type> map = new HashMap<>();
35+
36+
public InfoMatchingOpRef(OpInfo info, Nil<?> specialType) {
37+
this.name = info.names().get(0);
38+
Type from = specialType.getType();
39+
Type to = info.opType();
40+
this.type = Types.getExactSuperType(to, Types.raw(from));
41+
if (this.type instanceof ParameterizedType) {
42+
if (!GenericAssignability.checkGenericAssignability(from,
43+
(ParameterizedType) this.type, this.map, true))
44+
throw new IllegalArgumentException();
45+
}
46+
else {
47+
if (!Types.isAssignable(from, this.type, this.map))
48+
throw new IllegalArgumentException();
49+
}
50+
args = info.inputs().stream().map(m -> Types
51+
.substituteTypeVariables(m.getType(), this.map)).toArray(Type[]::new);
52+
outType = Types.substituteTypeVariables(info.output().getType(),
53+
this.map);
54+
55+
}
56+
57+
@Override
58+
public String getName() {
59+
return this.name;
60+
}
61+
62+
@Override
63+
public Type getType() {
64+
return this.type;
65+
}
66+
67+
@Override
68+
public Type getOutType() {
69+
return this.outType;
70+
}
71+
72+
@Override
73+
public Type[] getArgs() {
74+
return this.args;
75+
}
76+
77+
@Override
78+
public String getLabel() {
79+
final StringBuilder sb = new StringBuilder();
80+
OpRef.append(sb, name);
81+
if (type != null) {
82+
OpRef.append(sb, Types.name(type));
83+
}
84+
return sb.toString();
85+
}
86+
87+
@Override
88+
public boolean typesMatch(Type opType) {
89+
return typesMatch(opType, new HashMap<>());
90+
}
91+
92+
@Override
93+
public boolean typesMatch(Type opType,
94+
Map<TypeVariable<?>, Type> typeVarAssigns)
95+
{
96+
if (type == null) return true;
97+
if (type instanceof ParameterizedType) {
98+
if (!GenericAssignability.checkGenericAssignability(opType,
99+
(ParameterizedType) type, typeVarAssigns, true))
100+
{
101+
return false;
102+
}
103+
}
104+
else {
105+
if (!Types.isAssignable(opType, type)) {
106+
return false;
107+
}
108+
}
109+
return true;
110+
}
111+
112+
// -- Object methods --
113+
114+
@Override
115+
public String toString() {
116+
return refString();
117+
}
118+
119+
@Override
120+
public boolean equals(final Object obj) {
121+
return refEquals(obj);
122+
}
123+
124+
@Override
125+
public int hashCode() {
126+
return refHashCode();
127+
}
128+
129+
}

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/simplify/ChainCluster.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.ArrayList;
77
import java.util.List;
88

9+
import org.scijava.ops.api.OpEnvironment;
910
import org.scijava.ops.api.OpInfo;
1011

1112
public class ChainCluster {
@@ -19,15 +20,15 @@ private ChainCluster(TypePair pairing) {
1920
}
2021

2122
public static ChainCluster generateCluster(TypePair pairing,
22-
List<OpInfo> simplifiers, List<OpInfo> focusers)
23+
List<OpInfo> simplifiers, List<OpInfo> focusers, OpEnvironment env)
2324
{
2425
ChainCluster cluster = new ChainCluster(pairing);
2526
List<List<OpInfo>> chains = Lists.cartesianProduct(simplifiers, focusers);
2627

2728
for (List<OpInfo> chainList : chains) {
2829
OpInfo simplifier = chainList.get(0);
2930
OpInfo focuser = chainList.get(1);
30-
MutatorChain chain = new MutatorChain(simplifier, focuser, pairing);
31+
MutatorChain chain = new MutatorChain(simplifier, focuser, pairing, env);
3132
if (chain.isValid()) cluster.addChain(chain);
3233
}
3334
return cluster;

scijava/scijava-ops-engine/src/main/java/org/scijava/ops/engine/simplify/InfoSimplificationGenerator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Optional;
1111

1212
import org.scijava.ops.api.Hints;
13+
import org.scijava.ops.api.InfoChain;
1314
import org.scijava.ops.api.OpEnvironment;
1415
import org.scijava.ops.api.OpInfo;
1516
import org.scijava.ops.api.OpRef;
@@ -63,7 +64,7 @@ public OpInfo generateSuitableInfo(SimplifiedOpRef ref) {
6364
Map<TypePair, MutatorChain> chains = new HashMap<>();
6465
pathways.forEach((pair, cluster) -> chains.put(pair, resolveCluster(cluster)));
6566

66-
SimplificationMetadata metadata = new SimplificationMetadata(ref, info, argPairings, outPairing, chains, env);
67+
SimplificationMetadata metadata = new SimplificationMetadata(ref, info, argPairings, outPairing, chains);
6768
return new SimplifiedOpInfo(info, env, metadata);
6869
}
6970

@@ -96,14 +97,14 @@ private Map<TypePair, ChainCluster> findPathways(SimplifiedOpRef ref, TypePair[]
9697
if (pathways.keySet().contains(pairing)) continue;
9798
List<OpInfo> simplifiers = ref.simplifierSets().get(i);
9899
List<OpInfo> focusers = infoFocusers.get(i);
99-
ChainCluster cluster = ChainCluster.generateCluster(pairing, simplifiers, focusers);
100+
ChainCluster cluster = ChainCluster.generateCluster(pairing, simplifiers, focusers, env);
100101
pathways.put(pairing, cluster);
101102
}
102103

103104
if(!pathways.keySet().contains(outPairing)) {
104105
List<OpInfo> simplifiers = outputSimplifiers;
105106
List<OpInfo> focusers = ref.outputFocusers();
106-
ChainCluster cluster = ChainCluster.generateCluster(outPairing, simplifiers, focusers);
107+
ChainCluster cluster = ChainCluster.generateCluster(outPairing, simplifiers, focusers, env);
107108
pathways.put(outPairing, cluster);
108109
}
109110

0 commit comments

Comments
 (0)